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