LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_time.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 529 890 59.4 %
Date: 2021-10-13 02:24:04 Functions: 27 34 79.4 %

          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 "sql_datetime.h"
      12             : #include "mal_instruction.h"
      13             : 
      14             : static inline daytime
      15             : daytime_2time_daytime_imp(daytime input,
      16             : #ifdef HAVE_HGE
      17             : hge shift, hge divider, hge multiplier
      18             : #else
      19             : lng shift, lng divider, lng multiplier
      20             : #endif
      21             : )
      22             : {
      23        2320 :         return ((input + shift) / divider) * multiplier;
      24             : }
      25             : 
      26             : str
      27        2511 : daytime_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      28             : {
      29             :         str msg = MAL_SUCCEED;
      30             :         BAT *b = NULL, *s = NULL, *res = NULL;
      31             :         BUN q = 0;
      32             :         daytime *restrict ret = NULL;
      33        4994 :         int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
      34             :         bool is_a_bat = false, nils = false;
      35        2511 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
      36        2511 :         struct canditer ci = {0};
      37             : #ifdef HAVE_HGE
      38             :         hge shift = 0, divider = 1, multiplier = 1;
      39             : #else
      40             :         lng shift = 0, divider = 1, multiplier = 1;
      41             : #endif
      42             : 
      43             :         (void) cntxt;
      44        2511 :         if (d < 0 || (size_t) d >= sizeof(scales) / sizeof(scales[0])) {
      45           0 :                 msg = createException(SQL, "batcalc.daytime_2time_daytime", SQLSTATE(42000) "Digits out of bounds");
      46           0 :                 goto bailout;
      47             :         }
      48        2511 :         is_a_bat = isaBatType(tpe);
      49        2511 :         if (is_a_bat) {
      50             :                 tpe = getBatType(tpe);
      51          28 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
      52           0 :                         msg = createException(SQL, "batcalc.daytime_2time_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      53           0 :                         goto bailout;
      54             :                 }
      55          28 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
      56           0 :                         msg = createException(SQL, "batcalc.timestamp_2_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      57           0 :                         goto bailout;
      58             :                 }
      59          28 :                 q = canditer_init(&ci, b, s);
      60          28 :                 if (!(res = COLnew(ci.hseq, TYPE_daytime, q, TRANSIENT))) {
      61           0 :                         msg = createException(SQL, "batcalc.daytime_2time_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      62           0 :                         goto bailout;
      63             :                 }
      64          28 :                 r = getArgReference_bat(stk, pci, 0);
      65          28 :                 ret = (daytime*) Tloc(res, 0);
      66             :         } else {
      67        2483 :                 ret = (daytime*) getArgReference(stk, pci, 0);
      68             :         }
      69             : 
      70             :         /* correct fraction */
      71        2511 :         if (d < 6) {
      72        2480 :                 divider *= scales[6 - d];
      73             : #ifndef TRUNCATE_NUMBERS
      74        2480 :                 shift += (scales[6 - d] >> 1);
      75             : #endif
      76             :                 multiplier *= scales[6 - d];
      77             :         }
      78             : 
      79        2511 :         if (is_a_bat) {
      80          28 :                 oid off = b->hseqbase;
      81          28 :                 BATiter bi = bat_iterator(b);
      82          28 :                 daytime *restrict vals = (daytime*) bi.base;
      83          28 :                 if (ci.tpe == cand_dense) {
      84          79 :                         for (BUN i = 0; i < q; i++) {
      85          51 :                                 oid p = (canditer_next_dense(&ci) - off);
      86          51 :                                 daytime next = vals[p];
      87             : 
      88          51 :                                 if (is_daytime_nil(next)) {
      89          11 :                                         ret[i] = daytime_nil;
      90             :                                         nils = true;
      91             :                                 } else {
      92          40 :                                         ret[i] = daytime_2time_daytime_imp(next, shift, divider, multiplier);
      93             :                                 }
      94             :                         }
      95             :                 } else {
      96           0 :                         for (BUN i = 0 ; i < q ; i++) {
      97           0 :                                 oid p = (canditer_next(&ci) - off);
      98           0 :                                 daytime next = vals[p];
      99             : 
     100           0 :                                 if (is_daytime_nil(next)) {
     101           0 :                                         ret[i] = daytime_nil;
     102             :                                         nils = true;
     103             :                                 } else {
     104           0 :                                         ret[i] = daytime_2time_daytime_imp(next, shift, divider, multiplier);
     105             :                                 }
     106             :                         }
     107             :                 }
     108          28 :                 bat_iterator_end(&bi);
     109             :         } else {
     110        2483 :                 daytime next = *(daytime*)getArgReference(stk, pci, 1);
     111        4803 :                 *ret = is_daytime_nil(next) ? daytime_nil : daytime_2time_daytime_imp(next, shift, divider, multiplier);
     112             :         }
     113             : 
     114        2511 : bailout:
     115        2511 :         if (res && !msg) {
     116          28 :                 BATsetcount(res, q);
     117          28 :                 res->tnil = nils;
     118          28 :                 res->tnonil = !nils;
     119          28 :                 res->tkey = b->tkey;
     120          28 :                 res->tsorted = b->tsorted;
     121          28 :                 res->trevsorted  = b->trevsorted;
     122          28 :                 BBPkeepref(*r = res->batCacheid);
     123        2483 :         } else if (res)
     124           0 :                 BBPreclaim(res);
     125        2511 :         if (b)
     126          28 :                 BBPunfix(b->batCacheid);
     127        2511 :         if (s)
     128          19 :                 BBPunfix(s->batCacheid);
     129        2511 :         return msg;
     130             : }
     131             : 
     132             : static inline daytime
     133          12 : second_interval_2_daytime_imp(lng next,
     134             : #ifdef HAVE_HGE
     135             : hge shift, hge divider, hge multiplier
     136             : #else
     137             : lng shift, lng divider, lng multiplier
     138             : #endif
     139             : ) {
     140          12 :         lng usec = (next % (24*60*60*1000)) * 1000;
     141          12 :         if (usec < 0) /* for negative intervals add the complement */
     142           2 :                 usec = DAY_USEC - (-usec);
     143          12 :         daytime d = daytime_add_usec(daytime_create(0, 0, 0, 0), usec);
     144          12 :         assert(!is_daytime_nil(d));
     145          12 :         return daytime_2time_daytime_imp(d, shift, divider, multiplier);
     146             : }
     147             : 
     148             : str
     149           7 : second_interval_2_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     150             : {
     151             :         str msg = MAL_SUCCEED;
     152             :         daytime *restrict ret = NULL;
     153          10 :         int tpe = getArgType(mb, pci, 1), digits = *getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2);
     154             :         bool is_a_bat = false, nils = false;
     155             :         BAT *b = NULL, *s = NULL, *res = NULL;
     156           7 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2) : NULL;
     157             :         BUN q = 0;
     158           7 :         struct canditer ci = {0};
     159             : #ifdef HAVE_HGE
     160             :         hge shift = 0, divider = 1, multiplier = 1;
     161             : #else
     162             :         lng shift = 0, divider = 1, multiplier = 1;
     163             : #endif
     164             : 
     165             :         (void) cntxt;
     166           7 :         if (digits < 0 || (size_t) digits >= sizeof(scales) / sizeof(scales[0])) {
     167           0 :                 msg = createException(SQL, "batcalc.second_interval_2_daytime", SQLSTATE(42000) "Digits out of bounds");
     168           0 :                 goto bailout;
     169             :         }
     170           7 :         is_a_bat = isaBatType(tpe);
     171           7 :         if (is_a_bat) {
     172             :                 tpe = getBatType(tpe);
     173           4 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     174           0 :                         msg = createException(SQL, "batcalc.second_interval_2_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     175           0 :                         goto bailout;
     176             :                 }
     177           4 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     178           0 :                         msg = createException(SQL, "batcalc.second_interval_2_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     179           0 :                         goto bailout;
     180             :                 }
     181           4 :                 q = canditer_init(&ci, b, s);
     182           4 :                 if (!(res = COLnew(ci.hseq, TYPE_daytime, q, TRANSIENT))) {
     183           0 :                         msg = createException(SQL, "batcalc.second_interval_2_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     184           0 :                         goto bailout;
     185             :                 }
     186           4 :                 r = getArgReference_bat(stk, pci, 0);
     187           4 :                 ret = (daytime*) Tloc(res, 0);
     188             :         } else {
     189           3 :                 ret = (daytime*) getArgReference(stk, pci, 0);
     190             :         }
     191             : 
     192           7 :         if (digits < 6) {
     193           5 :                 divider *= scales[6 - digits];
     194             : #ifndef TRUNCATE_NUMBERS
     195           5 :                 shift += (scales[6 - digits] >> 1);
     196             : #endif
     197             :                 multiplier *= scales[6 - digits];
     198             :         }
     199             : 
     200           7 :         if (is_a_bat) {
     201           4 :                 oid off = b->hseqbase;
     202           4 :                 BATiter bi = bat_iterator(b);
     203           4 :                 lng *restrict vals = (lng*) bi.base;
     204           4 :                 if (ci.tpe == cand_dense) {
     205          14 :                         for (BUN i = 0 ; i < q ; i++) {
     206          10 :                                 oid p = (canditer_next_dense(&ci) - off);
     207          10 :                                 lng next = vals[p];
     208             : 
     209          10 :                                 if (is_lng_nil(next)) {
     210           1 :                                         ret[i] = daytime_nil;
     211             :                                         nils = true;
     212             :                                 } else {
     213           9 :                                         ret[i] = second_interval_2_daytime_imp(next, shift, divider, multiplier);
     214             :                                 }
     215             :                         }
     216             :                 } else {
     217           0 :                         for (BUN i = 0 ; i < q ; i++) {
     218           0 :                                 oid p = (canditer_next(&ci) - off);
     219           0 :                                 lng next = vals[p];
     220             : 
     221           0 :                                 if (is_lng_nil(next)) {
     222           0 :                                         ret[i] = daytime_nil;
     223             :                                         nils = true;
     224             :                                 } else {
     225           0 :                                         ret[i] = second_interval_2_daytime_imp(next, shift, divider, multiplier);
     226             :                                 }
     227             :                         }
     228             :                 }
     229           4 :                 bat_iterator_end(&bi);
     230             :         } else {
     231           3 :                 lng next = *(lng*)getArgReference(stk, pci, 1);
     232           3 :                 *ret = is_lng_nil(next) ? daytime_nil : second_interval_2_daytime_imp(next, shift, divider, multiplier);
     233             :         }
     234             : 
     235           7 : bailout:
     236           7 :         if (b)
     237           4 :                 BBPunfix(b->batCacheid);
     238           7 :         if (s)
     239           0 :                 BBPunfix(s->batCacheid);
     240           7 :         if (res && !msg) {
     241           4 :                 BATsetcount(res, q);
     242           4 :                 res->tnil = nils;
     243           4 :                 res->tnonil = !nils;
     244           4 :                 res->tkey = BATcount(res) <= 1;
     245           4 :                 res->tsorted = BATcount(res) <= 1;
     246           4 :                 res->trevsorted = BATcount(res) <= 1;
     247           4 :                 BBPkeepref(*r = res->batCacheid);
     248           3 :         } else if (res)
     249           0 :                 BBPreclaim(res);
     250           7 :         return msg;
     251             : }
     252             : 
     253             : str
     254           0 : nil_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     255             : {
     256             :         BAT *b = NULL, *res = NULL;
     257             :         bat *r = NULL;
     258             : 
     259             :         (void) cntxt;
     260           0 :         if (isaBatType(getArgType(mb, pci, 1))) {
     261           0 :                 daytime d = daytime_nil;
     262           0 :                 if (!(b = BBPquickdesc(*getArgReference_bat(stk, pci, 1))))
     263           0 :                         throw(SQL, "batcalc.nil_2time_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     264           0 :                 res = BATconstant(b->hseqbase, TYPE_daytime, &d, BATcount(b), TRANSIENT);
     265           0 :                 if (!res)
     266           0 :                         throw(SQL, "batcalc.nil_2time_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     267           0 :                 r = getArgReference_bat(stk, pci, 0);
     268           0 :                 BBPkeepref(*r = res->batCacheid);
     269             :         } else {
     270           0 :                 daytime *ret = (daytime*) getArgReference(stk, pci, 0);
     271           0 :                 *ret = daytime_nil;
     272             :         }
     273             :         return MAL_SUCCEED;
     274             : }
     275             : 
     276             : static inline str
     277          53 : str_2time_daytimetz_internal_imp(daytime *ret, str next, ssize_t (*fromstr_func)(const char *, size_t *, daytime **, bool),
     278             : #ifdef HAVE_HGE
     279             : hge shift, hge divider, hge multiplier
     280             : #else
     281             : lng shift, lng divider, lng multiplier
     282             : #endif
     283             : )
     284             : {
     285             :         ssize_t pos = 0;
     286          53 :         daytime dt = 0, *conv = &dt;
     287             : 
     288          53 :         pos = fromstr_func(next, &(size_t){sizeof(daytime)}, &conv, false);
     289          53 :         if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_daytime_nil(*conv))
     290          48 :                 return createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(22007) "Daytime '%s' has incorrect format", next);
     291           5 :         *ret = daytime_2time_daytime_imp(*conv, shift, divider, multiplier);
     292           5 :         return MAL_SUCCEED;
     293             : }
     294             : 
     295             : static str
     296          53 : str_2time_daytimetz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, int tz)
     297             : {
     298             :         str msg = MAL_SUCCEED;
     299             :         BAT *b = NULL, *s = NULL, *res = NULL;
     300             :         BUN q = 0;
     301             :         daytime *restrict ret = NULL;
     302          53 :         int d = (digits) ? digits - 1 : 0;
     303             :         bool is_a_bat = false, nils = false;
     304             :         bat *r = NULL;
     305          53 :         ssize_t (*fromstr_func)(const char *, size_t *, daytime **, bool) = tz ? daytime_tz_fromstr : daytime_fromstr;
     306          53 :         struct canditer ci = {0};
     307             : #ifdef HAVE_HGE
     308             :         hge shift = 0, divider = 1, multiplier = 1;
     309             : #else
     310             :         lng shift = 0, divider = 1, multiplier = 1;
     311             : #endif
     312             : 
     313          53 :         if (d < 0 || (size_t) d >= sizeof(scales) / sizeof(scales[0])) {
     314           0 :                 msg = createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(42000) "Digits out of bounds");
     315           0 :                 goto bailout;
     316             :         }
     317          53 :         is_a_bat = isaBatType(tpe);
     318          53 :         if (is_a_bat) {
     319             :                 tpe = getBatType(tpe);
     320          13 :                 if (!(b = BATdescriptor(*(bat*) in))) {
     321           0 :                         msg = createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     322           0 :                         goto bailout;
     323             :                 }
     324          13 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     325           0 :                         msg = createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     326           0 :                         goto bailout;
     327             :                 }
     328          13 :                 q = canditer_init(&ci, b, s);
     329          13 :                 if (!(res = COLnew(ci.hseq, TYPE_daytime, q, TRANSIENT))) {
     330           0 :                         msg = createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     331           0 :                         goto bailout;
     332             :                 }
     333             :                 r = (bat*) out;
     334          13 :                 ret = (daytime*) Tloc(res, 0);
     335             :         } else {
     336             :                 ret = (daytime*) out;
     337             :         }
     338             : 
     339             :         /* correct fraction */
     340          53 :         if (d < 6) {
     341          42 :                 divider *= scales[6 - d];
     342             : #ifndef TRUNCATE_NUMBERS
     343          42 :                 shift += (scales[6 - d] >> 1);
     344             : #endif
     345             :                 multiplier *= scales[6 - d];
     346             :         }
     347             : 
     348          53 :         if (is_a_bat) {
     349          13 :                 oid off = b->hseqbase;
     350          13 :                 BATiter it = bat_iterator(b);
     351          13 :                 if (ci.tpe == cand_dense) {
     352          26 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     353          13 :                                 oid p = (canditer_next_dense(&ci) - off);
     354          13 :                                 str next = BUNtvar(it, p);
     355             : 
     356          13 :                                 if (strNil(next)) {
     357           0 :                                         ret[i] = daytime_nil;
     358             :                                         nils = true;
     359             :                                 } else {
     360          13 :                                         msg = str_2time_daytimetz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
     361             :                                 }
     362             :                         }
     363             :                 } else {
     364           0 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     365           0 :                                 oid p = (canditer_next(&ci) - off);
     366           0 :                                 str next = BUNtvar(it, p);
     367             : 
     368           0 :                                 if (strNil(next)) {
     369           0 :                                         ret[i] = daytime_nil;
     370             :                                         nils = true;
     371             :                                 } else {
     372           0 :                                         msg = str_2time_daytimetz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
     373             :                                 }
     374             :                         }
     375             :                 }
     376          13 :                 bat_iterator_end(&it);
     377             :         } else {
     378          40 :                 str next = *(str*)in;
     379          40 :                 if (strNil(next))
     380           0 :                         *ret = daytime_nil;
     381             :                 else
     382          40 :                         msg = str_2time_daytimetz_internal_imp(ret, next, fromstr_func, shift, divider, multiplier);
     383             :         }
     384             : 
     385          53 : bailout:
     386          53 :         if (b)
     387          13 :                 BBPunfix(b->batCacheid);
     388          53 :         if (s)
     389           0 :                 BBPunfix(s->batCacheid);
     390          53 :         if (res && !msg) {
     391           1 :                 BATsetcount(res, q);
     392           1 :                 res->tnil = nils;
     393           1 :                 res->tnonil = !nils;
     394           1 :                 res->tkey = BATcount(res) <= 1;
     395           1 :                 res->tsorted = BATcount(res) <= 1;
     396           1 :                 res->trevsorted = BATcount(res) <= 1;
     397           1 :                 BBPkeepref(*r = res->batCacheid);
     398          52 :         } else if (res)
     399          12 :                 BBPreclaim(res);
     400          53 :         return msg;
     401             : }
     402             : 
     403             : str
     404          38 : str_2time_daytimetz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     405             : {
     406          38 :         int tpe = getArgType(mb, pci, 1),
     407          70 :                 digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2),
     408          70 :                 tz = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
     409          38 :         bat *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
     410             :         (void) cntxt;
     411          38 :         return str_2time_daytimetz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), sid, tpe, digits, tz);
     412             : }
     413             : 
     414             : str
     415           7 : batstr_2time_daytime(bat *res, const bat *bid, const bat *s, const int *digits)
     416             : {
     417           7 :         return str_2time_daytimetz_internal((ptr) res, (ptr) bid, s, newBatType(TYPE_str), *digits, 0);
     418             : }
     419             : 
     420             : str
     421           8 : str_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     422             : {
     423           8 :         int tpe = getArgType(mb, pci, 1), digits = *getArgReference_int(stk, pci, 2);
     424             :         (void) cntxt;
     425           8 :         return str_2time_daytimetz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, 0);
     426             : }
     427             : 
     428             : static inline daytime
     429             : timestamp_2_daytime_imp(timestamp input,
     430             : #ifdef HAVE_HGE
     431             : hge shift, hge divider, hge multiplier
     432             : #else
     433             : lng shift, lng divider, lng multiplier
     434             : #endif
     435             : )
     436             : {
     437          35 :         daytime dt = timestamp_daytime(input);
     438           3 :         return ((dt + shift) / divider) * multiplier;
     439             : }
     440             : 
     441             : str
     442          11 : timestamp_2_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     443             : {
     444             :         str msg = MAL_SUCCEED;
     445             :         BAT *b = NULL, *s = NULL, *res = NULL;
     446             :         BUN q = 0;
     447             :         daytime *restrict ret = NULL;
     448          14 :         int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
     449             :         bool is_a_bat = false, nils = false;
     450          11 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
     451          11 :         struct canditer ci = {0};
     452             : #ifdef HAVE_HGE
     453             :         hge shift = 0, divider = 1, multiplier = 1;
     454             : #else
     455             :         lng shift = 0, divider = 1, multiplier = 1;
     456             : #endif
     457             : 
     458             :         (void) cntxt;
     459          11 :         if (d < 0 || (size_t) d >= sizeof(scales) / sizeof(scales[0])) {
     460           0 :                 msg = createException(SQL, "batcalc.timestamp_2_daytime", SQLSTATE(42000) "Digits out of bounds");
     461           0 :                 goto bailout;
     462             :         }
     463          11 :         is_a_bat = isaBatType(tpe);
     464          11 :         if (is_a_bat) {
     465             :                 tpe = getBatType(tpe);
     466           8 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     467           0 :                         msg = createException(SQL, "batcalc.timestamp_2_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     468           0 :                         goto bailout;
     469             :                 }
     470           8 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     471           0 :                         msg = createException(SQL, "batcalc.timestamp_2_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     472           0 :                         goto bailout;
     473             :                 }
     474           8 :                 q = canditer_init(&ci, b, s);
     475           8 :                 if (!(res = COLnew(ci.hseq, TYPE_daytime, q, TRANSIENT))) {
     476           0 :                         msg = createException(SQL, "batcalc.timestamp_2_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     477           0 :                         goto bailout;
     478             :                 }
     479           8 :                 r = getArgReference_bat(stk, pci, 0);
     480           8 :                 ret = (daytime*) Tloc(res, 0);
     481             :         } else {
     482           3 :                 ret = (daytime*) getArgReference(stk, pci, 0);
     483             :         }
     484             : 
     485             :         /* correct fraction */
     486          11 :         if (d < 6) {
     487          10 :                 divider *= scales[6 - d];
     488             : #ifndef TRUNCATE_NUMBERS
     489          10 :                 shift += (scales[6 - d] >> 1);
     490             : #endif
     491             :                 multiplier *= scales[6 - d];
     492             :         }
     493             : 
     494          11 :         if (is_a_bat) {
     495           8 :                 oid off = b->hseqbase;
     496           8 :                 BATiter bi = bat_iterator(b);
     497           8 :                 timestamp *restrict vals = (timestamp*) bi.base;
     498           8 :                 if (ci.tpe == cand_dense) {
     499          48 :                         for (BUN i = 0 ; i < q; i++) {
     500          40 :                                 oid p = (canditer_next_dense(&ci) - off);
     501          40 :                                 timestamp next = vals[p];
     502             : 
     503          40 :                                 if (is_timestamp_nil(next)) {
     504           8 :                                         ret[i] = daytime_nil;
     505             :                                         nils = true;
     506             :                                 } else {
     507          32 :                                         ret[i] = timestamp_2_daytime_imp(next, shift, divider, multiplier);
     508             :                                 }
     509             :                         }
     510             :                 } else {
     511           0 :                         for (BUN i = 0 ; i < q; i++) {
     512           0 :                                 oid p = (canditer_next(&ci) - off);
     513           0 :                                 timestamp next = vals[p];
     514             : 
     515           0 :                                 if (is_timestamp_nil(next)) {
     516           0 :                                         ret[i] = daytime_nil;
     517             :                                         nils = true;
     518             :                                 } else {
     519           0 :                                         ret[i] = timestamp_2_daytime_imp(next, shift, divider, multiplier);
     520             :                                 }
     521             :                         }
     522             :                 }
     523           8 :                 bat_iterator_end(&bi);
     524             :         } else {
     525           3 :                 timestamp next = *(timestamp*)getArgReference(stk, pci, 1);
     526           6 :                 *ret = is_timestamp_nil(next) ? daytime_nil : timestamp_2_daytime_imp(next, shift, divider, multiplier);
     527             :         }
     528             : 
     529          11 : bailout:
     530          11 :         if (b)
     531           8 :                 BBPunfix(b->batCacheid);
     532          11 :         if (s)
     533           0 :                 BBPunfix(s->batCacheid);
     534          11 :         if (res && !msg) {
     535           8 :                 BATsetcount(res, q);
     536           8 :                 res->tnil = nils;
     537           8 :                 res->tnonil = !nils;
     538           8 :                 res->tkey = BATcount(res) <= 1;
     539           8 :                 res->tsorted = BATcount(res) <= 1;
     540           8 :                 res->trevsorted = BATcount(res) <= 1;
     541           8 :                 BBPkeepref(*r = res->batCacheid);
     542           3 :         } else if (res)
     543           0 :                 BBPreclaim(res);
     544          11 :         return msg;
     545             : }
     546             : 
     547             : str
     548          43 : date_2_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     549             : {
     550             :         str msg = MAL_SUCCEED;
     551             :         BAT *b = NULL, *s = NULL, *res = NULL;
     552             :         BUN q = 0;
     553             :         timestamp *restrict ret = NULL;
     554          43 :         int tpe = getArgType(mb, pci, 1);
     555             :         bool is_a_bat = false, nils = false;
     556          43 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2) : NULL;
     557          43 :         struct canditer ci = {0};
     558             : 
     559             :         (void) cntxt;
     560          43 :         is_a_bat = isaBatType(tpe);
     561          43 :         if (is_a_bat) {
     562             :                 tpe = getBatType(tpe);
     563          30 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     564           0 :                         msg = createException(SQL, "batcalc.date_2_timestamp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     565           0 :                         goto bailout;
     566             :                 }
     567          30 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     568           0 :                         msg = createException(SQL, "batcalc.date_2_timestamp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     569           0 :                         goto bailout;
     570             :                 }
     571          30 :                 q = canditer_init(&ci, b, s);
     572          30 :                 if (!(res = COLnew(ci.hseq, TYPE_timestamp, q, TRANSIENT))) {
     573           0 :                         msg = createException(SQL, "batcalc.date_2_timestamp", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     574           0 :                         goto bailout;
     575             :                 }
     576          30 :                 r = getArgReference_bat(stk, pci, 0);
     577          30 :                 ret = (timestamp*) Tloc(res, 0);
     578             :         } else {
     579          13 :                 ret = (timestamp*) getArgReference(stk, pci, 0);
     580             :         }
     581             : 
     582          43 :         if (is_a_bat) {
     583          30 :                 oid off = b->hseqbase;
     584          30 :                 BATiter bi = bat_iterator(b);
     585          30 :                 date *restrict vals = (date*) bi.base;
     586          30 :                 if (ci.tpe == cand_dense) {
     587         350 :                         for (BUN i = 0 ; i < q; i++) {
     588         320 :                                 oid p = (canditer_next_dense(&ci) - off);
     589         320 :                                 ret[i] = timestamp_fromdate(vals[p]);
     590         320 :                                 nils |= is_timestamp_nil(ret[i]);
     591             :                         }
     592             :                 } else {
     593           0 :                         for (BUN i = 0 ; i < q; i++) {
     594           0 :                                 oid p = (canditer_next(&ci) - off);
     595           0 :                                 ret[i] = timestamp_fromdate(vals[p]);
     596           0 :                                 nils |= is_timestamp_nil(ret[i]);
     597             :                         }
     598             :                 }
     599          30 :                 bat_iterator_end(&bi);
     600             :         } else {
     601          13 :                 *ret = timestamp_fromdate(*(date*)getArgReference(stk, pci, 1));
     602             :         }
     603             : 
     604          43 : bailout:
     605          43 :         if (res && !msg) {
     606          30 :                 BATsetcount(res, q);
     607          30 :                 res->tnil = nils;
     608          30 :                 res->tnonil = !nils;
     609          30 :                 res->tkey = b->tkey;
     610          30 :                 res->tsorted = b->tsorted;
     611          30 :                 res->trevsorted  = b->trevsorted;
     612          30 :                 BBPkeepref(*r = res->batCacheid);
     613          13 :         } else if (res)
     614           0 :                 BBPreclaim(res);
     615          43 :         if (b)
     616          30 :                 BBPunfix(b->batCacheid);
     617          43 :         if (s)
     618           0 :                 BBPunfix(s->batCacheid);
     619          43 :         return msg;
     620             : }
     621             : 
     622             : static inline timestamp
     623        3311 : timestamp_2time_timestamp_imp(timestamp input,
     624             : #ifdef HAVE_HGE
     625             : hge shift, hge divider, hge multiplier
     626             : #else
     627             : lng shift, lng divider, lng multiplier
     628             : #endif
     629             : )
     630             : {
     631        3311 :         date dt = timestamp_date(input);
     632        3311 :         daytime tm = timestamp_daytime(input);
     633        3311 :         tm = ((tm + shift) / divider) * multiplier;
     634        3311 :         return timestamp_create(dt, tm);
     635             : }
     636             : 
     637             : str
     638       45063 : timestamp_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     639             : {
     640             :         str msg = MAL_SUCCEED;
     641             :         BAT *b = NULL, *s = NULL, *res = NULL;
     642             :         BUN q = 0;
     643             :         timestamp *restrict ret = NULL;
     644       89978 :         int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
     645             :         bool is_a_bat = false, nils = false;
     646       45063 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
     647       45063 :         struct canditer ci = {0};
     648             : #ifdef HAVE_HGE
     649             :         hge shift = 0, divider = 1, multiplier = 1;
     650             : #else
     651             :         lng shift = 0, divider = 1, multiplier = 1;
     652             : #endif
     653             : 
     654             :         (void) cntxt;
     655       45063 :         if (d < 0 || (size_t) d >= sizeof(scales) / sizeof(scales[0])) {
     656           0 :                 msg = createException(SQL, "batcalc.timestamp_2time_timestamp", SQLSTATE(42000) "Digits out of bounds");
     657           0 :                 goto bailout;
     658             :         }
     659       45063 :         is_a_bat = isaBatType(tpe);
     660       45063 :         if (is_a_bat) {
     661             :                 tpe = getBatType(tpe);
     662         148 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     663           0 :                         msg = createException(SQL, "batcalc.timestamp_2time_timestamp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     664           0 :                         goto bailout;
     665             :                 }
     666         148 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     667           0 :                         msg = createException(SQL, "batcalc.timestamp_2time_timestamp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     668           0 :                         goto bailout;
     669             :                 }
     670         148 :                 q = canditer_init(&ci, b, s);
     671         148 :                 if (!(res = COLnew(ci.hseq, TYPE_timestamp, q, TRANSIENT))) {
     672           0 :                         msg = createException(SQL, "batcalc.timestamp_2time_timestamp", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     673           0 :                         goto bailout;
     674             :                 }
     675         148 :                 r = getArgReference_bat(stk, pci, 0);
     676         148 :                 ret = (timestamp*) Tloc(res, 0);
     677             :         } else {
     678       44915 :                 ret = (timestamp*) getArgReference(stk, pci, 0);
     679             :         }
     680             : 
     681             :         /* correct fraction */
     682       45063 :         if (d < 6) {
     683          50 :                 divider *= scales[6 - d];
     684             : #ifndef TRUNCATE_NUMBERS
     685          50 :                 shift += (scales[6 - d] >> 1);
     686             : #endif
     687             :                 multiplier *= scales[6 - d];
     688             :         }
     689             : 
     690       45063 :         if (is_a_bat) {
     691         148 :                 oid off = b->hseqbase;
     692         148 :                 BATiter bi = bat_iterator(b);
     693         148 :                 timestamp *restrict vals = (timestamp*) bi.base;
     694         148 :                 if (ci.tpe == cand_dense) {
     695         471 :                         for (BUN i = 0 ; i < q; i++) {
     696         324 :                                 oid p = (canditer_next_dense(&ci) - off);
     697         324 :                                 timestamp next = vals[p];
     698             : 
     699         324 :                                 if (is_timestamp_nil(next)) {
     700          12 :                                         ret[i] = timestamp_nil;
     701             :                                         nils = true;
     702             :                                 } else {
     703         312 :                                         ret[i] = timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
     704             :                                 }
     705             :                         }
     706             :                 } else {
     707           1 :                         for (BUN i = 0 ; i < q; i++) {
     708           1 :                                 oid p = (canditer_next(&ci) - off);
     709           0 :                                 timestamp next = vals[p];
     710             : 
     711           0 :                                 if (is_timestamp_nil(next)) {
     712           0 :                                         ret[i] = timestamp_nil;
     713             :                                         nils = true;
     714             :                                 } else {
     715           0 :                                         ret[i] = timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
     716             :                                 }
     717             :                         }
     718             :                 }
     719         147 :                 bat_iterator_end(&bi);
     720             :         } else {
     721       44915 :                 timestamp next = *(timestamp*)getArgReference(stk, pci, 1);
     722       44915 :                 *ret = is_timestamp_nil(next) ? timestamp_nil : timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
     723             :         }
     724             : 
     725       45062 : bailout:
     726       45062 :         if (res && !msg) {
     727         147 :                 BATsetcount(res, q);
     728         148 :                 res->tnil = nils;
     729         148 :                 res->tnonil = !nils;
     730         148 :                 res->tkey = b->tkey;
     731         148 :                 res->tsorted = b->tsorted;
     732         148 :                 res->trevsorted  = b->trevsorted;
     733         148 :                 BBPkeepref(*r = res->batCacheid);
     734       44915 :         } else if (res)
     735           0 :                 BBPreclaim(res);
     736       45063 :         if (b)
     737         148 :                 BBPunfix(b->batCacheid);
     738       45063 :         if (s)
     739          68 :                 BBPunfix(s->batCacheid);
     740       45063 :         return msg;
     741             : }
     742             : 
     743             : str
     744           0 : nil_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     745             : {
     746             :         BAT *b = NULL, *res = NULL;
     747             :         bat *r = NULL;
     748             : 
     749             :         (void) cntxt;
     750           0 :         if (isaBatType(getArgType(mb, pci, 1))) {
     751           0 :                 timestamp d = timestamp_nil;
     752           0 :                 if (!(b = BBPquickdesc(*getArgReference_bat(stk, pci, 1))))
     753           0 :                         throw(SQL, "batcalc.nil_2time_timestamp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     754           0 :                 res = BATconstant(b->hseqbase, TYPE_timestamp, &d, BATcount(b), TRANSIENT);
     755           0 :                 if (!res)
     756           0 :                         throw(SQL, "batcalc.nil_2time_timestamp", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     757           0 :                 r = getArgReference_bat(stk, pci, 0);
     758           0 :                 BBPkeepref(*r = res->batCacheid);
     759             :         } else {
     760           0 :                 timestamp *ret = (timestamp*) getArgReference(stk, pci, 0);
     761           0 :                 *ret = timestamp_nil;
     762             :         }
     763             :         return MAL_SUCCEED;
     764             : }
     765             : 
     766             : static inline str
     767         308 : str_2time_timestamptz_internal_imp(timestamp *ret, str next, ssize_t (*fromstr_func)(const char *, size_t *, timestamp **, bool),
     768             : #ifdef HAVE_HGE
     769             : hge shift, hge divider, hge multiplier
     770             : #else
     771             : lng shift, lng divider, lng multiplier
     772             : #endif
     773             : )
     774             : {
     775             :         ssize_t pos = 0;
     776         308 :         timestamp tp = 0, *conv = &tp;
     777             : 
     778         308 :         pos = fromstr_func(next, &(size_t){sizeof(timestamp)}, &conv, false);
     779         308 :         if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_timestamp_nil(*conv))
     780         280 :                 return createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(22007) "Timestamp '%s' has incorrect format", next);
     781          28 :         *ret = timestamp_2time_timestamp_imp(*conv, shift, divider, multiplier);
     782          28 :         return MAL_SUCCEED;
     783             : }
     784             : 
     785             : static str
     786         308 : str_2time_timestamptz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, int tz)
     787             : {
     788             :         str msg = MAL_SUCCEED;
     789             :         BAT *b = NULL, *s = NULL, *res = NULL;
     790             :         BUN q = 0;
     791             :         timestamp *restrict ret = NULL;
     792         308 :         int d = (digits) ? digits - 1 : 0;
     793             :         bool is_a_bat = false, nils = false;
     794             :         bat *r = NULL;
     795         308 :         ssize_t (*fromstr_func)(const char *, size_t *, timestamp **, bool) = tz ? timestamp_tz_fromstr : timestamp_fromstr;
     796         308 :         struct canditer ci = {0};
     797             : #ifdef HAVE_HGE
     798             :         hge shift = 0, divider = 1, multiplier = 1;
     799             : #else
     800             :         lng shift = 0, divider = 1, multiplier = 1;
     801             : #endif
     802             : 
     803         308 :         if (d < 0 || (size_t) d >= sizeof(scales) / sizeof(scales[0])) {
     804           0 :                 msg = createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(42000) "Digits out of bounds");
     805           0 :                 goto bailout;
     806             :         }
     807         308 :         is_a_bat = isaBatType(tpe);
     808         308 :         if (is_a_bat) {
     809             :                 tpe = getBatType(tpe);
     810          13 :                 if (!(b = BATdescriptor(*(bat*) in))) {
     811           0 :                         msg = createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     812           0 :                         goto bailout;
     813             :                 }
     814          13 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     815           0 :                         msg = createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     816           0 :                         goto bailout;
     817             :                 }
     818          13 :                 q = canditer_init(&ci, b, s);
     819          13 :                 if (!(res = COLnew(ci.hseq, TYPE_timestamp, q, TRANSIENT))) {
     820           0 :                         msg = createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     821           0 :                         goto bailout;
     822             :                 }
     823             :                 r = (bat*) out;
     824          13 :                 ret = (timestamp*) Tloc(res, 0);
     825             :         } else {
     826             :                 ret = (timestamp*) out;
     827             :         }
     828             : 
     829             :         /* correct fraction */
     830         308 :         if (d < 6) {
     831         267 :                 divider *= scales[6 - d];
     832             : #ifndef TRUNCATE_NUMBERS
     833         267 :                 shift += (scales[6 - d] >> 1);
     834             : #endif
     835             :                 multiplier *= scales[6 - d];
     836             :         }
     837             : 
     838         308 :         if (is_a_bat) {
     839          13 :                 oid off = b->hseqbase;
     840          13 :                 BATiter bi = bat_iterator(b);
     841          13 :                 if (ci.tpe == cand_dense) {
     842          26 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     843          13 :                                 oid p = (canditer_next_dense(&ci) - off);
     844          13 :                                 str next = BUNtvar(bi, p);
     845             : 
     846          13 :                                 if (strNil(next)) {
     847           0 :                                         ret[i] = timestamp_nil;
     848             :                                         nils = true;
     849             :                                 } else {
     850          13 :                                         msg = str_2time_timestamptz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
     851             :                                 }
     852             :                         }
     853             :                 } else {
     854           0 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     855           0 :                                 oid p = (canditer_next(&ci) - off);
     856           0 :                                 str next = BUNtvar(bi, p);
     857             : 
     858           0 :                                 if (strNil(next)) {
     859           0 :                                         ret[i] = timestamp_nil;
     860             :                                         nils = true;
     861             :                                 } else {
     862           0 :                                         msg = str_2time_timestamptz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
     863             :                                 }
     864             :                         }
     865             :                 }
     866          13 :                 bat_iterator_end(&bi);
     867             :         } else {
     868         295 :                 str next = *(str*)in;
     869         295 :                 if (strNil(next))
     870           0 :                         *ret = timestamp_nil;
     871             :                 else
     872         295 :                         msg = str_2time_timestamptz_internal_imp(ret, next, fromstr_func, shift, divider, multiplier);
     873             :         }
     874             : 
     875         308 : bailout:
     876         308 :         if (b)
     877          13 :                 BBPunfix(b->batCacheid);
     878         308 :         if (s)
     879           0 :                 BBPunfix(s->batCacheid);
     880         308 :         if (res && !msg) {
     881           1 :                 BATsetcount(res, q);
     882           1 :                 res->tnil = nils;
     883           1 :                 res->tnonil = !nils;
     884           1 :                 res->tkey = BATcount(res) <= 1;
     885           1 :                 res->tsorted = BATcount(res) <= 1;
     886           1 :                 res->trevsorted = BATcount(res) <= 1;
     887           1 :                 BBPkeepref(*r = res->batCacheid);
     888         307 :         } else if (res)
     889          12 :                 BBPreclaim(res);
     890         308 :         return msg;
     891             : }
     892             : 
     893             : str
     894         157 : str_2time_timestamptz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     895             : {
     896         157 :         int tpe = getArgType(mb, pci, 1),
     897         314 :                 digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2),
     898         314 :                 tz = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
     899             :         (void) cntxt;
     900         157 :         return str_2time_timestamptz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, tz);
     901             : }
     902             : 
     903             : str
     904           6 : batstr_2time_timestamptz(bat *res, const bat *bid, const bat *sid, const int *digits, int *tz)
     905             : {
     906           6 :         return str_2time_timestamptz_internal((ptr) res, (ptr) bid, sid, newBatType(TYPE_str), *digits, *tz);
     907             : }
     908             : 
     909             : str
     910         138 : str_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     911             : {
     912         138 :         int tpe = getArgType(mb, pci, 1), digits = *getArgReference_int(stk, pci, 2);
     913             :         (void) cntxt;
     914         138 :         return str_2time_timestamptz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, 0);
     915             : }
     916             : 
     917             : str
     918           7 : batstr_2time_timestamp(bat *res, const bat *bid, const bat *sid, const int *digits)
     919             : {
     920           7 :         return str_2time_timestamptz_internal((ptr) res, (ptr) bid, sid, newBatType(TYPE_str), *digits, 0);
     921             : }
     922             : 
     923             : static inline str
     924          11 : month_interval_str_imp(int *ret, str next, int d, int sk)
     925             : {
     926             :         lng upcast;
     927          11 :         if (interval_from_str(next, d, sk, &upcast) < 0)
     928           5 :                 return createException(SQL, "batcalc.month_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
     929           6 :         assert((lng) GDK_int_min <= upcast && upcast <= (lng) GDK_int_max);
     930           6 :         *ret = (int) upcast;
     931           6 :         return MAL_SUCCEED;
     932             : }
     933             : 
     934             : str
     935          11 : month_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     936             : {
     937             :         str msg = MAL_SUCCEED;
     938             :         int *restrict ret = NULL;
     939          23 :         int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
     940          11 :                 tpe = getArgType(mb, pci, 1);
     941             :         bool is_a_bat = false, nils = false;
     942             :         BAT *b = NULL, *s = NULL, *res = NULL;
     943          11 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
     944             :         BUN q = 0;
     945          11 :         struct canditer ci = {0};
     946             : 
     947             :         (void) cntxt;
     948          11 :         is_a_bat = isaBatType(tpe);
     949          11 :         if (is_a_bat) {
     950             :                 tpe = getBatType(tpe);
     951           5 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     952           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     953           0 :                         goto bailout;
     954             :                 }
     955           5 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     956           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     957           0 :                         goto bailout;
     958             :                 }
     959           5 :                 q = canditer_init(&ci, b, s);
     960           5 :                 if (!(res = COLnew(ci.hseq, TYPE_int, q, TRANSIENT))) {
     961           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     962           0 :                         goto bailout;
     963             :                 }
     964           5 :                 r = getArgReference_bat(stk, pci, 0);
     965           5 :                 ret = (int*) Tloc(res, 0);
     966             :         } else {
     967           6 :                 ret = getArgReference_int(stk, pci, 0);
     968             :         }
     969             : 
     970          11 :         if (is_a_bat) {
     971           5 :                 oid off = b->hseqbase;
     972           5 :                 BATiter bi = bat_iterator(b);
     973           5 :                 if (ci.tpe == cand_dense) {
     974          12 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     975           7 :                                 oid p = (canditer_next_dense(&ci) - off);
     976           7 :                                 str next = BUNtvar(bi, p);
     977             : 
     978           7 :                                 if (strNil(next)) {
     979           2 :                                         ret[i] = int_nil;
     980             :                                         nils = true;
     981             :                                 } else {
     982           5 :                                         msg = month_interval_str_imp(&(ret[i]), next, d, sk);
     983             :                                 }
     984             :                         }
     985             :                 } else {
     986           0 :                         for (BUN i = 0 ; i < q && !msg; i++) {
     987           0 :                                 oid p = (canditer_next(&ci) - off);
     988           0 :                                 str next = BUNtvar(bi, p);
     989             : 
     990           0 :                                 if (strNil(next)) {
     991           0 :                                         ret[i] = int_nil;
     992             :                                         nils = true;
     993             :                                 } else {
     994           0 :                                         msg = month_interval_str_imp(&(ret[i]), next, d, sk);
     995             :                                 }
     996             :                         }
     997             :                 }
     998           5 :                 bat_iterator_end(&bi);
     999             :         } else {
    1000           6 :                 const str next = *getArgReference_str(stk, pci, 1);
    1001             : 
    1002           6 :                 if (strNil(next))
    1003           0 :                         *ret = int_nil;
    1004             :                 else
    1005           6 :                         msg = month_interval_str_imp(ret, next, d, sk);
    1006             :         }
    1007             : 
    1008          11 : bailout:
    1009          11 :         if (b)
    1010           5 :                 BBPunfix(b->batCacheid);
    1011          11 :         if (s)
    1012           0 :                 BBPunfix(s->batCacheid);
    1013          11 :         if (res && !msg) {
    1014           2 :                 BATsetcount(res, q);
    1015           2 :                 res->tnil = nils;
    1016           2 :                 res->tnonil = !nils;
    1017           2 :                 res->tkey = BATcount(res) <= 1;
    1018           2 :                 res->tsorted = BATcount(res) <= 1;
    1019           2 :                 res->trevsorted = BATcount(res) <= 1;
    1020           2 :                 BBPkeepref(*r = res->batCacheid);
    1021           9 :         } else if (res)
    1022           3 :                 BBPreclaim(res);
    1023          11 :         return msg;
    1024             : }
    1025             : 
    1026             : static inline str
    1027         123 : second_interval_str_imp(lng *ret, str next, int d, int sk)
    1028             : {
    1029         123 :         if (interval_from_str(next, d, sk, ret) < 0)
    1030          88 :                 return createException(SQL, "batcalc.second_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
    1031             :         return MAL_SUCCEED;
    1032             : }
    1033             : 
    1034             : str
    1035         122 : second_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1036             : {
    1037             :         str msg = MAL_SUCCEED;
    1038             :         lng *restrict ret = NULL;
    1039         364 :         int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
    1040         122 :                 tpe = getArgType(mb, pci, 1);
    1041             :         bool is_a_bat = false, nils = false;
    1042             :         BAT *b = NULL, *s = NULL, *res = NULL;
    1043         122 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
    1044             :         BUN q = 0;
    1045         122 :         struct canditer ci = {0};
    1046             : 
    1047             :         (void) cntxt;
    1048         122 :         is_a_bat = isaBatType(tpe);
    1049         122 :         if (is_a_bat) {
    1050             :                 tpe = getBatType(tpe);
    1051           1 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1052           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1053           0 :                         goto bailout;
    1054             :                 }
    1055           1 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1056           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1057           0 :                         goto bailout;
    1058             :                 }
    1059           1 :                 q = canditer_init(&ci, b, s);
    1060           1 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, q, TRANSIENT))) {
    1061           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1062           0 :                         goto bailout;
    1063             :                 }
    1064           1 :                 r = getArgReference_bat(stk, pci, 0);
    1065           1 :                 ret = (lng*) Tloc(res, 0);
    1066             :         } else {
    1067         121 :                 ret = getArgReference_lng(stk, pci, 0);
    1068             :         }
    1069             : 
    1070         122 :         if (is_a_bat) {
    1071           1 :                 oid off = b->hseqbase;
    1072           1 :                 BATiter bi = bat_iterator(b);
    1073           1 :                 if (ci.tpe == cand_dense) {
    1074           5 :                         for (BUN i = 0 ; i < q && !msg; i++) {
    1075           4 :                                 oid p = (canditer_next_dense(&ci) - off);
    1076           4 :                                 str next = BUNtvar(bi, p);
    1077             : 
    1078           4 :                                 if (strNil(next)) {
    1079           2 :                                         ret[i] = lng_nil;
    1080             :                                         nils = true;
    1081             :                                 } else {
    1082           2 :                                         msg = second_interval_str_imp(&(ret[i]), next, d, sk);
    1083             :                                 }
    1084             :                         }
    1085             :                 } else {
    1086           0 :                         for (BUN i = 0 ; i < q && !msg; i++) {
    1087           0 :                                 oid p = (canditer_next(&ci) - off);
    1088           0 :                                 str next = BUNtvar(bi, p);
    1089             : 
    1090           0 :                                 if (strNil(next)) {
    1091           0 :                                         ret[i] = lng_nil;
    1092             :                                         nils = true;
    1093             :                                 } else {
    1094           0 :                                         msg = second_interval_str_imp(&(ret[i]), next, d, sk);
    1095             :                                 }
    1096             :                         }
    1097             :                 }
    1098           1 :                 bat_iterator_end(&bi);
    1099             :         } else {
    1100         121 :                 const str next = *getArgReference_str(stk, pci, 1);
    1101             : 
    1102         121 :                 if (strNil(next))
    1103           0 :                         *ret = lng_nil;
    1104             :                 else
    1105         121 :                         msg = second_interval_str_imp(ret, next, d, sk);
    1106             :         }
    1107             : 
    1108         122 : bailout:
    1109         122 :         if (b)
    1110           1 :                 BBPunfix(b->batCacheid);
    1111         122 :         if (s)
    1112           0 :                 BBPunfix(s->batCacheid);
    1113         122 :         if (res && !msg) {
    1114           1 :                 BATsetcount(res, q);
    1115           1 :                 res->tnil = nils;
    1116           1 :                 res->tnonil = !nils;
    1117           1 :                 res->tkey = BATcount(res) <= 1;
    1118           1 :                 res->tsorted = BATcount(res) <= 1;
    1119           1 :                 res->trevsorted = BATcount(res) <= 1;
    1120           1 :                 BBPkeepref(*r = res->batCacheid);
    1121         121 :         } else if (res)
    1122           0 :                 BBPreclaim(res);
    1123         122 :         return msg;
    1124             : }
    1125             : 
    1126             : #define interval_loop(FUNC, TPE_IN, TPE_OUT, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1127             :         do { \
    1128             :                 if (is_a_bat) { \
    1129             :                         oid off = b->hseqbase; \
    1130             :                         TPE_IN *restrict vals = bi.base; \
    1131             :                         if (ci.tpe == cand_dense) { \
    1132             :                                 for (BUN i = 0; i < q; i++) { \
    1133             :                                         oid p = (canditer_next_dense(&ci) - off); \
    1134             :                                         TPE_IN next = vals[p]; \
    1135             :                                         if (is_##TPE_IN##_nil(next)) { \
    1136             :                                                 ret[i] = TPE_OUT##_nil; \
    1137             :                                                 nils = true; \
    1138             :                                         } else { \
    1139             :                                                 FUNC(ret[i], TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1140             :                                         } \
    1141             :                                 } \
    1142             :                         } else { \
    1143             :                                 for (BUN i = 0; i < q; i++) { \
    1144             :                                         oid p = (canditer_next(&ci) - off); \
    1145             :                                         TPE_IN next = vals[p]; \
    1146             :                                         if (is_##TPE_IN##_nil(next)) { \
    1147             :                                                 ret[i] = TPE_OUT##_nil; \
    1148             :                                                 nils = true; \
    1149             :                                         } else { \
    1150             :                                                 FUNC(ret[i], TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1151             :                                         } \
    1152             :                                 } \
    1153             :                         } \
    1154             :                 } else { \
    1155             :                         TPE_IN next = *(TPE_IN*)getArgReference(stk, pci, 1); \
    1156             :                         if (is_##TPE_IN##_nil(next)) \
    1157             :                                 *ret = TPE_OUT##_nil;   \
    1158             :                         else    \
    1159             :                                 FUNC(*ret, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1160             :                 } \
    1161             :         } while(0)
    1162             : 
    1163             : #define month_interval_convert(OUT, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1164             :         do { \
    1165             :                 int cast, r; \
    1166             :                 CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1167             :                 cast = (int) next; \
    1168             :                 r = cast * multiplier; \
    1169             :                 MUL_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1170             :                 OUT = r; \
    1171             :         } while (0)
    1172             : 
    1173             : #define DO_NOTHING(TPE_IN, FUNC_NAME, MAX_VALUE) ;
    1174             : 
    1175             : #define CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE) \
    1176             :         do { \
    1177             :                 if (next > (TPE_IN) MAX_VALUE) { \
    1178             :                         size_t len = 0; \
    1179             :                         char *str_val = NULL; \
    1180             :                         if (BATatoms[tpe].atomToStr(&str_val, &len, &next, false) < 0) { \
    1181             :                                 msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1182             :                                 goto bailout1; \
    1183             :                         } \
    1184             :                         msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(22003) "Value %s too large to fit at a " FUNC_NAME, str_val); \
    1185             :                         GDKfree(str_val); \
    1186             :                         goto bailout1; \
    1187             :                 } \
    1188             :         } while (0)
    1189             : 
    1190             : #define MUL_OVERFLOW(TPE_IN, FUNC_NAME, MAX_VALUE) /* TPE_IN and MAX_VALUE are ignored on this macro */ \
    1191             :         do { \
    1192             :                 if (r < cast) { \
    1193             :                         size_t len = 0; \
    1194             :                         char *str_val = NULL; \
    1195             :                         if (BATatoms[tpe].atomToStr(&str_val, &len, &cast, false) < 0) { \
    1196             :                                 msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1197             :                                 goto bailout1; \
    1198             :                         } \
    1199             :                         msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(22003) "Overflow in conversion of %s to " FUNC_NAME, str_val); \
    1200             :                         GDKfree(str_val); \
    1201             :                         goto bailout1; \
    1202             :                 } \
    1203             :         } while (0)
    1204             : 
    1205             : str
    1206           0 : month_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1207             : {
    1208             :         str msg = MAL_SUCCEED;
    1209           0 :         int *restrict ret = NULL, multiplier = 1, k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2)),
    1210           0 :                 tpe = getArgType(mb, pci, 1);
    1211             :         bool is_a_bat = false, nils = false;
    1212             :         BAT *b = NULL, *s = NULL, *res = NULL;
    1213           0 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
    1214             :         BUN q = 0;
    1215           0 :         struct canditer ci = {0};
    1216             :         BATiter bi;
    1217             : 
    1218             :         (void) cntxt;
    1219           0 :         is_a_bat = isaBatType(tpe);
    1220           0 :         if (is_a_bat) {
    1221           0 :                 tpe = getBatType(tpe);
    1222           0 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1223           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1224           0 :                         goto bailout;
    1225             :                 }
    1226           0 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1227           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1228           0 :                         goto bailout;
    1229             :                 }
    1230           0 :                 q = canditer_init(&ci, b, s);
    1231           0 :                 if (!(res = COLnew(ci.hseq, TYPE_int, q, TRANSIENT))) {
    1232           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1233           0 :                         goto bailout;
    1234             :                 }
    1235           0 :                 r = getArgReference_bat(stk, pci, 0);
    1236           0 :                 ret = (int*) Tloc(res, 0);
    1237             :         } else {
    1238           0 :                 ret = getArgReference_int(stk, pci, 0);
    1239             :         }
    1240             : 
    1241           0 :         switch (k) {
    1242           0 :         case iyear:
    1243             :                 multiplier *= 12;
    1244           0 :                 break;
    1245             :         case imonth:
    1246             :                 break;
    1247           0 :         default: {
    1248           0 :                 msg = createException(ILLARG, "batcalc.month_interval", SQLSTATE(42000) "Illegal argument");
    1249           0 :                 goto bailout;
    1250             :         }
    1251             :         }
    1252             : 
    1253           0 :         bi = bat_iterator(b);
    1254           0 :         switch (tpe) {
    1255           0 :         case TYPE_bte:
    1256           0 :                 interval_loop(month_interval_convert, bte, int, "month_interval", GDK_int_max, DO_NOTHING, DO_NOTHING);
    1257             :                 break;
    1258           0 :         case TYPE_sht:
    1259           0 :                 interval_loop(month_interval_convert, sht, int, "month_interval", GDK_int_max, DO_NOTHING, DO_NOTHING);
    1260             :                 break;
    1261           0 :         case TYPE_int:
    1262           0 :                 interval_loop(month_interval_convert, int, int, "month_interval", GDK_int_max, DO_NOTHING, MUL_OVERFLOW);
    1263             :                 break;
    1264           0 :         case TYPE_lng:
    1265           0 :                 interval_loop(month_interval_convert, lng, int, "month_interval", GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
    1266             :                 break;
    1267             : #ifdef HAVE_HGE
    1268           0 :         case TYPE_hge:
    1269           0 :                 interval_loop(month_interval_convert, hge, int, "month_interval", GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
    1270             :                 break;
    1271             : #endif
    1272           0 :         default: {
    1273           0 :                 msg = createException(ILLARG, "batcalc.month_interval", SQLSTATE(42000) "Illegal argument in month interval");
    1274             :         }
    1275             :         }
    1276           0 : bailout1:
    1277           0 :         bat_iterator_end(&bi);
    1278             : 
    1279           0 : bailout:
    1280           0 :         if (res && !msg) {
    1281           0 :                 BATsetcount(res, q);
    1282           0 :                 res->tnil = nils;
    1283           0 :                 res->tnonil = !nils;
    1284           0 :                 res->tkey = b->tkey;
    1285           0 :                 res->tsorted = b->tsorted;
    1286           0 :                 res->trevsorted  = b->trevsorted;
    1287           0 :                 BBPkeepref(*r = res->batCacheid);
    1288           0 :         } else if (res)
    1289           0 :                 BBPreclaim(res);
    1290           0 :         if (b)
    1291           0 :                 BBPunfix(b->batCacheid);
    1292           0 :         if (s)
    1293           0 :                 BBPunfix(s->batCacheid);
    1294           0 :         return msg;
    1295             : }
    1296             : 
    1297             : #define second_interval_convert(OUT, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1298             :         do { \
    1299             :                 lng cast, r; \
    1300             :                 CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1301             :                 cast = (lng) next; \
    1302             :                 r = cast * multiplier; \
    1303             :                 if (scale) { \
    1304             :                         r += shift; \
    1305             :                         r /= divider; \
    1306             :                 } \
    1307             :                 MUL_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1308             :                 OUT = r; \
    1309             :         } while (0)
    1310             : 
    1311             : str
    1312           1 : second_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1313             : {
    1314             :         str msg = MAL_SUCCEED;
    1315             :         lng *restrict ret = NULL, multiplier = 1;
    1316           2 :         int tpe = getArgType(mb, pci, 1), k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2)),
    1317           2 :                 scale = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
    1318             :         bool is_a_bat = false, nils = false;
    1319             :         BAT *b = NULL, *s = NULL, *res = NULL;
    1320           1 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
    1321             :         BUN q = 0;
    1322           1 :         struct canditer ci = {0};
    1323             : #ifdef HAVE_HGE
    1324             :         hge shift = 0, divider = 1;
    1325             : #else
    1326             :         lng shift = 0, divider = 1;
    1327             : #endif
    1328             :         BATiter bi;
    1329             : 
    1330             :         (void) cntxt;
    1331           1 :         if (scale < 0 || (size_t) scale >= sizeof(scales) / sizeof(scales[0])) {
    1332           0 :                 msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(42000) "Digits out of bounds");
    1333           0 :                 goto bailout;
    1334             :         }
    1335           1 :         is_a_bat = isaBatType(tpe);
    1336           1 :         if (is_a_bat) {
    1337           0 :                 tpe = getBatType(tpe);
    1338           0 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1339           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1340           0 :                         goto bailout;
    1341             :                 }
    1342           0 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1343           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1344           0 :                         goto bailout;
    1345             :                 }
    1346           0 :                 q = canditer_init(&ci, b, s);
    1347           0 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, q, TRANSIENT))) {
    1348           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1349           0 :                         goto bailout;
    1350             :                 }
    1351           0 :                 r = getArgReference_bat(stk, pci, 0);
    1352           0 :                 ret = (lng*) Tloc(res, 0);
    1353             :         } else {
    1354           1 :                 ret = getArgReference_lng(stk, pci, 0);
    1355             :         }
    1356             : 
    1357           1 :         switch (k) {
    1358           0 :         case iday:
    1359             :                 multiplier *= 24;
    1360             :                 /* fall through */
    1361           0 :         case ihour:
    1362           0 :                 multiplier *= 60;
    1363             :                 /* fall through */
    1364           0 :         case imin:
    1365           0 :                 multiplier *= 60;
    1366             :                 /* fall through */
    1367           1 :         case isec:
    1368           1 :                 multiplier *= 1000;
    1369             :                 break;
    1370           0 :         default: {
    1371           0 :                 msg = createException(ILLARG, "batcalc.sec_interval", SQLSTATE(42000) "Illegal argument in second interval");
    1372           0 :                 goto bailout;
    1373             :         }
    1374             :         }
    1375           1 :         if (scale) {
    1376             : #ifndef TRUNCATE_NUMBERS
    1377           0 :                 shift += 5*scales[scale-1];
    1378             : #endif
    1379           0 :                 divider = scales[scale];
    1380             :         }
    1381             : 
    1382           1 :         bi = bat_iterator(b);
    1383           1 :         switch (tpe) {
    1384           0 :         case TYPE_bte:
    1385           0 :                 interval_loop(second_interval_convert, bte, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1386             :                 break;
    1387           0 :         case TYPE_sht:
    1388           0 :                 interval_loop(second_interval_convert, sht, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1389             :                 break;
    1390           0 :         case TYPE_int:
    1391           0 :                 interval_loop(second_interval_convert, int, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1392             :                 break;
    1393           1 :         case TYPE_lng:
    1394           1 :                 interval_loop(second_interval_convert, lng, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1395             :                 break;
    1396             : #ifdef HAVE_HGE
    1397           0 :         case TYPE_hge:
    1398           0 :                 interval_loop(second_interval_convert, hge, lng, "sec_interval", GDK_lng_max, CAST_VALIDATION, MUL_OVERFLOW);
    1399             :                 break;
    1400             : #endif
    1401           0 :         default: {
    1402           0 :                 msg = createException(ILLARG, "batcalc.sec_interval", SQLSTATE(42000) "Illegal argument in second interval");
    1403             :         }
    1404             :         }
    1405           1 : bailout1:
    1406           1 :         bat_iterator_end(&bi);
    1407             : 
    1408           1 : bailout:
    1409           1 :         if (res && !msg) {
    1410           0 :                 BATsetcount(res, q);
    1411           0 :                 res->tnil = nils;
    1412           0 :                 res->tnonil = !nils;
    1413           0 :                 res->tkey = b->tkey;
    1414           0 :                 res->tsorted = b->tsorted;
    1415           0 :                 res->trevsorted  = b->trevsorted;
    1416           0 :                 BBPkeepref(*r = res->batCacheid);
    1417           1 :         } else if (res)
    1418           0 :                 BBPreclaim(res);
    1419           1 :         if (b)
    1420           0 :                 BBPunfix(b->batCacheid);
    1421           1 :         if (s)
    1422           0 :                 BBPunfix(s->batCacheid);
    1423           1 :         return msg;
    1424             : }
    1425             : 
    1426             : str
    1427           0 : second_interval_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1428             : {
    1429             :         str msg = MAL_SUCCEED;
    1430             :         lng *restrict ret = NULL, multiplier = 1, divider = 1;
    1431           0 :         int tpe = getArgType(mb, pci, 1), k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2));
    1432             :         bool is_a_bat = false, nils = false;
    1433             :         BAT *b = NULL, *s = NULL, *res = NULL;
    1434           0 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
    1435             :         BUN q = 0;
    1436           0 :         struct canditer ci = {0};
    1437             : 
    1438             :         (void) cntxt;
    1439           0 :         is_a_bat = isaBatType(tpe);
    1440           0 :         if (is_a_bat) {
    1441             :                 tpe = getBatType(tpe);
    1442           0 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1443           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1444           0 :                         goto bailout;
    1445             :                 }
    1446           0 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1447           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1448           0 :                         goto bailout;
    1449             :                 }
    1450           0 :                 q = canditer_init(&ci, b, s);
    1451           0 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, q, TRANSIENT))) {
    1452           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1453           0 :                         goto bailout;
    1454             :                 }
    1455           0 :                 r = getArgReference_bat(stk, pci, 0);
    1456           0 :                 ret = (lng*) Tloc(res, 0);
    1457             :         } else {
    1458           0 :                 ret = getArgReference_lng(stk, pci, 0);
    1459             :         }
    1460             : 
    1461           0 :         switch (k) {
    1462             :         case isec:
    1463             :                 break;
    1464             :         case imin:
    1465             :                 divider *= 60000;
    1466             :                 multiplier *= 60000;
    1467             :                 break;
    1468             :         case ihour:
    1469             :                 divider *= 3600000;
    1470             :                 multiplier *= 3600000;
    1471             :                 break;
    1472             :         case iday:
    1473             :                 divider *= (24 * 3600000);
    1474             :                 multiplier *= (24 * 3600000);
    1475             :                 break;
    1476           0 :         default: {
    1477           0 :                 msg = createException(ILLARG, "batcalc.second_interval_daytime", SQLSTATE(42000) "Illegal argument in daytime interval");
    1478           0 :                 goto bailout;
    1479             :         }
    1480             :         }
    1481             : 
    1482           0 :         if (is_a_bat) {
    1483           0 :                 oid off = b->hseqbase;
    1484           0 :                 BATiter bi = bat_iterator(b);
    1485           0 :                 daytime *restrict vals = (daytime*) bi.base;
    1486           0 :                 if (ci.tpe == cand_dense) {
    1487           0 :                         for (BUN i = 0 ; i < q; i++) {
    1488           0 :                                 oid p = (canditer_next_dense(&ci) - off);
    1489           0 :                                 daytime next = vals[p];
    1490             : 
    1491           0 :                                 if (is_daytime_nil(next)) {
    1492           0 :                                         ret[i] = lng_nil;
    1493             :                                         nils = true;
    1494             :                                 } else {
    1495           0 :                                         ret[i] = (next / divider) * multiplier;
    1496             :                                 }
    1497             :                         }
    1498             :                 } else {
    1499           0 :                         for (BUN i = 0 ; i < q; i++) {
    1500           0 :                                 oid p = (canditer_next(&ci) - off);
    1501           0 :                                 daytime next = vals[p];
    1502             : 
    1503           0 :                                 if (is_daytime_nil(next)) {
    1504           0 :                                         ret[i] = lng_nil;
    1505             :                                         nils = true;
    1506             :                                 } else {
    1507           0 :                                         ret[i] = (next / divider) * multiplier;
    1508             :                                 }
    1509             :                         }
    1510             :                 }
    1511           0 :                 bat_iterator_end(&bi);
    1512             :         } else {
    1513           0 :                 daytime next = *(daytime*)getArgReference(stk, pci, 1);
    1514           0 :                 *ret = is_daytime_nil(next) ? lng_nil : (next / divider) * multiplier;
    1515             :         }
    1516             : 
    1517           0 : bailout:
    1518           0 :         if (res && !msg) {
    1519           0 :                 BATsetcount(res, q);
    1520           0 :                 res->tnil = nils;
    1521           0 :                 res->tnonil = !nils;
    1522           0 :                 res->tkey = b->tkey;
    1523           0 :                 res->tsorted = b->tsorted;
    1524           0 :                 res->trevsorted  = b->trevsorted;
    1525           0 :                 BBPkeepref(*r = res->batCacheid);
    1526           0 :         } else if (res)
    1527           0 :                 BBPreclaim(res);
    1528           0 :         if (b)
    1529           0 :                 BBPunfix(b->batCacheid);
    1530           0 :         if (s)
    1531           0 :                 BBPunfix(s->batCacheid);
    1532           0 :         return msg;
    1533             : }
    1534             : 
    1535             : str
    1536           0 : nil_2_date(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1537             : {
    1538             :         BAT *b = NULL, *res = NULL;
    1539             :         bat *r = NULL;
    1540             : 
    1541             :         (void) cntxt;
    1542           0 :         if (isaBatType(getArgType(mb, pci, 1))) {
    1543           0 :                 date d = date_nil;
    1544           0 :                 if (!(b = BBPquickdesc(*getArgReference_bat(stk, pci, 1))))
    1545           0 :                         throw(SQL, "batcalc.nil_2_date", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1546           0 :                 res = BATconstant(b->hseqbase, TYPE_date, &d, BATcount(b), TRANSIENT);
    1547           0 :                 if (!res)
    1548           0 :                         throw(SQL, "batcalc.nil_2_date", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1549           0 :                 r = getArgReference_bat(stk, pci, 0);
    1550           0 :                 BBPkeepref(*r = res->batCacheid);
    1551             :         } else {
    1552           0 :                 date *ret = (date*) getArgReference(stk, pci, 0);
    1553           0 :                 *ret = date_nil;
    1554             :         }
    1555             :         return MAL_SUCCEED;
    1556             : }
    1557             : 
    1558             : static inline str
    1559          21 : str_2_date_internal_imp(date *ret, str next)
    1560             : {
    1561             :         ssize_t pos = 0;
    1562          21 :         date dt = 0, *conv = &dt;
    1563             : 
    1564          21 :         pos = date_fromstr(next, &(size_t){sizeof(date)}, &conv, false);
    1565          21 :         if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_date_nil(*conv))
    1566          12 :                 return createException(SQL, "batcalc.str_2_date", SQLSTATE(22007) "Date '%s' has incorrect format", next);
    1567           9 :         *ret = *conv;
    1568           9 :         return MAL_SUCCEED;
    1569             : }
    1570             : 
    1571             : static str
    1572          21 : str_2_date_internal(ptr out, ptr in, const bat *sid, int tpe)
    1573             : {
    1574             :         str msg = MAL_SUCCEED;
    1575             :         BAT *b = NULL, *s = NULL, *res = NULL;
    1576             :         BUN q = 0;
    1577             :         date *restrict ret = NULL;
    1578             :         bool is_a_bat = false, nils = false;
    1579             :         bat *r = NULL;
    1580          21 :         struct canditer ci = {0};
    1581             : 
    1582          21 :         is_a_bat = isaBatType(tpe);
    1583          21 :         if (is_a_bat) {
    1584             :                 tpe = getBatType(tpe);
    1585          13 :                 if (!(b = BATdescriptor(*(bat*) in))) {
    1586           0 :                         msg = createException(SQL, "batcalc.batstr_2_date", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1587           0 :                         goto bailout;
    1588             :                 }
    1589          13 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1590           0 :                         msg = createException(SQL, "batcalc.batstr_2_date", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1591           0 :                         goto bailout;
    1592             :                 }
    1593          13 :                 q = canditer_init(&ci, b, s);
    1594          13 :                 if (!(res = COLnew(ci.hseq, TYPE_date, q, TRANSIENT))) {
    1595           0 :                         msg = createException(SQL, "batcalc.batstr_2_date", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1596           0 :                         goto bailout;
    1597             :                 }
    1598             :                 r = (bat*) out;
    1599          13 :                 ret = (date*) Tloc(res, 0);
    1600             :         } else {
    1601             :                 ret = (date*) out;
    1602             :         }
    1603             : 
    1604          21 :         if (is_a_bat) {
    1605          13 :                 oid off = b->hseqbase;
    1606          13 :                 BATiter it = bat_iterator(b);
    1607          13 :                 if (ci.tpe == cand_dense) {
    1608          39 :                         for (BUN i = 0 ; i < q && !msg; i++) {
    1609          26 :                                 oid p = (canditer_next_dense(&ci) - off);
    1610          26 :                                 str next = BUNtvar(it, p);
    1611             : 
    1612          26 :                                 if (strNil(next)) {
    1613          13 :                                         ret[i] = date_nil;
    1614             :                                         nils = true;
    1615             :                                 } else {
    1616          13 :                                         msg = str_2_date_internal_imp(&(ret[i]), next);
    1617             :                                 }
    1618             :                         }
    1619             :                 } else {
    1620           0 :                         for (BUN i = 0 ; i < q && !msg; i++) {
    1621           0 :                                 oid p = (canditer_next(&ci) - off);
    1622           0 :                                 str next = BUNtvar(it, p);
    1623             : 
    1624           0 :                                 if (strNil(next)) {
    1625           0 :                                         ret[i] = date_nil;
    1626             :                                         nils = true;
    1627             :                                 } else {
    1628           0 :                                         msg = str_2_date_internal_imp(&(ret[i]), next);
    1629             :                                 }
    1630             :                         }
    1631             :                 }
    1632          13 :                 bat_iterator_end(&it);
    1633             :         } else {
    1634           8 :                 str next = *(str*)in;
    1635           8 :                 if (strNil(next))
    1636           0 :                         *ret = date_nil;
    1637             :                 else
    1638           8 :                         msg = str_2_date_internal_imp(ret, next);
    1639             :         }
    1640             : 
    1641          21 : bailout:
    1642          21 :         if (b)
    1643          13 :                 BBPunfix(b->batCacheid);
    1644          21 :         if (s)
    1645           0 :                 BBPunfix(s->batCacheid);
    1646          21 :         if (res && !msg) {
    1647           7 :                 BATsetcount(res, q);
    1648           7 :                 res->tnil = nils;
    1649           7 :                 res->tnonil = !nils;
    1650           7 :                 res->tkey = BATcount(res) <= 1;
    1651           7 :                 res->tsorted = BATcount(res) <= 1;
    1652           7 :                 res->trevsorted = BATcount(res) <= 1;
    1653           7 :                 BBPkeepref(*r = res->batCacheid);
    1654          14 :         } else if (res)
    1655           6 :                 BBPreclaim(res);
    1656          21 :         return msg;
    1657             : }
    1658             : 
    1659             : str
    1660          13 : batstr_2_date(bat *res, const bat *bid, const bat *s)
    1661             : {
    1662          13 :         return str_2_date_internal((ptr) res, (ptr) bid, s, newBatType(TYPE_str));
    1663             : }
    1664             : 
    1665             : str
    1666           8 : str_2_date(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1667             : {
    1668           8 :         int tpe = getArgType(mb, pci, 1);
    1669             :         (void) cntxt;
    1670           8 :         return str_2_date_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe);
    1671             : }
    1672             : 
    1673             : str
    1674           0 : SQLcurrent_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1675             : {
    1676           0 :         mvc *m = NULL;
    1677             :         str msg;
    1678           0 :         daytime *res = getArgReference_TYPE(stk, pci, 0, daytime);
    1679             : 
    1680           0 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
    1681             :                 return msg;
    1682             : 
    1683           0 :         *res = timestamp_daytime(timestamp_add_usec(timestamp_current(),
    1684           0 :                                                          m->timezone * LL_CONSTANT(1000)));
    1685           0 :         return msg;
    1686             : }
    1687             : 
    1688             : str
    1689           0 : SQLcurrent_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1690             : {
    1691           0 :         mvc *m = NULL;
    1692             :         str msg;
    1693           0 :         timestamp *res = getArgReference_TYPE(stk, pci, 0, timestamp);
    1694             : 
    1695           0 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
    1696             :                 return msg;
    1697             : 
    1698           0 :         *res = timestamp_add_usec(timestamp_current(), m->timezone * LL_CONSTANT(1000));
    1699           0 :         return msg;
    1700             : }

Generated by: LCOV version 1.14