LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_time.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 613 986 62.2 %
Date: 2024-11-14 20:04:02 Functions: 25 30 83.3 %

          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        2413 : 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        2413 :         return ((input + shift) / divider) * multiplier;
      28             : }
      29             : 
      30             : str
      31        2563 : daytime_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      32             : {
      33        2563 :         str msg = MAL_SUCCEED;
      34        2563 :         BAT *b = NULL, *s = NULL, *res = NULL;
      35        2563 :         daytime *restrict ret = NULL;
      36        5098 :         int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
      37        2563 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
      38        2563 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
      39        2563 :         struct canditer ci = {0};
      40             : #ifdef HAVE_HGE
      41        2563 :         hge shift = 0, divider = 1, multiplier = 1;
      42             : #else
      43             :         lng shift = 0, divider = 1, multiplier = 1;
      44             : #endif
      45             : 
      46        2563 :         (void) cntxt;
      47        2563 :         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        2563 :         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        2563 :         is_a_bat = isaBatType(tpe);
      56        2563 :         if (is_a_bat) {
      57          28 :                 tpe = getBatType(tpe);
      58          28 :                 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          28 :                 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          28 :                 canditer_init(&ci, b, s);
      67          28 :                 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          28 :                 r = getArgReference_bat(stk, pci, 0);
      72          28 :                 ret = (daytime*) Tloc(res, 0);
      73             :         } else {
      74        2535 :                 ret = (daytime*) getArgReference(stk, pci, 0);
      75             :         }
      76             : 
      77             :         /* correct fraction */
      78        2563 :         if (d < 6) {
      79        2500 :                 divider *= scales[6 - d];
      80             : #ifndef TRUNCATE_NUMBERS
      81        2500 :                 shift += (scales[6 - d] >> 1);
      82             : #endif
      83        2500 :                 multiplier *= scales[6 - d];
      84             :         }
      85             : 
      86        2563 :         if (is_a_bat) {
      87          28 :                 oid off = b->hseqbase;
      88          28 :                 BATiter bi = bat_iterator(b);
      89          28 :                 daytime *restrict vals = (daytime*) bi.base;
      90          28 :                 if (ci.tpe == cand_dense) {
      91          82 :                         for (BUN i = 0; i < ci.ncand; i++) {
      92          54 :                                 oid p = (canditer_next_dense(&ci) - off);
      93          54 :                                 daytime next = vals[p];
      94             : 
      95          54 :                                 if (is_daytime_nil(next)) {
      96          19 :                                         ret[i] = daytime_nil;
      97          19 :                                         nils = true;
      98             :                                 } else {
      99          35 :                                         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          28 :                 btkey = bi.key;
     116          28 :                 btsorted = bi.sorted;
     117          28 :                 btrevsorted = bi.revsorted;
     118          28 :                 bat_iterator_end(&bi);
     119             :         } else {
     120        2535 :                 daytime next = *(daytime*)getArgReference(stk, pci, 1);
     121        2535 :                 *ret = is_daytime_nil(next) ? daytime_nil : daytime_2time_daytime_imp(next, shift, divider, multiplier);
     122             :         }
     123             : 
     124        2563 : bailout:
     125        2563 :         BBPreclaim(b);
     126        2563 :         BBPreclaim(s);
     127        2563 :         if (res && !msg) {
     128          28 :                 BATsetcount(res, ci.ncand);
     129          28 :                 res->tnil = nils;
     130          28 :                 res->tnonil = !nils;
     131          28 :                 res->tkey = btkey;
     132          28 :                 res->tsorted = btsorted;
     133          28 :                 res->trevsorted = btrevsorted;
     134          28 :                 *r = res->batCacheid;
     135          28 :                 BBPkeepref(res);
     136        2535 :         } else if (res)
     137           0 :                 BBPreclaim(res);
     138        2563 :         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          48 : 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          48 :         ssize_t pos = 0;
     298          48 :         daytime dt = 0;
     299             : 
     300          48 :         pos = fromstr_func(next, &dt, tz_off, false);
     301          48 :         if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_daytime_nil(dt))
     302          44 :                 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          48 : str_2time_daytimetz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, lng tz)
     309             : {
     310          48 :         str msg = MAL_SUCCEED;
     311          48 :         BAT *b = NULL, *s = NULL, *res = NULL;
     312          48 :         daytime *restrict ret = NULL;
     313          48 :         int d = (digits) ? digits - 1 : 0;
     314          48 :         bool is_a_bat = false, nils = false;
     315          48 :         bat *r = NULL;
     316          48 :         ssize_t (*fromstr_func)(const char *, daytime *, long, bool) = sql_daytime_fromstr;
     317          48 :         struct canditer ci = {0};
     318             : #ifdef HAVE_HGE
     319          48 :         hge shift = 0, divider = 1, multiplier = 1;
     320             : #else
     321             :         lng shift = 0, divider = 1, multiplier = 1;
     322             : #endif
     323             : 
     324          48 :         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          48 :         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          48 :         is_a_bat = isaBatType(tpe);
     333          48 :         if (is_a_bat) {
     334          18 :                 tpe = getBatType(tpe);
     335          18 :                 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          18 :                 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          18 :                 canditer_init(&ci, b, s);
     344          18 :                 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          18 :                 r = (bat*) out;
     349          18 :                 ret = (daytime*) Tloc(res, 0);
     350             :         } else {
     351             :                 ret = (daytime*) out;
     352             :         }
     353             : 
     354             :         /* correct fraction */
     355          48 :         if (d < 6) {
     356          41 :                 divider *= scales[6 - d];
     357             : #ifndef TRUNCATE_NUMBERS
     358          41 :                 shift += (scales[6 - d] >> 1);
     359             : #endif
     360          41 :                 multiplier *= scales[6 - d];
     361             :         }
     362             : 
     363          48 :         if (is_a_bat) {
     364          18 :                 oid off = b->hseqbase;
     365          18 :                 BATiter it = bat_iterator(b);
     366          18 :                 if (ci.tpe == cand_dense) {
     367          36 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
     368          18 :                                 oid p = (canditer_next_dense(&ci) - off);
     369          18 :                                 const char *next = BUNtvar(it, p);
     370             : 
     371          18 :                                 if (strNil(next)) {
     372           0 :                                         ret[i] = daytime_nil;
     373           0 :                                         nils = true;
     374             :                                 } else {
     375          18 :                                         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          18 :                 bat_iterator_end(&it);
     392             :         } else {
     393          30 :                 const char *next = *(str*)in;
     394          30 :                 if (strNil(next))
     395           0 :                         *ret = daytime_nil;
     396             :                 else
     397          30 :                         msg = str_2time_daytimetz_internal_imp(ret, next, fromstr_func, shift, divider, multiplier, (long)(tz/1000));
     398             :         }
     399             : 
     400          48 : bailout:
     401          48 :         BBPreclaim(b);
     402          48 :         BBPreclaim(s);
     403          48 :         if (res && !msg) {
     404           2 :                 BATsetcount(res, ci.ncand);
     405           2 :                 res->tnil = nils;
     406           2 :                 res->tnonil = !nils;
     407           2 :                 res->tkey = BATcount(res) <= 1;
     408           2 :                 res->tsorted = BATcount(res) <= 1;
     409           2 :                 res->trevsorted = BATcount(res) <= 1;
     410           2 :                 *r = res->batCacheid;
     411           2 :                 BBPkeepref(res);
     412          46 :         } else if (res)
     413          16 :                 BBPreclaim(res);
     414          48 :         return msg;
     415             : }
     416             : 
     417             : str
     418          34 : str_2time_daytimetz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     419             : {
     420          34 :         int tpe = getArgType(mb, pci, 1),
     421          56 :                 digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2);
     422          56 :         lng tz = *getArgReference_lng(stk, pci, pci->argc == 5 ? 4 : 3);
     423          34 :         bat *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
     424          34 :         (void) cntxt;
     425          34 :         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          48 : date_2_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     565             : {
     566          48 :         str msg = MAL_SUCCEED;
     567          48 :         BAT *b = NULL, *s = NULL, *res = NULL;
     568          48 :         timestamp *restrict ret = NULL;
     569          48 :         int tpe = getArgType(mb, pci, 1);
     570          48 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
     571          48 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2) : NULL;
     572          48 :         struct canditer ci = {0};
     573             : 
     574          48 :         (void) cntxt;
     575          48 :         is_a_bat = isaBatType(tpe);
     576          48 :         if (is_a_bat) {
     577          35 :                 tpe = getBatType(tpe);
     578          35 :                 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          35 :                 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          35 :                 canditer_init(&ci, b, s);
     587          35 :                 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          35 :                 r = getArgReference_bat(stk, pci, 0);
     592          35 :                 ret = (timestamp*) Tloc(res, 0);
     593             :         } else {
     594          13 :                 ret = (timestamp*) getArgReference(stk, pci, 0);
     595             :         }
     596             : 
     597          48 :         if (is_a_bat) {
     598          35 :                 oid off = b->hseqbase;
     599          35 :                 BATiter bi = bat_iterator(b);
     600          35 :                 date *restrict vals = (date*) bi.base;
     601          35 :                 if (ci.tpe == cand_dense) {
     602         357 :                         for (BUN i = 0 ; i < ci.ncand; i++) {
     603         322 :                                 oid p = (canditer_next_dense(&ci) - off);
     604         322 :                                 ret[i] = timestamp_fromdate(vals[p]);
     605         322 :                                 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          35 :                 btkey = bi.key;
     615          35 :                 btsorted = bi.sorted;
     616          35 :                 btrevsorted = bi.revsorted;
     617          35 :                 bat_iterator_end(&bi);
     618             :         } else {
     619          13 :                 *ret = timestamp_fromdate(*(date*)getArgReference(stk, pci, 1));
     620             :         }
     621             : 
     622          48 : bailout:
     623          48 :         BBPreclaim(b);
     624          48 :         BBPreclaim(s);
     625          48 :         if (res && !msg) {
     626          35 :                 BATsetcount(res, ci.ncand);
     627          35 :                 res->tnil = nils;
     628          35 :                 res->tnonil = !nils;
     629          35 :                 res->tkey = btkey;
     630          35 :                 res->tsorted = btsorted;
     631          35 :                 res->trevsorted = btrevsorted;
     632          35 :                 *r = res->batCacheid;
     633          35 :                 BBPkeepref(res);
     634          13 :         } else if (res)
     635           0 :                 BBPreclaim(res);
     636          48 :         return msg;
     637             : }
     638             : 
     639             : static inline timestamp
     640        3626 : 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        3626 :         date dt = timestamp_date(input);
     649        3626 :         daytime tm = timestamp_daytime(input);
     650        3626 :         tm = ((tm + shift) / divider) * multiplier;
     651        3626 :         return timestamp_create(dt, tm);
     652             : }
     653             : 
     654             : str
     655       45182 : timestamp_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     656             : {
     657       45182 :         str msg = MAL_SUCCEED;
     658       45182 :         BAT *b = NULL, *s = NULL, *res = NULL;
     659       45182 :         timestamp *restrict ret = NULL;
     660       90206 :         int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
     661       45182 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
     662       45182 :         bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
     663       45182 :         struct canditer ci = {0};
     664             : #ifdef HAVE_HGE
     665       45182 :         hge shift = 0, divider = 1, multiplier = 1;
     666             : #else
     667             :         lng shift = 0, divider = 1, multiplier = 1;
     668             : #endif
     669             : 
     670       45182 :         (void) cntxt;
     671       45182 :         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       45182 :         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       45182 :         is_a_bat = isaBatType(tpe);
     680       45182 :         if (is_a_bat) {
     681         158 :                 tpe = getBatType(tpe);
     682         158 :                 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         158 :                 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         158 :                 canditer_init(&ci, b, s);
     691         158 :                 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         158 :                 r = getArgReference_bat(stk, pci, 0);
     696         158 :                 ret = (timestamp*) Tloc(res, 0);
     697             :         } else {
     698       45024 :                 ret = (timestamp*) getArgReference(stk, pci, 0);
     699             :         }
     700             : 
     701             :         /* correct fraction */
     702       45182 :         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       45182 :         if (is_a_bat) {
     711         158 :                 oid off = b->hseqbase;
     712         158 :                 BATiter bi = bat_iterator(b);
     713         158 :                 timestamp *restrict vals = (timestamp*) bi.base;
     714         158 :                 if (ci.tpe == cand_dense) {
     715         609 :                         for (BUN i = 0 ; i < ci.ncand; i++) {
     716         451 :                                 oid p = (canditer_next_dense(&ci) - off);
     717         451 :                                 timestamp next = vals[p];
     718             : 
     719         451 :                                 if (is_timestamp_nil(next)) {
     720          27 :                                         ret[i] = timestamp_nil;
     721          27 :                                         nils = true;
     722             :                                 } else {
     723         424 :                                         ret[i] = timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
     724             :                                 }
     725             :                         }
     726             :                 } else {
     727           0 :                         for (BUN i = 0 ; i < ci.ncand; i++) {
     728           0 :                                 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         158 :                 btkey = bi.key;
     740         158 :                 btsorted = bi.sorted;
     741         158 :                 btrevsorted = bi.revsorted;
     742         158 :                 bat_iterator_end(&bi);
     743             :         } else {
     744       45024 :                 timestamp next = *(timestamp*)getArgReference(stk, pci, 1);
     745       45024 :                 *ret = is_timestamp_nil(next) ? timestamp_nil : timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
     746             :         }
     747             : 
     748       45182 : bailout:
     749       45182 :         BBPreclaim(b);
     750       45182 :         BBPreclaim(s);
     751       45182 :         if (res && !msg) {
     752         158 :                 BATsetcount(res, ci.ncand);
     753         158 :                 res->tnil = nils;
     754         158 :                 res->tnonil = !nils;
     755         158 :                 res->tkey = btkey;
     756         158 :                 res->tsorted = btsorted;
     757         158 :                 res->trevsorted = btrevsorted;
     758         158 :                 *r = res->batCacheid;
     759         158 :                 BBPkeepref(res);
     760       45024 :         } else if (res)
     761           0 :                 BBPreclaim(res);
     762       45182 :         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         407 : 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         407 :         ssize_t pos = 0;
     799         407 :         timestamp tp = 0;
     800             : 
     801         407 :         pos = fromstr_func(next, &tp, (long)tz_off, false);
     802         407 :         if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_timestamp_nil(tp))
     803         282 :                 return createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(22007) "Timestamp '%s' has incorrect format", next);
     804         125 :         *ret = timestamp_2time_timestamp_imp(tp, shift, divider, multiplier);
     805         125 :         return MAL_SUCCEED;
     806             : }
     807             : 
     808             : static str
     809         344 : str_2time_timestamptz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, lng tz)
     810             : {
     811         344 :         str msg = MAL_SUCCEED;
     812         344 :         BAT *b = NULL, *s = NULL, *res = NULL;
     813         344 :         timestamp *restrict ret = NULL;
     814         344 :         int d = (digits) ? digits - 1 : 0;
     815         344 :         bool is_a_bat = false, nils = false;
     816         344 :         bat *r = NULL;
     817         344 :         ssize_t (*fromstr_func)(const char *, timestamp *, long, bool) = sql_timestamp_fromstr;
     818         344 :         struct canditer ci = {0};
     819             : #ifdef HAVE_HGE
     820         344 :         hge shift = 0, divider = 1, multiplier = 1;
     821             : #else
     822             :         lng shift = 0, divider = 1, multiplier = 1;
     823             : #endif
     824             : 
     825         344 :         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         344 :         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         344 :         is_a_bat = isaBatType(tpe);
     834         344 :         if (is_a_bat) {
     835          67 :                 tpe = getBatType(tpe);
     836          67 :                 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          67 :                 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          67 :                 canditer_init(&ci, b, s);
     845          67 :                 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          67 :                 r = (bat*) out;
     850          67 :                 ret = (timestamp*) Tloc(res, 0);
     851             :         } else {
     852             :                 ret = (timestamp*) out;
     853             :         }
     854             : 
     855             :         /* correct fraction */
     856         344 :         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         344 :         if (is_a_bat) {
     865          67 :                 oid off = b->hseqbase;
     866          67 :                 BATiter bi = bat_iterator(b);
     867          67 :                 if (ci.tpe == cand_dense) {
     868         197 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
     869         130 :                                 oid p = (canditer_next_dense(&ci) - off);
     870         130 :                                 const char *next = BUNtvar(bi, p);
     871             : 
     872         130 :                                 if (strNil(next)) {
     873           0 :                                         ret[i] = timestamp_nil;
     874           0 :                                         nils = true;
     875             :                                 } else {
     876         130 :                                         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          67 :                 bat_iterator_end(&bi);
     893             :         } else {
     894         277 :                 const char *next = *(str*)in;
     895         277 :                 if (strNil(next))
     896           0 :                         *ret = timestamp_nil;
     897             :                 else
     898         277 :                         msg = str_2time_timestamptz_internal_imp(ret, next, fromstr_func, shift, divider, multiplier, (long)(tz/1000));
     899             :         }
     900             : 
     901         344 : bailout:
     902         344 :         BBPreclaim(b);
     903         344 :         BBPreclaim(s);
     904         344 :         if (res && !msg) {
     905          47 :                 BATsetcount(res, ci.ncand);
     906          47 :                 res->tnil = nils;
     907          47 :                 res->tnonil = !nils;
     908          47 :                 res->tkey = BATcount(res) <= 1;
     909          47 :                 res->tsorted = BATcount(res) <= 1;
     910          47 :                 res->trevsorted = BATcount(res) <= 1;
     911          47 :                 *r = res->batCacheid;
     912          47 :                 BBPkeepref(res);
     913         297 :         } else if (res)
     914          20 :                 BBPreclaim(res);
     915         344 :         return msg;
     916             : }
     917             : 
     918             : str
     919         145 : str_2time_timestamptz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     920             : {
     921         145 :         int tpe = getArgType(mb, pci, 1),
     922         290 :                 digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2);
     923         290 :         lng tz = *getArgReference_lng(stk, pci, pci->argc == 5 ? 4 : 3);
     924         145 :         (void) cntxt;
     925         145 :         return str_2time_timestamptz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, tz);
     926             : }
     927             : 
     928             : str
     929          53 : batstr_2time_timestamptz(bat *res, const bat *bid, const bat *sid, const int *digits, const lng *tz)
     930             : {
     931          53 :         return str_2time_timestamptz_internal((ptr) res, (ptr) bid, sid, newBatType(TYPE_str), *digits, *tz);
     932             : }
     933             : 
     934             : str
     935         132 : str_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     936             : {
     937         132 :         int tpe = getArgType(mb, pci, 1), digits = *getArgReference_int(stk, pci, 2);
     938         132 :         (void) cntxt;
     939         132 :         return str_2time_timestamptz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, 0);
     940             : }
     941             : 
     942             : str
     943          14 : batstr_2time_timestamp(bat *res, const bat *bid, const bat *sid, const int *digits)
     944             : {
     945          14 :         return str_2time_timestamptz_internal((ptr) res, (ptr) bid, sid, newBatType(TYPE_str), *digits, 0);
     946             : }
     947             : 
     948             : static inline str
     949          17 : month_interval_str_imp(int *ret, const char *next, int d, int sk)
     950             : {
     951          17 :         lng upcast;
     952          17 :         if (interval_from_str(next, d, sk, &upcast) < 0)
     953           4 :                 return createException(SQL, "batcalc.month_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
     954          13 :         if (upcast < (lng) GDK_int_min || upcast > (lng) GDK_int_max)
     955           1 :                 throw(SQL, "batcalc.month_interval_str", SQLSTATE(22003) "value out of range");
     956          12 :         *ret = (int) upcast;
     957          12 :         return MAL_SUCCEED;
     958             : }
     959             : 
     960             : str
     961          17 : month_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     962             : {
     963          17 :         str msg = MAL_SUCCEED;
     964          17 :         int *restrict ret = NULL;
     965          41 :         int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
     966          17 :                 tpe = getArgType(mb, pci, 1);
     967          17 :         bool is_a_bat = false, nils = false;
     968          17 :         BAT *b = NULL, *s = NULL, *res = NULL;
     969          17 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
     970          17 :         struct canditer ci = {0};
     971             : 
     972          17 :         (void) cntxt;
     973          17 :         is_a_bat = isaBatType(tpe);
     974          17 :         if (is_a_bat) {
     975           5 :                 tpe = getBatType(tpe);
     976           5 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
     977           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     978           0 :                         goto bailout;
     979             :                 }
     980           5 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     981           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     982           0 :                         goto bailout;
     983             :                 }
     984           5 :                 canditer_init(&ci, b, s);
     985           5 :                 if (!(res = COLnew(ci.hseq, TYPE_int, ci.ncand, TRANSIENT))) {
     986           0 :                         msg = createException(SQL, "batcalc.month_interval_str", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     987           0 :                         goto bailout;
     988             :                 }
     989           5 :                 r = getArgReference_bat(stk, pci, 0);
     990           5 :                 ret = (int*) Tloc(res, 0);
     991             :         } else {
     992          12 :                 ret = getArgReference_int(stk, pci, 0);
     993             :         }
     994             : 
     995          17 :         if (is_a_bat) {
     996           5 :                 oid off = b->hseqbase;
     997           5 :                 BATiter bi = bat_iterator(b);
     998           5 :                 if (ci.tpe == cand_dense) {
     999          12 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
    1000           7 :                                 oid p = (canditer_next_dense(&ci) - off);
    1001           7 :                                 const char *next = BUNtvar(bi, p);
    1002             : 
    1003           7 :                                 if (strNil(next)) {
    1004           2 :                                         ret[i] = int_nil;
    1005           2 :                                         nils = true;
    1006             :                                 } else {
    1007           5 :                                         msg = month_interval_str_imp(&(ret[i]), next, d, sk);
    1008             :                                 }
    1009             :                         }
    1010             :                 } else {
    1011           0 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
    1012           0 :                                 oid p = (canditer_next(&ci) - off);
    1013           0 :                                 const char *next = BUNtvar(bi, p);
    1014             : 
    1015           0 :                                 if (strNil(next)) {
    1016           0 :                                         ret[i] = int_nil;
    1017           0 :                                         nils = true;
    1018             :                                 } else {
    1019           0 :                                         msg = month_interval_str_imp(&(ret[i]), next, d, sk);
    1020             :                                 }
    1021             :                         }
    1022             :                 }
    1023           5 :                 bat_iterator_end(&bi);
    1024             :         } else {
    1025          12 :                 const char *next = *getArgReference_str(stk, pci, 1);
    1026             : 
    1027          12 :                 if (strNil(next))
    1028           0 :                         *ret = int_nil;
    1029             :                 else
    1030          12 :                         msg = month_interval_str_imp(ret, next, d, sk);
    1031             :         }
    1032             : 
    1033          17 : bailout:
    1034          17 :         BBPreclaim(b);
    1035          17 :         BBPreclaim(s);
    1036          17 :         if (res && !msg) {
    1037           2 :                 BATsetcount(res, ci.ncand);
    1038           2 :                 res->tnil = nils;
    1039           2 :                 res->tnonil = !nils;
    1040           2 :                 res->tkey = BATcount(res) <= 1;
    1041           2 :                 res->tsorted = BATcount(res) <= 1;
    1042           2 :                 res->trevsorted = BATcount(res) <= 1;
    1043           2 :                 *r = res->batCacheid;
    1044           2 :                 BBPkeepref(res);
    1045          15 :         } else if (res)
    1046           3 :                 BBPreclaim(res);
    1047          17 :         return msg;
    1048             : }
    1049             : 
    1050             : static inline str
    1051         143 : second_interval_str_imp(lng *ret, const char *next, int d, int sk)
    1052             : {
    1053         143 :         if (interval_from_str(next, d, sk, ret) < 0)
    1054          89 :                 return createException(SQL, "batcalc.second_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
    1055             :         return MAL_SUCCEED;
    1056             : }
    1057             : 
    1058             : str
    1059         142 : second_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1060             : {
    1061         142 :         str msg = MAL_SUCCEED;
    1062         142 :         lng *restrict ret = NULL;
    1063         382 :         int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
    1064         142 :                 tpe = getArgType(mb, pci, 1);
    1065         142 :         bool is_a_bat = false, nils = false;
    1066         142 :         BAT *b = NULL, *s = NULL, *res = NULL;
    1067         142 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
    1068         142 :         struct canditer ci = {0};
    1069             : 
    1070         142 :         (void) cntxt;
    1071         142 :         is_a_bat = isaBatType(tpe);
    1072         142 :         if (is_a_bat) {
    1073          22 :                 tpe = getBatType(tpe);
    1074          22 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1075           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1076           0 :                         goto bailout;
    1077             :                 }
    1078          22 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1079           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1080           0 :                         goto bailout;
    1081             :                 }
    1082          22 :                 canditer_init(&ci, b, s);
    1083          22 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, ci.ncand, TRANSIENT))) {
    1084           0 :                         msg = createException(SQL, "batcalc.second_interval_str", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1085           0 :                         goto bailout;
    1086             :                 }
    1087          22 :                 r = getArgReference_bat(stk, pci, 0);
    1088          22 :                 ret = (lng*) Tloc(res, 0);
    1089             :         } else {
    1090         120 :                 ret = getArgReference_lng(stk, pci, 0);
    1091             :         }
    1092             : 
    1093         142 :         if (is_a_bat) {
    1094          22 :                 oid off = b->hseqbase;
    1095          22 :                 BATiter bi = bat_iterator(b);
    1096          22 :                 if (ci.tpe == cand_dense) {
    1097          47 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
    1098          25 :                                 oid p = (canditer_next_dense(&ci) - off);
    1099          25 :                                 const char *next = BUNtvar(bi, p);
    1100             : 
    1101          25 :                                 if (strNil(next)) {
    1102           2 :                                         ret[i] = lng_nil;
    1103           2 :                                         nils = true;
    1104             :                                 } else {
    1105          23 :                                         msg = second_interval_str_imp(&(ret[i]), next, d, sk);
    1106             :                                 }
    1107             :                         }
    1108             :                 } else {
    1109           0 :                         for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
    1110           0 :                                 oid p = (canditer_next(&ci) - off);
    1111           0 :                                 const char *next = BUNtvar(bi, p);
    1112             : 
    1113           0 :                                 if (strNil(next)) {
    1114           0 :                                         ret[i] = lng_nil;
    1115           0 :                                         nils = true;
    1116             :                                 } else {
    1117           0 :                                         msg = second_interval_str_imp(&(ret[i]), next, d, sk);
    1118             :                                 }
    1119             :                         }
    1120             :                 }
    1121          22 :                 bat_iterator_end(&bi);
    1122             :         } else {
    1123         120 :                 const char *next = *getArgReference_str(stk, pci, 1);
    1124             : 
    1125         120 :                 if (strNil(next))
    1126           0 :                         *ret = lng_nil;
    1127             :                 else
    1128         120 :                         msg = second_interval_str_imp(ret, next, d, sk);
    1129             :         }
    1130             : 
    1131         142 : bailout:
    1132         142 :         BBPreclaim(b);
    1133         142 :         BBPreclaim(s);
    1134         142 :         if (res && !msg) {
    1135           3 :                 BATsetcount(res, ci.ncand);
    1136           3 :                 res->tnil = nils;
    1137           3 :                 res->tnonil = !nils;
    1138           3 :                 res->tkey = BATcount(res) <= 1;
    1139           3 :                 res->tsorted = BATcount(res) <= 1;
    1140           3 :                 res->trevsorted = BATcount(res) <= 1;
    1141           3 :                 *r = res->batCacheid;
    1142           3 :                 BBPkeepref(res);
    1143         139 :         } else if (res)
    1144          19 :                 BBPreclaim(res);
    1145         142 :         return msg;
    1146             : }
    1147             : 
    1148             : #define interval_loop(FUNC, TPE_IN, TPE_OUT, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1149             :         do { \
    1150             :                 if (is_a_bat) { \
    1151             :                         oid off = b->hseqbase; \
    1152             :                         TPE_IN *restrict vals = bi.base; \
    1153             :                         if (ci.tpe == cand_dense) { \
    1154             :                                 for (BUN i = 0; i < ci.ncand; i++) { \
    1155             :                                         oid p = (canditer_next_dense(&ci) - off); \
    1156             :                                         TPE_IN next = vals[p]; \
    1157             :                                         if (is_##TPE_IN##_nil(next)) { \
    1158             :                                                 ret[i] = TPE_OUT##_nil; \
    1159             :                                                 nils = true; \
    1160             :                                         } else { \
    1161             :                                                 FUNC(ret[i], TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1162             :                                         } \
    1163             :                                 } \
    1164             :                         } else { \
    1165             :                                 for (BUN i = 0; i < ci.ncand; i++) { \
    1166             :                                         oid p = (canditer_next(&ci) - off); \
    1167             :                                         TPE_IN next = vals[p]; \
    1168             :                                         if (is_##TPE_IN##_nil(next)) { \
    1169             :                                                 ret[i] = TPE_OUT##_nil; \
    1170             :                                                 nils = true; \
    1171             :                                         } else { \
    1172             :                                                 FUNC(ret[i], TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1173             :                                         } \
    1174             :                                 } \
    1175             :                         } \
    1176             :                 } else { \
    1177             :                         TPE_IN next = *(TPE_IN*)getArgReference(stk, pci, 1); \
    1178             :                         if (is_##TPE_IN##_nil(next)) \
    1179             :                                 *ret = TPE_OUT##_nil;   \
    1180             :                         else    \
    1181             :                                 FUNC(*ret, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION); \
    1182             :                 } \
    1183             :         } while(0)
    1184             : 
    1185             : #define month_interval_convert(OUT, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1186             :         do { \
    1187             :                 int cast, r; \
    1188             :                 CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1189             :                 cast = (int) next; \
    1190             :                 r = cast * multiplier; \
    1191             :                 MUL_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1192             :                 OUT = r; \
    1193             :         } while (0)
    1194             : 
    1195             : #define DO_NOTHING(TPE_IN, FUNC_NAME, MAX_VALUE) ;
    1196             : 
    1197             : #define CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE) \
    1198             :         do { \
    1199             :                 if (next > (TPE_IN) MAX_VALUE) { \
    1200             :                         size_t len = 0; \
    1201             :                         char *str_val = NULL; \
    1202             :                         if (BATatoms[tpe].atomToStr(&str_val, &len, &next, false) < 0) { \
    1203             :                                 msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1204             :                                 goto bailout1; \
    1205             :                         } \
    1206             :                         msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(22003) "Value %s too large to fit at a " FUNC_NAME, str_val); \
    1207             :                         GDKfree(str_val); \
    1208             :                         goto bailout1; \
    1209             :                 } \
    1210             :         } while (0)
    1211             : 
    1212             : #define MUL_OVERFLOW(TPE_IN, FUNC_NAME, MAX_VALUE) /* TPE_IN and MAX_VALUE are ignored on this macro */ \
    1213             :         do { \
    1214             :                 if (r < cast) { \
    1215             :                         size_t len = 0; \
    1216             :                         char *str_val = NULL; \
    1217             :                         if (BATatoms[tpe].atomToStr(&str_val, &len, &cast, false) < 0) { \
    1218             :                                 msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1219             :                                 goto bailout1; \
    1220             :                         } \
    1221             :                         msg = createException(SQL, "batcalc." FUNC_NAME, SQLSTATE(22003) "Overflow in conversion of %s to " FUNC_NAME, str_val); \
    1222             :                         GDKfree(str_val); \
    1223             :                         goto bailout1; \
    1224             :                 } \
    1225             :         } while (0)
    1226             : 
    1227             : str
    1228           8 : month_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1229             : {
    1230           8 :         str msg = MAL_SUCCEED;
    1231          15 :         int *restrict ret = NULL, multiplier = 1, k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2)),
    1232           8 :                 tpe = getArgType(mb, pci, 1);
    1233           8 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
    1234           8 :         BAT *b = NULL, *s = NULL, *res = NULL;
    1235           8 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
    1236           8 :         struct canditer ci = {0};
    1237           8 :         BATiter bi;
    1238             : 
    1239           8 :         (void) cntxt;
    1240           8 :         is_a_bat = isaBatType(tpe);
    1241           8 :         if (is_a_bat) {
    1242           1 :                 tpe = getBatType(tpe);
    1243           1 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1244           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1245           0 :                         goto bailout;
    1246             :                 }
    1247           1 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1248           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1249           0 :                         goto bailout;
    1250             :                 }
    1251           1 :                 canditer_init(&ci, b, s);
    1252           1 :                 if (!(res = COLnew(ci.hseq, TYPE_int, ci.ncand, TRANSIENT))) {
    1253           0 :                         msg = createException(SQL, "batcalc.month_interval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1254           0 :                         goto bailout;
    1255             :                 }
    1256           1 :                 r = getArgReference_bat(stk, pci, 0);
    1257           1 :                 ret = (int*) Tloc(res, 0);
    1258             :         } else {
    1259           7 :                 ret = getArgReference_int(stk, pci, 0);
    1260             :         }
    1261             : 
    1262           8 :         switch (k) {
    1263           1 :         case iyear:
    1264           1 :                 multiplier *= 12;
    1265           1 :                 break;
    1266             :         case imonth:
    1267             :                 break;
    1268           0 :         default: {
    1269           0 :                 msg = createException(ILLARG, "batcalc.month_interval", SQLSTATE(42000) "Illegal argument");
    1270           0 :                 goto bailout;
    1271             :         }
    1272             :         }
    1273             : 
    1274           8 :         bi = bat_iterator(b);
    1275           8 :         switch (tpe) {
    1276           0 :         case TYPE_bte:
    1277           0 :                 interval_loop(month_interval_convert, bte, int, "month_interval", GDK_int_max, DO_NOTHING, DO_NOTHING);
    1278             :                 break;
    1279           0 :         case TYPE_sht:
    1280           0 :                 interval_loop(month_interval_convert, sht, int, "month_interval", GDK_int_max, DO_NOTHING, DO_NOTHING);
    1281             :                 break;
    1282           8 :         case TYPE_int:
    1283          10 :                 interval_loop(month_interval_convert, int, int, "month_interval", GDK_int_max, DO_NOTHING, MUL_OVERFLOW);
    1284             :                 break;
    1285           0 :         case TYPE_lng:
    1286           0 :                 interval_loop(month_interval_convert, lng, int, "month_interval", GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
    1287             :                 break;
    1288             : #ifdef HAVE_HGE
    1289           0 :         case TYPE_hge:
    1290           0 :                 interval_loop(month_interval_convert, hge, int, "month_interval", GDK_int_max, CAST_VALIDATION, MUL_OVERFLOW);
    1291             :                 break;
    1292             : #endif
    1293           0 :         default: {
    1294           0 :                 msg = createException(ILLARG, "batcalc.month_interval", SQLSTATE(42000) "Illegal argument in month interval");
    1295             :         }
    1296             :         }
    1297           8 :         if (b) {
    1298           1 :                 btkey = bi.key;
    1299           1 :                 btsorted = bi.sorted;
    1300           1 :                 btrevsorted = bi.revsorted;
    1301             :         }
    1302           7 : bailout1:
    1303           8 :         bat_iterator_end(&bi);
    1304             : 
    1305           8 : bailout:
    1306           8 :         BBPreclaim(b);
    1307           8 :         BBPreclaim(s);
    1308           8 :         if (res && !msg) {
    1309           1 :                 BATsetcount(res, ci.ncand);
    1310           1 :                 res->tnil = nils;
    1311           1 :                 res->tnonil = !nils;
    1312           1 :                 res->tkey = btkey;
    1313           1 :                 res->tsorted = btsorted;
    1314           1 :                 res->trevsorted = btrevsorted;
    1315           1 :                 *r = res->batCacheid;
    1316           1 :                 BBPkeepref(res);
    1317           7 :         } else if (res)
    1318           0 :                 BBPreclaim(res);
    1319           8 :         return msg;
    1320             : }
    1321             : 
    1322             : #define second_interval_convert(OUT, TPE_IN, FUNC_NAME, MAX_VALUE, CAST_VALIDATION, MUL_VALIDATION) \
    1323             :         do { \
    1324             :                 lng cast, r; \
    1325             :                 CAST_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1326             :                 cast = (lng) next; \
    1327             :                 r = cast * multiplier; \
    1328             :                 if (scale) { \
    1329             :                         r += shift; \
    1330             :                         r /= divider; \
    1331             :                 } \
    1332             :                 MUL_VALIDATION(TPE_IN, FUNC_NAME, MAX_VALUE); \
    1333             :                 OUT = r; \
    1334             :         } while (0)
    1335             : 
    1336             : str
    1337           0 : second_interval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1338             : {
    1339           0 :         str msg = MAL_SUCCEED;
    1340           0 :         lng *restrict ret = NULL, multiplier = 1;
    1341           0 :         int tpe = getArgType(mb, pci, 1), k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2)),
    1342           0 :                 scale = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
    1343           0 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
    1344           0 :         BAT *b = NULL, *s = NULL, *res = NULL;
    1345           0 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
    1346           0 :         struct canditer ci = {0};
    1347             : #ifdef HAVE_HGE
    1348           0 :         hge shift = 0, divider = 1;
    1349             : #else
    1350             :         lng shift = 0, divider = 1;
    1351             : #endif
    1352           0 :         BATiter bi;
    1353             : 
    1354           0 :         (void) cntxt;
    1355           0 :         if (is_int_nil(scale)) {
    1356           0 :                 msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(42000) "Scale cannot be NULL");
    1357           0 :                 goto bailout;
    1358             :         }
    1359           0 :         if (scale < 0 || (size_t) scale >= sizeof(scales) / sizeof(scales[0])) {
    1360           0 :                 msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(42000) "Scale out of bounds");
    1361           0 :                 goto bailout;
    1362             :         }
    1363           0 :         is_a_bat = isaBatType(tpe);
    1364           0 :         if (is_a_bat) {
    1365           0 :                 tpe = getBatType(tpe);
    1366           0 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1367           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1368           0 :                         goto bailout;
    1369             :                 }
    1370           0 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1371           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1372           0 :                         goto bailout;
    1373             :                 }
    1374           0 :                 canditer_init(&ci, b, s);
    1375           0 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, ci.ncand, TRANSIENT))) {
    1376           0 :                         msg = createException(SQL, "batcalc.sec_interval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1377           0 :                         goto bailout;
    1378             :                 }
    1379           0 :                 r = getArgReference_bat(stk, pci, 0);
    1380           0 :                 ret = (lng*) Tloc(res, 0);
    1381             :         } else {
    1382           0 :                 ret = getArgReference_lng(stk, pci, 0);
    1383             :         }
    1384             : 
    1385           0 :         switch (k) {
    1386           0 :         case iday:
    1387           0 :                 multiplier *= 24;
    1388             :                 /* fall through */
    1389           0 :         case ihour:
    1390           0 :                 multiplier *= 60;
    1391             :                 /* fall through */
    1392           0 :         case imin:
    1393           0 :                 multiplier *= 60;
    1394             :                 /* fall through */
    1395           0 :         case isec:
    1396           0 :                 multiplier *= 1000;
    1397           0 :                 break;
    1398           0 :         default: {
    1399           0 :                 msg = createException(ILLARG, "batcalc.sec_interval", SQLSTATE(42000) "Illegal argument in second interval");
    1400           0 :                 goto bailout;
    1401             :         }
    1402             :         }
    1403           0 :         if (scale) {
    1404             : #ifndef TRUNCATE_NUMBERS
    1405           0 :                 shift += 5*scales[scale-1];
    1406             : #endif
    1407           0 :                 divider = scales[scale];
    1408             :         }
    1409             : 
    1410           0 :         bi = bat_iterator(b);
    1411           0 :         switch (tpe) {
    1412           0 :         case TYPE_bte:
    1413           0 :                 interval_loop(second_interval_convert, bte, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1414             :                 break;
    1415           0 :         case TYPE_sht:
    1416           0 :                 interval_loop(second_interval_convert, sht, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1417             :                 break;
    1418           0 :         case TYPE_int:
    1419           0 :                 interval_loop(second_interval_convert, int, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1420             :                 break;
    1421           0 :         case TYPE_lng:
    1422           0 :                 interval_loop(second_interval_convert, lng, lng, "sec_interval", GDK_lng_max, DO_NOTHING, MUL_OVERFLOW);
    1423             :                 break;
    1424             : #ifdef HAVE_HGE
    1425           0 :         case TYPE_hge:
    1426           0 :                 interval_loop(second_interval_convert, hge, lng, "sec_interval", GDK_lng_max, CAST_VALIDATION, MUL_OVERFLOW);
    1427             :                 break;
    1428             : #endif
    1429           0 :         default: {
    1430           0 :                 msg = createException(ILLARG, "batcalc.sec_interval", SQLSTATE(42000) "Illegal argument in second interval");
    1431             :         }
    1432             :         }
    1433           0 :         if (b) {
    1434           0 :                 btkey = bi.key;
    1435           0 :                 btsorted = bi.sorted;
    1436           0 :                 btrevsorted = bi.revsorted;
    1437             :         }
    1438           0 : bailout1:
    1439           0 :         bat_iterator_end(&bi);
    1440             : 
    1441           0 : bailout:
    1442           0 :         BBPreclaim(b);
    1443           0 :         BBPreclaim(s);
    1444           0 :         if (res && !msg) {
    1445           0 :                 BATsetcount(res, ci.ncand);
    1446           0 :                 res->tnil = nils;
    1447           0 :                 res->tnonil = !nils;
    1448           0 :                 res->tkey = btkey;
    1449           0 :                 res->tsorted = btsorted;
    1450           0 :                 res->trevsorted = btrevsorted;
    1451           0 :                 *r = res->batCacheid;
    1452           0 :                 BBPkeepref(res);
    1453           0 :         } else if (res)
    1454           0 :                 BBPreclaim(res);
    1455           0 :         return msg;
    1456             : }
    1457             : 
    1458             : str
    1459           0 : second_interval_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1460             : {
    1461           0 :         str msg = MAL_SUCCEED;
    1462           0 :         lng *restrict ret = NULL, multiplier = 1, divider = 1;
    1463           0 :         int tpe = getArgType(mb, pci, 1), k = digits2ek(*getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2));
    1464           0 :         bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
    1465           0 :         BAT *b = NULL, *s = NULL, *res = NULL;
    1466           0 :         bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
    1467           0 :         struct canditer ci = {0};
    1468             : 
    1469           0 :         (void) cntxt;
    1470           0 :         is_a_bat = isaBatType(tpe);
    1471           0 :         if (is_a_bat) {
    1472           0 :                 tpe = getBatType(tpe);
    1473           0 :                 if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
    1474           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1475           0 :                         goto bailout;
    1476             :                 }
    1477           0 :                 if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
    1478           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1479           0 :                         goto bailout;
    1480             :                 }
    1481           0 :                 canditer_init(&ci, b, s);
    1482           0 :                 if (!(res = COLnew(ci.hseq, TYPE_lng, ci.ncand, TRANSIENT))) {
    1483           0 :                         msg = createException(SQL, "batcalc.second_interval_daytime", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1484           0 :                         goto bailout;
    1485             :                 }
    1486           0 :                 r = getArgReference_bat(stk, pci, 0);
    1487           0 :                 ret = (lng*) Tloc(res, 0);
    1488             :         } else {
    1489           0 :                 ret = getArgReference_lng(stk, pci, 0);
    1490             :         }
    1491             : 
    1492           0 :         switch (k) {
    1493             :         case isec:
    1494             :                 break;
    1495             :         case imin:
    1496             :                 divider *= 60000;
    1497             :                 multiplier *= 60000;
    1498             :                 break;
    1499             :         case ihour:
    1500             :                 divider *= 3600000;
    1501             :                 multiplier *= 3600000;
    1502             :                 break;
    1503             :         case iday:
    1504             :                 divider *= (24 * 3600000);
    1505             :                 multiplier *= (24 * 3600000);
    1506             :                 break;
    1507           0 :         default: {
    1508           0 :                 msg = createException(ILLARG, "batcalc.second_interval_daytime", SQLSTATE(42000) "Illegal argument in daytime interval");
    1509           0 :                 goto bailout;
    1510             :         }
    1511             :         }
    1512             : 
    1513           0 :         if (is_a_bat) {
    1514           0 :                 oid off = b->hseqbase;
    1515           0 :                 BATiter bi = bat_iterator(b);
    1516           0 :                 daytime *restrict vals = (daytime*) bi.base;
    1517           0 :                 if (ci.tpe == cand_dense) {
    1518           0 :                         for (BUN i = 0 ; i < ci.ncand; i++) {
    1519           0 :                                 oid p = (canditer_next_dense(&ci) - off);
    1520           0 :                                 daytime next = vals[p];
    1521             : 
    1522           0 :                                 if (is_daytime_nil(next)) {
    1523           0 :                                         ret[i] = lng_nil;
    1524           0 :                                         nils = true;
    1525             :                                 } else {
    1526           0 :                                         ret[i] = (next / divider) * multiplier;
    1527             :                                 }
    1528             :                         }
    1529             :                 } else {
    1530           0 :                         for (BUN i = 0 ; i < ci.ncand; i++) {
    1531           0 :                                 oid p = (canditer_next(&ci) - off);
    1532           0 :                                 daytime next = vals[p];
    1533             : 
    1534           0 :                                 if (is_daytime_nil(next)) {
    1535           0 :                                         ret[i] = lng_nil;
    1536           0 :                                         nils = true;
    1537             :                                 } else {
    1538           0 :                                         ret[i] = (next / divider) * multiplier;
    1539             :                                 }
    1540             :                         }
    1541             :                 }
    1542           0 :                 btkey = bi.key;
    1543           0 :                 btsorted = bi.sorted;
    1544           0 :                 btrevsorted = bi.revsorted;
    1545           0 :                 bat_iterator_end(&bi);
    1546             :         } else {
    1547           0 :                 daytime next = *(daytime*)getArgReference(stk, pci, 1);
    1548           0 :                 *ret = is_daytime_nil(next) ? lng_nil : (next / divider) * multiplier;
    1549             :         }
    1550             : 
    1551           0 : bailout:
    1552           0 :         BBPreclaim(b);
    1553           0 :         BBPreclaim(s);
    1554           0 :         if (res && !msg) {
    1555           0 :                 BATsetcount(res, ci.ncand);
    1556           0 :                 res->tnil = nils;
    1557           0 :                 res->tnonil = !nils;
    1558           0 :                 res->tkey = btkey;
    1559           0 :                 res->tsorted = btsorted;
    1560           0 :                 res->trevsorted = btrevsorted;
    1561           0 :                 *r = res->batCacheid;
    1562           0 :                 BBPkeepref(res);
    1563           0 :         } else if (res)
    1564           0 :                 BBPreclaim(res);
    1565           0 :         return msg;
    1566             : }
    1567             : 
    1568             : str
    1569           0 : nil_2_date(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1570             : {
    1571           0 :         BAT *b = NULL, *res = NULL;
    1572           0 :         bat *r = NULL;
    1573             : 
    1574           0 :         (void) cntxt;
    1575           0 :         if (isaBatType(getArgType(mb, pci, 1))) {
    1576           0 :                 date d = date_nil;
    1577           0 :                 if (!(b = BBPquickdesc(*getArgReference_bat(stk, pci, 1))))
    1578           0 :                         throw(SQL, "batcalc.nil_2_date", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1579           0 :                 res = BATconstant(b->hseqbase, TYPE_date, &d, BATcount(b), TRANSIENT);
    1580           0 :                 if (!res)
    1581           0 :                         throw(SQL, "batcalc.nil_2_date", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1582           0 :                 r = getArgReference_bat(stk, pci, 0);
    1583           0 :                 *r = res->batCacheid;
    1584           0 :                 BBPkeepref(res);
    1585             :         } else {
    1586           0 :                 date *ret = (date*) getArgReference(stk, pci, 0);
    1587           0 :                 *ret = date_nil;
    1588             :         }
    1589             :         return MAL_SUCCEED;
    1590             : }
    1591             : 
    1592             : str
    1593           2 : SQLcurrent_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1594             : {
    1595           2 :         mvc *m = NULL;
    1596           2 :         str msg;
    1597           2 :         daytime *res = getArgReference_TYPE(stk, pci, 0, daytime);
    1598             : 
    1599           2 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
    1600             :                 return msg;
    1601             : 
    1602           4 :         *res = timestamp_daytime(timestamp_add_usec(timestamp_current(),
    1603           2 :                                                          m->timezone * LL_CONSTANT(1000)));
    1604           2 :         return msg;
    1605             : }
    1606             : 
    1607             : str
    1608           2 : SQLcurrent_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1609             : {
    1610           2 :         mvc *m = NULL;
    1611           2 :         str msg;
    1612           2 :         timestamp *res = getArgReference_TYPE(stk, pci, 0, timestamp);
    1613             : 
    1614           2 :         if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
    1615             :                 return msg;
    1616             : 
    1617           2 :         *res = timestamp_add_usec(timestamp_current(), m->timezone * LL_CONSTANT(1000));
    1618           2 :         return msg;
    1619             : }

Generated by: LCOV version 1.14