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 2412 : 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 2412 : return ((input + shift) / divider) * multiplier;
28 : }
29 :
30 : str
31 2561 : daytime_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
32 : {
33 2561 : str msg = MAL_SUCCEED;
34 2561 : BAT *b = NULL, *s = NULL, *res = NULL;
35 2561 : daytime *restrict ret = NULL;
36 5094 : int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
37 2561 : bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
38 2561 : bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
39 2561 : struct canditer ci = {0};
40 : #ifdef HAVE_HGE
41 2561 : hge shift = 0, divider = 1, multiplier = 1;
42 : #else
43 : lng shift = 0, divider = 1, multiplier = 1;
44 : #endif
45 :
46 2561 : (void) cntxt;
47 2561 : 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 2561 : 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 2561 : is_a_bat = isaBatType(tpe);
56 2561 : 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 2533 : ret = (daytime*) getArgReference(stk, pci, 0);
75 : }
76 :
77 : /* correct fraction */
78 2561 : if (d < 6) {
79 2498 : divider *= scales[6 - d];
80 : #ifndef TRUNCATE_NUMBERS
81 2498 : shift += (scales[6 - d] >> 1);
82 : #endif
83 2498 : multiplier *= scales[6 - d];
84 : }
85 :
86 2561 : 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 2533 : daytime next = *(daytime*)getArgReference(stk, pci, 1);
121 2533 : *ret = is_daytime_nil(next) ? daytime_nil : daytime_2time_daytime_imp(next, shift, divider, multiplier);
122 : }
123 :
124 2561 : bailout:
125 2561 : BBPreclaim(b);
126 2561 : BBPreclaim(s);
127 2561 : 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 2533 : } else if (res)
137 0 : BBPreclaim(res);
138 2561 : 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 3625 : 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 3625 : date dt = timestamp_date(input);
649 3625 : daytime tm = timestamp_daytime(input);
650 3625 : tm = ((tm + shift) / divider) * multiplier;
651 3625 : 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 406 : 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 406 : ssize_t pos = 0;
799 406 : timestamp tp = 0;
800 :
801 406 : pos = fromstr_func(next, &tp, (long)tz_off, false);
802 406 : if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_timestamp_nil(tp))
803 281 : 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 343 : str_2time_timestamptz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, lng tz)
810 : {
811 343 : str msg = MAL_SUCCEED;
812 343 : BAT *b = NULL, *s = NULL, *res = NULL;
813 343 : timestamp *restrict ret = NULL;
814 343 : int d = (digits) ? digits - 1 : 0;
815 343 : bool is_a_bat = false, nils = false;
816 343 : bat *r = NULL;
817 343 : ssize_t (*fromstr_func)(const char *, timestamp *, long, bool) = sql_timestamp_fromstr;
818 343 : struct canditer ci = {0};
819 : #ifdef HAVE_HGE
820 343 : hge shift = 0, divider = 1, multiplier = 1;
821 : #else
822 : lng shift = 0, divider = 1, multiplier = 1;
823 : #endif
824 :
825 343 : 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 343 : 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 343 : is_a_bat = isaBatType(tpe);
834 343 : if (is_a_bat) {
835 66 : tpe = getBatType(tpe);
836 66 : 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 66 : 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 66 : canditer_init(&ci, b, s);
845 66 : 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 66 : r = (bat*) out;
850 66 : ret = (timestamp*) Tloc(res, 0);
851 : } else {
852 : ret = (timestamp*) out;
853 : }
854 :
855 : /* correct fraction */
856 343 : 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 343 : if (is_a_bat) {
865 66 : oid off = b->hseqbase;
866 66 : BATiter bi = bat_iterator(b);
867 66 : if (ci.tpe == cand_dense) {
868 195 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
869 129 : oid p = (canditer_next_dense(&ci) - off);
870 129 : const char *next = BUNtvar(bi, p);
871 :
872 129 : if (strNil(next)) {
873 0 : ret[i] = timestamp_nil;
874 0 : nils = true;
875 : } else {
876 129 : 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 66 : 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 343 : bailout:
902 343 : BBPreclaim(b);
903 343 : BBPreclaim(s);
904 343 : 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 296 : } else if (res)
914 19 : BBPreclaim(res);
915 343 : 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 13 : batstr_2time_timestamp(bat *res, const bat *bid, const bat *sid, const int *digits)
944 : {
945 13 : return str_2time_timestamptz_internal((ptr) res, (ptr) bid, sid, newBatType(TYPE_str), *digits, 0);
946 : }
947 :
948 : static inline str
949 18 : month_interval_str_imp(int *ret, const char *next, int d, int sk)
950 : {
951 18 : lng upcast;
952 18 : if (interval_from_str(next, d, sk, &upcast) < 0)
953 5 : return createException(SQL, "batcalc.month_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
954 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 18 : month_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
962 : {
963 18 : str msg = MAL_SUCCEED;
964 18 : int *restrict ret = NULL;
965 42 : int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
966 18 : tpe = getArgType(mb, pci, 1);
967 18 : bool is_a_bat = false, nils = false;
968 18 : BAT *b = NULL, *s = NULL, *res = NULL;
969 18 : bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
970 18 : struct canditer ci = {0};
971 :
972 18 : (void) cntxt;
973 18 : is_a_bat = isaBatType(tpe);
974 18 : if (is_a_bat) {
975 6 : tpe = getBatType(tpe);
976 6 : 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 6 : 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 6 : canditer_init(&ci, b, s);
985 6 : 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 6 : r = getArgReference_bat(stk, pci, 0);
990 6 : ret = (int*) Tloc(res, 0);
991 : } else {
992 12 : ret = getArgReference_int(stk, pci, 0);
993 : }
994 :
995 18 : if (is_a_bat) {
996 6 : oid off = b->hseqbase;
997 6 : BATiter bi = bat_iterator(b);
998 6 : if (ci.tpe == cand_dense) {
999 14 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
1000 8 : oid p = (canditer_next_dense(&ci) - off);
1001 8 : const char *next = BUNtvar(bi, p);
1002 :
1003 8 : if (strNil(next)) {
1004 2 : ret[i] = int_nil;
1005 2 : nils = true;
1006 : } else {
1007 6 : 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 6 : 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 18 : bailout:
1034 18 : BBPreclaim(b);
1035 18 : BBPreclaim(s);
1036 18 : 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 16 : } else if (res)
1046 4 : BBPreclaim(res);
1047 18 : 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 : }
|