LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_datetrunc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 48 126 38.1 %
Date: 2021-10-13 02:24:04 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "sql.h"
      11             : #include "mal_instruction.h"
      12             : 
      13             : #define do_date_trunc(val, DIVISOR)                                     \
      14             :         timestamp_create(timestamp_date(val),                           \
      15             :                          (timestamp_daytime(val) / (DIVISOR)) * (DIVISOR))
      16             : 
      17             : #define date_trunc_time_loop(NAME, DIVISOR)                             \
      18             :         do {                                                            \
      19             :                 if  ( strcasecmp(*scale, NAME) == 0){                   \
      20             :                         for( ; lo < hi; lo++)                                \
      21             :                                 if (is_timestamp_nil(bt[lo])) {         \
      22             :                                         dt[lo] = timestamp_nil;         \
      23             :                                 } else {                                \
      24             :                                         dt[lo] = do_date_trunc(bt[lo], DIVISOR); \
      25             :                                 }                                       \
      26             :                 }                                                       \
      27             :         } while (0)
      28             : 
      29             : static inline bool
      30          77 : truncate_check(const char *scale)
      31             : {
      32             :         return
      33         147 :                 strcasecmp(scale, "millennium") == 0 ||
      34          70 :                 strcasecmp(scale, "century") == 0  ||
      35          60 :                 strcasecmp(scale, "decade") == 0 ||
      36          52 :                 strcasecmp(scale, "year") == 0 ||
      37          47 :                 strcasecmp(scale, "quarter" ) == 0 ||
      38          42 :                 strcasecmp(scale, "month") == 0 ||
      39          37 :                 strcasecmp(scale, "week") == 0 ||
      40          30 :                 strcasecmp(scale, "day") == 0  ||
      41          25 :                 strcasecmp(scale, "hour") == 0 ||
      42          20 :                 strcasecmp(scale, "minute") == 0 ||
      43          15 :                 strcasecmp(scale, "second") == 0 ||
      44          87 :                 strcasecmp(scale, "milliseconds") == 0 ||
      45           5 :                 strcasecmp(scale, "microseconds") == 0;
      46             : }
      47             : 
      48             : str
      49           0 : bat_date_trunc(bat *res, const str *scale, const bat *bid)
      50             : {
      51             :         BAT *b, *bn;
      52             :         oid lo, hi;
      53             :         const timestamp *bt;
      54             :         timestamp *dt;
      55             :         char *msg = NULL;
      56             :         date days;
      57             : 
      58           0 :         if ( truncate_check(*scale) == 0)
      59           0 :                 throw(SQL, "batcalc.truncate_timestamp", SQLSTATE(HY005) "Improper directive ");
      60             : 
      61           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
      62           0 :                 throw(SQL, "batcalc.truncate_timestamp", SQLSTATE(HY005) "Cannot access column descriptor");
      63             :         }
      64           0 :         bn = COLnew(b->hseqbase, TYPE_timestamp, BATcount(b), TRANSIENT);
      65           0 :         if (bn == NULL) {
      66           0 :                 BBPunfix(b->batCacheid);
      67           0 :                 throw(SQL, "sql.truncate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      68             :         }
      69             : 
      70           0 :         BATiter bi = bat_iterator(b);
      71           0 :         bt = (const timestamp *) bi.base;
      72           0 :         dt = (timestamp *) Tloc(bn, 0);
      73             : 
      74             :         lo = 0;
      75           0 :         hi = lo + BATcount(b);
      76             : 
      77           0 :         date_trunc_time_loop("microseconds", 1);
      78           0 :         date_trunc_time_loop("milliseconds", 1000);
      79           0 :         date_trunc_time_loop("second", 1000000);
      80           0 :         date_trunc_time_loop("minute", 1000000 * 60);
      81           0 :         date_trunc_time_loop("hour", LL_CONSTANT(1000000) * 60 * 60);
      82             : 
      83           0 :         if  ( strcasecmp(*scale, "day") == 0){
      84           0 :                 for( ; lo < hi; lo++)
      85           0 :                         if (is_timestamp_nil(bt[lo])) {
      86           0 :                                 dt[lo] = timestamp_nil;
      87             :                         } else {
      88           0 :                                 days = timestamp_date(bt[lo]);
      89           0 :                                 dt[lo] = timestamp_fromdate(days);
      90             :                         }
      91             :         }
      92             : 
      93           0 :         if  ( strcasecmp(*scale, "week") == 0){
      94           0 :                 for( ; lo < hi; lo++)
      95           0 :                         if (is_timestamp_nil(bt[lo])) {
      96           0 :                                 dt[lo] = timestamp_nil;
      97             :                         } else {
      98           0 :                                 days = timestamp_date(bt[lo]);
      99           0 :                                 dt[lo] = timestamp_fromdate(date_add_day(days, 1 - date_dayofweek(days)));
     100             :                         }
     101             :         }
     102             : 
     103           0 :         if  ( strcasecmp(*scale, "month") == 0){
     104           0 :                 for( ; lo < hi; lo++)
     105           0 :                         if (is_timestamp_nil(bt[lo])) {
     106           0 :                                 dt[lo] = timestamp_nil;
     107             :                         } else {
     108           0 :                                 days = timestamp_date(bt[lo]);
     109           0 :                                 dt[lo] = timestamp_fromdate(
     110             :                                         date_create(date_year(days),
     111             :                                                     date_month(days),
     112             :                                                     1));
     113             :                         }
     114             :         }
     115             : 
     116           0 :         if  ( strcasecmp(*scale, "quarter") == 0){
     117           0 :                 for( ; lo < hi; lo++)
     118           0 :                         if (is_timestamp_nil(bt[lo])) {
     119           0 :                                 dt[lo] = timestamp_nil;
     120             :                         } else {
     121           0 :                                 days = timestamp_date(bt[lo]);
     122           0 :                                 dt[lo] = timestamp_fromdate(
     123             :                                         date_create(date_year(days),
     124           0 :                                                     ((date_month(days) - 1) / 3) * 3 + 1,
     125             :                                                     1));
     126             :                         }
     127             :         }
     128             : 
     129           0 :         if  ( strcasecmp(*scale, "year") == 0){
     130           0 :                 for( ; lo < hi; lo++)
     131           0 :                         if (is_timestamp_nil(bt[lo])) {
     132           0 :                                 dt[lo] = timestamp_nil;
     133             :                         } else {
     134           0 :                                 days = timestamp_date(bt[lo]);
     135           0 :                                 dt[lo] = timestamp_fromdate(date_create(date_year(days), 1, 1));
     136             :                         }
     137             :         }
     138             : 
     139           0 :         if  ( strcasecmp(*scale, "decade") == 0){
     140           0 :                 for( ; lo < hi; lo++)
     141           0 :                         if (is_timestamp_nil(bt[lo])) {
     142           0 :                                 dt[lo] = timestamp_nil;
     143             :                         } else {
     144           0 :                                 days = timestamp_date(bt[lo]);
     145           0 :                                 dt[lo] = timestamp_fromdate(date_create((date_year(days) / 10) * 10, 1, 1));
     146             :                         }
     147             :         }
     148             : 
     149           0 :         if  ( strcasecmp(*scale, "century") == 0){
     150           0 :                 for( ; lo < hi; lo++)
     151           0 :                         if (is_timestamp_nil(bt[lo])) {
     152           0 :                                 dt[lo] = timestamp_nil;
     153             :                         } else {
     154           0 :                                 days = timestamp_date(bt[lo]);
     155           0 :                                 dt[lo] = timestamp_fromdate(date_create((date_year(days) / 100) * 100, 1, 1));
     156             :                         }
     157             :         }
     158             : 
     159           0 :         if  ( strcasecmp(*scale, "millennium") == 0){
     160           0 :                 for( ; lo < hi; lo++)
     161           0 :                         if (is_timestamp_nil(bt[lo])) {
     162           0 :                                 dt[lo] = timestamp_nil;
     163             :                         } else {
     164           0 :                                 days = timestamp_date(bt[lo]);
     165           0 :                                 dt[lo] = timestamp_fromdate(date_create((date_year(days) / 1000) * 1000, 1, 1));
     166             :                         }
     167             :         }
     168             : 
     169           0 :         bat_iterator_end(&bi);
     170           0 :         BATsetcount(bn, (BUN) lo);
     171             :         /* we can inherit most properties */
     172           0 :         bn->tnonil = b->tnonil;
     173           0 :         bn->tnil = b->tnil;
     174           0 :         bn->tsorted = b->tsorted;
     175           0 :         bn->trevsorted = b->trevsorted;
     176           0 :         bn->tkey = false;    /* can't be sure */
     177           0 :         BBPkeepref(*res = bn->batCacheid);
     178           0 :         BBPunfix(b->batCacheid);
     179           0 :         return msg;
     180             : }
     181             : 
     182             : #define date_trunc_single_time(NAME, DIVISOR)                   \
     183             :         do {                                                    \
     184             :                 if  ( strcasecmp(*scale, NAME) == 0){           \
     185             :                         *dt = do_date_trunc(*bt, DIVISOR);      \
     186             :                 }                                               \
     187             :         } while (0)
     188             : 
     189             : str
     190          77 : date_trunc(timestamp *dt, const str *scale, const timestamp *bt)
     191             : {
     192             :         str msg = MAL_SUCCEED;
     193             :         date days;
     194             : 
     195          77 :         if (truncate_check(*scale) == 0)
     196           0 :                 throw(SQL, "sql.truncate", SQLSTATE(HY013) "Improper directive ");
     197             : 
     198          77 :         if (is_timestamp_nil(*bt)) {
     199          13 :                 *dt = timestamp_nil;
     200          13 :                 return MAL_SUCCEED;
     201             :         }
     202             : 
     203          64 :         date_trunc_single_time("microseconds", 1);
     204          64 :         date_trunc_single_time("milliseconds", 1000);
     205          64 :         date_trunc_single_time("second", 1000000);
     206          64 :         date_trunc_single_time("minute", 1000000 * 60);
     207          64 :         date_trunc_single_time("hour", LL_CONSTANT(1000000) * 60 * 60);
     208             : 
     209          64 :         if  ( strcasecmp(*scale, "day") == 0){
     210           4 :                 days = timestamp_date(*bt);
     211           4 :                 *dt = timestamp_fromdate(days);
     212             :         }
     213             : 
     214          64 :         if  ( strcasecmp(*scale, "week") == 0){
     215           6 :                 days = timestamp_date(*bt);
     216           6 :                 *dt = timestamp_fromdate(date_add_day(days, 1 - date_dayofweek(days)));
     217             :         }
     218             : 
     219          64 :         if  ( strcasecmp(*scale, "month") == 0){
     220           4 :                 days = timestamp_date(*bt);
     221           4 :                 *dt = timestamp_fromdate(date_create(date_year(days), date_month(days), 1));
     222             :         }
     223             : 
     224          64 :         if  ( strcasecmp(*scale, "quarter") == 0){
     225           4 :                 days = timestamp_date(*bt);
     226           4 :                 *dt = timestamp_fromdate(date_create(date_year(days), ((date_month(days) - 1) / 3) * 3 + 1, 1));
     227             :         }
     228             : 
     229          64 :         if  ( strcasecmp(*scale, "year") == 0){
     230           4 :                 days = timestamp_date(*bt);
     231           4 :                 *dt = timestamp_fromdate(date_create(date_year(days), 1, 1));
     232             :         }
     233             : 
     234          64 :         if  ( strcasecmp(*scale, "decade") == 0){
     235           7 :                 days = timestamp_date(*bt);
     236           7 :                 *dt = timestamp_fromdate(date_create((date_year(days) / 10) * 10, 1, 1));
     237             :         }
     238             : 
     239          64 :         if  ( strcasecmp(*scale, "century") == 0){
     240           9 :                 days = timestamp_date(*bt);
     241           9 :                 *dt = timestamp_fromdate(date_create((date_year(days) / 100) * 100, 1, 1));
     242             :         }
     243             : 
     244          64 :         if  ( strcasecmp(*scale, "millennium") == 0){
     245           6 :                 days = timestamp_date(*bt);
     246           6 :                 *dt = timestamp_fromdate(date_create((date_year(days) / 1000) * 1000, 1, 1));
     247             :         }
     248             :         return msg;
     249             : }

Generated by: LCOV version 1.14