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 | |
15 | static str |
16 | mythrow(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 | |
37 | mal_export str CMDvarSUBsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
38 | |
39 | str |
40 | CMDvarSUBsignal(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 | |
50 | mal_export str CMDvarSUB(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
51 | |
52 | str |
53 | CMDvarSUB(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 | |
63 | mal_export str CMDvarADDsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
64 | |
65 | str |
66 | CMDvarADDsignal(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 | |
76 | mal_export str CMDvarADD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
77 | |
78 | str |
79 | CMDvarADD(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 | |
89 | mal_export str CMDvarADDstr(str *ret, str *s1, str *s2); |
90 | |
91 | str |
92 | CMDvarADDstr(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 | |
112 | mal_export str CMDvarADDstrint(str *ret, str *s1, int *i); |
113 | |
114 | str |
115 | CMDvarADDstrint(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 | |
135 | mal_export str CMDvarMULsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
136 | |
137 | str |
138 | CMDvarMULsignal(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 | |
148 | mal_export str CMDvarMUL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
149 | |
150 | str |
151 | CMDvarMUL(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 | |
161 | mal_export str CMDvarDIVsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
162 | |
163 | str |
164 | CMDvarDIVsignal(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 | |
174 | mal_export str CMDvarDIV(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
175 | |
176 | str |
177 | CMDvarDIV(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 | |
187 | mal_export str CMDvarMODsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
188 | |
189 | str |
190 | CMDvarMODsignal(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 | |
200 | mal_export str CMDvarMOD(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
201 | |
202 | str |
203 | CMDvarMOD(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 | |
213 | mal_export str CMDvarLSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
214 | |
215 | str |
216 | CMDvarLSHsignal(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 | |
226 | mal_export str CMDvarLSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
227 | |
228 | str |
229 | CMDvarLSH(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 | |
239 | mal_export str CMDvarRSHsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
240 | |
241 | str |
242 | CMDvarRSHsignal(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 | |
252 | mal_export str CMDvarRSH(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
253 | |
254 | str |
255 | CMDvarRSH(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 | |
265 | mal_export str CMDvarAND(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
266 | |
267 | str |
268 | CMDvarAND(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 | |
278 | mal_export str CMDvarOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
279 | |
280 | str |
281 | CMDvarOR(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 | |
291 | mal_export str CMDvarXOR(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
292 | |
293 | str |
294 | CMDvarXOR(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 | |
304 | mal_export str CMDvarLT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
305 | |
306 | str |
307 | CMDvarLT(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 | |
317 | mal_export str CMDvarLE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
318 | |
319 | str |
320 | CMDvarLE(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 | |
330 | mal_export str CMDvarGT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
331 | |
332 | str |
333 | CMDvarGT(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 | |
343 | mal_export str CMDvarGE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
344 | |
345 | str |
346 | CMDvarGE(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 | |
356 | mal_export str CMDvarEQ(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
357 | |
358 | str |
359 | CMDvarEQ(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 | |
373 | mal_export str CMDvarNE(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
374 | |
375 | str |
376 | CMDvarNE(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 | |
390 | mal_export str CMDvarCMP(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
391 | |
392 | str |
393 | CMDvarCMP(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 | |
403 | mal_export str CMDvarBETWEEN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
404 | |
405 | str |
406 | CMDvarBETWEEN(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 | |
422 | mal_export str CMDstrlength(int *ret, str *v); |
423 | |
424 | str |
425 | CMDstrlength(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 | |
435 | mal_export str CMDvarCONVERT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
436 | |
437 | str |
438 | CMDvarCONVERT(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 | |
452 | mal_export str CMDvarCONVERTptr(ptr *ret, ptr *v); |
453 | |
454 | str |
455 | CMDvarCONVERTptr(ptr *ret, ptr *v) |
456 | { |
457 | *ret = *v; |
458 | return MAL_SUCCEED; |
459 | } |
460 | |
461 | mal_export str CMDvarISZERO(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
462 | |
463 | str |
464 | CMDvarISZERO(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 | |
478 | mal_export str CMDvarISNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
479 | |
480 | str |
481 | CMDvarISNIL(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 | |
495 | mal_export str CMDvarISNOTNIL(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
496 | |
497 | str |
498 | CMDvarISNOTNIL(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 | |
512 | mal_export str CMDvarNOT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
513 | |
514 | str |
515 | CMDvarNOT(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 | |
529 | mal_export str CMDvarABS(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
530 | |
531 | str |
532 | CMDvarABS(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 | |
546 | mal_export str CMDvarSIGN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
547 | |
548 | str |
549 | CMDvarSIGN(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 | |
563 | mal_export str CMDvarNEG(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
564 | |
565 | str |
566 | CMDvarNEG(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 | |
580 | mal_export str CMDvarINCRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
581 | |
582 | str |
583 | CMDvarINCRsignal(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 | |
597 | mal_export str CMDvarDECRsignal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
598 | |
599 | str |
600 | CMDvarDECRsignal(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 | |
614 | mal_export str CALCswitchbit(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
615 | |
616 | str |
617 | CALCswitchbit(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 | |
651 | mal_export str CALCmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
652 | |
653 | str |
654 | CALCmin(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 | |
678 | mal_export str CALCmin_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
679 | |
680 | str |
681 | CALCmin_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 | |
704 | mal_export str CALCmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
705 | |
706 | str |
707 | CALCmax(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 | |
731 | mal_export str CALCmax_no_nil(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
732 | |
733 | str |
734 | CALCmax_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 | |
757 | static str |
758 | CMDBATsumprod(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 | |
797 | mal_export str CMDBATsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
798 | |
799 | str |
800 | CMDBATsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
801 | { |
802 | (void) cntxt; |
803 | |
804 | return CMDBATsumprod(mb, stk, pci, BATsum, "aggr.sum" ); |
805 | } |
806 | |
807 | mal_export str CMDBATprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
808 | |
809 | str |
810 | CMDBATprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
811 | { |
812 | (void) cntxt; |
813 | |
814 | return CMDBATsumprod(mb, stk, pci, BATprod, "aggr.prod" ); |
815 | } |
816 | |
817 | mal_export str CMDBATstr_group_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); |
818 | |
819 | str |
820 | CMDBATstr_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 | |