1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "gdk.h"
11#include <math.h>
12#include "mal_exception.h"
13#include "mal_interpreter.h"
14
15static str
16mythrow(enum malexception type, const char *fcn, const char *msg)
17{
18 char *errbuf = GDKerrbuf;
19 char *s;
20
21 if (errbuf && *errbuf) {
22 if (strncmp(errbuf, "!ERROR: ", 8) == 0)
23 errbuf += 8;
24 if (strchr(errbuf, '!') == errbuf + 5) {
25 s = createException(type, fcn, "%s", errbuf);
26 } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') {
27 s = createException(type, fcn, "%s", s + 2);
28 } else {
29 s = createException(type, fcn, "%s", errbuf);
30 }
31 GDKclrerr();
32 return s;
33 }
34 return createException(type, fcn, "%s", msg);
35}
36
37mal_export str CMDvarSUBsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
38
39str
40CMDvarSUBsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
41{
42 (void) cntxt;
43 (void) mb;
44
45 if (VARcalcsub(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
46 return mythrow(MAL, "calc.-", OPERATION_FAILED);
47 return MAL_SUCCEED;
48}
49
50mal_export str CMDvarSUB(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
51
52str
53CMDvarSUB(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
54{
55 (void) cntxt;
56 (void) mb;
57
58 if (VARcalcsub(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
59 return mythrow(MAL, "calc.sub_noerror", OPERATION_FAILED);
60 return MAL_SUCCEED;
61}
62
63mal_export str CMDvarADDsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
64
65str
66CMDvarADDsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
67{
68 (void) cntxt;
69 (void) mb;
70
71 if (VARcalcadd(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
72 return mythrow(MAL, "calc.+", OPERATION_FAILED);
73 return MAL_SUCCEED;
74}
75
76mal_export str CMDvarADD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
77
78str
79CMDvarADD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
80{
81 (void) cntxt;
82 (void) mb;
83
84 if (VARcalcadd(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
85 return mythrow(MAL, "calc.add_noerror", OPERATION_FAILED);
86 return MAL_SUCCEED;
87}
88
89mal_export str CMDvarADDstr(str *ret, str *s1, str *s2);
90
91str
92CMDvarADDstr(str *ret, str *s1, str *s2)
93{
94 str s;
95 size_t l1;
96
97 if (strNil(*s1) || strNil(*s2)) {
98 *ret= GDKstrdup(str_nil);
99 if (*ret == NULL)
100 return mythrow(MAL, "calc.+", SQLSTATE(HY001) MAL_MALLOC_FAIL);
101 return MAL_SUCCEED;
102 }
103 s = GDKzalloc((l1 = strlen(*s1)) + strlen(*s2) + 1);
104 if (s == NULL)
105 return mythrow(MAL, "calc.+", SQLSTATE(HY001) MAL_MALLOC_FAIL);
106 strcpy(s, *s1);
107 strcpy(s + l1, *s2);
108 *ret = s;
109 return MAL_SUCCEED;
110}
111
112mal_export str CMDvarADDstrint(str *ret, str *s1, int *i);
113
114str
115CMDvarADDstrint(str *ret, str *s1, int *i)
116{
117 str s;
118 size_t len;
119
120 if (strNil(*s1) || is_int_nil(*i)) {
121 *ret= GDKstrdup(str_nil);
122 if (*ret == NULL)
123 return mythrow(MAL, "calc.+", SQLSTATE(HY001) MAL_MALLOC_FAIL);
124 return MAL_SUCCEED;
125 }
126 len = strlen(*s1) + 16; /* maxint = 2147483647 which fits easily */
127 s = GDKmalloc(len);
128 if (s == NULL)
129 return mythrow(MAL, "calc.+", SQLSTATE(HY001) MAL_MALLOC_FAIL);
130 snprintf(s, len, "%s%d", *s1, *i);
131 *ret = s;
132 return MAL_SUCCEED;
133}
134
135mal_export str CMDvarMULsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
136
137str
138CMDvarMULsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
139{
140 (void) cntxt;
141 (void) mb;
142
143 if (VARcalcmul(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
144 return mythrow(MAL, "calc.*", OPERATION_FAILED);
145 return MAL_SUCCEED;
146}
147
148mal_export str CMDvarMUL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
149
150str
151CMDvarMUL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
152{
153 (void) cntxt;
154 (void) mb;
155
156 if (VARcalcmul(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
157 return mythrow(MAL, "calc.mul_noerror", OPERATION_FAILED);
158 return MAL_SUCCEED;
159}
160
161mal_export str CMDvarDIVsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
162
163str
164CMDvarDIVsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
165{
166 (void) cntxt;
167 (void) mb;
168
169 if (VARcalcdiv(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
170 return mythrow(MAL, "calc./", OPERATION_FAILED);
171 return MAL_SUCCEED;
172}
173
174mal_export str CMDvarDIV(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
175
176str
177CMDvarDIV(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
178{
179 (void) cntxt;
180 (void) mb;
181
182 if (VARcalcdiv(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
183 return mythrow(MAL, "calc.div_noerror", OPERATION_FAILED);
184 return MAL_SUCCEED;
185}
186
187mal_export str CMDvarMODsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
188
189str
190CMDvarMODsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
191{
192 (void) cntxt;
193 (void) mb;
194
195 if (VARcalcmod(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
196 return mythrow(MAL, "calc.%", OPERATION_FAILED);
197 return MAL_SUCCEED;
198}
199
200mal_export str CMDvarMOD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
201
202str
203CMDvarMOD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
204{
205 (void) cntxt;
206 (void) mb;
207
208 if (VARcalcmod(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
209 return mythrow(MAL, "calc.modmod", OPERATION_FAILED);
210 return MAL_SUCCEED;
211}
212
213mal_export str CMDvarLSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
214
215str
216CMDvarLSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
217{
218 (void) cntxt;
219 (void) mb;
220
221 if (VARcalclsh(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
222 return mythrow(MAL, "calc.<<", OPERATION_FAILED);
223 return MAL_SUCCEED;
224}
225
226mal_export str CMDvarLSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
227
228str
229CMDvarLSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
230{
231 (void) cntxt;
232 (void) mb;
233
234 if (VARcalclsh(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
235 return mythrow(MAL, "calc.lsh_noerror", OPERATION_FAILED);
236 return MAL_SUCCEED;
237}
238
239mal_export str CMDvarRSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
240
241str
242CMDvarRSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
243{
244 (void) cntxt;
245 (void) mb;
246
247 if (VARcalcrsh(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 1) != GDK_SUCCEED)
248 return mythrow(MAL, "calc.>>", OPERATION_FAILED);
249 return MAL_SUCCEED;
250}
251
252mal_export str CMDvarRSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
253
254str
255CMDvarRSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
256{
257 (void) cntxt;
258 (void) mb;
259
260 if (VARcalcrsh(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], 0) != GDK_SUCCEED)
261 return mythrow(MAL, "calc.rsh_noerror", OPERATION_FAILED);
262 return MAL_SUCCEED;
263}
264
265mal_export str CMDvarAND(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
266
267str
268CMDvarAND(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
269{
270 (void) cntxt;
271 (void) mb;
272
273 if (VARcalcand(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
274 return mythrow(MAL, "calc.and", OPERATION_FAILED);
275 return MAL_SUCCEED;
276}
277
278mal_export str CMDvarOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
279
280str
281CMDvarOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
282{
283 (void) cntxt;
284 (void) mb;
285
286 if (VARcalcor(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
287 return mythrow(MAL, "calc.or", OPERATION_FAILED);
288 return MAL_SUCCEED;
289}
290
291mal_export str CMDvarXOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
292
293str
294CMDvarXOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
295{
296 (void) cntxt;
297 (void) mb;
298
299 if (VARcalcxor(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
300 return mythrow(MAL, "calc.xor", OPERATION_FAILED);
301 return MAL_SUCCEED;
302}
303
304mal_export str CMDvarLT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
305
306str
307CMDvarLT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
308{
309 (void) cntxt;
310 (void) mb;
311
312 if (VARcalclt(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
313 return mythrow(MAL, "calc.<", OPERATION_FAILED);
314 return MAL_SUCCEED;
315}
316
317mal_export str CMDvarLE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
318
319str
320CMDvarLE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
321{
322 (void) cntxt;
323 (void) mb;
324
325 if (VARcalcle(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
326 return mythrow(MAL, "calc.<=", OPERATION_FAILED);
327 return MAL_SUCCEED;
328}
329
330mal_export str CMDvarGT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
331
332str
333CMDvarGT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
334{
335 (void) cntxt;
336 (void) mb;
337
338 if (VARcalcgt(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
339 return mythrow(MAL, "calc.>", OPERATION_FAILED);
340 return MAL_SUCCEED;
341}
342
343mal_export str CMDvarGE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
344
345str
346CMDvarGE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
347{
348 (void) cntxt;
349 (void) mb;
350
351 if (VARcalcge(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
352 return mythrow(MAL, "calc.>=", OPERATION_FAILED);
353 return MAL_SUCCEED;
354}
355
356mal_export str CMDvarEQ(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
357
358str
359CMDvarEQ(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
360{
361 (void) cntxt;
362 (void) mb;
363
364 if (VARcalceq(&stk->stk[getArg(pci, 0)],
365 &stk->stk[getArg(pci, 1)],
366 &stk->stk[getArg(pci, 2)],
367 pci->argc == 3 ? false : *getArgReference_bit(stk, pci, 3)
368 ) != GDK_SUCCEED)
369 return mythrow(MAL, "calc.==", OPERATION_FAILED);
370 return MAL_SUCCEED;
371}
372
373mal_export str CMDvarNE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
374
375str
376CMDvarNE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
377{
378 (void) cntxt;
379 (void) mb;
380
381 if (VARcalcne(&stk->stk[getArg(pci, 0)],
382 &stk->stk[getArg(pci, 1)],
383 &stk->stk[getArg(pci, 2)],
384 pci->argc == 3 ? false : *getArgReference_bit(stk, pci, 3)
385 ) != GDK_SUCCEED)
386 return mythrow(MAL, "calc.!=", OPERATION_FAILED);
387 return MAL_SUCCEED;
388}
389
390mal_export str CMDvarCMP(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
391
392str
393CMDvarCMP(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
394{
395 (void) cntxt;
396 (void) mb;
397
398 if (VARcalccmp(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)]) != GDK_SUCCEED)
399 return mythrow(MAL, "calc.cmp", OPERATION_FAILED);
400 return MAL_SUCCEED;
401}
402
403mal_export str CMDvarBETWEEN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
404
405str
406CMDvarBETWEEN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
407{
408 (void) cntxt;
409 (void) mb;
410 bool symmetric, linc, hinc, nils_false, anti;
411
412 symmetric = *getArgReference_bit(stk, pci, 4);
413 linc = *getArgReference_bit(stk, pci, 5);
414 hinc = *getArgReference_bit(stk, pci, 6);
415 nils_false = *getArgReference_bit(stk, pci, 6);
416 anti = *getArgReference_bit(stk, pci, 7);
417 if (VARcalcbetween(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], &stk->stk[getArg(pci, 2)], &stk->stk[getArg(pci, 3)], symmetric, linc, hinc, nils_false, anti) != GDK_SUCCEED)
418 return mythrow(MAL, "calc.between", OPERATION_FAILED);
419 return MAL_SUCCEED;
420}
421
422mal_export str CMDstrlength(int *ret, str *v);
423
424str
425CMDstrlength(int *ret, str *v)
426{
427 size_t l = strlen(*v);
428
429 if (l > (size_t) GDK_int_max)
430 return mythrow(MAL, "calc.length", OPERATION_FAILED);
431 *ret = (int) l;
432 return MAL_SUCCEED;
433}
434
435mal_export str CMDvarCONVERT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
436
437str
438CMDvarCONVERT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
439{
440 char buf[20];
441
442 (void) cntxt;
443 (void) mb;
444
445 if (VARconvert(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], 1) != GDK_SUCCEED) {
446 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
447 return mythrow(MAL, buf, OPERATION_FAILED);
448 }
449 return MAL_SUCCEED;
450}
451
452mal_export str CMDvarCONVERTptr(ptr *ret, ptr *v);
453
454str
455CMDvarCONVERTptr(ptr *ret, ptr *v)
456{
457 *ret = *v;
458 return MAL_SUCCEED;
459}
460
461mal_export str CMDvarISZERO(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
462
463str
464CMDvarISZERO(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
465{
466 char buf[20];
467
468 (void) cntxt;
469 (void) mb;
470
471 if (VARcalciszero(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
472 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
473 return mythrow(MAL, buf, OPERATION_FAILED);
474 }
475 return MAL_SUCCEED;
476}
477
478mal_export str CMDvarISNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
479
480str
481CMDvarISNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
482{
483 char buf[20];
484
485 (void) cntxt;
486 (void) mb;
487
488 if (VARcalcisnil(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
489 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
490 return mythrow(MAL, buf, OPERATION_FAILED);
491 }
492 return MAL_SUCCEED;
493}
494
495mal_export str CMDvarISNOTNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
496
497str
498CMDvarISNOTNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
499{
500 char buf[20];
501
502 (void) cntxt;
503 (void) mb;
504
505 if (VARcalcisnotnil(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
506 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
507 return mythrow(MAL, buf, OPERATION_FAILED);
508 }
509 return MAL_SUCCEED;
510}
511
512mal_export str CMDvarNOT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
513
514str
515CMDvarNOT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
516{
517 char buf[20];
518
519 (void) cntxt;
520 (void) mb;
521
522 if (VARcalcnot(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
523 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
524 return mythrow(MAL, buf, OPERATION_FAILED);
525 }
526 return MAL_SUCCEED;
527}
528
529mal_export str CMDvarABS(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
530
531str
532CMDvarABS(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
533{
534 char buf[20];
535
536 (void) cntxt;
537 (void) mb;
538
539 if (VARcalcabsolute(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
540 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
541 return mythrow(MAL, buf, OPERATION_FAILED);
542 }
543 return MAL_SUCCEED;
544}
545
546mal_export str CMDvarSIGN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
547
548str
549CMDvarSIGN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
550{
551 char buf[20];
552
553 (void) cntxt;
554 (void) mb;
555
556 if (VARcalcsign(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
557 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
558 return mythrow(MAL, buf, OPERATION_FAILED);
559 }
560 return MAL_SUCCEED;
561}
562
563mal_export str CMDvarNEG(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
564
565str
566CMDvarNEG(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
567{
568 char buf[20];
569
570 (void) cntxt;
571 (void) mb;
572
573 if (VARcalcnegate(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)]) != GDK_SUCCEED) {
574 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
575 return mythrow(MAL, buf, OPERATION_FAILED);
576 }
577 return MAL_SUCCEED;
578}
579
580mal_export str CMDvarINCRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
581
582str
583CMDvarINCRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
584{
585 char buf[20];
586
587 (void) cntxt;
588 (void) mb;
589
590 if (VARcalcincr(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], 1) != GDK_SUCCEED) {
591 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
592 return mythrow(MAL, buf, OPERATION_FAILED);
593 }
594 return MAL_SUCCEED;
595}
596
597mal_export str CMDvarDECRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
598
599str
600CMDvarDECRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
601{
602 char buf[20];
603
604 (void) cntxt;
605 (void) mb;
606
607 if (VARcalcdecr(&stk->stk[getArg(pci, 0)], &stk->stk[getArg(pci, 1)], 1) != GDK_SUCCEED) {
608 snprintf(buf, sizeof(buf), "%s.%s", pci->modname, pci->fcnname);
609 return mythrow(MAL, buf, OPERATION_FAILED);
610 }
611 return MAL_SUCCEED;
612}
613
614mal_export str CALCswitchbit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p);
615
616str
617CALCswitchbit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
618{
619 ptr p;
620 ptr retval = getArgReference(stk, pci, 0);
621 bit b = *getArgReference_bit(stk, pci, 1);
622 int t1 = getArgType(mb, pci, 2);
623 int t2 = getArgType(mb, pci, 3);
624
625 (void) cntxt;
626 if (t1 != t2)
627 return mythrow(MAL, "ifthenelse", SEMANTIC_TYPE_MISMATCH);
628
629 if (is_bit_nil(b)) {
630 if (VALinit(&stk->stk[pci->argv[0]], t1, ATOMnilptr(t1)) == NULL)
631 return mythrow(MAL, "ifthenelse", SQLSTATE(HY001) MAL_MALLOC_FAIL);
632 return MAL_SUCCEED;
633 }
634 if (b) {
635 p = getArgReference(stk, pci, 2);
636 } else {
637 p = getArgReference(stk, pci, 3);
638 }
639 if (ATOMextern(t1)) {
640 *(ptr **) retval = ATOMdup(t1, *(ptr**)p);
641 if (*(ptr **) retval == NULL)
642 throw(MAL, "ifthenelse", SQLSTATE(HY001) MAL_MALLOC_FAIL);
643 } else if (t1 == TYPE_void) {
644 memcpy(retval, p, sizeof(oid));
645 } else {
646 memcpy(retval, p, ATOMsize(t1));
647 }
648 return MAL_SUCCEED;
649}
650
651mal_export str CALCmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p);
652
653str
654CALCmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
655{
656 int t = getArgType(mb, pci, 1);
657 const void *p1 = getArgReference(stk, pci, 1);
658 const void *p2 = getArgReference(stk, pci, 2);
659 const void *nil;
660
661 (void) cntxt;
662 if (t != getArgType(mb, pci, 2))
663 return mythrow(MAL, "calc.min", SEMANTIC_TYPE_MISMATCH);
664 nil = ATOMnilptr(t);
665 if (t >= TYPE_str && ATOMstorage(t) >= TYPE_str) {
666 p1 = *(ptr *)p1;
667 p2 = *(ptr *)p2;
668 }
669 if (ATOMcmp(t, p1, nil) == 0 || ATOMcmp(t, p2, nil) == 0)
670 p1 = nil;
671 else if (ATOMcmp(t, p1, p2) > 0)
672 p1 = p2;
673 if (VALinit(&stk->stk[getArg(pci, 0)], t, p1) == NULL)
674 return mythrow(MAL, "calc.min", SQLSTATE(HY001) MAL_MALLOC_FAIL);
675 return MAL_SUCCEED;
676}
677
678mal_export str CALCmin_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p);
679
680str
681CALCmin_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
682{
683 int t = getArgType(mb, pci, 1);
684 ptr p1 = getArgReference(stk, pci, 1);
685 ptr p2 = getArgReference(stk, pci, 2);
686 const void *nil;
687
688 (void) cntxt;
689 if (t != getArgType(mb, pci, 2))
690 return mythrow(MAL, "calc.min", SEMANTIC_TYPE_MISMATCH);
691 nil = ATOMnilptr(t);
692 if (t >= TYPE_str && ATOMstorage(t) >= TYPE_str) {
693 p1 = *(ptr *)p1;
694 p2 = *(ptr *)p2;
695 }
696 if (ATOMcmp(t, p1, nil) == 0 ||
697 (ATOMcmp(t, p2, nil) != 0 && ATOMcmp(t, p1, p2) > 0))
698 p1 = p2;
699 if (VALinit(&stk->stk[getArg(pci, 0)], t, p1) == NULL)
700 return mythrow(MAL, "calc.min", SQLSTATE(HY001) MAL_MALLOC_FAIL);
701 return MAL_SUCCEED;
702}
703
704mal_export str CALCmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p);
705
706str
707CALCmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
708{
709 int t = getArgType(mb, pci, 1);
710 const void *p1 = getArgReference(stk, pci, 1);
711 const void *p2 = getArgReference(stk, pci, 2);
712 const void *nil;
713
714 (void) cntxt;
715 if (t != getArgType(mb, pci, 2))
716 return mythrow(MAL, "calc.max", SEMANTIC_TYPE_MISMATCH);
717 nil = ATOMnilptr(t);
718 if (t >= TYPE_str && ATOMstorage(t) >= TYPE_str) {
719 p1 = *(ptr *)p1;
720 p2 = *(ptr *)p2;
721 }
722 if (ATOMcmp(t, p1, nil) == 0 || ATOMcmp(t, p2, nil) == 0)
723 p1 = nil;
724 else if (ATOMcmp(t, p1, p2) < 0)
725 p1 = p2;
726 if (VALinit(&stk->stk[getArg(pci, 0)], t, p1) == NULL)
727 return mythrow(MAL, "calc.max", SQLSTATE(HY001) MAL_MALLOC_FAIL);
728 return MAL_SUCCEED;
729}
730
731mal_export str CALCmax_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p);
732
733str
734CALCmax_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
735{
736 int t = getArgType(mb, pci, 1);
737 ptr p1 = getArgReference(stk, pci, 1);
738 ptr p2 = getArgReference(stk, pci, 2);
739 const void *nil;
740
741 (void) cntxt;
742 if (t != getArgType(mb, pci, 2))
743 return mythrow(MAL, "calc.max", SEMANTIC_TYPE_MISMATCH);
744 nil = ATOMnilptr(t);
745 if (t >= TYPE_str && ATOMstorage(t) >= TYPE_str) {
746 p1 = *(ptr *)p1;
747 p2 = *(ptr *)p2;
748 }
749 if (ATOMcmp(t, p1, nil) == 0 ||
750 (ATOMcmp(t, p2, nil) != 0 && ATOMcmp(t, p1, p2) < 0))
751 p1 = p2;
752 if (VALinit(&stk->stk[getArg(pci, 0)], t, p1) == NULL)
753 return mythrow(MAL, "calc.max", SQLSTATE(HY001) MAL_MALLOC_FAIL);
754 return MAL_SUCCEED;
755}
756
757static str
758CMDBATsumprod(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,
759 gdk_return (*sumprod)(void *, int, BAT *, BAT *, bool, bool, bool),
760 const char *func)
761{
762 ValPtr ret = &stk->stk[getArg(pci, 0)];
763 bat bid = * getArgReference_bat(stk, pci, 1);
764 BAT *b;
765 BAT *s = NULL;
766 bool nil_if_empty = true;
767 gdk_return r;
768
769 if ((b = BATdescriptor(bid)) == NULL)
770 throw(MAL, func, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
771 if (pci->argc >= 3) {
772 if (getArgType(mb, pci, 2) == TYPE_bit) {
773 assert(pci->argc == 3);
774 nil_if_empty = * getArgReference_bit(stk, pci, 2);
775 } else {
776 bat sid = * getArgReference_bat(stk, pci, 2);
777 if ((s = BATdescriptor(sid)) == NULL) {
778 BBPunfix(b->batCacheid);
779 throw(MAL, func, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
780 }
781 if (pci->argc >= 4) {
782 assert(pci->argc == 4);
783 assert(getArgType(mb, pci, 3) == TYPE_bit);
784 nil_if_empty = * getArgReference_bit(stk, pci, 3);
785 }
786 }
787 }
788 r = (*sumprod)(VALget(ret), ret->vtype, b, s, true, true, nil_if_empty);
789 BBPunfix(b->batCacheid);
790 if (s)
791 BBPunfix(s->batCacheid);
792 if (r != GDK_SUCCEED)
793 return mythrow(MAL, func, OPERATION_FAILED);
794 return MAL_SUCCEED;
795}
796
797mal_export str CMDBATsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
798
799str
800CMDBATsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
801{
802 (void) cntxt;
803
804 return CMDBATsumprod(mb, stk, pci, BATsum, "aggr.sum");
805}
806
807mal_export str CMDBATprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
808
809str
810CMDBATprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
811{
812 (void) cntxt;
813
814 return CMDBATsumprod(mb, stk, pci, BATprod, "aggr.prod");
815}
816
817mal_export str CMDBATstr_group_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
818
819str
820CMDBATstr_group_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
821{
822 ValPtr ret = &stk->stk[getArg(pci, 0)];
823 bat bid = * getArgReference_bat(stk, pci, 1), ssid = 0;
824 BAT *b, *s = NULL, *sep = NULL;
825 BATiter bi;
826 bool nil_if_empty = true;
827 int next_argument = 2;
828 str separator = ",";
829 gdk_return r;
830
831 (void) cntxt;
832
833 if ((b = BATdescriptor(bid)) == NULL)
834 throw(MAL, "aggr.str_group_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
835
836 if (isaBatType(getArgType(mb, pci, 2))) {
837 ssid = * getArgReference_bat(stk, pci, 2);
838 if ((sep = BATdescriptor(ssid)) == NULL) {
839 BBPunfix(b->batCacheid);
840 throw(MAL, "aggr.str_group_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
841 }
842 if(sep->ttype == TYPE_str) { /* the separator bat */
843 next_argument = 3;
844 bi = bat_iterator(sep);
845 separator = BUNtvar(bi, 0);
846 }
847 }
848
849 if (pci->argc >= (next_argument + 1)) {
850 if (getArgType(mb, pci, next_argument) == TYPE_bit) {
851 assert(pci->argc == (next_argument + 1));
852 nil_if_empty = * getArgReference_bit(stk, pci, next_argument);
853 } else {
854 if(next_argument == 3) {
855 bat sid = * getArgReference_bat(stk, pci, next_argument);
856 if ((s = BATdescriptor(sid)) == NULL) {
857 BBPunfix(b->batCacheid);
858 BBPunfix(sep->batCacheid);
859 throw(MAL, "aggr.str_group_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
860 }
861 } else {
862 s = sep;
863 sep = NULL;
864 }
865 if (pci->argc >= (next_argument + 2)) {
866 assert(pci->argc == (next_argument + 2));
867 assert(getArgType(mb, pci, (next_argument + 1)) == TYPE_bit);
868 nil_if_empty = * getArgReference_bit(stk, pci, (next_argument + 1));
869 }
870 }
871 }
872
873 r = BATstr_group_concat(ret, b, s, true, true, nil_if_empty, separator);
874 BBPunfix(b->batCacheid);
875 if (sep)
876 BBPunfix(sep->batCacheid);
877 if (s)
878 BBPunfix(s->batCacheid);
879 if (r != GDK_SUCCEED)
880 return mythrow(MAL, "aggr.str_group_concat", OPERATION_FAILED);
881 return MAL_SUCCEED;
882}
883