LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_time.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 547 985 55.5 %
Date: 2024-04-26 00:35:57 Functions: 23 30 76.7 %

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

Generated by: LCOV version 1.14