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 2421 : 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 2421 : return ((input + shift) / divider) * multiplier;
28 : }
29 :
30 : str
31 2559 : daytime_2time_daytime(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
32 : {
33 2559 : str msg = MAL_SUCCEED;
34 2559 : BAT *b = NULL, *s = NULL, *res = NULL;
35 2559 : daytime *restrict ret = NULL;
36 5097 : int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
37 2559 : bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
38 2559 : bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
39 2559 : struct canditer ci = {0};
40 : #ifdef HAVE_HGE
41 2559 : hge shift = 0, divider = 1, multiplier = 1;
42 : #else
43 : lng shift = 0, divider = 1, multiplier = 1;
44 : #endif
45 :
46 2559 : (void) cntxt;
47 2559 : 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 2559 : 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 2559 : is_a_bat = isaBatType(tpe);
56 2559 : if (is_a_bat) {
57 21 : tpe = getBatType(tpe);
58 21 : 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 21 : 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 21 : canditer_init(&ci, b, s);
67 21 : 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 21 : r = getArgReference_bat(stk, pci, 0);
72 21 : ret = (daytime*) Tloc(res, 0);
73 : } else {
74 2538 : ret = (daytime*) getArgReference(stk, pci, 0);
75 : }
76 :
77 : /* correct fraction */
78 2559 : if (d < 6) {
79 2507 : divider *= scales[6 - d];
80 : #ifndef TRUNCATE_NUMBERS
81 2507 : shift += (scales[6 - d] >> 1);
82 : #endif
83 2507 : multiplier *= scales[6 - d];
84 : }
85 :
86 2559 : if (is_a_bat) {
87 21 : oid off = b->hseqbase;
88 21 : BATiter bi = bat_iterator(b);
89 21 : daytime *restrict vals = (daytime*) bi.base;
90 21 : if (ci.tpe == cand_dense) {
91 64 : for (BUN i = 0; i < ci.ncand; i++) {
92 43 : oid p = (canditer_next_dense(&ci) - off);
93 43 : daytime next = vals[p];
94 :
95 43 : if (is_daytime_nil(next)) {
96 8 : ret[i] = daytime_nil;
97 8 : 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 21 : btkey = bi.key;
116 21 : btsorted = bi.sorted;
117 21 : btrevsorted = bi.revsorted;
118 21 : bat_iterator_end(&bi);
119 : } else {
120 2538 : daytime next = *(daytime*)getArgReference(stk, pci, 1);
121 2538 : *ret = is_daytime_nil(next) ? daytime_nil : daytime_2time_daytime_imp(next, shift, divider, multiplier);
122 : }
123 :
124 2559 : bailout:
125 2559 : BBPreclaim(b);
126 2559 : BBPreclaim(s);
127 2559 : if (res && !msg) {
128 21 : BATsetcount(res, ci.ncand);
129 21 : res->tnil = nils;
130 21 : res->tnonil = !nils;
131 21 : res->tkey = btkey;
132 21 : res->tsorted = btsorted;
133 21 : res->trevsorted = btrevsorted;
134 21 : *r = res->batCacheid;
135 21 : BBPkeepref(res);
136 2538 : } else if (res)
137 0 : BBPreclaim(res);
138 2559 : 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 52 : str_2time_daytimetz_internal_imp(daytime *ret, const char *next, ssize_t (*fromstr_func)(const char *, size_t *, daytime **, bool),
290 : #ifdef HAVE_HGE
291 : hge shift, hge divider, hge multiplier
292 : #else
293 : lng shift, lng divider, lng multiplier
294 : #endif
295 : )
296 : {
297 52 : ssize_t pos = 0;
298 52 : daytime dt = 0, *conv = &dt;
299 :
300 52 : pos = fromstr_func(next, &(size_t){sizeof(daytime)}, &conv, false);
301 52 : if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_daytime_nil(*conv))
302 48 : return createException(SQL, "batcalc.str_2time_daytimetz", SQLSTATE(22007) "Daytime '%s' has incorrect format", next);
303 4 : *ret = daytime_2time_daytime_imp(*conv, shift, divider, multiplier);
304 4 : return MAL_SUCCEED;
305 : }
306 :
307 : static str
308 52 : str_2time_daytimetz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, int tz)
309 : {
310 52 : str msg = MAL_SUCCEED;
311 52 : BAT *b = NULL, *s = NULL, *res = NULL;
312 52 : daytime *restrict ret = NULL;
313 52 : int d = (digits) ? digits - 1 : 0;
314 52 : bool is_a_bat = false, nils = false;
315 52 : bat *r = NULL;
316 52 : ssize_t (*fromstr_func)(const char *, size_t *, daytime **, bool) = tz ? daytime_tz_fromstr : daytime_fromstr;
317 52 : struct canditer ci = {0};
318 : #ifdef HAVE_HGE
319 52 : hge shift = 0, divider = 1, multiplier = 1;
320 : #else
321 : lng shift = 0, divider = 1, multiplier = 1;
322 : #endif
323 :
324 52 : 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 52 : 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 52 : is_a_bat = isaBatType(tpe);
333 12 : if (is_a_bat) {
334 12 : tpe = getBatType(tpe);
335 12 : 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 12 : 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 12 : canditer_init(&ci, b, s);
344 12 : 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 12 : r = (bat*) out;
349 12 : ret = (daytime*) Tloc(res, 0);
350 : } else {
351 : ret = (daytime*) out;
352 : }
353 :
354 : /* correct fraction */
355 52 : 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 52 : if (is_a_bat) {
364 12 : oid off = b->hseqbase;
365 12 : BATiter it = bat_iterator(b);
366 12 : if (ci.tpe == cand_dense) {
367 24 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
368 12 : oid p = (canditer_next_dense(&ci) - off);
369 12 : const char *next = BUNtvar(it, p);
370 :
371 12 : if (strNil(next)) {
372 0 : ret[i] = daytime_nil;
373 0 : nils = true;
374 : } else {
375 12 : msg = str_2time_daytimetz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
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);
388 : }
389 : }
390 : }
391 12 : 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);
398 : }
399 :
400 52 : bailout:
401 52 : BBPreclaim(b);
402 52 : BBPreclaim(s);
403 52 : 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 52 : } else if (res)
413 12 : BBPreclaim(res);
414 52 : return msg;
415 : }
416 :
417 : str
418 38 : str_2time_daytimetz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
419 : {
420 38 : int tpe = getArgType(mb, pci, 1),
421 70 : digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2),
422 70 : tz = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
423 38 : bat *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2) : NULL;
424 38 : (void) cntxt;
425 38 : 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 33 : tpe = getBatType(tpe);
578 33 : 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 33 : 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 33 : canditer_init(&ci, b, s);
587 33 : 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 33 : r = getArgReference_bat(stk, pci, 0);
592 33 : ret = (timestamp*) Tloc(res, 0);
593 : } else {
594 15 : ret = (timestamp*) getArgReference(stk, pci, 0);
595 : }
596 :
597 48 : if (is_a_bat) {
598 33 : oid off = b->hseqbase;
599 33 : BATiter bi = bat_iterator(b);
600 33 : date *restrict vals = (date*) bi.base;
601 33 : if (ci.tpe == cand_dense) {
602 353 : 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 33 : btkey = bi.key;
615 33 : btsorted = bi.sorted;
616 33 : btrevsorted = bi.revsorted;
617 33 : bat_iterator_end(&bi);
618 : } else {
619 15 : *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 33 : BATsetcount(res, ci.ncand);
627 33 : res->tnil = nils;
628 33 : res->tnonil = !nils;
629 33 : res->tkey = btkey;
630 33 : res->tsorted = btsorted;
631 33 : res->trevsorted = btrevsorted;
632 33 : *r = res->batCacheid;
633 33 : BBPkeepref(res);
634 15 : } else if (res)
635 0 : BBPreclaim(res);
636 48 : return msg;
637 : }
638 :
639 : static inline timestamp
640 3417 : 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 3417 : date dt = timestamp_date(input);
649 3417 : daytime tm = timestamp_daytime(input);
650 3417 : tm = ((tm + shift) / divider) * multiplier;
651 3417 : return timestamp_create(dt, tm);
652 : }
653 :
654 : str
655 45172 : timestamp_2time_timestamp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
656 : {
657 45172 : str msg = MAL_SUCCEED;
658 45172 : BAT *b = NULL, *s = NULL, *res = NULL;
659 45172 : timestamp *restrict ret = NULL;
660 90201 : int tpe = getArgType(mb, pci, 1), *digits = getArgReference_int(stk, pci, pci->argc == 4 ? 3 : 2), d = (*digits) ? *digits - 1 : 0;
661 45172 : bool is_a_bat = false, nils = false, btsorted = false, btrevsorted = false, btkey = false;
662 45172 : bat *r = NULL, *sid = pci->argc == 4 ? getArgReference_bat(stk, pci, 2): NULL;
663 45172 : struct canditer ci = {0};
664 : #ifdef HAVE_HGE
665 45172 : hge shift = 0, divider = 1, multiplier = 1;
666 : #else
667 : lng shift = 0, divider = 1, multiplier = 1;
668 : #endif
669 :
670 45172 : (void) cntxt;
671 45172 : 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 45172 : 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 45172 : is_a_bat = isaBatType(tpe);
680 45172 : if (is_a_bat) {
681 143 : tpe = getBatType(tpe);
682 143 : 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 143 : 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 143 : canditer_init(&ci, b, s);
691 143 : 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 143 : r = getArgReference_bat(stk, pci, 0);
696 143 : ret = (timestamp*) Tloc(res, 0);
697 : } else {
698 45029 : ret = (timestamp*) getArgReference(stk, pci, 0);
699 : }
700 :
701 : /* correct fraction */
702 45172 : 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 45172 : if (is_a_bat) {
711 143 : oid off = b->hseqbase;
712 143 : BATiter bi = bat_iterator(b);
713 143 : timestamp *restrict vals = (timestamp*) bi.base;
714 143 : if (ci.tpe == cand_dense) {
715 469 : for (BUN i = 0 ; i < ci.ncand; i++) {
716 326 : oid p = (canditer_next_dense(&ci) - off);
717 326 : timestamp next = vals[p];
718 :
719 326 : if (is_timestamp_nil(next)) {
720 12 : ret[i] = timestamp_nil;
721 12 : nils = true;
722 : } else {
723 314 : 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 143 : btkey = bi.key;
740 143 : btsorted = bi.sorted;
741 143 : btrevsorted = bi.revsorted;
742 143 : bat_iterator_end(&bi);
743 : } else {
744 45029 : timestamp next = *(timestamp*)getArgReference(stk, pci, 1);
745 45029 : *ret = is_timestamp_nil(next) ? timestamp_nil : timestamp_2time_timestamp_imp(next, shift, divider, multiplier);
746 : }
747 :
748 45172 : bailout:
749 45172 : BBPreclaim(b);
750 45172 : BBPreclaim(s);
751 45172 : if (res && !msg) {
752 143 : BATsetcount(res, ci.ncand);
753 143 : res->tnil = nils;
754 143 : res->tnonil = !nils;
755 143 : res->tkey = btkey;
756 143 : res->tsorted = btsorted;
757 143 : res->trevsorted = btrevsorted;
758 143 : *r = res->batCacheid;
759 143 : BBPkeepref(res);
760 45029 : } else if (res)
761 0 : BBPreclaim(res);
762 45172 : 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 305 : str_2time_timestamptz_internal_imp(timestamp *ret, const char *next, ssize_t (*fromstr_func)(const char *, size_t *, timestamp **, bool),
791 : #ifdef HAVE_HGE
792 : hge shift, hge divider, hge multiplier
793 : #else
794 : lng shift, lng divider, lng multiplier
795 : #endif
796 : )
797 : {
798 305 : ssize_t pos = 0;
799 305 : timestamp tp = 0, *conv = &tp;
800 :
801 305 : pos = fromstr_func(next, &(size_t){sizeof(timestamp)}, &conv, false);
802 305 : if (pos < (ssize_t) strlen(next) || /* includes pos < 0 */ is_timestamp_nil(*conv))
803 280 : return createException(SQL, "batcalc.str_2time_timestamptz_internal", SQLSTATE(22007) "Timestamp '%s' has incorrect format", next);
804 25 : *ret = timestamp_2time_timestamp_imp(*conv, shift, divider, multiplier);
805 25 : return MAL_SUCCEED;
806 : }
807 :
808 : static str
809 305 : str_2time_timestamptz_internal(ptr out, ptr in, const bat *sid, int tpe, int digits, int tz)
810 : {
811 305 : str msg = MAL_SUCCEED;
812 305 : BAT *b = NULL, *s = NULL, *res = NULL;
813 305 : timestamp *restrict ret = NULL;
814 305 : int d = (digits) ? digits - 1 : 0;
815 305 : bool is_a_bat = false, nils = false;
816 305 : bat *r = NULL;
817 305 : ssize_t (*fromstr_func)(const char *, size_t *, timestamp **, bool) = tz ? timestamp_tz_fromstr : timestamp_fromstr;
818 305 : struct canditer ci = {0};
819 : #ifdef HAVE_HGE
820 305 : hge shift = 0, divider = 1, multiplier = 1;
821 : #else
822 : lng shift = 0, divider = 1, multiplier = 1;
823 : #endif
824 :
825 305 : 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 305 : 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 305 : is_a_bat = isaBatType(tpe);
834 12 : if (is_a_bat) {
835 12 : tpe = getBatType(tpe);
836 12 : 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 12 : 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 12 : canditer_init(&ci, b, s);
845 12 : 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 12 : r = (bat*) out;
850 12 : ret = (timestamp*) Tloc(res, 0);
851 : } else {
852 : ret = (timestamp*) out;
853 : }
854 :
855 : /* correct fraction */
856 305 : 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 305 : if (is_a_bat) {
865 12 : oid off = b->hseqbase;
866 12 : BATiter bi = bat_iterator(b);
867 12 : if (ci.tpe == cand_dense) {
868 24 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
869 12 : oid p = (canditer_next_dense(&ci) - off);
870 12 : const char *next = BUNtvar(bi, p);
871 :
872 12 : if (strNil(next)) {
873 0 : ret[i] = timestamp_nil;
874 0 : nils = true;
875 : } else {
876 12 : msg = str_2time_timestamptz_internal_imp(&(ret[i]), next, fromstr_func, shift, divider, multiplier);
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);
889 : }
890 : }
891 : }
892 12 : bat_iterator_end(&bi);
893 : } else {
894 293 : const char *next = *(str*)in;
895 293 : if (strNil(next))
896 0 : *ret = timestamp_nil;
897 : else
898 293 : msg = str_2time_timestamptz_internal_imp(ret, next, fromstr_func, shift, divider, multiplier);
899 : }
900 :
901 305 : bailout:
902 305 : BBPreclaim(b);
903 305 : BBPreclaim(s);
904 305 : 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 305 : } else if (res)
914 12 : BBPreclaim(res);
915 305 : return msg;
916 : }
917 :
918 : str
919 155 : str_2time_timestamptz(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
920 : {
921 155 : int tpe = getArgType(mb, pci, 1),
922 310 : digits = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2),
923 310 : tz = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3);
924 155 : (void) cntxt;
925 155 : return str_2time_timestamptz_internal(getArgReference(stk, pci, 0), getArgReference(stk, pci, 1), NULL, tpe, digits, tz);
926 : }
927 :
928 : str
929 6 : batstr_2time_timestamptz(bat *res, const bat *bid, const bat *sid, const int *digits, int *tz)
930 : {
931 6 : 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 14 : month_interval_str_imp(int *ret, const char *next, int d, int sk)
950 : {
951 14 : lng upcast;
952 14 : if (interval_from_str(next, d, sk, &upcast) < 0)
953 4 : return createException(SQL, "batcalc.month_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
954 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 13 : month_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
961 : {
962 13 : str msg = MAL_SUCCEED;
963 13 : int *restrict ret = NULL;
964 33 : int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
965 13 : tpe = getArgType(mb, pci, 1);
966 13 : bool is_a_bat = false, nils = false;
967 13 : BAT *b = NULL, *s = NULL, *res = NULL;
968 13 : bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
969 13 : struct canditer ci = {0};
970 :
971 13 : (void) cntxt;
972 13 : is_a_bat = isaBatType(tpe);
973 13 : if (is_a_bat) {
974 3 : tpe = getBatType(tpe);
975 3 : 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 3 : 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 3 : canditer_init(&ci, b, s);
984 3 : 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 3 : r = getArgReference_bat(stk, pci, 0);
989 3 : ret = (int*) Tloc(res, 0);
990 : } else {
991 10 : ret = getArgReference_int(stk, pci, 0);
992 : }
993 :
994 13 : if (is_a_bat) {
995 3 : oid off = b->hseqbase;
996 3 : BATiter bi = bat_iterator(b);
997 3 : if (ci.tpe == cand_dense) {
998 9 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
999 6 : oid p = (canditer_next_dense(&ci) - off);
1000 6 : const char *next = BUNtvar(bi, p);
1001 :
1002 6 : if (strNil(next)) {
1003 2 : ret[i] = int_nil;
1004 2 : nils = true;
1005 : } else {
1006 4 : 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 3 : 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 13 : bailout:
1033 13 : BBPreclaim(b);
1034 13 : BBPreclaim(s);
1035 13 : 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 12 : } else if (res)
1045 2 : BBPreclaim(res);
1046 13 : return msg;
1047 : }
1048 :
1049 : static inline str
1050 1140 : second_interval_str_imp(lng *ret, const char *next, int d, int sk)
1051 : {
1052 1140 : if (interval_from_str(next, d, sk, ret) < 0)
1053 92 : return createException(SQL, "batcalc.second_interval_str", SQLSTATE(42000) "Wrong format (%s)", next);
1054 : return MAL_SUCCEED;
1055 : }
1056 :
1057 : str
1058 141 : second_interval_str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1059 : {
1060 141 : str msg = MAL_SUCCEED;
1061 141 : lng *restrict ret = NULL;
1062 419 : int d = *getArgReference_int(stk, pci, pci->argc == 5 ? 3 : 2), sk = *getArgReference_int(stk, pci, pci->argc == 5 ? 4 : 3),
1063 141 : tpe = getArgType(mb, pci, 1);
1064 141 : bool is_a_bat = false, nils = false;
1065 141 : BAT *b = NULL, *s = NULL, *res = NULL;
1066 141 : bat *r = NULL, *sid = pci->argc == 5 ? getArgReference_bat(stk, pci, 2): NULL;
1067 141 : struct canditer ci = {0};
1068 :
1069 141 : (void) cntxt;
1070 141 : is_a_bat = isaBatType(tpe);
1071 141 : if (is_a_bat) {
1072 2 : tpe = getBatType(tpe);
1073 2 : 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 2 : 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 2 : canditer_init(&ci, b, s);
1082 2 : 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 2 : r = getArgReference_bat(stk, pci, 0);
1087 2 : ret = (lng*) Tloc(res, 0);
1088 : } else {
1089 139 : ret = getArgReference_lng(stk, pci, 0);
1090 : }
1091 :
1092 141 : if (is_a_bat) {
1093 2 : oid off = b->hseqbase;
1094 2 : BATiter bi = bat_iterator(b);
1095 2 : if (ci.tpe == cand_dense) {
1096 1005 : for (BUN i = 0 ; i < ci.ncand && !msg; i++) {
1097 1003 : oid p = (canditer_next_dense(&ci) - off);
1098 1003 : const char *next = BUNtvar(bi, p);
1099 :
1100 1003 : if (strNil(next)) {
1101 2 : ret[i] = lng_nil;
1102 2 : nils = true;
1103 : } else {
1104 1001 : 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 2 : bat_iterator_end(&bi);
1121 : } else {
1122 139 : const char *next = *getArgReference_str(stk, pci, 1);
1123 :
1124 139 : if (strNil(next))
1125 0 : *ret = lng_nil;
1126 : else
1127 139 : msg = second_interval_str_imp(ret, next, d, sk);
1128 : }
1129 :
1130 141 : bailout:
1131 141 : BBPreclaim(b);
1132 141 : BBPreclaim(s);
1133 141 : if (res && !msg) {
1134 2 : BATsetcount(res, ci.ncand);
1135 2 : res->tnil = nils;
1136 2 : res->tnonil = !nils;
1137 2 : res->tkey = BATcount(res) <= 1;
1138 2 : res->tsorted = BATcount(res) <= 1;
1139 2 : res->trevsorted = BATcount(res) <= 1;
1140 2 : *r = res->batCacheid;
1141 2 : BBPkeepref(res);
1142 139 : } else if (res)
1143 0 : BBPreclaim(res);
1144 141 : 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 : }
|