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_mem.h"
15 : #include "sql_stack.h"
16 : #include "sql_statement.h"
17 : #include "sql_gencode.h"
18 : #include "rel_rel.h"
19 : #include "rel_exp.h"
20 : #include "rel_prop.h"
21 :
22 : #include "mal_namespace.h"
23 : #include "mal_builder.h"
24 : #include "opt_prelude.h"
25 :
26 : /*
27 : * Some utility routines to generate code
28 : * The equality operator in MAL is '==' instead of '='.
29 : */
30 : static const char *
31 17929 : convertMultiplexMod(const char *mod, const char *op)
32 : {
33 17929 : if (strcmp(op, "=") == 0)
34 0 : return "calc";
35 : return mod;
36 : }
37 :
38 : static const char *
39 255856 : convertMultiplexFcn(const char *op)
40 : {
41 255856 : if (strcmp(op, "=") == 0)
42 32784 : return "==";
43 : return op;
44 : }
45 :
46 : static InstrPtr
47 17852 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
48 : {
49 17852 : InstrPtr q = NULL;
50 :
51 17852 : q = newStmt(mb, malRef, multiplexRef);
52 17852 : if (q == NULL)
53 : return NULL;
54 17852 : setVarType(mb, getArg(q, 0), newBatType(rtype));
55 17852 : q = pushStr(mb, q, convertMultiplexMod(mod, name));
56 17852 : q = pushStr(mb, q, convertMultiplexFcn(name));
57 17852 : q = pushArgument(mb, q, o1);
58 17852 : q = pushArgument(mb, q, o2);
59 17852 : pushInstruction(mb, q);
60 17852 : return q;
61 : }
62 :
63 : static InstrPtr
64 50933 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
65 : {
66 50933 : InstrPtr q = NULL;
67 :
68 50933 : if (o1 == NULL || o1->nr < 0)
69 : return NULL;
70 50933 : q = newStmt(mb, mod, name);
71 50933 : q = pushArgument(mb, q, o1->nr);
72 50933 : pushInstruction(mb, q);
73 50933 : return q;
74 : }
75 :
76 : static InstrPtr
77 180466 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
78 : {
79 180466 : InstrPtr q = NULL;
80 :
81 180466 : if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
82 : return NULL;
83 180466 : q = newStmt(mb, mod, name);
84 180466 : q = pushArgument(mb, q, o1->nr);
85 180466 : q = pushArgument(mb, q, o2->nr);
86 180466 : pushInstruction(mb, q);
87 180466 : return q;
88 : }
89 :
90 : static InstrPtr
91 268 : pushPtr(MalBlkPtr mb, InstrPtr q, ptr val)
92 : {
93 268 : int _t;
94 268 : ValRecord cst;
95 :
96 268 : if (q == NULL || mb->errors)
97 : return q;
98 268 : cst.vtype= TYPE_ptr;
99 268 : cst.val.pval = val;
100 268 : cst.len = 0;
101 268 : _t = defConstant(mb, TYPE_ptr, &cst);
102 268 : if( _t >= 0)
103 268 : return pushArgument(mb, q, _t);
104 : return q;
105 : }
106 :
107 : static InstrPtr
108 2062487 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
109 : {
110 2062487 : if (t->s)
111 2062487 : return pushArgument(mb, q, getStrConstant(mb,t->s->base.name));
112 : else
113 0 : return pushNil(mb, q, TYPE_str);
114 : }
115 :
116 : int
117 0 : stmt_key(stmt *s)
118 : {
119 0 : const char *nme = column_name(NULL, s);
120 :
121 0 : return hash_key(nme);
122 : }
123 :
124 : /* #TODO make proper traversal operations */
125 : stmt *
126 209 : stmt_atom_string(backend *be, const char *S)
127 : {
128 209 : const char *s = sa_strdup(be->mvc->sa, S);
129 209 : sql_subtype t;
130 :
131 209 : if (s == NULL)
132 : return NULL;
133 209 : sql_find_subtype(&t, "varchar", _strlen(s), 0);
134 209 : return stmt_atom(be, atom_string(be->mvc->sa, &t, s));
135 : }
136 :
137 : stmt *
138 19458 : stmt_atom_string_nil(backend *be)
139 : {
140 19458 : sql_subtype t;
141 :
142 19458 : sql_find_subtype(&t, "varchar", 0, 0);
143 19458 : return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
144 : }
145 :
146 : stmt *
147 5814 : stmt_atom_int(backend *be, int i)
148 : {
149 5814 : sql_subtype t;
150 :
151 5814 : sql_find_subtype(&t, "int", 32, 0);
152 5814 : return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
153 : }
154 :
155 : stmt *
156 106661 : stmt_atom_lng(backend *be, lng i)
157 : {
158 106661 : sql_subtype t;
159 :
160 106661 : sql_find_subtype(&t, "bigint", 64, 0);
161 106658 : return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
162 : }
163 :
164 : stmt *
165 26 : stmt_atom_lng_nil(backend *be)
166 : {
167 26 : sql_subtype t;
168 :
169 26 : sql_find_subtype(&t, "bigint", 64, 0);
170 26 : return stmt_atom(be, atom_general(be->mvc->sa, &t, NULL, 0));
171 : }
172 :
173 : stmt *
174 40415 : stmt_bool(backend *be, int b)
175 : {
176 40415 : sql_subtype t;
177 :
178 40415 : sql_find_subtype(&t, "boolean", 0, 0);
179 :
180 40415 : if (b == bit_nil) {
181 0 : return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
182 40415 : } else if (b) {
183 39286 : return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
184 : } else {
185 1129 : return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
186 : }
187 : }
188 :
189 : static stmt *
190 17433551 : stmt_create(allocator *sa, st_type type)
191 : {
192 17433551 : stmt *s = SA_NEW(sa, stmt);
193 :
194 17433297 : if (!s)
195 : return NULL;
196 17433297 : *s = (stmt) {
197 : .type = type,
198 : };
199 17433297 : return s;
200 : }
201 :
202 : stmt *
203 27773 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
204 : {
205 27773 : MalBlkPtr mb = be->mb;
206 27773 : InstrPtr q = NULL;
207 :
208 27773 : if (s == NULL || s->nr < 0)
209 0 : goto bailout;
210 27773 : if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
211 0 : goto bailout;
212 :
213 27773 : q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
214 27773 : if (q == NULL)
215 0 : goto bailout;
216 :
217 : /* output variables extent and hist */
218 27773 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
219 27773 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
220 27773 : q = pushArgument(mb, q, s->nr);
221 27773 : if (grp)
222 6188 : q = pushArgument(mb, q, grp->nr);
223 :
224 27773 : bool enabled = be->mvc->sa->eb.enabled;
225 27773 : be->mvc->sa->eb.enabled = false;
226 27773 : stmt *ns = stmt_create(be->mvc->sa, st_group);
227 27773 : be->mvc->sa->eb.enabled = enabled;
228 27773 : if (ns == NULL) {
229 0 : freeInstruction(q);
230 0 : goto bailout;
231 : }
232 :
233 27773 : ns->op1 = s;
234 :
235 27773 : if (grp) {
236 6188 : ns->op2 = grp;
237 6188 : ns->op3 = ext;
238 6188 : ns->op4.stval = cnt;
239 : }
240 27773 : ns->nrcols = s->nrcols;
241 27773 : ns->key = 0;
242 27773 : ns->q = q;
243 27773 : ns->nr = getDestVar(q);
244 27773 : pushInstruction(mb, q);
245 27773 : return ns;
246 :
247 0 : bailout:
248 0 : if (be->mvc->sa->eb.enabled)
249 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
250 : return NULL;
251 : }
252 :
253 : stmt *
254 76 : stmt_unique(backend *be, stmt *s)
255 : {
256 76 : MalBlkPtr mb = be->mb;
257 76 : InstrPtr q = NULL;
258 :
259 76 : if (s == NULL || s->nr < 0)
260 0 : goto bailout;
261 :
262 76 : q = newStmt(mb, algebraRef, uniqueRef);
263 76 : if (q == NULL)
264 0 : goto bailout;
265 :
266 76 : q = pushArgument(mb, q, s->nr);
267 76 : q = pushNilBat(mb, q); /* candidate list */
268 :
269 76 : bool enabled = be->mvc->sa->eb.enabled;
270 76 : be->mvc->sa->eb.enabled = false;
271 76 : stmt *ns = stmt_create(be->mvc->sa, st_unique);
272 76 : be->mvc->sa->eb.enabled = enabled;
273 76 : if (ns == NULL) {
274 0 : freeInstruction(q);
275 0 : goto bailout;
276 : }
277 :
278 76 : ns->op1 = s;
279 76 : ns->nrcols = s->nrcols;
280 76 : ns->key = 1;
281 76 : ns->q = q;
282 76 : ns->nr = getDestVar(q);
283 76 : pushInstruction(mb, q);
284 76 : return ns;
285 :
286 0 : bailout:
287 0 : if (be->mvc->sa->eb.enabled)
288 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
289 : return NULL;
290 : }
291 :
292 : stmt *
293 0 : stmt_none(backend *be)
294 : {
295 0 : return stmt_create(be->mvc->sa, st_none);
296 : }
297 :
298 : static int
299 55 : create_bat(MalBlkPtr mb, int tt)
300 : {
301 55 : InstrPtr q = newStmt(mb, batRef, newRef);
302 :
303 55 : if (q == NULL)
304 : return -1;
305 55 : setVarType(mb, getArg(q, 0), newBatType(tt));
306 55 : q = pushType(mb, q, tt);
307 55 : pushInstruction(mb, q);
308 55 : return getDestVar(q);
309 : }
310 :
311 : static int *
312 20 : dump_table(allocator *sa, MalBlkPtr mb, sql_table *t)
313 : {
314 20 : int i = 0;
315 20 : node *n;
316 20 : int *l = SA_NEW_ARRAY(sa, int, ol_length(t->columns) + 1);
317 :
318 20 : if (!l)
319 : return NULL;
320 :
321 : /* tid column */
322 20 : if ((l[i++] = create_bat(mb, TYPE_oid)) < 0)
323 : return NULL;
324 :
325 55 : for (n = ol_first_node(t->columns); n; n = n->next) {
326 35 : sql_column *c = n->data;
327 :
328 35 : if ((l[i++] = create_bat(mb, c->type.type->localtype)) < 0)
329 : return NULL;
330 : }
331 : return l;
332 : }
333 :
334 : stmt *
335 2776 : stmt_var(backend *be, const char *sname, const char *varname, sql_subtype *t, int declare, int level)
336 : {
337 2776 : MalBlkPtr mb = be->mb;
338 2776 : InstrPtr q = NULL;
339 2776 : char *buf;
340 :
341 2776 : if (level == 0) { /* global */
342 433 : int tt = t->type->localtype;
343 :
344 433 : assert(sname);
345 433 : q = newStmt(mb, sqlRef, getVariableRef);
346 433 : if (q == NULL)
347 0 : goto bailout;
348 433 : q = pushArgument(mb, q, be->mvc_var);
349 433 : q = pushStr(mb, q, sname); /* all global variables have a schema */
350 433 : q = pushStr(mb, q, varname);
351 433 : setVarType(mb, getArg(q, 0), tt);
352 2343 : } else if (!declare) {
353 1954 : char levelstr[16];
354 :
355 1954 : assert(!sname);
356 1954 : snprintf(levelstr, sizeof(levelstr), "%d", level);
357 1954 : buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
358 1954 : if (!buf)
359 1 : goto bailout;
360 1954 : stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
361 1954 : q = newAssignment(mb);
362 1954 : if (q == NULL)
363 1 : goto bailout;
364 1953 : q = pushArgumentId(mb, q, buf);
365 : } else {
366 389 : int tt = t->type->localtype;
367 389 : char levelstr[16];
368 :
369 389 : assert(!sname);
370 389 : snprintf(levelstr, sizeof(levelstr), "%d", level);
371 389 : buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
372 389 : if (!buf)
373 0 : goto bailout;
374 389 : stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
375 :
376 389 : q = newInstruction(mb, NULL, NULL);
377 389 : if (q == NULL) {
378 0 : goto bailout;
379 : }
380 389 : q->argc = q->retc = 0;
381 389 : q = pushArgumentId(mb, q, buf);
382 389 : q = pushNil(mb, q, tt);
383 389 : q->retc++;
384 : }
385 2775 : bool enabled = be->mvc->sa->eb.enabled;
386 2775 : be->mvc->sa->eb.enabled = false;
387 2775 : stmt *s = stmt_create(be->mvc->sa, st_var);
388 2775 : be->mvc->sa->eb.enabled = enabled;
389 2775 : if (s == NULL) {
390 0 : freeInstruction(q);
391 0 : goto bailout;
392 : }
393 :
394 2775 : if (t)
395 2775 : s->op4.typeval = *t;
396 : else
397 0 : s->op4.typeval.type = NULL;
398 2775 : s->flag = declare + (level << 1);
399 2775 : s->key = 1;
400 2775 : s->q = q;
401 2775 : s->nr = getDestVar(q);
402 2775 : pushInstruction(mb, q);
403 2775 : return s;
404 :
405 1 : bailout:
406 1 : if (be->mvc->sa->eb.enabled)
407 1 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
408 : return NULL;
409 : }
410 :
411 : stmt *
412 20 : stmt_vars(backend *be, const char *varname, sql_table *t, int declare, int level)
413 : {
414 20 : MalBlkPtr mb = be->mb;
415 20 : int *l;
416 :
417 20 : (void)varname;
418 : /* declared table */
419 20 : if ((l = dump_table(be->mvc->sa, mb, t)) != NULL) {
420 20 : stmt *s = stmt_create(be->mvc->sa, st_var);
421 :
422 20 : if (s == NULL) {
423 : return NULL;
424 : }
425 :
426 20 : ATOMIC_PTR_SET(&t->data, l);
427 : /*
428 : s->op2 = (stmt*)l;
429 : s->op3 = (stmt*)t;
430 : */
431 20 : s->flag = declare + (level << 1);
432 20 : s->key = 1;
433 20 : s->nr = l[0];
434 20 : return s;
435 : }
436 0 : if (be->mvc->sa->eb.enabled)
437 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
438 : return NULL;
439 : }
440 :
441 : stmt *
442 2052 : stmt_varnr(backend *be, int nr, sql_subtype *t)
443 : {
444 2052 : MalBlkPtr mb = be->mb;
445 2052 : InstrPtr q = newAssignment(mb);
446 2052 : char buf[IDLENGTH];
447 :
448 2052 : if (q == NULL)
449 0 : goto bailout;
450 :
451 2052 : (void) snprintf(buf, sizeof(buf), "A%d", nr);
452 2052 : q = pushArgumentId(mb, q, buf);
453 :
454 2052 : bool enabled = be->mvc->sa->eb.enabled;
455 2052 : be->mvc->sa->eb.enabled = false;
456 2052 : stmt *s = stmt_create(be->mvc->sa, st_var);
457 2052 : be->mvc->sa->eb.enabled = enabled;
458 2052 : if (s == NULL) {
459 0 : freeInstruction(q);
460 0 : goto bailout;
461 : }
462 :
463 2052 : s->op1 = NULL;
464 2052 : if (t)
465 2052 : s->op4.typeval = *t;
466 : else
467 0 : s->op4.typeval.type = NULL;
468 2052 : s->flag = nr;
469 2052 : s->key = 1;
470 2052 : s->q = q;
471 2052 : s->nr = getDestVar(q);
472 2052 : pushInstruction(mb, q);
473 2052 : return s;
474 :
475 0 : bailout:
476 0 : if (be->mvc->sa->eb.enabled)
477 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
478 : return NULL;
479 : }
480 :
481 : stmt *
482 688 : stmt_table(backend *be, stmt *cols, int temp)
483 : {
484 688 : MalBlkPtr mb = be->mb;
485 :
486 688 : if (cols == NULL || cols->nr < 0)
487 0 : goto bailout;
488 :
489 688 : stmt *s = stmt_create(be->mvc->sa, st_table);
490 :
491 688 : if (s == NULL)
492 0 : goto bailout;
493 :
494 688 : if (cols->type != st_list) {
495 0 : InstrPtr q = newAssignment(mb);
496 0 : if (q == NULL)
497 0 : goto bailout;
498 0 : pushInstruction(mb, q);
499 0 : q = newStmt(mb, sqlRef, printRef);
500 0 : if (q == NULL)
501 0 : goto bailout;
502 0 : q = pushStr(mb, q, "not a valid output list\n");
503 0 : pushInstruction(mb, q);
504 : }
505 688 : s->op1 = cols;
506 688 : s->flag = temp;
507 688 : s->nr = cols->nr;
508 688 : s->nrcols = cols->nrcols;
509 688 : return s;
510 :
511 0 : bailout:
512 0 : if (be->mvc->sa->eb.enabled)
513 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
514 : return NULL;
515 : }
516 :
517 : stmt *
518 223154 : stmt_temp(backend *be, sql_subtype *t)
519 : {
520 223154 : int tt = t->type->localtype;
521 223154 : MalBlkPtr mb = be->mb;
522 223154 : InstrPtr q = newStmt(mb, batRef, newRef);
523 :
524 223207 : if (q == NULL)
525 0 : goto bailout;
526 223207 : setVarType(mb, getArg(q, 0), newBatType(tt));
527 223207 : q = pushType(mb, q, tt);
528 223197 : bool enabled = be->mvc->sa->eb.enabled;
529 223197 : be->mvc->sa->eb.enabled = false;
530 223197 : stmt *s = stmt_create(be->mvc->sa, st_temp);
531 223185 : be->mvc->sa->eb.enabled = enabled;
532 :
533 223185 : if (s == NULL) {
534 0 : freeInstruction(q);
535 0 : goto bailout;
536 : }
537 223185 : s->op4.typeval = *t;
538 223185 : s->nrcols = 1;
539 223185 : s->q = q;
540 223185 : s->nr = getDestVar(q);
541 223185 : pushInstruction(mb, q);
542 223185 : return s;
543 :
544 0 : bailout:
545 0 : if (be->mvc->sa->eb.enabled)
546 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
547 : return NULL;
548 : }
549 :
550 : stmt *
551 216 : stmt_blackbox_result(backend *be, InstrPtr q, int retnr, sql_subtype *t)
552 : {
553 216 : if (q == NULL)
554 : return NULL;
555 216 : stmt *s = stmt_create(be->mvc->sa, st_result);
556 216 : if (s == NULL)
557 : return NULL;
558 216 : s->op4.typeval = *t;
559 216 : s->nrcols = 1;
560 216 : s->q = q;
561 216 : s->nr = getArg(q, retnr);
562 216 : s->flag = retnr;
563 216 : return s;
564 : }
565 :
566 :
567 : stmt *
568 203361 : stmt_tid(backend *be, sql_table *t, int partition)
569 : {
570 203361 : int tt = TYPE_oid;
571 203361 : MalBlkPtr mb = be->mb;
572 203361 : InstrPtr q;
573 :
574 203361 : if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
575 16 : stmt *s = stmt_create(be->mvc->sa, st_tid);
576 16 : int *l = ATOMIC_PTR_GET(&t->data);
577 :
578 16 : if (s == NULL) {
579 0 : goto bailout;
580 : }
581 16 : assert(partition == 0);
582 16 : s->partition = partition;
583 16 : s->op4.tval = t;
584 16 : s->nrcols = 1;
585 16 : s->nr = l[0];
586 16 : return s;
587 : }
588 203345 : q = newStmt(mb, sqlRef, tidRef);
589 203343 : if (q == NULL)
590 0 : goto bailout;
591 203343 : setVarType(mb, getArg(q, 0), newBatType(tt));
592 203343 : q = pushArgument(mb, q, be->mvc_var);
593 203345 : q = pushSchema(mb, q, t);
594 203345 : q = pushStr(mb, q, t->base.name);
595 203344 : if (t && isTable(t) && partition) {
596 75833 : sql_trans *tr = be->mvc->session->tr;
597 75833 : sqlstore *store = tr->store;
598 75833 : BUN rows = (BUN) store->storage_api.count_col(tr, ol_first_node(t->columns)->data, RDONLY);
599 75833 : setRowCnt(mb,getArg(q,0),rows);
600 : }
601 :
602 203344 : bool enabled = be->mvc->sa->eb.enabled;
603 203344 : be->mvc->sa->eb.enabled = false;
604 203344 : stmt *s = stmt_create(be->mvc->sa, st_tid);
605 203344 : be->mvc->sa->eb.enabled = enabled;
606 203344 : if (s == NULL) {
607 0 : freeInstruction(q);
608 0 : goto bailout;
609 : }
610 :
611 203344 : s->partition = partition;
612 203344 : s->op4.tval = t;
613 203344 : s->nrcols = 1;
614 203344 : s->nr = getDestVar(q);
615 203344 : s->q = q;
616 203344 : pushInstruction(mb, q);
617 203344 : return s;
618 :
619 0 : bailout:
620 0 : if (be->mvc->sa->eb.enabled)
621 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
622 : return NULL;
623 : }
624 :
625 : static sql_column *
626 988100 : find_real_column(backend *be, sql_column *c)
627 : {
628 988100 : if (c && c->t && c->t->s && c->t->persistence == SQL_DECLARED_TABLE) {
629 36780 : sql_table *nt = find_sql_table_id(be->mvc->session->tr, c->t->s, c->t->base.id);
630 36780 : if (nt) {
631 36780 : node *n = ol_find_id(nt->columns, c->base.id);
632 36780 : if (n)
633 36780 : return n->data;
634 : }
635 : }
636 : return c;
637 : }
638 :
639 : stmt *
640 988099 : stmt_bat(backend *be, sql_column *c, int access, int partition)
641 : {
642 988099 : int tt = c->type.type->localtype;
643 988099 : MalBlkPtr mb = be->mb;
644 988099 : InstrPtr q;
645 :
646 988099 : c = find_real_column(be, c);
647 :
648 988102 : if (access == RD_EXT)
649 176 : partition = 0;
650 :
651 : /* for read access tid.project(col) */
652 988102 : if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
653 23 : stmt *s = stmt_create(be->mvc->sa, st_bat);
654 23 : int *l = ATOMIC_PTR_GET(&c->t->data);
655 :
656 23 : if (s == NULL) {
657 0 : goto bailout;
658 : }
659 23 : assert(partition == 0);
660 23 : s->partition = partition;
661 23 : s->op4.cval = c;
662 23 : s->nrcols = 1;
663 23 : s->flag = access;
664 23 : s->nr = l[c->colnr+1];
665 23 : s->tname = c->t?c->t->base.name:NULL;
666 23 : s->cname = c->base.name;
667 23 : return s;
668 : }
669 988079 : q = newStmtArgs(mb, sqlRef, bindRef, 9);
670 988070 : if (q == NULL)
671 0 : goto bailout;
672 988070 : if (c->storage_type && access != RD_EXT) {
673 368 : sql_trans *tr = be->mvc->session->tr;
674 368 : sqlstore *store = tr->store;
675 368 : BAT *b = store->storage_api.bind_col(tr, c, QUICK);
676 368 : if (!b) {
677 0 : freeInstruction(q);
678 0 : goto bailout;
679 : }
680 368 : tt = b->ttype;
681 : }
682 987894 : if (access == RD_UPD_ID) {
683 480097 : q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
684 : } else {
685 507973 : setVarType(mb, getArg(q, 0), newBatType(tt));
686 : }
687 988075 : q = pushArgument(mb, q, be->mvc_var);
688 988081 : q = pushSchema(mb, q, c->t);
689 988077 : q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
690 988061 : q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
691 988072 : q = pushArgument(mb, q, getIntConstant(mb,access));
692 :
693 988065 : if (access == RD_UPD_ID) {
694 480097 : setVarType(mb, getArg(q, 1), newBatType(tt));
695 : }
696 988065 : if (partition) {
697 546903 : sql_trans *tr = be->mvc->session->tr;
698 546903 : sqlstore *store = tr->store;
699 :
700 546903 : if (c && isTable(c->t)) {
701 546902 : BUN rows = (BUN) store->storage_api.count_col(tr, c, RDONLY);
702 546926 : setRowCnt(mb,getArg(q,0),rows);
703 : }
704 : }
705 :
706 988089 : bool enabled = be->mvc->sa->eb.enabled;
707 988089 : be->mvc->sa->eb.enabled = false;
708 988089 : stmt *s = stmt_create(be->mvc->sa, st_bat);
709 988083 : be->mvc->sa->eb.enabled = enabled;
710 988083 : if (s == NULL) {
711 0 : freeInstruction(q);
712 0 : goto bailout;
713 : }
714 :
715 988083 : s->partition = partition;
716 988083 : s->op4.cval = c;
717 988083 : s->nrcols = 1;
718 988083 : s->flag = access;
719 988083 : s->nr = getDestVar(q);
720 988083 : s->q = q;
721 988083 : s->tname = c->t->base.name;
722 988083 : s->cname = c->base.name;
723 988083 : pushInstruction(mb, q);
724 988083 : return s;
725 :
726 0 : bailout:
727 0 : if (be->mvc->sa->eb.enabled)
728 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
729 : return NULL;
730 : }
731 :
732 : stmt *
733 6467 : stmt_idxbat(backend *be, sql_idx *i, int access, int partition)
734 : {
735 6467 : int tt = hash_index(i->type)?TYPE_lng:TYPE_oid;
736 6467 : MalBlkPtr mb = be->mb;
737 6467 : InstrPtr q = newStmtArgs(mb, sqlRef, bindidxRef, 9);
738 :
739 6467 : if (q == NULL)
740 0 : goto bailout;
741 :
742 6467 : if (access == RD_UPD_ID) {
743 2871 : q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
744 : } else {
745 3596 : setVarType(mb, getArg(q, 0), newBatType(tt));
746 : }
747 :
748 6467 : q = pushArgument(mb, q, be->mvc_var);
749 6467 : q = pushSchema(mb, q, i->t);
750 6467 : q = pushArgument(mb, q, getStrConstant(mb, i->t->base.name));
751 6467 : q = pushArgument(mb, q, getStrConstant(mb, i->base.name));
752 6467 : q = pushArgument(mb, q, getIntConstant(mb, access));
753 :
754 6467 : if (access == RD_UPD_ID) {
755 2871 : setVarType(mb, getArg(q, 1), newBatType(tt));
756 : }
757 6467 : if (partition) {
758 3550 : sql_trans *tr = be->mvc->session->tr;
759 3550 : sqlstore *store = tr->store;
760 :
761 3550 : if (i && isTable(i->t)) {
762 3550 : BUN rows = (BUN) store->storage_api.count_idx(tr, i, QUICK);
763 3550 : setRowCnt(mb,getArg(q,0),rows);
764 : }
765 : }
766 :
767 6467 : bool enabled = be->mvc->sa->eb.enabled;
768 6467 : be->mvc->sa->eb.enabled = false;
769 6467 : stmt *s = stmt_create(be->mvc->sa, st_idxbat);
770 6467 : be->mvc->sa->eb.enabled = enabled;
771 6467 : if (s == NULL) {
772 0 : freeInstruction(q);
773 0 : goto bailout;
774 : }
775 :
776 6467 : s->partition = partition;
777 6467 : s->op4.idxval = i;
778 6467 : s->nrcols = 1;
779 6467 : s->flag = access;
780 6467 : s->nr = getDestVar(q);
781 6467 : s->q = q;
782 6467 : s->tname = i->t->base.name;
783 6467 : s->cname = i->base.name;
784 6467 : pushInstruction(mb, q);
785 6467 : return s;
786 :
787 0 : bailout:
788 0 : if (be->mvc->sa->eb.enabled)
789 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
790 : return NULL;
791 : }
792 :
793 : stmt *
794 566833 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
795 : {
796 566833 : MalBlkPtr mb = be->mb;
797 566833 : InstrPtr q = NULL;
798 :
799 566833 : if (b == NULL || b->nr < 0)
800 0 : goto bailout;
801 :
802 566833 : if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
803 23 : int *l = ATOMIC_PTR_GET(&c->t->data);
804 :
805 23 : if (c->colnr == 0) { /* append to tid column */
806 18 : q = newStmt(mb, sqlRef, growRef);
807 18 : if (q == NULL)
808 0 : goto bailout;
809 18 : q = pushArgument(mb, q, l[0]);
810 18 : q = pushArgument(mb, q, b->nr);
811 18 : pushInstruction(mb, q);
812 : }
813 23 : q = newStmt(mb, batRef, appendRef);
814 23 : if (q == NULL)
815 0 : goto bailout;
816 23 : q = pushArgument(mb, q, l[c->colnr+1]);
817 23 : q = pushArgument(mb, q, b->nr);
818 23 : q = pushBit(mb, q, TRUE);
819 23 : getArg(q,0) = l[c->colnr+1];
820 566810 : } else if (!fake) { /* fake append */
821 566810 : if (offset == NULL || offset->nr < 0)
822 0 : goto bailout;
823 566810 : q = newStmt(mb, sqlRef, appendRef);
824 566826 : if (q == NULL)
825 0 : goto bailout;
826 566826 : q = pushArgument(mb, q, be->mvc_var);
827 566832 : int tmpvar = newTmpVariable(mb, TYPE_int);
828 566835 : getArg(q, 0) = tmpvar;
829 566835 : if (mvc_var_update != NULL)
830 566835 : *mvc_var_update = tmpvar;
831 566835 : q = pushSchema(mb, q, c->t);
832 566831 : q = pushStr(mb, q, c->t->base.name);
833 566837 : q = pushStr(mb, q, c->base.name);
834 566807 : q = pushArgument(mb, q, offset->nr);
835 : /* also the offsets */
836 566804 : assert(offset->q->retc == 2);
837 566804 : q = pushArgument(mb, q, getArg(offset->q, 1));
838 566805 : q = pushArgument(mb, q, b->nr);
839 566803 : if (mvc_var_update != NULL)
840 566803 : *mvc_var_update = getDestVar(q);
841 : } else {
842 : return b;
843 : }
844 566826 : bool enabled = be->mvc->sa->eb.enabled;
845 566826 : be->mvc->sa->eb.enabled = false;
846 566826 : stmt *s = stmt_create(be->mvc->sa, st_append_col);
847 566819 : be->mvc->sa->eb.enabled = enabled;
848 :
849 566819 : if (s == NULL) {
850 0 : freeInstruction(q);
851 0 : goto bailout;
852 : }
853 566819 : s->op1 = b;
854 566819 : s->op2 = offset;
855 566819 : s->op4.cval = c;
856 566819 : s->q = q;
857 566819 : s->nr = getDestVar(q);
858 566819 : pushInstruction(mb, q);
859 566819 : return s;
860 :
861 0 : bailout:
862 0 : if (be->mvc->sa->eb.enabled)
863 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
864 : return NULL;
865 : }
866 :
867 : stmt *
868 2220 : stmt_append_idx(backend *be, sql_idx *i, stmt *offset, stmt *b)
869 : {
870 2220 : MalBlkPtr mb = be->mb;
871 2220 : InstrPtr q = NULL;
872 :
873 2220 : if (offset == NULL || b == NULL || offset->nr < 0 || b->nr < 0)
874 0 : goto bailout;
875 :
876 2220 : q = newStmt(mb, sqlRef, appendRef);
877 2220 : if (q == NULL)
878 0 : goto bailout;
879 2220 : q = pushArgument(mb, q, be->mvc_var);
880 2220 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
881 2220 : q = pushSchema(mb, q, i->t);
882 2220 : q = pushStr(mb, q, i->t->base.name);
883 2220 : q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
884 2220 : q = pushArgument(mb, q, offset->nr);
885 : /* also the offsets */
886 2220 : assert(offset->q->retc == 2);
887 2220 : q = pushArgument(mb, q, getArg(offset->q, 1));
888 2220 : q = pushArgument(mb, q, b->nr);
889 2220 : be->mvc_var = getDestVar(q);
890 :
891 2220 : bool enabled = be->mvc->sa->eb.enabled;
892 2220 : be->mvc->sa->eb.enabled = false;
893 2220 : stmt *s = stmt_create(be->mvc->sa, st_append_idx);
894 2220 : be->mvc->sa->eb.enabled = enabled;
895 2220 : if (s == NULL) {
896 0 : freeInstruction(q);
897 0 : goto bailout;
898 : }
899 :
900 2220 : s->op1 = b;
901 2220 : s->op2 = offset;
902 2220 : s->op4.idxval = i;
903 2220 : s->q = q;
904 2220 : s->nr = getDestVar(q);
905 2220 : pushInstruction(mb, q);
906 2220 : return s;
907 :
908 0 : bailout:
909 0 : if (be->mvc->sa->eb.enabled)
910 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
911 : return NULL;
912 : }
913 :
914 : stmt *
915 3000 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
916 : {
917 3000 : MalBlkPtr mb = be->mb;
918 3000 : InstrPtr q = NULL;
919 :
920 3000 : if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
921 0 : goto bailout;
922 :
923 3001 : if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
924 1 : int *l = ATOMIC_PTR_GET(&c->t->data);
925 :
926 1 : q = newStmt(mb, batRef, replaceRef);
927 1 : if (q == NULL)
928 0 : goto bailout;
929 1 : q = pushArgument(mb, q, l[c->colnr+1]);
930 1 : q = pushArgument(mb, q, tids->nr);
931 1 : q = pushArgument(mb, q, upd->nr);
932 : } else {
933 2999 : q = newStmt(mb, sqlRef, updateRef);
934 2999 : if (q == NULL)
935 0 : goto bailout;
936 2999 : q = pushArgument(mb, q, be->mvc_var);
937 2999 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
938 2999 : q = pushSchema(mb, q, c->t);
939 2999 : q = pushStr(mb, q, c->t->base.name);
940 2999 : q = pushStr(mb, q, c->base.name);
941 2999 : q = pushArgument(mb, q, tids->nr);
942 2999 : q = pushArgument(mb, q, upd->nr);
943 2999 : be->mvc_var = getDestVar(q);
944 : }
945 3000 : bool enabled = be->mvc->sa->eb.enabled;
946 3000 : be->mvc->sa->eb.enabled = false;
947 3000 : stmt *s = stmt_create(be->mvc->sa, st_update_col);
948 3000 : be->mvc->sa->eb.enabled = enabled;
949 :
950 3000 : if (s == NULL) {
951 0 : freeInstruction(q);
952 0 : goto bailout;
953 : }
954 3000 : s->op1 = tids;
955 3000 : s->op2 = upd;
956 3000 : s->op4.cval = c;
957 3000 : s->q = q;
958 3000 : s->nr = getDestVar(q);
959 3000 : pushInstruction(mb, q);
960 3000 : return s;
961 :
962 0 : bailout:
963 0 : if (be->mvc->sa->eb.enabled)
964 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
965 : return NULL;
966 : }
967 :
968 :
969 : stmt *
970 823 : stmt_update_idx(backend *be, sql_idx *i, stmt *tids, stmt *upd)
971 : {
972 823 : MalBlkPtr mb = be->mb;
973 823 : InstrPtr q = NULL;
974 :
975 823 : if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
976 0 : goto bailout;
977 :
978 823 : q = newStmt(mb, sqlRef, updateRef);
979 823 : if (q == NULL)
980 0 : goto bailout;
981 823 : q = pushArgument(mb, q, be->mvc_var);
982 823 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
983 823 : q = pushSchema(mb, q, i->t);
984 823 : q = pushStr(mb, q, i->t->base.name);
985 823 : q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
986 823 : q = pushArgument(mb, q, tids->nr);
987 823 : q = pushArgument(mb, q, upd->nr);
988 823 : be->mvc_var = getDestVar(q);
989 823 : bool enabled = be->mvc->sa->eb.enabled;
990 823 : be->mvc->sa->eb.enabled = false;
991 823 : stmt *s = stmt_create(be->mvc->sa, st_update_idx);
992 823 : be->mvc->sa->eb.enabled = enabled;
993 823 : if (s == NULL) {
994 0 : freeInstruction(q);
995 0 : goto bailout;
996 : }
997 :
998 823 : s->op1 = tids;
999 823 : s->op2 = upd;
1000 823 : s->op4.idxval = i;
1001 823 : s->q = q;
1002 823 : s->nr = getDestVar(q);
1003 823 : pushInstruction(mb, q);
1004 823 : return s;
1005 :
1006 0 : bailout:
1007 0 : if (be->mvc->sa->eb.enabled)
1008 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1009 : return NULL;
1010 : }
1011 :
1012 : stmt *
1013 349 : stmt_delete(backend *be, sql_table *t, stmt *tids)
1014 : {
1015 349 : MalBlkPtr mb = be->mb;
1016 349 : InstrPtr q = NULL;
1017 :
1018 349 : if (tids == NULL || tids->nr < 0)
1019 0 : goto bailout;
1020 :
1021 350 : if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
1022 1 : int *l = ATOMIC_PTR_GET(&t->data);
1023 :
1024 1 : q = newStmt(mb, batRef, deleteRef);
1025 1 : if (q == NULL)
1026 0 : goto bailout;
1027 1 : q = pushArgument(mb, q, l[0]);
1028 1 : q = pushArgument(mb, q, tids->nr);
1029 : } else {
1030 348 : q = newStmt(mb, sqlRef, deleteRef);
1031 348 : if (q == NULL)
1032 0 : goto bailout;
1033 348 : q = pushArgument(mb, q, be->mvc_var);
1034 348 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
1035 348 : q = pushSchema(mb, q, t);
1036 348 : q = pushStr(mb, q, t->base.name);
1037 348 : q = pushArgument(mb, q, tids->nr);
1038 348 : be->mvc_var = getDestVar(q);
1039 : }
1040 349 : bool enabled = be->mvc->sa->eb.enabled;
1041 349 : be->mvc->sa->eb.enabled = false;
1042 349 : stmt *s = stmt_create(be->mvc->sa, st_delete);
1043 349 : be->mvc->sa->eb.enabled = enabled;
1044 349 : if (s == NULL) {
1045 0 : freeInstruction(q);
1046 0 : goto bailout;
1047 : }
1048 :
1049 349 : s->op1 = tids;
1050 349 : s->op4.tval = t;
1051 349 : s->q = q;
1052 349 : s->nr = getDestVar(q);
1053 349 : pushInstruction(mb, q);
1054 349 : return s;
1055 :
1056 0 : bailout:
1057 0 : if (be->mvc->sa->eb.enabled)
1058 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1059 : return NULL;
1060 : }
1061 :
1062 : stmt *
1063 123885 : stmt_const(backend *be, stmt *s, stmt *val)
1064 : {
1065 123885 : InstrPtr q = NULL;
1066 123885 : MalBlkPtr mb = be->mb;
1067 :
1068 123885 : if (s == NULL)
1069 0 : goto bailout;
1070 123885 : if (val)
1071 123885 : q = dump_2(mb, algebraRef, projectRef, s, val);
1072 : else
1073 0 : q = dump_1(mb, algebraRef, projectRef, s);
1074 123885 : if (q) {
1075 123885 : stmt *ns = stmt_create(be->mvc->sa, st_const);
1076 123885 : if (ns == NULL) {
1077 0 : goto bailout;
1078 : }
1079 :
1080 123885 : ns->op1 = s;
1081 123885 : ns->op2 = val;
1082 123885 : ns->nrcols = s->nrcols;
1083 123885 : ns->key = s->key;
1084 123885 : ns->aggr = s->aggr;
1085 123885 : ns->q = q;
1086 123885 : ns->nr = getDestVar(q);
1087 123885 : ns->tname = val->tname;
1088 123885 : ns->cname = val->cname;
1089 123885 : return ns;
1090 : }
1091 0 : bailout:
1092 0 : if (be->mvc->sa->eb.enabled)
1093 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1094 : return NULL;
1095 : }
1096 :
1097 : stmt *
1098 2397 : stmt_gen_group(backend *be, stmt *gids, stmt *cnts)
1099 : {
1100 2397 : MalBlkPtr mb = be->mb;
1101 :
1102 2397 : if (gids == NULL || cnts == NULL)
1103 0 : goto bailout;
1104 :
1105 2397 : InstrPtr q = dump_2(mb, algebraRef, groupbyRef, gids, cnts);
1106 :
1107 2397 : if (q) {
1108 2397 : stmt *ns = stmt_create(be->mvc->sa, st_gen_group);
1109 2397 : if (ns == NULL) {
1110 0 : goto bailout;
1111 : }
1112 :
1113 2397 : ns->op1 = gids;
1114 2397 : ns->op2 = cnts;
1115 :
1116 2397 : ns->nrcols = gids->nrcols;
1117 2397 : ns->key = 0;
1118 2397 : ns->aggr = 0;
1119 2397 : ns->q = q;
1120 2397 : ns->nr = getDestVar(q);
1121 2397 : return ns;
1122 : }
1123 0 : bailout:
1124 0 : if (be->mvc->sa->eb.enabled)
1125 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1126 : return NULL;
1127 : }
1128 :
1129 : stmt *
1130 50933 : stmt_mirror(backend *be, stmt *s)
1131 : {
1132 50933 : MalBlkPtr mb = be->mb;
1133 :
1134 50933 : if (s == NULL)
1135 0 : goto bailout;
1136 :
1137 50933 : InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
1138 :
1139 50933 : if (q) {
1140 50933 : stmt *ns = stmt_create(be->mvc->sa, st_mirror);
1141 50933 : if (ns == NULL) {
1142 0 : goto bailout;
1143 : }
1144 :
1145 50933 : ns->op1 = s;
1146 50933 : ns->nrcols = 2;
1147 50933 : ns->key = s->key;
1148 50933 : ns->aggr = s->aggr;
1149 50933 : ns->q = q;
1150 50933 : ns->nr = getDestVar(q);
1151 50933 : return ns;
1152 : }
1153 0 : bailout:
1154 0 : if (be->mvc->sa->eb.enabled)
1155 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1156 : return NULL;
1157 : }
1158 :
1159 : #define MARKJOIN 100
1160 : stmt *
1161 320129 : stmt_result(backend *be, stmt *s, int nr)
1162 : {
1163 320129 : stmt *ns;
1164 :
1165 320129 : if (s == NULL)
1166 : return NULL;
1167 :
1168 320129 : if (s->type == st_join && s->flag == cmp_joined) {
1169 5521 : if (nr)
1170 2334 : return s->op2;
1171 3187 : return s->op1;
1172 : }
1173 :
1174 314608 : if (s->op1->nr < 0)
1175 : return NULL;
1176 :
1177 314608 : ns = stmt_create(be->mvc->sa, st_result);
1178 314608 : if(!ns) {
1179 : return NULL;
1180 : }
1181 314608 : if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
1182 0 : assert(0);
1183 314608 : } else if (nr) {
1184 179921 : int v = getArg(s->q, nr);
1185 :
1186 179921 : assert(s->q->retc > nr);
1187 179921 : ns->nr = v;
1188 : } else {
1189 134687 : ns->nr = s->nr;
1190 : }
1191 314608 : ns->op1 = s;
1192 314608 : if (!nr && (s->type == st_order || s->type == st_reorder))
1193 23826 : ns->op4.typeval = *tail_type(s->op1);
1194 179921 : else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
1195 2946 : ns->op4.typeval = *sql_bind_localtype("bit");
1196 : else
1197 287836 : ns->op4.typeval = *sql_bind_localtype("oid");
1198 314608 : ns->flag = nr;
1199 314608 : ns->nrcols = s->nrcols;
1200 314608 : ns->key = s->key;
1201 314608 : ns->aggr = s->aggr;
1202 314608 : return ns;
1203 : }
1204 :
1205 :
1206 : /* limit maybe atom nil */
1207 : stmt *
1208 17432 : stmt_limit(backend *be, stmt *col, stmt *piv, stmt *gid, stmt *offset, stmt *limit, int distinct, int dir, int nullslast, int last, int order)
1209 : {
1210 17432 : MalBlkPtr mb = be->mb;
1211 17432 : InstrPtr q = NULL;
1212 17432 : int l, p, g, c;
1213 :
1214 17432 : if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
1215 0 : goto bailout;
1216 17432 : if (piv && (piv->nr < 0 || gid->nr < 0))
1217 0 : goto bailout;
1218 :
1219 17432 : c = (col) ? col->nr : 0;
1220 17432 : p = (piv) ? piv->nr : 0;
1221 17432 : g = (gid) ? gid->nr : 0;
1222 :
1223 : /* first insert single value into a bat */
1224 17432 : if (col->nrcols == 0) {
1225 0 : int k, tt = tail_type(col)->type->localtype;
1226 :
1227 0 : q = newStmt(mb, batRef, newRef);
1228 0 : if (q == NULL)
1229 0 : goto bailout;
1230 0 : setVarType(mb, getArg(q, 0), newBatType(tt));
1231 0 : q = pushType(mb, q, tt);
1232 0 : k = getDestVar(q);
1233 0 : pushInstruction(mb, q);
1234 :
1235 0 : q = newStmt(mb, batRef, appendRef);
1236 0 : if (q == NULL)
1237 0 : goto bailout;
1238 0 : q = pushArgument(mb, q, k);
1239 0 : q = pushArgument(mb, q, c);
1240 0 : pushInstruction(mb, q);
1241 0 : c = k;
1242 : }
1243 17432 : if (order) {
1244 581 : int topn = 0;
1245 :
1246 581 : q = newStmt(mb, calcRef, plusRef);
1247 581 : if (q == NULL)
1248 0 : goto bailout;
1249 581 : q = pushArgument(mb, q, offset->nr);
1250 581 : q = pushArgument(mb, q, limit->nr);
1251 581 : topn = getDestVar(q);
1252 581 : pushInstruction(mb, q);
1253 :
1254 581 : q = newStmtArgs(mb, algebraRef, firstnRef, 9);
1255 581 : if (q == NULL)
1256 0 : goto bailout;
1257 581 : if (!last) /* we need the groups for the next firstn */
1258 310 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1259 581 : q = pushArgument(mb, q, c);
1260 581 : if (p)
1261 310 : q = pushArgument(mb, q, p);
1262 : else
1263 271 : q = pushNilBat(mb, q);
1264 581 : if (g)
1265 310 : q = pushArgument(mb, q, g);
1266 : else
1267 271 : q = pushNilBat(mb, q);
1268 581 : q = pushArgument(mb, q, topn);
1269 581 : q = pushBit(mb, q, dir);
1270 581 : q = pushBit(mb, q, nullslast);
1271 581 : q = pushBit(mb, q, distinct != 0);
1272 :
1273 581 : l = getArg(q, 0);
1274 581 : l = getDestVar(q);
1275 581 : pushInstruction(mb, q);
1276 : } else {
1277 16851 : int len;
1278 :
1279 16851 : q = newStmt(mb, calcRef, plusRef);
1280 16852 : if (q == NULL)
1281 0 : goto bailout;
1282 16852 : q = pushArgument(mb, q, offset->nr);
1283 16852 : q = pushArgument(mb, q, limit->nr);
1284 16852 : len = getDestVar(q);
1285 16852 : pushInstruction(mb, q);
1286 :
1287 : /* since both arguments of algebra.subslice are
1288 : inclusive correct the LIMIT value by
1289 : subtracting 1 */
1290 16852 : q = newStmt(mb, calcRef, minusRef);
1291 16852 : if (q == NULL)
1292 0 : goto bailout;
1293 16852 : q = pushArgument(mb, q, len);
1294 16851 : q = pushInt(mb, q, 1);
1295 16850 : len = getDestVar(q);
1296 16850 : pushInstruction(mb, q);
1297 :
1298 16850 : q = newStmt(mb, algebraRef, subsliceRef);
1299 16852 : if (q == NULL)
1300 0 : goto bailout;
1301 16852 : q = pushArgument(mb, q, c);
1302 16852 : q = pushArgument(mb, q, offset->nr);
1303 16852 : q = pushArgument(mb, q, len);
1304 16852 : l = getDestVar(q);
1305 16852 : pushInstruction(mb, q);
1306 : }
1307 : /* retrieve the single values again */
1308 17433 : if (col->nrcols == 0) {
1309 0 : q = newStmt(mb, algebraRef, findRef);
1310 0 : if (q == NULL)
1311 0 : goto bailout;
1312 0 : q = pushArgument(mb, q, l);
1313 0 : q = pushOid(mb, q, 0);
1314 0 : l = getDestVar(q);
1315 0 : pushInstruction(mb, q);
1316 : }
1317 :
1318 34556 : stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
1319 17433 : if (ns == NULL) {
1320 0 : goto bailout;
1321 : }
1322 :
1323 17433 : ns->op1 = col;
1324 17433 : ns->op2 = offset;
1325 17433 : ns->op3 = limit;
1326 17433 : ns->nrcols = col->nrcols;
1327 17433 : ns->key = col->key;
1328 17433 : ns->aggr = col->aggr;
1329 17433 : ns->q = q;
1330 17433 : ns->nr = l;
1331 17433 : return ns;
1332 :
1333 0 : bailout:
1334 0 : if (be->mvc->sa->eb.enabled)
1335 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1336 : return NULL;
1337 : }
1338 :
1339 : stmt *
1340 21 : stmt_sample(backend *be, stmt *s, stmt *sample, stmt *seed)
1341 : {
1342 21 : MalBlkPtr mb = be->mb;
1343 21 : InstrPtr q = NULL;
1344 :
1345 21 : if (s == NULL || sample == NULL || s->nr < 0 || sample->nr < 0)
1346 0 : goto bailout;
1347 21 : q = newStmt(mb, sampleRef, subuniformRef);
1348 21 : if (q == NULL)
1349 0 : goto bailout;
1350 21 : q = pushArgument(mb, q, s->nr);
1351 21 : q = pushArgument(mb, q, sample->nr);
1352 :
1353 21 : if (seed) {
1354 12 : if (seed->nr < 0)
1355 0 : goto bailout;
1356 :
1357 12 : q = pushArgument(mb, q, seed->nr);
1358 : }
1359 :
1360 21 : bool enabled = be->mvc->sa->eb.enabled;
1361 21 : be->mvc->sa->eb.enabled = false;
1362 21 : stmt *ns = stmt_create(be->mvc->sa, st_sample);
1363 21 : be->mvc->sa->eb.enabled = enabled;
1364 21 : if (ns == NULL) {
1365 0 : freeInstruction(q);
1366 0 : goto bailout;
1367 : }
1368 :
1369 21 : ns->op1 = s;
1370 21 : ns->op2 = sample;
1371 :
1372 21 : if (seed) {
1373 12 : ns->op3 = seed;
1374 : }
1375 :
1376 21 : ns->nrcols = s->nrcols;
1377 21 : ns->key = s->key;
1378 21 : ns->aggr = s->aggr;
1379 21 : ns->flag = 0;
1380 21 : ns->q = q;
1381 21 : ns->nr = getDestVar(q);
1382 21 : pushInstruction(mb, q);
1383 21 : return ns;
1384 :
1385 0 : bailout:
1386 0 : if (be->mvc->sa->eb.enabled)
1387 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1388 : return NULL;
1389 : }
1390 :
1391 :
1392 : stmt *
1393 10513 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
1394 : {
1395 10513 : MalBlkPtr mb = be->mb;
1396 10513 : InstrPtr q = NULL;
1397 :
1398 10513 : if (s == NULL || s->nr < 0)
1399 0 : goto bailout;
1400 10513 : q = newStmt(mb, algebraRef, sortRef);
1401 10513 : if (q == NULL)
1402 0 : goto bailout;
1403 : /* both ordered result and oid's order en subgroups */
1404 10513 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1405 10513 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1406 10513 : q = pushArgument(mb, q, s->nr);
1407 10513 : q = pushBit(mb, q, !direction);
1408 10513 : q = pushBit(mb, q, nullslast);
1409 10513 : q = pushBit(mb, q, FALSE);
1410 :
1411 10513 : bool enabled = be->mvc->sa->eb.enabled;
1412 10513 : be->mvc->sa->eb.enabled = false;
1413 10513 : stmt *ns = stmt_create(be->mvc->sa, st_order);
1414 10513 : be->mvc->sa->eb.enabled = enabled;
1415 10513 : if (ns == NULL) {
1416 0 : freeInstruction(q);
1417 0 : goto bailout;
1418 : }
1419 :
1420 10513 : ns->op1 = s;
1421 10513 : ns->flag = direction;
1422 10513 : ns->nrcols = s->nrcols;
1423 10513 : ns->key = s->key;
1424 10513 : ns->aggr = s->aggr;
1425 10513 : ns->q = q;
1426 10513 : ns->nr = getDestVar(q);
1427 10513 : pushInstruction(mb, q);
1428 10513 : return ns;
1429 :
1430 0 : bailout:
1431 0 : if (be->mvc->sa->eb.enabled)
1432 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1433 : return NULL;
1434 : }
1435 :
1436 : stmt *
1437 13828 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
1438 : {
1439 13828 : MalBlkPtr mb = be->mb;
1440 13828 : InstrPtr q = NULL;
1441 :
1442 13828 : if (s == NULL || orderby_ids == NULL || orderby_grp == NULL || s->nr < 0 || orderby_ids->nr < 0 || orderby_grp->nr < 0)
1443 0 : goto bailout;
1444 13828 : q = newStmtArgs(mb, algebraRef, sortRef, 9);
1445 13828 : if (q == NULL)
1446 0 : goto bailout;
1447 : /* both ordered result and oid's order en subgroups */
1448 13828 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1449 13828 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1450 13828 : q = pushArgument(mb, q, s->nr);
1451 13828 : q = pushArgument(mb, q, orderby_ids->nr);
1452 13828 : q = pushArgument(mb, q, orderby_grp->nr);
1453 13828 : q = pushBit(mb, q, !direction);
1454 13828 : q = pushBit(mb, q, nullslast);
1455 13828 : q = pushBit(mb, q, FALSE);
1456 :
1457 13828 : bool enabled = be->mvc->sa->eb.enabled;
1458 13828 : be->mvc->sa->eb.enabled = false;
1459 13828 : stmt *ns = stmt_create(be->mvc->sa, st_reorder);
1460 13828 : be->mvc->sa->eb.enabled = enabled;
1461 13828 : if (ns == NULL) {
1462 0 : freeInstruction(q);
1463 0 : goto bailout;
1464 : }
1465 :
1466 13828 : ns->op1 = s;
1467 13828 : ns->op2 = orderby_ids;
1468 13828 : ns->op3 = orderby_grp;
1469 13828 : ns->flag = direction;
1470 13828 : ns->nrcols = s->nrcols;
1471 13828 : ns->key = s->key;
1472 13828 : ns->aggr = s->aggr;
1473 13828 : ns->nr = getDestVar(q);
1474 13828 : ns->q = q;
1475 13828 : pushInstruction(mb, q);
1476 13828 : return ns;
1477 :
1478 0 : bailout:
1479 0 : if (be->mvc->sa->eb.enabled)
1480 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1481 : return NULL;
1482 : }
1483 :
1484 : stmt *
1485 3293749 : stmt_atom(backend *be, atom *a)
1486 : {
1487 3293749 : MalBlkPtr mb = be->mb;
1488 :
1489 3293749 : if (a == NULL)
1490 0 : goto bailout;
1491 :
1492 3293749 : InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->impl) : newAssignment(mb);
1493 :
1494 3293711 : if (q == NULL)
1495 0 : goto bailout;
1496 3293711 : if (atom_null(a)) {
1497 151663 : q = pushNil(mb, q, atom_type(a)->type->localtype);
1498 : } else {
1499 3142048 : int k;
1500 3142048 : if ((k = constantAtom(be, mb, a)) == -1) {
1501 0 : freeInstruction(q);
1502 0 : goto bailout;
1503 : }
1504 3142065 : q = pushArgument(mb, q, k);
1505 : }
1506 : /* digits of the result timestamp/daytime */
1507 3293717 : if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
1508 47462 : q = pushInt(mb, q, atom_type(a)->digits);
1509 3293640 : bool enabled = be->mvc->sa->eb.enabled;
1510 3293640 : be->mvc->sa->eb.enabled = false;
1511 3293640 : stmt *s = stmt_create(be->mvc->sa, st_atom);
1512 3293616 : be->mvc->sa->eb.enabled = enabled;
1513 3293616 : if (s == NULL) {
1514 0 : freeInstruction(q);
1515 0 : goto bailout;
1516 : }
1517 :
1518 3293616 : s->op4.aval = a;
1519 3293616 : s->key = 1; /* values are also unique */
1520 3293616 : s->q = q;
1521 3293616 : s->nr = getDestVar(q);
1522 3293616 : pushInstruction(mb, q);
1523 3293616 : return s;
1524 :
1525 0 : bailout:
1526 0 : if (be->mvc->sa->eb.enabled)
1527 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1528 : return NULL;
1529 : }
1530 :
1531 : stmt *
1532 3272 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
1533 : {
1534 3272 : MalBlkPtr mb = be->mb;
1535 3272 : InstrPtr q = NULL;
1536 3272 : const char *mod, *op;
1537 3272 : node *n;
1538 3272 : int k;
1539 :
1540 3272 : if (lops == NULL || rops == NULL)
1541 0 : goto bailout;
1542 :
1543 3272 : if (backend_create_subfunc(be, f, NULL) < 0)
1544 0 : goto bailout;
1545 3272 : op = backend_function_imp(be, f->func);
1546 3272 : mod = sql_func_mod(f->func);
1547 :
1548 3272 : if (rops->nrcols >= 1) {
1549 56 : bit need_not = FALSE;
1550 :
1551 56 : int narg = 3;
1552 112 : for (n = lops->op4.lval->h; n; n = n->next)
1553 56 : narg++;
1554 178 : for (n = rops->op4.lval->h; n; n = n->next)
1555 122 : narg++;
1556 56 : q = newStmtArgs(mb, malRef, multiplexRef, narg);
1557 56 : if (q == NULL)
1558 0 : goto bailout;
1559 56 : setVarType(mb, getArg(q, 0), newBatType(TYPE_bit));
1560 56 : q = pushStr(mb, q, convertMultiplexMod(mod, op));
1561 56 : q = pushStr(mb, q, convertMultiplexFcn(op));
1562 112 : for (n = lops->op4.lval->h; n; n = n->next) {
1563 56 : stmt *op = n->data;
1564 :
1565 56 : q = pushArgument(mb, q, op->nr);
1566 : }
1567 178 : for (n = rops->op4.lval->h; n; n = n->next) {
1568 122 : stmt *op = n->data;
1569 :
1570 122 : q = pushArgument(mb, q, op->nr);
1571 : }
1572 56 : k = getDestVar(q);
1573 56 : pushInstruction(mb, q);
1574 :
1575 56 : q = newStmtArgs(mb, algebraRef, selectRef, 9);
1576 56 : if (q == NULL)
1577 0 : goto bailout;
1578 56 : q = pushArgument(mb, q, k);
1579 56 : if (sub)
1580 36 : q = pushArgument(mb, q, sub->nr);
1581 56 : q = pushBit(mb, q, !need_not);
1582 56 : q = pushBit(mb, q, !need_not);
1583 56 : q = pushBit(mb, q, TRUE);
1584 56 : q = pushBit(mb, q, TRUE);
1585 56 : q = pushBit(mb, q, anti);
1586 : } else {
1587 3216 : node *n;
1588 :
1589 3216 : op = sa_strconcat(be->mvc->sa, op, selectRef);
1590 3216 : q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
1591 3216 : if (q == NULL)
1592 0 : goto bailout;
1593 : // push pointer to the SQL structure into the MAL call
1594 : // allows getting argument names for example
1595 3216 : if (LANG_EXT(f->func->lang))
1596 0 : q = pushPtr(mb, q, f->func); // nothing to see here, please move along
1597 : // f->query contains the R code to be run
1598 3216 : if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
1599 0 : q = pushStr(mb, q, f->func->query);
1600 :
1601 6432 : for (n = lops->op4.lval->h; n; n = n->next) {
1602 3216 : stmt *op = n->data;
1603 :
1604 3216 : q = pushArgument(mb, q, op->nr);
1605 : }
1606 : /* candidate lists */
1607 3216 : if (sub)
1608 3147 : q = pushArgument(mb, q, sub->nr);
1609 : else
1610 69 : q = pushNilBat(mb, q);
1611 :
1612 12847 : for (n = rops->op4.lval->h; n; n = n->next) {
1613 9631 : stmt *op = n->data;
1614 :
1615 9631 : q = pushArgument(mb, q, op->nr);
1616 : }
1617 :
1618 3216 : q = pushBit(mb, q, anti);
1619 : }
1620 :
1621 3272 : bool enabled = be->mvc->sa->eb.enabled;
1622 3272 : be->mvc->sa->eb.enabled = false;
1623 3272 : stmt *s = stmt_create(be->mvc->sa, st_uselect);
1624 3272 : be->mvc->sa->eb.enabled = enabled;
1625 3272 : if (s == NULL) {
1626 0 : freeInstruction(q);
1627 0 : goto bailout;
1628 : }
1629 :
1630 3272 : s->op1 = lops;
1631 3272 : s->op2 = rops;
1632 3272 : s->op3 = sub;
1633 3272 : s->key = lops->nrcols == 0 && rops->nrcols == 0;
1634 3272 : s->flag = cmp_filter;
1635 3272 : s->nrcols = lops->nrcols;
1636 3272 : s->nr = getDestVar(q);
1637 3272 : s->q = q;
1638 3272 : s->cand = sub;
1639 3272 : pushInstruction(mb, q);
1640 3272 : return s;
1641 :
1642 0 : bailout:
1643 0 : if (be->mvc->sa->eb.enabled)
1644 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1645 : return NULL;
1646 : }
1647 :
1648 : stmt *
1649 214998 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
1650 : {
1651 214998 : MalBlkPtr mb = be->mb;
1652 214998 : InstrPtr q = NULL;
1653 214998 : int l, r;
1654 214998 : stmt *sel = sub;
1655 :
1656 214998 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
1657 0 : goto bailout;
1658 214998 : l = op1->nr;
1659 214998 : r = op2->nr;
1660 :
1661 214998 : if (op2->nrcols >= 1 && op1->nrcols == 0) { /* swap */
1662 79 : stmt *v = op1;
1663 79 : op1 = op2;
1664 79 : op2 = v;
1665 79 : int n = l;
1666 79 : l = r;
1667 79 : r = n;
1668 79 : cmptype = swap_compare(cmptype);
1669 : }
1670 214998 : if (op2->nrcols >= 1) {
1671 17852 : bit need_not = FALSE;
1672 17852 : const char *mod = calcRef;
1673 17852 : const char *op = "=";
1674 17852 : int k;
1675 :
1676 17852 : switch (cmptype) {
1677 : case cmp_equal:
1678 : op = "=";
1679 : break;
1680 : case cmp_notequal:
1681 17852 : op = "!=";
1682 : break;
1683 917 : case cmp_lt:
1684 917 : op = "<";
1685 917 : break;
1686 775 : case cmp_lte:
1687 775 : op = "<=";
1688 775 : break;
1689 4831 : case cmp_gt:
1690 4831 : op = ">";
1691 4831 : break;
1692 800 : case cmp_gte:
1693 800 : op = ">=";
1694 800 : break;
1695 0 : default:
1696 0 : TRC_ERROR(SQL_EXECUTION, "Unknown operator\n");
1697 : }
1698 :
1699 28115 : if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
1700 0 : goto bailout;
1701 17852 : if (sub && (op1->cand || op2->cand)) {
1702 1694 : if (op1->cand && !op2->cand) {
1703 30 : if (op1->nrcols > 0)
1704 30 : q = pushNilBat(mb, q);
1705 30 : q = pushArgument(mb, q, sub->nr);
1706 1664 : } else if (!op1->cand && op2->cand) {
1707 1629 : q = pushArgument(mb, q, sub->nr);
1708 1629 : if (op2->nrcols > 0)
1709 1629 : q = pushNilBat(mb, q);
1710 : }
1711 : sub = NULL;
1712 : }
1713 17852 : if (is_semantics)
1714 2972 : q = pushBit(mb, q, TRUE);
1715 17852 : k = getDestVar(q);
1716 :
1717 17852 : q = newStmtArgs(mb, algebraRef, selectRef, 9);
1718 17852 : if (q == NULL)
1719 0 : goto bailout;
1720 17852 : q = pushArgument(mb, q, k);
1721 17852 : if (sub)
1722 4363 : q = pushArgument(mb, q, sub->nr);
1723 17852 : q = pushBit(mb, q, !need_not);
1724 17852 : q = pushBit(mb, q, !need_not);
1725 17852 : q = pushBit(mb, q, TRUE);
1726 17852 : q = pushBit(mb, q, TRUE);
1727 17852 : q = pushBit(mb, q, anti);
1728 17852 : k = getDestVar(q);
1729 : } else {
1730 197146 : assert (cmptype != cmp_filter);
1731 197146 : if (is_semantics) {
1732 19576 : assert(cmptype == cmp_equal || cmptype == cmp_notequal);
1733 19576 : if (cmptype == cmp_notequal)
1734 73 : anti = !anti;
1735 19576 : q = newStmtArgs(mb, algebraRef, selectRef, 9);
1736 19576 : if (q == NULL)
1737 0 : goto bailout;
1738 19576 : q = pushArgument(mb, q, l);
1739 19576 : if (sub && !op1->cand) {
1740 1447 : q = pushArgument(mb, q, sub->nr);
1741 : } else {
1742 14 : assert(!sub || op1->cand == sub);
1743 : sub = NULL;
1744 : }
1745 19576 : q = pushArgument(mb, q, r);
1746 19576 : q = pushArgument(mb, q, r);
1747 19576 : q = pushBit(mb, q, TRUE);
1748 19576 : q = pushBit(mb, q, TRUE);
1749 19576 : q = pushBit(mb, q, anti);
1750 : } else {
1751 177570 : q = newStmt(mb, algebraRef, thetaselectRef);
1752 177569 : if (q == NULL)
1753 0 : goto bailout;
1754 177569 : q = pushArgument(mb, q, l);
1755 177570 : if (sub && !op1->cand) {
1756 126956 : q = pushArgument(mb, q, sub->nr);
1757 : } else {
1758 610 : assert(!sub || op1->cand == sub);
1759 50614 : q = pushNilBat(mb, q);
1760 50614 : sub = NULL;
1761 : }
1762 177570 : q = pushArgument(mb, q, r);
1763 177570 : switch (cmptype) {
1764 141826 : case cmp_equal:
1765 141826 : q = pushStr(mb, q, anti?"!=":"==");
1766 141826 : break;
1767 32594 : case cmp_notequal:
1768 32594 : q = pushStr(mb, q, anti?"==":"!=");
1769 32594 : break;
1770 365 : case cmp_lt:
1771 365 : q = pushStr(mb, q, anti?">=":"<");
1772 365 : break;
1773 73 : case cmp_lte:
1774 73 : q = pushStr(mb, q, anti?">":"<=");
1775 73 : break;
1776 2433 : case cmp_gt:
1777 2433 : q = pushStr(mb, q, anti?"<=":">");
1778 2433 : break;
1779 279 : case cmp_gte:
1780 279 : q = pushStr(mb, q, anti?"<":">=");
1781 279 : break;
1782 0 : default:
1783 0 : TRC_ERROR(SQL_EXECUTION, "Impossible select compare\n");
1784 0 : if (q)
1785 0 : freeInstruction(q);
1786 0 : q = NULL;
1787 0 : goto bailout;
1788 : }
1789 : }
1790 : }
1791 :
1792 214998 : bool enabled = be->mvc->sa->eb.enabled;
1793 214998 : be->mvc->sa->eb.enabled = false;
1794 214998 : stmt *s = stmt_create(be->mvc->sa, st_uselect);
1795 214998 : be->mvc->sa->eb.enabled = enabled;
1796 214998 : if (s == NULL) {
1797 0 : freeInstruction(q);
1798 0 : goto bailout;
1799 : }
1800 :
1801 214998 : s->op1 = op1;
1802 214998 : s->op2 = op2;
1803 214998 : s->op3 = sub;
1804 214998 : s->flag = cmptype;
1805 214998 : s->key = op1->nrcols == 0 && op2->nrcols == 0;
1806 214998 : s->nrcols = op1->nrcols;
1807 214998 : s->nr = getDestVar(q);
1808 214998 : s->q = q;
1809 214998 : s->cand = sub;
1810 214998 : pushInstruction(mb, q);
1811 214998 : if (!sub && sel) /* project back the old ids */
1812 2318 : return stmt_project(be, s, sel);
1813 : return s;
1814 :
1815 0 : bailout:
1816 0 : if (be->mvc->sa->eb.enabled)
1817 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1818 : return NULL;
1819 : }
1820 :
1821 : /*
1822 : static int
1823 : range_join_convertable(stmt *s, stmt **base, stmt **L, stmt **H)
1824 : {
1825 : int ls = 0, hs = 0;
1826 : stmt *l = NULL, *h = NULL;
1827 : stmt *bl = s->op2, *bh = s->op3;
1828 : int tt = tail_type(s->op2)->type->localtype;
1829 :
1830 : #ifdef HAVE_HGE
1831 : if (tt > TYPE_hge)
1832 : #else
1833 : if (tt > TYPE_lng)
1834 : #endif
1835 : return 0;
1836 : if (s->op2->type == st_Nop && list_length(s->op2->op1->op4.lval) == 2) {
1837 : bl = s->op2->op1->op4.lval->h->data;
1838 : l = s->op2->op1->op4.lval->t->data;
1839 : }
1840 : if (s->op3->type == st_Nop && list_length(s->op3->op1->op4.lval) == 2) {
1841 : bh = s->op3->op1->op4.lval->h->data;
1842 : h = s->op3->op1->op4.lval->t->data;
1843 : }
1844 :
1845 : if (((ls = (l && strcmp(s->op2->op4.funcval->func->base.name, "sql_sub") == 0 && l->nrcols == 0)) || (hs = (h && strcmp(s->op3->op4.funcval->func->base.name, "sql_add") == 0 && h->nrcols == 0))) && (ls || hs) && bl == bh) {
1846 : *base = bl;
1847 : *L = l;
1848 : *H = h;
1849 : return 1;
1850 : }
1851 : return 0;
1852 : }
1853 :
1854 : static int
1855 : argumentZero(MalBlkPtr mb, int tpe)
1856 : {
1857 : ValRecord cst;
1858 : str msg;
1859 :
1860 : cst.vtype = TYPE_int;
1861 : cst.val.ival = 0;
1862 : msg = convertConstant(tpe, &cst);
1863 : if( msg)
1864 : freeException(msg); // will not be called
1865 : return defConstant(mb, tpe, &cst);
1866 : }
1867 : */
1868 :
1869 : static InstrPtr
1870 5107 : select2_join2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt **Sub, int anti, int symmetric, int swapped, int type, int reduce)
1871 : {
1872 5107 : MalBlkPtr mb = be->mb;
1873 5107 : InstrPtr p, q;
1874 5107 : int l;
1875 5107 : const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
1876 5107 : stmt *sub = (Sub)?*Sub:NULL;
1877 :
1878 5107 : if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
1879 0 : goto bailout;
1880 5107 : l = op1->nr;
1881 8479 : if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
1882 3601 : int k;
1883 3601 : int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
1884 :
1885 3601 : if (op2->nr < 0 || op3->nr < 0)
1886 0 : goto bailout;
1887 :
1888 3601 : if (nrcols)
1889 3560 : p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
1890 : else
1891 41 : p = newStmtArgs(mb, calcRef, betweenRef, 9);
1892 3601 : if (p == NULL)
1893 0 : goto bailout;
1894 3601 : p = pushArgument(mb, p, l);
1895 3601 : p = pushArgument(mb, p, op2->nr);
1896 3601 : p = pushArgument(mb, p, op3->nr);
1897 :
1898 : /* cands */
1899 3601 : if ((sub && !reduce) || op1->cand || op2->cand || op3->cand) { /* some already handled the previous selection */
1900 1570 : if (op1->cand && op1->nrcols)
1901 1287 : p = pushNilBat(mb, p);
1902 283 : else if (op1->nrcols)
1903 283 : p = pushArgument(mb, p, sub->nr);
1904 1570 : if (op2->nrcols) {
1905 1466 : if (op2->cand)
1906 1220 : p = pushNilBat(mb, p);
1907 246 : else if (op2->nrcols)
1908 246 : p = pushArgument(mb, p, sub->nr);
1909 : }
1910 1570 : if (op3->nrcols) {
1911 1461 : if (op3->cand)
1912 1336 : p = pushNilBat(mb, p);
1913 125 : else if (op3->nrcols)
1914 125 : p = pushArgument(mb, p, sub->nr);
1915 : }
1916 : sub = NULL;
1917 : }
1918 :
1919 3601 : p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
1920 3601 : p = pushBit(mb, p, (cmp & 1) != 0); /* lo inclusive */
1921 3601 : p = pushBit(mb, p, (cmp & 2) != 0); /* hi inclusive */
1922 3601 : p = pushBit(mb, p, FALSE); /* nils_false */
1923 3601 : p = pushBit(mb, p, (anti)?TRUE:FALSE); /* anti */
1924 3601 : pushInstruction(mb, p);
1925 3601 : if (!reduce)
1926 : return p;
1927 3372 : k = getDestVar(p);
1928 :
1929 3372 : q = newStmtArgs(mb, algebraRef, selectRef, 9);
1930 3372 : if (q == NULL)
1931 0 : goto bailout;
1932 3372 : q = pushArgument(mb, q, k);
1933 3372 : if (sub)
1934 896 : q = pushArgument(mb, q, sub->nr);
1935 3372 : q = pushBit(mb, q, TRUE);
1936 3372 : q = pushBit(mb, q, TRUE);
1937 3372 : q = pushBit(mb, q, TRUE);
1938 3372 : q = pushBit(mb, q, TRUE);
1939 3372 : q = pushBit(mb, q, FALSE);
1940 3372 : pushInstruction(mb, q);
1941 : } else {
1942 : /* if st_join2 try to convert to bandjoin */
1943 : /* ie check if we subtract/add a constant, to the
1944 : same column */
1945 : /* move this optimization into the relational phase! */
1946 : /*
1947 : stmt *base, *low = NULL, *high = NULL;
1948 : if (type == st_join2 && range_join_convertable(s, &base, &low, &high)) {
1949 : int tt = tail_type(base)->type->localtype;
1950 :
1951 : if ((rs = _dumpstmt(sql, mb, base)) < 0)
1952 : return -1;
1953 : if (low) {
1954 : if ((r1 = _dumpstmt(sql, mb, low)) < 0)
1955 : return -1;
1956 : } else
1957 : r1 = argumentZero(mb, tt);
1958 : if (high) {
1959 : if ((r2 = _dumpstmt(sql, mb, high)) < 0)
1960 : return -1;
1961 : } else
1962 : r2 = argumentZero(mb, tt);
1963 : cmd = bandjoinRef;
1964 : }
1965 : */
1966 :
1967 1506 : int r1 = op2->nr;
1968 1506 : int r2 = op3->nr;
1969 1506 : int rs = 0;
1970 1506 : q = newStmtArgs(mb, algebraRef, cmd, 12);
1971 1506 : if (q == NULL)
1972 0 : goto bailout;
1973 1506 : if (type == st_join2)
1974 54 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1975 1506 : q = pushArgument(mb, q, l);
1976 1506 : if (sub) {
1977 1187 : int cand = op1->cand || op2->cand || op3->cand;
1978 1180 : if (cand) {
1979 7 : assert(!op1->nrcols || op1->cand);
1980 7 : assert(!op2->nrcols || op2->cand);
1981 7 : assert(!op3->nrcols || op3->cand);
1982 : sub = NULL;
1983 : }
1984 : }
1985 1180 : if (sub) /* only for uselect2 */
1986 1180 : q = pushArgument(mb, q, sub->nr);
1987 1506 : if (rs) {
1988 : q = pushArgument(mb, q, rs);
1989 : } else {
1990 1506 : q = pushArgument(mb, q, r1);
1991 1506 : q = pushArgument(mb, q, r2);
1992 : }
1993 1506 : if (type == st_join2) {
1994 54 : q = pushNilBat(mb, q);
1995 54 : q = pushNilBat(mb, q);
1996 : }
1997 :
1998 1506 : switch (cmp & 3) {
1999 59 : case 0:
2000 59 : q = pushBit(mb, q, FALSE);
2001 59 : q = pushBit(mb, q, FALSE);
2002 59 : break;
2003 228 : case 1:
2004 228 : q = pushBit(mb, q, TRUE);
2005 228 : q = pushBit(mb, q, FALSE);
2006 228 : break;
2007 11 : case 2:
2008 11 : q = pushBit(mb, q, FALSE);
2009 11 : q = pushBit(mb, q, TRUE);
2010 11 : break;
2011 1208 : case 3:
2012 1208 : q = pushBit(mb, q, TRUE);
2013 1208 : q = pushBit(mb, q, TRUE);
2014 1208 : break;
2015 : }
2016 1506 : q = pushBit(mb, q, anti);
2017 1506 : if (type == st_uselect2) {
2018 1452 : q = pushBit(mb, q, TRUE); /* all nil's are != */
2019 : } else {
2020 54 : q = pushBit(mb, q, (symmetric)?TRUE:FALSE);
2021 : }
2022 1506 : if (type == st_join2)
2023 54 : q = pushNil(mb, q, TYPE_lng); /* estimate */
2024 1506 : pushInstruction(mb, q);
2025 1506 : if (swapped) {
2026 2 : InstrPtr r = newInstruction(mb, NULL, NULL);
2027 2 : if (r == NULL)
2028 0 : goto bailout;
2029 2 : getArg(r, 0) = newTmpVariable(mb, TYPE_any);
2030 2 : r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
2031 2 : r = pushArgument(mb, r, getArg(q,1));
2032 2 : r = pushArgument(mb, r, getArg(q,0));
2033 2 : pushInstruction(mb, r);
2034 2 : q = r;
2035 : }
2036 : }
2037 4878 : if (Sub)
2038 4824 : *Sub = sub;
2039 : return q;
2040 :
2041 0 : bailout:
2042 0 : if (be->mvc->sa->eb.enabled)
2043 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2044 : return NULL;
2045 : }
2046 :
2047 : stmt *
2048 38 : stmt_outerselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
2049 : {
2050 38 : MalBlkPtr mb = be->mb;
2051 38 : InstrPtr q;
2052 :
2053 38 : q = newStmtArgs(mb, algebraRef, outerselectRef, 6);
2054 38 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2055 38 : q = pushArgument(mb, q, g->nr); /* group ids */
2056 38 : q = pushArgument(mb, q, m->nr); /* mark flag */
2057 38 : q = pushArgument(mb, q, p->nr); /* predicate */
2058 38 : q = pushBit(mb, q, (any)?TRUE:FALSE);
2059 38 : pushInstruction(mb, q);
2060 :
2061 38 : if (!q)
2062 : return NULL;
2063 38 : stmt *s = stmt_create(be->mvc->sa, st_uselect2);
2064 38 : if (s == NULL) {
2065 0 : freeInstruction(q);
2066 0 : return NULL;
2067 : }
2068 :
2069 38 : s->op1 = g;
2070 38 : s->op2 = m;
2071 38 : s->flag = MARKJOIN;
2072 38 : s->key = 0;
2073 38 : s->nrcols = g->nrcols;
2074 38 : s->nr = getDestVar(q);
2075 38 : s->q = q;
2076 38 : return s;
2077 : }
2078 :
2079 : stmt *
2080 402 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
2081 : {
2082 402 : MalBlkPtr mb = be->mb;
2083 402 : InstrPtr q;
2084 :
2085 402 : q = newStmtArgs(mb, algebraRef, markselectRef, 6);
2086 402 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2087 402 : q = pushArgument(mb, q, g->nr); /* left ids */
2088 402 : q = pushArgument(mb, q, m->nr); /* mark info mask */
2089 402 : q = pushArgument(mb, q, p->nr); /* predicate */
2090 402 : q = pushBit(mb, q, (any)?TRUE:FALSE);
2091 402 : pushInstruction(mb, q);
2092 :
2093 402 : if (!q)
2094 : return NULL;
2095 402 : stmt *s = stmt_create(be->mvc->sa, st_uselect2);
2096 402 : if (s == NULL) {
2097 0 : freeInstruction(q);
2098 0 : return NULL;
2099 : }
2100 :
2101 402 : s->op1 = g;
2102 402 : s->op2 = m;
2103 402 : s->flag = MARKJOIN;
2104 402 : s->key = 0;
2105 402 : s->nrcols = g->nrcols;
2106 402 : s->nr = getDestVar(q);
2107 402 : s->q = q;
2108 402 : return s;
2109 : }
2110 :
2111 : stmt *
2112 2501 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
2113 : {
2114 2501 : MalBlkPtr mb = be->mb;
2115 2501 : InstrPtr q;
2116 :
2117 2501 : q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
2118 2501 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2119 2501 : if (!final)
2120 5 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2121 2501 : q = pushArgument(mb, q, l->nr); /* left ids */
2122 2501 : q = pushArgument(mb, q, r->nr); /* mark info mask */
2123 2501 : q = pushNilBat(mb, q);
2124 2501 : q = pushNilBat(mb, q);
2125 2501 : q = pushNil(mb, q, TYPE_lng);
2126 2501 : pushInstruction(mb, q);
2127 :
2128 2501 : if (!q)
2129 : return NULL;
2130 2501 : stmt *s = stmt_create(be->mvc->sa, st_join);
2131 2501 : if (s == NULL) {
2132 0 : freeInstruction(q);
2133 0 : return NULL;
2134 : }
2135 :
2136 2501 : s->op1 = l;
2137 2501 : s->op2 = r;
2138 2501 : s->flag = MARKJOIN;
2139 2501 : s->key = 0;
2140 2501 : s->nrcols = l->nrcols;
2141 2501 : s->nr = getDestVar(q);
2142 2501 : s->q = q;
2143 2501 : return s;
2144 : }
2145 :
2146 : stmt *
2147 5053 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
2148 : {
2149 5053 : stmt *sel = sub;
2150 5053 : InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
2151 :
2152 5053 : if (q == NULL)
2153 : return NULL;
2154 :
2155 5053 : stmt *s = stmt_create(be->mvc->sa, st_uselect2);
2156 5053 : if (s == NULL) {
2157 : return NULL;
2158 : }
2159 :
2160 5053 : s->op1 = op1;
2161 5053 : s->op2 = op2;
2162 5053 : s->op3 = op3;
2163 5053 : s->op4.stval = sub;
2164 5053 : s->flag = cmp;
2165 5053 : s->nrcols = op1->nrcols;
2166 5053 : s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
2167 5053 : s->nr = getDestVar(q);
2168 5053 : s->q = q;
2169 5053 : s->cand = sub;
2170 5053 : s->reduce = reduce;
2171 5053 : if (!sub && sel) /* project back the old ids */
2172 1458 : return stmt_project(be, s, sel);
2173 : return s;
2174 : }
2175 :
2176 : stmt *
2177 54184 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
2178 : {
2179 54184 : InstrPtr q = NULL;
2180 54184 : MalBlkPtr mb = be->mb;
2181 :
2182 54184 : q = dump_2(mb, batRef, mergecandRef, op1, op2);
2183 54184 : if (q) {
2184 54184 : stmt *s = stmt_create(be->mvc->sa, st_tunion);
2185 54184 : if (s == NULL) {
2186 : return NULL;
2187 : }
2188 :
2189 54184 : s->op1 = op1;
2190 54184 : s->op2 = op2;
2191 54184 : s->nrcols = op1->nrcols;
2192 54184 : s->key = op1->key;
2193 54184 : s->aggr = op1->aggr;
2194 54184 : s->nr = getDestVar(q);
2195 54184 : s->q = q;
2196 54184 : return s;
2197 : }
2198 :
2199 0 : if (be->mvc->sa->eb.enabled)
2200 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2201 : return NULL;
2202 : }
2203 :
2204 : stmt *
2205 44682 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
2206 : {
2207 44682 : InstrPtr q = NULL;
2208 44682 : MalBlkPtr mb = be->mb;
2209 :
2210 44682 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2211 0 : goto bailout;
2212 44682 : q = newStmt(mb, algebraRef, differenceRef);
2213 44682 : if (q == NULL)
2214 0 : goto bailout;
2215 44682 : q = pushArgument(mb, q, op1->nr); /* left */
2216 44682 : q = pushArgument(mb, q, op2->nr); /* right */
2217 44682 : if (lcand)
2218 0 : q = pushArgument(mb, q, lcand->nr); /* left */
2219 : else
2220 44682 : q = pushNilBat(mb, q); /* left candidate */
2221 44682 : q = pushNilBat(mb, q); /* right candidate */
2222 44682 : q = pushBit(mb, q, FALSE); /* nil matches */
2223 44682 : q = pushBit(mb, q, FALSE); /* do not clear nils */
2224 44682 : q = pushNil(mb, q, TYPE_lng); /* estimate */
2225 :
2226 44682 : bool enabled = be->mvc->sa->eb.enabled;
2227 44682 : be->mvc->sa->eb.enabled = false;
2228 44682 : stmt *s = stmt_create(be->mvc->sa, st_tdiff);
2229 44682 : be->mvc->sa->eb.enabled = enabled;
2230 44682 : if (s == NULL) {
2231 0 : freeInstruction(q);
2232 0 : goto bailout;
2233 : }
2234 :
2235 44682 : s->op1 = op1;
2236 44682 : s->op2 = op2;
2237 44682 : s->nrcols = op1->nrcols;
2238 44682 : s->key = op1->key;
2239 44682 : s->aggr = op1->aggr;
2240 44682 : s->nr = getDestVar(q);
2241 44682 : s->q = q;
2242 44682 : pushInstruction(mb, q);
2243 44682 : return s;
2244 :
2245 0 : bailout:
2246 0 : if (be->mvc->sa->eb.enabled)
2247 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2248 : return NULL;
2249 : }
2250 :
2251 : stmt *
2252 1341 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
2253 : {
2254 1341 : InstrPtr q = NULL;
2255 1341 : MalBlkPtr mb = be->mb;
2256 :
2257 1341 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2258 0 : goto bailout;
2259 1341 : q = newStmt(mb, algebraRef, differenceRef);
2260 1341 : if (q == NULL)
2261 0 : goto bailout;
2262 1341 : q = pushArgument(mb, q, op1->nr); /* left */
2263 1341 : q = pushArgument(mb, q, op2->nr); /* right */
2264 1341 : if (lcand)
2265 0 : q = pushArgument(mb, q, lcand->nr); /* left */
2266 : else
2267 1341 : q = pushNilBat(mb, q); /* left candidate */
2268 1341 : q = pushNilBat(mb, q); /* right candidate */
2269 1341 : q = pushBit(mb, q, FALSE); /* nil matches */
2270 1341 : q = pushBit(mb, q, TRUE); /* not in */
2271 1341 : q = pushNil(mb, q, TYPE_lng); /* estimate */
2272 :
2273 1341 : bool enabled = be->mvc->sa->eb.enabled;
2274 1341 : be->mvc->sa->eb.enabled = false;
2275 1341 : stmt *s = stmt_create(be->mvc->sa, st_tdiff);
2276 1341 : be->mvc->sa->eb.enabled = enabled;
2277 1341 : if (s == NULL) {
2278 0 : freeInstruction(q);
2279 0 : goto bailout;
2280 : }
2281 :
2282 1341 : s->op1 = op1;
2283 1341 : s->op2 = op2;
2284 1341 : s->nrcols = op1->nrcols;
2285 1341 : s->key = op1->key;
2286 1341 : s->aggr = op1->aggr;
2287 1341 : s->nr = getDestVar(q);
2288 1341 : s->q = q;
2289 1341 : pushInstruction(mb, q);
2290 1341 : return s;
2291 :
2292 0 : bailout:
2293 0 : if (be->mvc->sa->eb.enabled)
2294 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2295 : return NULL;
2296 : }
2297 :
2298 : stmt *
2299 2062 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
2300 : {
2301 2062 : InstrPtr q = NULL;
2302 2062 : MalBlkPtr mb = be->mb;
2303 :
2304 2062 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2305 0 : goto bailout;
2306 2062 : q = newStmt(mb, algebraRef, intersectRef);
2307 2062 : if (q == NULL)
2308 0 : goto bailout;
2309 2062 : q = pushArgument(mb, q, op1->nr); /* left */
2310 2062 : q = pushArgument(mb, q, op2->nr); /* right */
2311 2062 : q = pushNilBat(mb, q); /* left candidate */
2312 2062 : q = pushNilBat(mb, q); /* right candidate */
2313 2062 : q = pushBit(mb, q, FALSE); /* nil matches */
2314 2062 : q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
2315 2062 : q = pushNil(mb, q, TYPE_lng); /* estimate */
2316 :
2317 2062 : bool enabled = be->mvc->sa->eb.enabled;
2318 2062 : be->mvc->sa->eb.enabled = false;
2319 2062 : stmt *s = stmt_create(be->mvc->sa, st_tinter);
2320 2062 : be->mvc->sa->eb.enabled = enabled;
2321 2062 : if (s == NULL) {
2322 0 : freeInstruction(q);
2323 0 : goto bailout;
2324 : }
2325 :
2326 2062 : s->op1 = op1;
2327 2062 : s->op2 = op2;
2328 2062 : s->nrcols = op1->nrcols;
2329 2062 : s->key = op1->key;
2330 2062 : s->aggr = op1->aggr;
2331 2062 : s->nr = getDestVar(q);
2332 2062 : s->q = q;
2333 2062 : pushInstruction(mb, q);
2334 2062 : return s;
2335 :
2336 0 : bailout:
2337 0 : if (be->mvc->sa->eb.enabled)
2338 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2339 : return NULL;
2340 : }
2341 :
2342 : stmt *
2343 94297 : stmt_join_cand(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int anti, comp_type cmptype, int need_left, int is_semantics, bool single, bool inner)
2344 : {
2345 94297 : MalBlkPtr mb = be->mb;
2346 94297 : InstrPtr q = NULL;
2347 94297 : const char *sjt = inner?joinRef:outerjoinRef;
2348 :
2349 94297 : (void)anti;
2350 94297 : (void)inner;
2351 :
2352 94297 : if (need_left) {
2353 653 : cmptype = cmp_equal;
2354 653 : sjt = leftjoinRef;
2355 : }
2356 94297 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2357 0 : goto bailout;
2358 :
2359 94297 : assert (!single || cmptype == cmp_all);
2360 :
2361 94297 : switch (cmptype) {
2362 76520 : case cmp_equal:
2363 76520 : q = newStmtArgs(mb, algebraRef, sjt, 9);
2364 76520 : if (q == NULL)
2365 0 : goto bailout;
2366 76520 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2367 76520 : q = pushArgument(mb, q, op1->nr);
2368 76520 : q = pushArgument(mb, q, op2->nr);
2369 76520 : if (!lcand)
2370 75453 : q = pushNilBat(mb, q);
2371 : else
2372 1067 : q = pushArgument(mb, q, lcand->nr);
2373 76520 : if (!rcand)
2374 76520 : q = pushNilBat(mb, q);
2375 : else
2376 0 : q = pushArgument(mb, q, rcand->nr);
2377 76520 : q = pushBit(mb, q, is_semantics?TRUE:FALSE);
2378 76520 : if (!inner)
2379 75 : q = pushBit(mb, q, FALSE); /* not match_one */
2380 76520 : q = pushNil(mb, q, TYPE_lng);
2381 76520 : pushInstruction(mb, q);
2382 76520 : break;
2383 34 : case cmp_notequal:
2384 34 : if (inner)
2385 34 : sjt = thetajoinRef;
2386 34 : q = newStmtArgs(mb, algebraRef, sjt, 9);
2387 34 : if (q == NULL)
2388 0 : goto bailout;
2389 34 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2390 34 : q = pushArgument(mb, q, op1->nr);
2391 34 : q = pushArgument(mb, q, op2->nr);
2392 34 : if (!lcand)
2393 34 : q = pushNilBat(mb, q);
2394 : else
2395 0 : q = pushArgument(mb, q, lcand->nr);
2396 34 : if (!rcand)
2397 34 : q = pushNilBat(mb, q);
2398 : else
2399 0 : q = pushArgument(mb, q, rcand->nr);
2400 34 : if (inner)
2401 34 : q = pushInt(mb, q, JOIN_NE);
2402 34 : q = pushBit(mb, q, is_semantics?TRUE:FALSE);
2403 34 : if (!inner)
2404 0 : q = pushBit(mb, q, FALSE); /* not match_one */
2405 34 : q = pushNil(mb, q, TYPE_lng);
2406 34 : pushInstruction(mb, q);
2407 34 : break;
2408 2583 : case cmp_lt:
2409 : case cmp_lte:
2410 : case cmp_gt:
2411 : case cmp_gte:
2412 2583 : q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
2413 2583 : if (q == NULL)
2414 0 : goto bailout;
2415 2583 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2416 2583 : q = pushArgument(mb, q, op1->nr);
2417 2583 : q = pushArgument(mb, q, op2->nr);
2418 2583 : if (!lcand)
2419 2583 : q = pushNilBat(mb, q);
2420 : else
2421 0 : q = pushArgument(mb, q, lcand->nr);
2422 2583 : if (!rcand)
2423 2583 : q = pushNilBat(mb, q);
2424 : else
2425 0 : q = pushArgument(mb, q, rcand->nr);
2426 2583 : if (cmptype == cmp_lt)
2427 2067 : q = pushInt(mb, q, JOIN_LT);
2428 516 : else if (cmptype == cmp_lte)
2429 8 : q = pushInt(mb, q, JOIN_LE);
2430 508 : else if (cmptype == cmp_gt)
2431 503 : q = pushInt(mb, q, JOIN_GT);
2432 5 : else if (cmptype == cmp_gte)
2433 5 : q = pushInt(mb, q, JOIN_GE);
2434 2583 : q = pushBit(mb, q, is_semantics?TRUE:FALSE);
2435 2583 : q = pushNil(mb, q, TYPE_lng);
2436 2583 : pushInstruction(mb, q);
2437 2583 : break;
2438 11973 : case cmp_all: /* aka cross table */
2439 11973 : q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
2440 11973 : if (q == NULL)
2441 0 : goto bailout;
2442 11973 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2443 11973 : q = pushArgument(mb, q, op1->nr);
2444 11973 : q = pushArgument(mb, q, op2->nr);
2445 11973 : if (!inner) {
2446 436 : q = pushNilBat(mb, q);
2447 436 : q = pushNilBat(mb, q);
2448 : }
2449 11973 : q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
2450 11973 : assert(!lcand && !rcand);
2451 11973 : pushInstruction(mb, q);
2452 11973 : break;
2453 3187 : case cmp_joined:
2454 3187 : q = op1->q;
2455 3187 : if (q == NULL)
2456 0 : goto bailout;
2457 : break;
2458 0 : default:
2459 0 : TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
2460 : }
2461 :
2462 94297 : stmt *s = stmt_create(be->mvc->sa, st_join);
2463 94297 : if (s == NULL) {
2464 0 : goto bailout;
2465 : }
2466 :
2467 94297 : s->op1 = op1;
2468 94297 : s->op2 = op2;
2469 94297 : s->flag = cmptype;
2470 94297 : s->key = 0;
2471 94297 : s->nrcols = 2;
2472 94297 : s->nr = getDestVar(q);
2473 94297 : s->q = q;
2474 94297 : return s;
2475 :
2476 0 : bailout:
2477 0 : if (be->mvc->sa->eb.enabled)
2478 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2479 : return NULL;
2480 : }
2481 :
2482 : stmt *
2483 90203 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
2484 : {
2485 90203 : return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
2486 : }
2487 :
2488 : stmt *
2489 1437 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
2490 : {
2491 1437 : MalBlkPtr mb = be->mb;
2492 1437 : InstrPtr q = NULL;
2493 :
2494 1437 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2495 0 : goto bailout;
2496 :
2497 1437 : if (single) {
2498 280 : q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
2499 280 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2500 : } else
2501 1157 : q = newStmt(mb, algebraRef, intersectRef);
2502 1437 : if (q == NULL)
2503 0 : goto bailout;
2504 1437 : q = pushArgument(mb, q, op1->nr);
2505 1437 : q = pushArgument(mb, q, op2->nr);
2506 1437 : if (lcand)
2507 1154 : q = pushArgument(mb, q, lcand->nr);
2508 : else
2509 283 : q = pushNilBat(mb, q);
2510 1437 : if (rcand)
2511 0 : q = pushArgument(mb, q, rcand->nr);
2512 : else
2513 1437 : q = pushNilBat(mb, q);
2514 1437 : q = pushBit(mb, q, is_semantics?TRUE:FALSE);
2515 1437 : q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
2516 1437 : q = pushNil(mb, q, TYPE_lng);
2517 :
2518 1437 : bool enabled = be->mvc->sa->eb.enabled;
2519 1437 : be->mvc->sa->eb.enabled = false;
2520 1437 : stmt *s = stmt_create(be->mvc->sa, st_semijoin);
2521 1437 : be->mvc->sa->eb.enabled = enabled;
2522 1437 : if (s == NULL) {
2523 0 : freeInstruction(q);
2524 0 : goto bailout;
2525 : }
2526 :
2527 1437 : s->op1 = op1;
2528 1437 : s->op2 = op2;
2529 1437 : s->flag = cmp_equal;
2530 1437 : s->key = 0;
2531 1437 : s->nrcols = 1;
2532 1437 : if (single)
2533 280 : s->nrcols = 2;
2534 1437 : s->nr = getDestVar(q);
2535 1437 : s->q = q;
2536 1437 : pushInstruction(mb, q);
2537 1437 : return s;
2538 :
2539 0 : bailout:
2540 0 : if (be->mvc->sa->eb.enabled)
2541 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2542 : return NULL;
2543 : }
2544 :
2545 : static InstrPtr
2546 3514566 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
2547 : {
2548 3514566 : MalBlkPtr mb = be->mb;
2549 3514566 : InstrPtr q = NULL;
2550 :
2551 3514566 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2552 : return NULL;
2553 : /* delta bat */
2554 3514566 : if (delta) {
2555 482975 : int uval = getArg(op2->q, 1);
2556 :
2557 482975 : q = newStmt(mb, sqlRef, deltaRef);
2558 482972 : q = pushArgument(mb, q, op1->nr);
2559 482973 : q = pushArgument(mb, q, op2->nr);
2560 482973 : q = pushArgument(mb, q, uval);
2561 : } else {
2562 : /* projections, ie left is void headed */
2563 3031591 : q = newStmt(mb, algebraRef, projectionRef);
2564 3031599 : q = pushArgument(mb, q, op1->nr);
2565 3031597 : q = pushArgument(mb, q, op2->nr);
2566 : }
2567 3514569 : pushInstruction(mb, q);
2568 3514569 : return q;
2569 : }
2570 :
2571 : stmt *
2572 3040879 : stmt_project(backend *be, stmt *op1, stmt *op2)
2573 : {
2574 3040879 : if (op1 == NULL || op2 == NULL)
2575 : return NULL;
2576 3040879 : if (!op2->nrcols)
2577 9286 : return stmt_const(be, op1, op2);
2578 3031593 : InstrPtr q = stmt_project_join(be, op1, op2, false);
2579 3031598 : if (q) {
2580 3031598 : stmt *s = stmt_create(be->mvc->sa, st_join);
2581 3031591 : if (s == NULL) {
2582 : return NULL;
2583 : }
2584 :
2585 3031591 : s->op1 = op1;
2586 3031591 : s->op2 = op2;
2587 3031591 : s->flag = cmp_project;
2588 3031591 : s->key = 0;
2589 3031591 : s->nrcols = MAX(op1->nrcols,op2->nrcols);
2590 3031591 : s->nr = getDestVar(q);
2591 3031591 : s->q = q;
2592 3031591 : s->tname = op2->tname;
2593 3031591 : s->cname = op2->cname;
2594 3031591 : s->label = op2->label;
2595 3031591 : return s;
2596 : }
2597 0 : if (be->mvc->sa->eb.enabled)
2598 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2599 : return NULL;
2600 : }
2601 :
2602 : stmt *
2603 482975 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
2604 : {
2605 482975 : InstrPtr q = stmt_project_join(be, col, upd, true);
2606 482973 : if (q) {
2607 482973 : stmt *s = stmt_create(be->mvc->sa, st_join);
2608 482973 : if (s == NULL) {
2609 : return NULL;
2610 : }
2611 :
2612 482973 : s->op1 = col;
2613 482973 : s->op2 = upd;
2614 482973 : s->flag = cmp_project;
2615 482973 : s->key = 0;
2616 482973 : s->nrcols = 2;
2617 482973 : s->nr = getDestVar(q);
2618 482973 : s->q = q;
2619 482973 : s->tname = col->tname;
2620 482973 : s->cname = col->cname;
2621 482973 : return s;
2622 : }
2623 :
2624 0 : if (be->mvc->sa->eb.enabled)
2625 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2626 : return NULL;
2627 : }
2628 :
2629 : stmt *
2630 43 : stmt_left_project(backend *be, stmt *op1, stmt *op2, stmt *op3)
2631 : {
2632 43 : MalBlkPtr mb = be->mb;
2633 43 : InstrPtr q = NULL;
2634 43 : if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || op2->nr < 0 || op3->nr < 0)
2635 0 : goto bailout;
2636 :
2637 43 : q = newStmt(mb, sqlRef, projectRef);
2638 43 : if (q == NULL)
2639 0 : goto bailout;
2640 43 : q = pushArgument(mb, q, op1->nr);
2641 43 : q = pushArgument(mb, q, op2->nr);
2642 43 : q = pushArgument(mb, q, op3->nr);
2643 :
2644 43 : bool enabled = be->mvc->sa->eb.enabled;
2645 43 : be->mvc->sa->eb.enabled = false;
2646 43 : stmt *s = stmt_create(be->mvc->sa, st_join);
2647 43 : be->mvc->sa->eb.enabled = enabled;
2648 43 : if (s == NULL) {
2649 0 : freeInstruction(q);
2650 0 : goto bailout;
2651 : }
2652 :
2653 43 : s->op1 = op1;
2654 43 : s->op2 = op2;
2655 43 : s->op3 = op3;
2656 43 : s->flag = cmp_left_project;
2657 43 : s->key = 0;
2658 43 : s->nrcols = 2;
2659 43 : s->nr = getDestVar(q);
2660 43 : s->q = q;
2661 43 : pushInstruction(mb, q);
2662 43 : return s;
2663 :
2664 0 : bailout:
2665 0 : if (be->mvc->sa->eb.enabled)
2666 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2667 : return NULL;
2668 : }
2669 :
2670 : stmt *
2671 176 : stmt_dict(backend *be, stmt *op1, stmt *op2)
2672 : {
2673 176 : MalBlkPtr mb = be->mb;
2674 176 : InstrPtr q = NULL;
2675 :
2676 176 : if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
2677 : return NULL;
2678 :
2679 176 : q = newStmt(mb, dictRef, decompressRef);
2680 176 : if (q == NULL)
2681 0 : goto bailout;
2682 176 : q = pushArgument(mb, q, op1->nr);
2683 176 : q = pushArgument(mb, q, op2->nr);
2684 :
2685 176 : bool enabled = be->mvc->sa->eb.enabled;
2686 176 : be->mvc->sa->eb.enabled = false;
2687 176 : stmt *s = stmt_create(be->mvc->sa, st_join);
2688 176 : be->mvc->sa->eb.enabled = enabled;
2689 176 : if (s == NULL) {
2690 0 : freeInstruction(q);
2691 0 : return NULL;
2692 : }
2693 :
2694 176 : s->op1 = op1;
2695 176 : s->op2 = op2;
2696 176 : s->flag = cmp_project;
2697 176 : s->key = 0;
2698 176 : s->nrcols = MAX(op1->nrcols,op2->nrcols);
2699 176 : s->nr = getDestVar(q);
2700 176 : s->q = q;
2701 176 : s->tname = op1->tname;
2702 176 : s->cname = op1->cname;
2703 176 : pushInstruction(mb, q);
2704 176 : return s;
2705 :
2706 0 : bailout:
2707 0 : if (be->mvc->sa->eb.enabled)
2708 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2709 : return NULL;
2710 : }
2711 :
2712 : stmt *
2713 8 : stmt_for(backend *be, stmt *op1, stmt *min_val)
2714 : {
2715 8 : MalBlkPtr mb = be->mb;
2716 8 : InstrPtr q = NULL;
2717 :
2718 8 : if (op1 == NULL || min_val == NULL || op1->nr < 0)
2719 : return NULL;
2720 :
2721 8 : q = newStmt(mb, forRef, decompressRef);
2722 8 : if (q == NULL)
2723 0 : goto bailout;
2724 8 : q = pushArgument(mb, q, op1->nr);
2725 8 : q = pushArgument(mb, q, min_val->nr);
2726 :
2727 8 : bool enabled = be->mvc->sa->eb.enabled;
2728 8 : be->mvc->sa->eb.enabled = false;
2729 8 : stmt *s = stmt_create(be->mvc->sa, st_join);
2730 8 : be->mvc->sa->eb.enabled = enabled;
2731 8 : if (s == NULL) {
2732 0 : freeInstruction(q);
2733 0 : return NULL;
2734 : }
2735 :
2736 8 : s->op1 = op1;
2737 8 : s->op2 = min_val;
2738 8 : s->flag = cmp_project;
2739 8 : s->key = 0;
2740 8 : s->nrcols = op1->nrcols;
2741 8 : s->nr = getDestVar(q);
2742 8 : s->q = q;
2743 8 : s->tname = op1->tname;
2744 8 : s->cname = op1->cname;
2745 8 : pushInstruction(mb, q);
2746 8 : return s;
2747 :
2748 0 : bailout:
2749 0 : if (be->mvc->sa->eb.enabled)
2750 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2751 : return NULL;
2752 : }
2753 :
2754 : stmt *
2755 54 : stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int symmetric, int swapped)
2756 : {
2757 54 : InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, swapped, st_join2, 1/*reduce semantics*/);
2758 54 : if (q == NULL)
2759 : return NULL;
2760 :
2761 54 : stmt *s = stmt_create(be->mvc->sa, st_join2);
2762 54 : if (s == NULL) {
2763 : return NULL;
2764 : }
2765 :
2766 54 : s->op1 = l;
2767 54 : s->op2 = ra;
2768 54 : s->op3 = rb;
2769 54 : s->flag = cmp;
2770 54 : s->nrcols = 2;
2771 54 : s->nr = getDestVar(q);
2772 54 : s->q = q;
2773 54 : s->reduce = 1;
2774 54 : return s;
2775 : }
2776 :
2777 : stmt *
2778 49 : stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
2779 : {
2780 49 : MalBlkPtr mb = be->mb;
2781 49 : InstrPtr q = NULL;
2782 49 : const char *mod, *fimp;
2783 49 : node *n;
2784 :
2785 49 : if (l == NULL || r == NULL)
2786 0 : goto bailout;
2787 49 : if (backend_create_subfunc(be, op, NULL) < 0)
2788 0 : goto bailout;
2789 49 : mod = sql_func_mod(op->func);
2790 49 : fimp = backend_function_imp(be, op->func);
2791 49 : fimp = sa_strconcat(be->mvc->sa, fimp, "join");
2792 :
2793 : /* filter qualifying tuples, return oids of h and tail */
2794 49 : q = newStmtArgs(mb, mod, fimp, list_length(l->op4.lval) + list_length(r->op4.lval) + 7);
2795 49 : if (q == NULL)
2796 0 : goto bailout;
2797 49 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2798 98 : for (n = l->op4.lval->h; n; n = n->next) {
2799 49 : stmt *op = n->data;
2800 :
2801 49 : q = pushArgument(mb, q, op->nr);
2802 : }
2803 :
2804 162 : for (n = r->op4.lval->h; n; n = n->next) {
2805 113 : stmt *op = n->data;
2806 :
2807 113 : q = pushArgument(mb, q, op->nr);
2808 : }
2809 49 : q = pushNilBat(mb, q); /* candidate lists */
2810 49 : q = pushNilBat(mb, q); /* candidate lists */
2811 49 : q = pushBit(mb, q, TRUE); /* nil_matches */
2812 49 : q = pushNil(mb, q, TYPE_lng); /* estimate */
2813 49 : q = pushBit(mb, q, anti?TRUE:FALSE); /* 'not' matching */
2814 49 : pushInstruction(mb, q);
2815 :
2816 49 : if (swapped) {
2817 7 : InstrPtr r = newInstruction(mb, NULL, NULL);
2818 7 : if (r == NULL)
2819 0 : goto bailout;
2820 7 : getArg(r, 0) = newTmpVariable(mb, TYPE_any);
2821 7 : r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
2822 7 : r = pushArgument(mb, r, getArg(q,1));
2823 7 : r = pushArgument(mb, r, getArg(q,0));
2824 7 : pushInstruction(mb, r);
2825 7 : q = r;
2826 : }
2827 :
2828 49 : stmt *s = stmt_create(be->mvc->sa, st_joinN);
2829 49 : if (s == NULL) {
2830 0 : goto bailout;
2831 : }
2832 :
2833 49 : s->op1 = l;
2834 49 : s->op2 = r;
2835 49 : s->op4.funcval = op;
2836 49 : s->nrcols = 2;
2837 49 : if (swapped)
2838 7 : s->flag |= SWAPPED;
2839 49 : s->nr = getDestVar(q);
2840 49 : s->q = q;
2841 49 : return s;
2842 :
2843 0 : bailout:
2844 0 : if (be->mvc->sa->eb.enabled)
2845 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2846 : return NULL;
2847 : }
2848 :
2849 : stmt *
2850 25594 : stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
2851 : {
2852 25594 : InstrPtr q = NULL;
2853 :
2854 25594 : if (rs == NULL || rs->nr < 0)
2855 : return NULL;
2856 25594 : q = rs->q;
2857 25594 : if (q) {
2858 25378 : stmt *s = stmt_create(be->mvc->sa, st_rs_column);
2859 25378 : if (s == NULL) {
2860 : return NULL;
2861 : }
2862 :
2863 25378 : s->op1 = rs;
2864 25378 : s->op4.typeval = *tpe;
2865 25378 : s->flag = i;
2866 25378 : s->nrcols = 1;
2867 25378 : s->key = 0;
2868 25378 : s->q = q;
2869 25378 : s->nr = getArg(q, s->flag);
2870 25378 : return s;
2871 216 : } else if (rs->type == st_list) {
2872 216 : list *cols = rs->op4.lval;
2873 216 : if (i < list_length(cols))
2874 216 : return list_fetch(cols, i);
2875 : }
2876 : return NULL;
2877 : }
2878 :
2879 : /*
2880 : * The dump_header produces a sequence of instructions for
2881 : * the front-end to prepare presentation of a result table.
2882 : *
2883 : * A secondary scheme is added to assemble all information
2884 : * in columns first. Then it can be returned to the environment.
2885 : */
2886 : #define NEWRESULTSET
2887 :
2888 : #define meta(P, Id, Tpe, Args) \
2889 : do { \
2890 : P = newStmtArgs(mb, batRef, packRef, Args); \
2891 : if (P) { \
2892 : Id = getArg(P,0); \
2893 : setVarType(mb, Id, newBatType(Tpe)); \
2894 : setVarFixed(mb, Id); \
2895 : list = pushArgument(mb, list, Id); \
2896 : pushInstruction(mb, P); \
2897 : } \
2898 : } while (0)
2899 :
2900 : static int
2901 32 : dump_export_header(mvc *sql, MalBlkPtr mb, list *l, int file, const char * format, const char * sep,const char * rsep,const char * ssep,const char * ns, int onclient)
2902 : {
2903 32 : node *n;
2904 32 : int ret = -1;
2905 32 : int args;
2906 :
2907 : // gather the meta information
2908 32 : int tblId, nmeId, tpeId, lenId, scaleId;
2909 32 : InstrPtr list;
2910 32 : InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
2911 :
2912 32 : args = list_length(l) + 1;
2913 :
2914 32 : list = newInstructionArgs(mb, sqlRef, export_tableRef, args + 13);
2915 32 : if (list == NULL)
2916 : return -1;
2917 32 : getArg(list,0) = newTmpVariable(mb,TYPE_int);
2918 32 : if( file >= 0){
2919 32 : list = pushArgument(mb, list, file);
2920 32 : list = pushStr(mb, list, format);
2921 32 : list = pushStr(mb, list, sep);
2922 32 : list = pushStr(mb, list, rsep);
2923 32 : list = pushStr(mb, list, ssep);
2924 32 : list = pushStr(mb, list, ns);
2925 32 : list = pushInt(mb, list, onclient);
2926 : }
2927 32 : meta(tblPtr, tblId, TYPE_str, args);
2928 32 : meta(nmePtr, nmeId, TYPE_str, args);
2929 32 : meta(tpePtr, tpeId, TYPE_str, args);
2930 32 : meta(lenPtr, lenId, TYPE_int, args);
2931 32 : meta(scalePtr, scaleId, TYPE_int, args);
2932 32 : if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
2933 : return -1;
2934 :
2935 172 : for (n = l->h; n; n = n->next) {
2936 140 : stmt *c = n->data;
2937 140 : sql_subtype *t = tail_type(c);
2938 140 : const char *tname = table_name(sql->sa, c);
2939 140 : const char *sname = schema_name(sql->sa, c);
2940 140 : const char *_empty = "";
2941 140 : const char *tn = (tname) ? tname : _empty;
2942 140 : const char *sn = (sname) ? sname : _empty;
2943 140 : const char *cn = column_name(sql->sa, c);
2944 140 : const char *ntn = sql_escape_ident(sql->ta, tn);
2945 140 : const char *nsn = sql_escape_ident(sql->ta, sn);
2946 140 : size_t fqtnl;
2947 140 : char *fqtn = NULL;
2948 :
2949 140 : if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
2950 140 : fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
2951 140 : if (fqtn == NULL)
2952 : return -1;
2953 140 : snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
2954 140 : tblPtr = pushStr(mb, tblPtr, fqtn);
2955 140 : nmePtr = pushStr(mb, nmePtr, cn);
2956 140 : tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
2957 140 : lenPtr = pushInt(mb, lenPtr, t->digits);
2958 140 : scalePtr = pushInt(mb, scalePtr, t->scale);
2959 140 : list = pushArgument(mb, list, c->nr);
2960 : } else
2961 : return -1;
2962 : }
2963 32 : sa_reset(sql->ta);
2964 32 : ret = getArg(list,0);
2965 32 : pushInstruction(mb,list);
2966 32 : return ret;
2967 : }
2968 :
2969 :
2970 : stmt *
2971 32 : stmt_export(backend *be, stmt *t, const char *sep, const char *rsep, const char *ssep, const char *null_string, int onclient, stmt *file)
2972 : {
2973 32 : MalBlkPtr mb = be->mb;
2974 32 : InstrPtr q = NULL;
2975 32 : int fnr;
2976 32 : list *l;
2977 :
2978 32 : if (t == NULL || t->nr < 0)
2979 0 : goto bailout;
2980 32 : l = t->op4.lval;
2981 32 : if (file) {
2982 23 : if (file->nr < 0)
2983 0 : goto bailout;
2984 : fnr = file->nr;
2985 : } else {
2986 9 : q = newAssignment(mb);
2987 9 : if (q == NULL)
2988 0 : goto bailout;
2989 9 : q = pushStr(mb,q,"stdout");
2990 9 : fnr = getArg(q,0);
2991 9 : pushInstruction(mb, q);
2992 : }
2993 32 : if (t->type == st_list) {
2994 32 : if (dump_export_header(be->mvc, mb, l, fnr, "csv", sep, rsep, ssep, null_string, onclient) < 0)
2995 0 : goto bailout;
2996 : } else {
2997 0 : q = newStmt(mb, sqlRef, raiseRef);
2998 0 : if (q == NULL)
2999 0 : goto bailout;
3000 0 : q = pushStr(mb, q, "not a valid output list\n");
3001 0 : pushInstruction(mb, q);
3002 : }
3003 32 : stmt *s = stmt_create(be->mvc->sa, st_export);
3004 32 : if(!s) {
3005 0 : goto bailout;
3006 : }
3007 32 : s->op1 = t;
3008 32 : s->op2 = file;
3009 32 : s->q = q;
3010 32 : s->nr = 1;
3011 32 : return s;
3012 :
3013 0 : bailout:
3014 0 : if (be->mvc->sa->eb.enabled)
3015 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3016 : return NULL;
3017 : }
3018 :
3019 : stmt *
3020 150 : stmt_export_bin(backend *be, stmt *colstmt, bool byteswap, const char *filename, int on_client)
3021 : {
3022 150 : MalBlkPtr mb = be->mb;
3023 150 : InstrPtr q;
3024 :
3025 150 : if (colstmt == NULL)
3026 0 : goto bailout;
3027 150 : q = newStmt(mb, sqlRef, export_bin_columnRef);
3028 150 : if (q == NULL)
3029 0 : goto bailout;
3030 150 : pushArgument(mb, q, colstmt->nr);
3031 150 : pushBit(mb, q, byteswap);
3032 150 : pushStr(mb, q, filename);
3033 150 : pushInt(mb, q, on_client);
3034 150 : pushInstruction(mb, q);
3035 :
3036 150 : stmt *s = stmt_create(be->mvc->sa, st_export);
3037 150 : if (!s)
3038 0 : goto bailout;
3039 :
3040 150 : s->q = q;
3041 150 : return s;
3042 :
3043 0 : bailout:
3044 0 : if (be->mvc->sa->eb.enabled)
3045 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3046 : return NULL;
3047 : }
3048 :
3049 : stmt *
3050 3162 : stmt_trans(backend *be, int type, stmt *chain, stmt *name)
3051 : {
3052 3162 : MalBlkPtr mb = be->mb;
3053 3162 : InstrPtr q = NULL;
3054 :
3055 3162 : if (chain == NULL || chain->nr < 0)
3056 0 : goto bailout;
3057 :
3058 3162 : switch(type){
3059 13 : case ddl_release:
3060 13 : q = newStmt(mb, sqlRef, transaction_releaseRef);
3061 13 : break;
3062 558 : case ddl_commit:
3063 558 : q = newStmt(mb, sqlRef, transaction_commitRef);
3064 558 : break;
3065 1084 : case ddl_rollback:
3066 1084 : q = newStmt(mb, sqlRef, transaction_rollbackRef);
3067 1084 : break;
3068 1507 : case ddl_trans:
3069 1507 : q = newStmt(mb, sqlRef, transaction_beginRef);
3070 1507 : break;
3071 0 : default:
3072 0 : TRC_ERROR(SQL_EXECUTION, "Unknown transaction type\n");
3073 0 : goto bailout;
3074 : }
3075 3162 : if (q == NULL)
3076 0 : goto bailout;
3077 3162 : q = pushArgument(mb, q, chain->nr);
3078 3162 : if (name)
3079 79 : q = pushArgument(mb, q, name->nr);
3080 : else
3081 3083 : q = pushNil(mb, q, TYPE_str);
3082 :
3083 3162 : bool enabled = be->mvc->sa->eb.enabled;
3084 3162 : be->mvc->sa->eb.enabled = false;
3085 3162 : stmt *s = stmt_create(be->mvc->sa, st_trans);
3086 3162 : be->mvc->sa->eb.enabled = enabled;
3087 3162 : if(!s) {
3088 0 : freeInstruction(q);
3089 0 : goto bailout;
3090 : }
3091 3162 : s->op1 = chain;
3092 3162 : s->op2 = name;
3093 3162 : s->flag = type;
3094 3162 : s->q = q;
3095 3162 : s->nr = getDestVar(q);
3096 3162 : pushInstruction(mb, q);
3097 3162 : return s;
3098 :
3099 0 : bailout:
3100 0 : if (be->mvc->sa->eb.enabled)
3101 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3102 : return NULL;
3103 : }
3104 :
3105 : stmt *
3106 283785 : stmt_catalog(backend *be, int type, stmt *args)
3107 : {
3108 283785 : MalBlkPtr mb = be->mb;
3109 283785 : InstrPtr q = NULL;
3110 283785 : node *n;
3111 :
3112 283785 : if (args == NULL || args->nr < 0)
3113 0 : goto bailout;
3114 :
3115 : /* cast them into properly named operations */
3116 283785 : const char *ref;
3117 283785 : switch(type){
3118 316 : case ddl_create_seq: ref = create_seqRef; break;
3119 47 : case ddl_alter_seq: ref = alter_seqRef; break;
3120 32 : case ddl_drop_seq: ref = drop_seqRef; break;
3121 1084 : case ddl_create_schema: ref = create_schemaRef; break;
3122 193 : case ddl_drop_schema: ref = drop_schemaRef; break;
3123 10120 : case ddl_create_table: ref = create_tableRef; break;
3124 22358 : case ddl_create_view: ref = create_viewRef; break;
3125 3691 : case ddl_drop_table: ref = drop_tableRef; break;
3126 314 : case ddl_drop_view: ref = drop_viewRef; break;
3127 150 : case ddl_drop_constraint: ref = drop_constraintRef; break;
3128 1372 : case ddl_alter_table: ref = alter_tableRef; break;
3129 906 : case ddl_create_type: ref = create_typeRef; break;
3130 4 : case ddl_drop_type: ref = drop_typeRef; break;
3131 40 : case ddl_grant_roles: ref = grant_rolesRef; break;
3132 10 : case ddl_revoke_roles: ref = revoke_rolesRef; break;
3133 18455 : case ddl_grant: ref = grantRef; break;
3134 15 : case ddl_revoke: ref = revokeRef; break;
3135 99018 : case ddl_grant_func: ref = grant_functionRef; break;
3136 1 : case ddl_revoke_func: ref = revoke_functionRef; break;
3137 358 : case ddl_create_user: ref = create_userRef; break;
3138 107 : case ddl_drop_user: ref = drop_userRef; break;
3139 83 : case ddl_alter_user: ref = alter_userRef; break;
3140 5 : case ddl_rename_user: ref = rename_userRef; break;
3141 26 : case ddl_create_role: ref = create_roleRef; break;
3142 19 : case ddl_drop_role: ref = drop_roleRef; break;
3143 160 : case ddl_drop_index: ref = drop_indexRef; break;
3144 669 : case ddl_drop_function: ref = drop_functionRef; break;
3145 120296 : case ddl_create_function: ref = create_functionRef; break;
3146 345 : case ddl_create_trigger: ref = create_triggerRef; break;
3147 84 : case ddl_drop_trigger: ref = drop_triggerRef; break;
3148 312 : case ddl_alter_table_add_table: ref = alter_add_tableRef; break;
3149 180 : case ddl_alter_table_del_table: ref = alter_del_tableRef; break;
3150 2310 : case ddl_alter_table_set_access:ref = alter_set_tableRef; break;
3151 225 : case ddl_alter_table_add_range_partition: ref = alter_add_range_partitionRef; break;
3152 60 : case ddl_alter_table_add_list_partition: ref = alter_add_value_partitionRef; break;
3153 354 : case ddl_comment_on: ref = comment_onRef; break;
3154 8 : case ddl_rename_schema: ref = rename_schemaRef; break;
3155 45 : case ddl_rename_table: ref = rename_tableRef; break;
3156 13 : case ddl_rename_column: ref = rename_columnRef; break;
3157 0 : default:
3158 0 : TRC_ERROR(SQL_EXECUTION, "Unknown catalog operation\n");
3159 0 : goto bailout;
3160 : }
3161 283785 : q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
3162 283785 : if (q == NULL)
3163 0 : goto bailout;
3164 : // pass all arguments as before
3165 1697052 : for (n = args->op4.lval->h; n; n = n->next) {
3166 1413267 : stmt *c = n->data;
3167 :
3168 1413267 : q = pushArgument(mb, q, c->nr);
3169 : }
3170 :
3171 283785 : bool enabled = be->mvc->sa->eb.enabled;
3172 283785 : be->mvc->sa->eb.enabled = false;
3173 283785 : stmt *s = stmt_create(be->mvc->sa, st_catalog);
3174 283785 : be->mvc->sa->eb.enabled = enabled;
3175 283785 : if(!s) {
3176 0 : freeInstruction(q);
3177 0 : goto bailout;
3178 : }
3179 283785 : s->op1 = args;
3180 283785 : s->flag = type;
3181 283785 : s->q = q;
3182 283785 : s->nr = getDestVar(q);
3183 283785 : pushInstruction(mb, q);
3184 283785 : return s;
3185 :
3186 0 : bailout:
3187 0 : if (be->mvc->sa->eb.enabled)
3188 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3189 : return NULL;
3190 : }
3191 :
3192 : void
3193 1830294 : stmt_set_nrcols(stmt *s)
3194 : {
3195 1830294 : unsigned nrcols = 0;
3196 1830294 : int key = 1;
3197 1830294 : node *n;
3198 1830294 : list *l = s->op4.lval;
3199 :
3200 1830294 : assert(s->type == st_list);
3201 8905855 : for (n = l->h; n; n = n->next) {
3202 7075561 : stmt *f = n->data;
3203 :
3204 7075561 : if (!f)
3205 0 : continue;
3206 7075561 : if (f->nrcols > nrcols)
3207 : nrcols = f->nrcols;
3208 7075561 : key &= f->key;
3209 7075561 : s->nr = f->nr;
3210 : }
3211 1830294 : s->nrcols = nrcols;
3212 1830294 : s->key = key;
3213 1830294 : }
3214 :
3215 : stmt *
3216 1433475 : stmt_list(backend *be, list *l)
3217 : {
3218 1433475 : if (l == NULL)
3219 : return NULL;
3220 1433475 : stmt *s = stmt_create(be->mvc->sa, st_list);
3221 1433463 : if(!s) {
3222 : return NULL;
3223 : }
3224 1433463 : s->op4.lval = l;
3225 1433463 : stmt_set_nrcols(s);
3226 1433463 : return s;
3227 : }
3228 :
3229 : static InstrPtr
3230 64724 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
3231 : {
3232 64724 : node *n;
3233 : // gather the meta information
3234 64724 : int tblId, nmeId, tpeId, lenId, scaleId;
3235 64724 : int args;
3236 64724 : InstrPtr list;
3237 64724 : InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
3238 :
3239 64724 : args = list_length(l) + 1;
3240 :
3241 64724 : list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 5);
3242 64725 : if(!list) {
3243 : return NULL;
3244 : }
3245 64725 : getArg(list,0) = newTmpVariable(mb,TYPE_int);
3246 64725 : meta(tblPtr, tblId, TYPE_str, args);
3247 64725 : meta(nmePtr, nmeId, TYPE_str, args);
3248 64724 : meta(tpePtr, tpeId, TYPE_str, args);
3249 64725 : meta(lenPtr, lenId, TYPE_int, args);
3250 64725 : meta(scalePtr, scaleId, TYPE_int, args);
3251 64725 : if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
3252 : return NULL;
3253 :
3254 340778 : for (n = l->h; n; n = n->next) {
3255 276053 : stmt *c = n->data;
3256 276053 : sql_subtype *t = tail_type(c);
3257 276053 : const char *tname = table_name(sql->sa, c);
3258 276052 : const char *sname = schema_name(sql->sa, c);
3259 276052 : const char *_empty = "";
3260 276052 : const char *tn = (tname) ? tname : _empty;
3261 276052 : const char *sn = (sname) ? sname : _empty;
3262 276052 : const char *cn = column_name(sql->sa, c);
3263 276051 : const char *ntn = sql_escape_ident(sql->ta, tn);
3264 276054 : const char *nsn = sql_escape_ident(sql->ta, sn);
3265 276060 : size_t fqtnl;
3266 :
3267 276060 : if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
3268 276060 : char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
3269 276059 : if (fqtn == NULL)
3270 : return NULL;
3271 276059 : snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
3272 276059 : tblPtr = pushStr(mb, tblPtr, fqtn);
3273 276059 : nmePtr = pushStr(mb, nmePtr, cn);
3274 276051 : tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
3275 276059 : lenPtr = pushInt(mb, lenPtr, t->digits);
3276 276052 : scalePtr = pushInt(mb, scalePtr, t->scale);
3277 276052 : list = pushArgument(mb,list,c->nr);
3278 : } else
3279 : return NULL;
3280 : }
3281 64725 : sa_reset(sql->ta);
3282 64725 : pushInstruction(mb,list);
3283 64725 : return list;
3284 : }
3285 :
3286 : int
3287 125193 : stmt_output(backend *be, stmt *lst)
3288 : {
3289 125193 : MalBlkPtr mb = be->mb;
3290 125193 : InstrPtr q = NULL;
3291 125193 : list *l = lst->op4.lval;
3292 125193 : int cnt = list_length(l), ok = 0;
3293 125190 : node *n = l->h;
3294 125190 : stmt *first = n->data;
3295 :
3296 : /* single value result, has a fast exit */
3297 125190 : if (cnt == 1 && first->nrcols <= 0 ){
3298 60467 : stmt *c = n->data;
3299 60467 : sql_subtype *t = tail_type(c);
3300 60472 : const char *tname = table_name(be->mvc->sa, c);
3301 60471 : const char *sname = schema_name(be->mvc->sa, c);
3302 60467 : const char *_empty = "";
3303 60467 : const char *tn = (tname) ? tname : _empty;
3304 60467 : const char *sn = (sname) ? sname : _empty;
3305 60467 : const char *cn = column_name(be->mvc->sa, c);
3306 60469 : const char *ntn = sql_escape_ident(be->mvc->ta, tn);
3307 60463 : const char *nsn = sql_escape_ident(be->mvc->ta, sn);
3308 :
3309 60468 : if (ntn && nsn) {
3310 60468 : size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
3311 60468 : char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
3312 60468 : if (fqtn == NULL)
3313 : return -1;
3314 60468 : ok = 1;
3315 60468 : snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
3316 :
3317 60468 : q = newStmt(mb, sqlRef, resultSetRef);
3318 60472 : if (q == NULL)
3319 : return -1;
3320 60472 : getArg(q,0) = newTmpVariable(mb,TYPE_int);
3321 60472 : q = pushStr(mb, q, fqtn);
3322 60470 : q = pushStr(mb, q, cn);
3323 60470 : q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
3324 60472 : q = pushInt(mb, q, t->digits);
3325 60471 : q = pushInt(mb, q, t->scale);
3326 60472 : q = pushInt(mb, q, t->type->eclass);
3327 60469 : q = pushArgument(mb, q, c->nr);
3328 60469 : pushInstruction(mb, q);
3329 : }
3330 60469 : sa_reset(be->mvc->ta);
3331 60469 : if (!ok)
3332 : return -1;
3333 : } else {
3334 64723 : if ((q = dump_header(be->mvc, mb, l)) == NULL)
3335 : return -1;
3336 : }
3337 : return 0;
3338 : }
3339 :
3340 : int
3341 138739 : stmt_affected_rows(backend *be, int lastnr)
3342 : {
3343 138739 : MalBlkPtr mb = be->mb;
3344 138739 : InstrPtr q = NULL;
3345 :
3346 138739 : q = newStmt(mb, sqlRef, affectedRowsRef);
3347 138737 : if (q == NULL)
3348 : return -1;
3349 138737 : q = pushArgument(mb, q, be->mvc_var);
3350 138737 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
3351 138739 : q = pushArgument(mb, q, lastnr);
3352 138738 : pushInstruction(mb, q);
3353 138739 : be->mvc_var = getDestVar(q);
3354 138739 : return 0;
3355 : }
3356 :
3357 : stmt *
3358 177385 : stmt_append(backend *be, stmt *c, stmt *a)
3359 : {
3360 177385 : MalBlkPtr mb = be->mb;
3361 177385 : InstrPtr q = NULL;
3362 :
3363 177385 : if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
3364 0 : goto bailout;
3365 177385 : q = newStmt(mb, batRef, appendRef);
3366 177385 : if (q == NULL)
3367 0 : goto bailout;
3368 177385 : q = pushArgument(mb, q, c->nr);
3369 177385 : q = pushArgument(mb, q, a->nr);
3370 177385 : q = pushBit(mb, q, TRUE);
3371 177385 : bool enabled = be->mvc->sa->eb.enabled;
3372 177385 : be->mvc->sa->eb.enabled = false;
3373 177385 : stmt *s = stmt_create(be->mvc->sa, st_append);
3374 177385 : be->mvc->sa->eb.enabled = enabled;
3375 177385 : if(!s) {
3376 0 : freeInstruction(q);
3377 0 : goto bailout;
3378 : }
3379 177385 : s->op1 = c;
3380 177385 : s->op2 = a;
3381 177385 : s->nrcols = c->nrcols;
3382 177385 : s->key = c->key;
3383 177385 : s->nr = getDestVar(q);
3384 177385 : s->q = q;
3385 177385 : pushInstruction(mb, q);
3386 177385 : return s;
3387 :
3388 0 : bailout:
3389 0 : if (be->mvc->sa->eb.enabled)
3390 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3391 : return NULL;
3392 : }
3393 :
3394 : stmt *
3395 137660 : stmt_append_bulk(backend *be, stmt *c, list *l)
3396 : {
3397 137660 : MalBlkPtr mb = be->mb;
3398 137660 : InstrPtr q = NULL;
3399 137660 : bool needs_columns = false;
3400 :
3401 137660 : if (c->nr < 0)
3402 0 : goto bailout;
3403 :
3404 : /* currently appendBulk accepts its inputs all either scalar or vectors
3405 : if there is one vector and any scala, then the scalars mut be upgraded to vectors */
3406 887972 : for (node *n = l->h; n; n = n->next) {
3407 750312 : stmt *t = n->data;
3408 750312 : needs_columns |= t->nrcols > 0;
3409 : }
3410 137660 : if (needs_columns) {
3411 0 : for (node *n = l->h; n; n = n->next) {
3412 0 : stmt *t = n->data;
3413 0 : if (t->nrcols == 0)
3414 0 : n->data = const_column(be, t);
3415 : }
3416 : }
3417 :
3418 137660 : q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3);
3419 137647 : if (q == NULL)
3420 0 : goto bailout;
3421 137647 : q = pushArgument(mb, q, c->nr);
3422 137651 : q = pushBit(mb, q, TRUE);
3423 887859 : for (node *n = l->h ; n ; n = n->next) {
3424 750226 : stmt *a = n->data;
3425 750226 : q = pushArgument(mb, q, a->nr);
3426 : }
3427 137633 : bool enabled = be->mvc->sa->eb.enabled;
3428 137633 : be->mvc->sa->eb.enabled = false;
3429 137633 : stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
3430 137635 : be->mvc->sa->eb.enabled = enabled;
3431 137635 : if(!s) {
3432 0 : freeInstruction(q);
3433 0 : goto bailout;
3434 : }
3435 137635 : s->op1 = c;
3436 137635 : s->op4.lval = l;
3437 137635 : s->nrcols = c->nrcols;
3438 137635 : s->key = c->key;
3439 137635 : s->nr = getDestVar(q);
3440 137635 : s->q = q;
3441 137635 : pushInstruction(mb, q);
3442 137635 : return s;
3443 :
3444 0 : bailout:
3445 0 : if (be->mvc->sa->eb.enabled)
3446 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3447 : return NULL;
3448 : }
3449 :
3450 : stmt *
3451 15921 : stmt_pack(backend *be, stmt *c, int n)
3452 : {
3453 15921 : MalBlkPtr mb = be->mb;
3454 15921 : InstrPtr q = NULL;
3455 :
3456 15921 : if (c == NULL || c->nr < 0)
3457 0 : goto bailout;
3458 15921 : q = newStmtArgs(mb, matRef, packIncrementRef, 3);
3459 15921 : if (q == NULL)
3460 0 : goto bailout;
3461 15921 : q = pushArgument(mb, q, c->nr);
3462 15921 : q = pushInt(mb, q, n);
3463 15921 : bool enabled = be->mvc->sa->eb.enabled;
3464 15921 : be->mvc->sa->eb.enabled = false;
3465 15921 : stmt *s = stmt_create(be->mvc->sa, st_append);
3466 15921 : be->mvc->sa->eb.enabled = enabled;
3467 15921 : if(!s) {
3468 0 : freeInstruction(q);
3469 0 : goto bailout;
3470 : }
3471 15921 : s->op1 = c;
3472 15921 : s->nrcols = c->nrcols;
3473 15921 : s->key = c->key;
3474 15921 : s->nr = getDestVar(q);
3475 15921 : s->q = q;
3476 15921 : pushInstruction(mb, q);
3477 15921 : return s;
3478 :
3479 0 : bailout:
3480 0 : if (be->mvc->sa->eb.enabled)
3481 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3482 : return NULL;
3483 :
3484 : }
3485 :
3486 : stmt *
3487 29641 : stmt_pack_add(backend *be, stmt *c, stmt *a)
3488 : {
3489 29641 : MalBlkPtr mb = be->mb;
3490 29641 : InstrPtr q = NULL;
3491 :
3492 29641 : if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
3493 0 : goto bailout;
3494 29641 : q = newStmtArgs(mb, matRef, packIncrementRef, 3);
3495 29641 : if (q == NULL)
3496 0 : goto bailout;
3497 29641 : q = pushArgument(mb, q, c->nr);
3498 29641 : q = pushArgument(mb, q, a->nr);
3499 29641 : bool enabled = be->mvc->sa->eb.enabled;
3500 29641 : be->mvc->sa->eb.enabled = false;
3501 29641 : stmt *s = stmt_create(be->mvc->sa, st_append);
3502 29641 : be->mvc->sa->eb.enabled = enabled;
3503 29641 : if(!s) {
3504 0 : freeInstruction(q);
3505 0 : goto bailout;
3506 : }
3507 29641 : s->op1 = c;
3508 29641 : s->op2 = a;
3509 29641 : s->nrcols = c->nrcols;
3510 29641 : s->key = c->key;
3511 29641 : s->nr = getDestVar(q);
3512 29641 : s->q = q;
3513 29641 : pushInstruction(mb, q);
3514 29641 : return s;
3515 :
3516 0 : bailout:
3517 0 : if (be->mvc->sa->eb.enabled)
3518 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3519 : return NULL;
3520 : }
3521 :
3522 : stmt *
3523 95733 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
3524 : {
3525 95733 : MalBlkPtr mb = be->mb;
3526 95733 : InstrPtr q = NULL;
3527 :
3528 95733 : if (!t || cnt->nr < 0)
3529 0 : goto bailout;
3530 95733 : assert(t->s); /* declared table */
3531 95733 : q = newStmtArgs(mb, sqlRef, claimRef, 6);
3532 95733 : if (q == NULL)
3533 0 : goto bailout;
3534 : /* returns offset or offsets */
3535 95733 : q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
3536 95733 : q = pushArgument(mb, q, be->mvc_var);
3537 95733 : q = pushSchema(mb, q, t);
3538 95733 : q = pushStr(mb, q, t->base.name);
3539 95733 : q = pushArgument(mb, q, cnt->nr);
3540 95733 : bool enabled = be->mvc->sa->eb.enabled;
3541 95733 : be->mvc->sa->eb.enabled = false;
3542 95733 : stmt *s = stmt_create(be->mvc->sa, st_claim);
3543 95733 : be->mvc->sa->eb.enabled = enabled;
3544 95733 : if(!s) {
3545 0 : freeInstruction(q);
3546 0 : goto bailout;
3547 : }
3548 95733 : s->op1 = cnt;
3549 95733 : s->op4.tval = t;
3550 95733 : s->nr = getDestVar(q);
3551 95733 : s->q = q;
3552 95733 : pushInstruction(mb, q);
3553 95733 : return s;
3554 :
3555 0 : bailout:
3556 0 : if (be->mvc->sa->eb.enabled)
3557 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3558 : return NULL;
3559 : }
3560 :
3561 : void
3562 138973 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
3563 : {
3564 138973 : MalBlkPtr mb = be->mb;
3565 138973 : InstrPtr q = NULL;
3566 :
3567 138973 : if (!t || cnt->nr < 0)
3568 0 : goto bailout;
3569 138973 : q = newStmtArgs(mb, sqlRef, dependRef, 4);
3570 138974 : if (q == NULL)
3571 0 : goto bailout;
3572 138974 : q = pushSchema(mb, q, t);
3573 138973 : q = pushStr(mb, q, t->base.name);
3574 138972 : q = pushArgument(mb, q, cnt->nr);
3575 138972 : pushInstruction(mb, q);
3576 138972 : return;
3577 :
3578 0 : bailout:
3579 0 : if (be->mvc->sa->eb.enabled)
3580 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3581 : }
3582 :
3583 : void
3584 14878 : stmt_add_column_predicate(backend *be, sql_column *c)
3585 : {
3586 14878 : MalBlkPtr mb = be->mb;
3587 14878 : InstrPtr q = NULL;
3588 :
3589 14878 : if (!c)
3590 0 : goto bailout;
3591 14878 : q = newStmtArgs(mb, sqlRef, predicateRef, 4);
3592 14878 : if (q == NULL)
3593 0 : goto bailout;
3594 14878 : q = pushSchema(mb, q, c->t);
3595 14878 : q = pushStr(mb, q, c->t->base.name);
3596 14878 : q = pushStr(mb, q, c->base.name);
3597 14878 : pushInstruction(mb, q);
3598 14878 : return;
3599 :
3600 0 : bailout:
3601 0 : if (be->mvc->sa->eb.enabled)
3602 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3603 : }
3604 :
3605 : stmt *
3606 55373 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
3607 : {
3608 55373 : MalBlkPtr mb = be->mb;
3609 55373 : InstrPtr q = NULL;
3610 :
3611 55373 : if (r->nr < 0)
3612 0 : goto bailout;
3613 :
3614 55373 : q = newStmt(mb, batRef, replaceRef);
3615 55373 : if (q == NULL)
3616 0 : goto bailout;
3617 55373 : q = pushArgument(mb, q, r->nr);
3618 55373 : q = pushArgument(mb, q, id->nr);
3619 55373 : q = pushArgument(mb, q, val->nr);
3620 55373 : q = pushBit(mb, q, TRUE); /* forced */
3621 55373 : bool enabled = be->mvc->sa->eb.enabled;
3622 55373 : be->mvc->sa->eb.enabled = false;
3623 55373 : stmt *s = stmt_create(be->mvc->sa, st_replace);
3624 55373 : be->mvc->sa->eb.enabled = enabled;
3625 55373 : if(!s) {
3626 0 : freeInstruction(q);
3627 0 : goto bailout;
3628 : }
3629 55373 : s->op1 = r;
3630 55373 : s->op2 = id;
3631 55373 : s->op3 = val;
3632 55373 : s->nrcols = r->nrcols;
3633 55373 : s->key = r->key;
3634 55373 : s->nr = getDestVar(q);
3635 55373 : s->q = q;
3636 55373 : s->cand = r->cand;
3637 55373 : pushInstruction(mb, q);
3638 55373 : return s;
3639 :
3640 0 : bailout:
3641 0 : if (be->mvc->sa->eb.enabled)
3642 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3643 : return NULL;
3644 : }
3645 :
3646 : stmt *
3647 41827 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
3648 : {
3649 41827 : MalBlkPtr mb = be->mb;
3650 41827 : InstrPtr q = NULL;
3651 :
3652 41827 : if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
3653 2 : int *l = ATOMIC_PTR_GET(&t->data), cnt = ol_length(t->columns)+1;
3654 :
3655 6 : for (int i = 0; i < cnt; i++) {
3656 4 : q = newStmt(mb, batRef, deleteRef);
3657 4 : if (q == NULL)
3658 0 : goto bailout;
3659 4 : q = pushArgument(mb, q, l[i]);
3660 4 : pushInstruction(mb, q);
3661 : }
3662 : /* declared tables don't have sequences */
3663 : } else {
3664 41825 : q = newStmt(mb, sqlRef, clear_tableRef);
3665 41824 : if (q == NULL)
3666 0 : goto bailout;
3667 41824 : q = pushSchema(mb, q, t);
3668 41824 : q = pushStr(mb, q, t->base.name);
3669 41825 : q = pushInt(mb, q, restart_sequences);
3670 41825 : pushInstruction(mb, q);
3671 : }
3672 41827 : stmt *s = stmt_create(be->mvc->sa, st_table_clear);
3673 :
3674 41826 : if(!s) {
3675 0 : goto bailout;
3676 : }
3677 41826 : s->op4.tval = t;
3678 41826 : s->nrcols = 0;
3679 41826 : s->nr = getDestVar(q);
3680 41826 : s->q = q;
3681 41826 : return s;
3682 :
3683 0 : bailout:
3684 0 : if (be->mvc->sa->eb.enabled)
3685 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3686 : return NULL;
3687 : }
3688 :
3689 : stmt *
3690 39495 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
3691 : {
3692 39495 : MalBlkPtr mb = be->mb;
3693 39495 : InstrPtr q = NULL;
3694 :
3695 39495 : if (cond->nr < 0)
3696 : return NULL;
3697 :
3698 : /* if(bit(l)) { error(r);} ==raising an exception */
3699 39495 : q = newStmt(mb, sqlRef, assertRef);
3700 39495 : if (q == NULL)
3701 0 : goto bailout;
3702 39495 : q = pushArgument(mb, q, cond->nr);
3703 39495 : q = pushStr(mb, q, errstr);
3704 39495 : bool enabled = be->mvc->sa->eb.enabled;
3705 39495 : be->mvc->sa->eb.enabled = false;
3706 39495 : stmt *s = stmt_create(be->mvc->sa, st_exception);
3707 39495 : be->mvc->sa->eb.enabled = enabled;
3708 39495 : if(!s) {
3709 0 : freeInstruction(q);
3710 0 : return NULL;
3711 : }
3712 39495 : assert(cond);
3713 39495 : s->op1 = cond;
3714 39495 : (void)errcode;
3715 39495 : s->nrcols = 0;
3716 39495 : s->q = q;
3717 39495 : s->nr = getDestVar(q);
3718 39495 : pushInstruction(mb, q);
3719 39495 : return s;
3720 :
3721 0 : bailout:
3722 0 : if (be->mvc->sa->eb.enabled)
3723 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3724 : return NULL;
3725 : }
3726 :
3727 : /* The type setting is not propagated to statements such as st_bat and st_append,
3728 : because they are not considered projections */
3729 : static void
3730 14825 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
3731 : {
3732 39939 : for (;;) {
3733 39939 : switch (st->type) {
3734 3689 : case st_const:
3735 3689 : st = st->op2;
3736 3689 : continue;
3737 18031 : case st_alias:
3738 : case st_gen_group:
3739 : case st_order:
3740 18031 : st = st->op1;
3741 18031 : continue;
3742 0 : case st_list:
3743 0 : st = st->op4.lval->h->data;
3744 0 : continue;
3745 3394 : case st_join:
3746 : case st_join2:
3747 : case st_joinN:
3748 3394 : if (st->flag == cmp_project) {
3749 3394 : st = st->op2;
3750 3394 : continue;
3751 : }
3752 : return;
3753 2780 : case st_aggr:
3754 : case st_Nop: {
3755 2780 : list *res = st->op4.funcval->res;
3756 :
3757 2780 : if (res && list_length(res) == 1)
3758 2780 : res->h->data = t;
3759 : return;
3760 : }
3761 6727 : case st_atom:
3762 6727 : st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
3763 6727 : return;
3764 60 : case st_convert:
3765 : case st_temp:
3766 : case st_single:
3767 60 : st->op4.typeval = *t;
3768 60 : return;
3769 86 : case st_var:
3770 86 : if (st->op4.typeval.type)
3771 86 : st->op4.typeval = *t;
3772 : return;
3773 : default:
3774 : return;
3775 : }
3776 : }
3777 : }
3778 :
3779 : #define trivial_string_conversion(x) ((x) == EC_BIT || (x) == EC_CHAR || (x) == EC_STRING || (x) == EC_NUM || (x) == EC_POS || (x) == EC_FLT \
3780 : || (x) == EC_DATE || (x) == EC_BLOB || (x) == EC_MONTH)
3781 :
3782 : static stmt *
3783 351 : temporal_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t, bool before)
3784 : {
3785 351 : MalBlkPtr mb = be->mb;
3786 351 : InstrPtr q = NULL;
3787 351 : const char *convert = t->type->impl, *mod = mtimeRef;
3788 351 : bool add_tz = false, pushed = (v->cand && v->cand == sel), cand = 0;
3789 :
3790 351 : if (before) {
3791 290 : if (f->type->eclass == EC_TIMESTAMP_TZ && (t->type->eclass == EC_TIMESTAMP || t->type->eclass == EC_TIME)) {
3792 : /* call timestamp+local_timezone */
3793 : convert = "timestamp_add_msec_interval";
3794 : add_tz = true;
3795 211 : } else if (f->type->eclass == EC_TIMESTAMP_TZ && t->type->eclass == EC_DATE) {
3796 : /* call convert timestamp with tz to date */
3797 13 : convert = "datetz";
3798 13 : mod = calcRef;
3799 13 : add_tz = true;
3800 198 : } else if (f->type->eclass == EC_TIMESTAMP && t->type->eclass == EC_TIMESTAMP_TZ) {
3801 : /* call timestamp+local_timezone */
3802 : convert = "timestamp_sub_msec_interval";
3803 : add_tz = true;
3804 159 : } else if (f->type->eclass == EC_TIME_TZ && (t->type->eclass == EC_TIME || t->type->eclass == EC_TIMESTAMP)) {
3805 : /* call times+local_timezone */
3806 : convert = "time_add_msec_interval";
3807 : add_tz = true;
3808 146 : } else if (f->type->eclass == EC_TIME && t->type->eclass == EC_TIME_TZ) {
3809 : /* call times+local_timezone */
3810 : convert = "time_sub_msec_interval";
3811 : add_tz = true;
3812 131 : } else if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass)) {
3813 124 : if (t->type->eclass == EC_TIME_TZ)
3814 : convert = "daytimetz";
3815 : else
3816 100 : convert = "timestamptz";
3817 124 : mod = calcRef;
3818 124 : add_tz = true;
3819 124 : cand = 1;
3820 : } else {
3821 : return v;
3822 : }
3823 : } else {
3824 61 : if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIMESTAMP_TZ) {
3825 : convert = "timestamp_sub_msec_interval";
3826 : add_tz = true;
3827 56 : } else if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIME_TZ) {
3828 : convert = "time_sub_msec_interval";
3829 : add_tz = true;
3830 : } else {
3831 : return v;
3832 : }
3833 : }
3834 :
3835 288 : if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) { /* simple calc */
3836 171 : q = newStmtArgs(mb, mod, convert, 13);
3837 171 : if (q == NULL)
3838 0 : goto bailout;
3839 : } else {
3840 117 : if (sel && !pushed && v->nrcols == 0) {
3841 1 : pushed = 1;
3842 1 : v = stmt_project(be, sel, v);
3843 1 : v->cand = sel;
3844 : }
3845 117 : q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
3846 117 : if (q == NULL)
3847 0 : goto bailout;
3848 : }
3849 288 : q = pushArgument(mb, q, v->nr);
3850 :
3851 288 : if (cand) {
3852 124 : if (sel && !pushed && !v->cand) {
3853 14 : q = pushArgument(mb, q, sel->nr);
3854 14 : pushed = 1;
3855 110 : } else if (v->nrcols > 0) {
3856 18 : q = pushNilBat(mb, q);
3857 : }
3858 : }
3859 :
3860 288 : if (EC_VARCHAR(f->type->eclass))
3861 124 : q = pushInt(mb, q, t->digits);
3862 :
3863 288 : if (add_tz)
3864 288 : q = pushLng(mb, q, be->mvc->timezone);
3865 :
3866 288 : if (!cand) {
3867 164 : if (sel && !pushed && !v->cand) {
3868 2 : q = pushArgument(mb, q, sel->nr);
3869 2 : pushed = 1;
3870 162 : } else if (v->nrcols > 0) {
3871 83 : q = pushNilBat(mb, q);
3872 : }
3873 : }
3874 :
3875 288 : bool enabled = be->mvc->sa->eb.enabled;
3876 288 : be->mvc->sa->eb.enabled = false;
3877 288 : stmt *s = stmt_create(be->mvc->sa, st_convert);
3878 288 : be->mvc->sa->eb.enabled = enabled;
3879 288 : if(!s) {
3880 0 : freeInstruction(q);
3881 0 : goto bailout;
3882 : }
3883 288 : s->op1 = v;
3884 288 : s->nrcols = 0; /* function without arguments returns single value */
3885 288 : s->key = v->key;
3886 288 : s->nrcols = v->nrcols;
3887 288 : s->aggr = v->aggr;
3888 288 : s->op4.typeval = *t;
3889 288 : s->nr = getDestVar(q);
3890 288 : s->q = q;
3891 288 : s->cand = pushed ? sel : NULL;
3892 288 : pushInstruction(mb, q);
3893 288 : return s;
3894 :
3895 0 : bailout:
3896 0 : if (be->mvc->sa->eb.enabled)
3897 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
3898 : return NULL;
3899 : }
3900 :
3901 : stmt *
3902 51294 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
3903 : {
3904 51294 : MalBlkPtr mb = be->mb;
3905 51294 : InstrPtr q = NULL;
3906 51294 : const char *convert = t->type->impl, *mod = calcRef;
3907 51294 : int pushed = (v->cand && v->cand == sel), no_candidates = 0;
3908 51294 : bool add_tz = false;
3909 : /* convert types and make sure they are rounded up correctly */
3910 :
3911 51294 : if (v->nr < 0)
3912 0 : goto bailout;
3913 :
3914 51294 : if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
3915 : /* general cases */
3916 50935 : ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
3917 50935 : !EC_INTERVAL(f->type->eclass) && f->type->eclass != EC_DEC && (t->digits == 0 || f->digits == t->digits) && type_has_tz(t) == type_has_tz(f)) ||
3918 : /* trivial decimal cases */
3919 1768 : (f->type->eclass == EC_DEC && t->type->eclass == EC_DEC && f->scale == t->scale && f->type->localtype == t->type->localtype) ||
3920 : /* trivial string cases */
3921 44196 : (EC_VARCHAR(f->type->eclass) && EC_VARCHAR(t->type->eclass) && (t->digits == 0 || (f->digits > 0 && t->digits >= f->digits))))) {
3922 : /* set output type. Despite the MAL code already being generated, the output type may still be checked */
3923 14825 : tail_set_type(be->mvc, v, t);
3924 14825 : return v;
3925 : }
3926 :
3927 : /* external types have sqlname convert functions,
3928 : these can generate errors (fromstr cannot) */
3929 36469 : if (t->type->eclass == EC_EXTERNAL)
3930 331 : convert = t->type->base.name;
3931 36138 : else if (t->type->eclass == EC_MONTH)
3932 : convert = "month_interval";
3933 36115 : else if (t->type->eclass == EC_SEC)
3934 100 : convert = "second_interval";
3935 :
3936 36469 : no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
3937 :
3938 36469 : if ((type_has_tz(f) && !type_has_tz(t) && !EC_VARCHAR(t->type->eclass)) || (!type_has_tz(f) && type_has_tz(t))) {
3939 290 : v = temporal_convert(be, v, sel, f, t, true);
3940 290 : sel = NULL;
3941 290 : pushed = 0;
3942 290 : if (EC_VARCHAR(f->type->eclass))
3943 : return v;
3944 : }
3945 :
3946 : /* Lookup the sql convert function, there is no need
3947 : * for single value vs bat, this is handled by the
3948 : * mal function resolution */
3949 36345 : if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) { /* simple calc */
3950 8168 : q = newStmtArgs(mb, mod, convert, 13);
3951 8168 : if (q == NULL)
3952 0 : goto bailout;
3953 28198 : } else if ((v->nrcols > 0 || (sel && sel->nrcols > 0)) && no_candidates) {
3954 21 : int type = t->type->localtype;
3955 :
3956 : /* with our current implementation, all internal SQL types have candidate list support on their conversions */
3957 21 : if (sel && !pushed) {
3958 0 : pushed = 1;
3959 0 : v = stmt_project(be, sel, v);
3960 0 : v->cand = sel;
3961 : }
3962 21 : q = newStmtArgs(mb, malRef, multiplexRef, 15);
3963 21 : if (q == NULL)
3964 0 : goto bailout;
3965 21 : setVarType(mb, getArg(q, 0), newBatType(type));
3966 21 : q = pushStr(mb, q, convertMultiplexMod(mod, convert));
3967 21 : q = pushStr(mb, q, convertMultiplexFcn(convert));
3968 : } else {
3969 28156 : if (v->nrcols == 0 && sel && !pushed) {
3970 877 : pushed = 1;
3971 877 : v = stmt_project(be, sel, v);
3972 877 : v->cand = sel;
3973 : }
3974 28156 : q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
3975 28156 : if (q == NULL)
3976 0 : goto bailout;
3977 : }
3978 :
3979 : /* convert to string is complex, we need full type info and mvc for the timezone */
3980 36519 : if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
3981 1852 : q = pushInt(mb, q, f->type->eclass);
3982 1852 : q = pushInt(mb, q, f->digits);
3983 1852 : q = pushInt(mb, q, f->scale);
3984 1852 : q = pushInt(mb, q, type_has_tz(f));
3985 34493 : } else if (f->type->eclass == EC_DEC) {
3986 : /* scale of the current decimal */
3987 1552 : q = pushInt(mb, q, f->scale);
3988 32941 : } else if (f->type->eclass == EC_SEC && (EC_COMPUTE(t->type->eclass) || t->type->eclass == EC_DEC)) {
3989 : /* scale of the current decimal */
3990 0 : q = pushInt(mb, q, 3);
3991 : }
3992 36345 : q = pushArgument(mb, q, v->nr);
3993 36345 : if (add_tz)
3994 : q = pushLng(mb, q, be->mvc->timezone);
3995 36345 : if (sel && !pushed && !v->cand) {
3996 3492 : q = pushArgument(mb, q, sel->nr);
3997 3492 : pushed = 1;
3998 32853 : } else if (v->nrcols > 0 && !no_candidates) {
3999 24664 : q = pushNilBat(mb, q);
4000 : }
4001 36345 : if (!add_tz && (t->type->eclass == EC_DEC || EC_TEMP_FRAC(t->type->eclass) || EC_INTERVAL(t->type->eclass))) {
4002 : /* digits, scale of the result decimal */
4003 3058 : q = pushInt(mb, q, t->digits);
4004 3058 : if (!EC_TEMP_FRAC(t->type->eclass))
4005 2719 : q = pushInt(mb, q, t->scale);
4006 : }
4007 : /* convert to string, give error on to large strings */
4008 36519 : if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
4009 1852 : q = pushInt(mb, q, t->digits);
4010 : /* convert a string to a time(stamp) with time zone */
4011 36345 : if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass))
4012 : //q = pushInt(mb, q, type_has_tz(t));
4013 0 : q = pushLng(mb, q, be->mvc->timezone);
4014 36345 : if (t->type->eclass == EC_GEOM) {
4015 : /* push the type and coordinates of the column */
4016 687 : q = pushInt(mb, q, t->digits);
4017 : /* push the SRID of the whole columns */
4018 687 : q = pushInt(mb, q, t->scale);
4019 : /* push the type and coordinates of the inserted value */
4020 : //q = pushInt(mb, q, f->digits);
4021 : /* push the SRID of the inserted value */
4022 : //q = pushInt(mb, q, f->scale);
4023 : /* we decided to create the EWKB type also used by PostGIS and has the SRID provided by the user inside already */
4024 : /* push the SRID provided for this value */
4025 : /* GEOS library is able to store in the returned wkb the type an
4026 : * number if coordinates but not the SRID so SRID should be provided
4027 : * from this level */
4028 : /* if(be->argc > 1)
4029 : f->scale = ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival;
4030 :
4031 : q = pushInt(mb, q, f->digits);
4032 : q = pushInt(mb, q, f->scale);
4033 : */ //q = pushInt(mb, q, ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival);
4034 : }
4035 :
4036 36345 : bool enabled = be->mvc->sa->eb.enabled;
4037 36345 : be->mvc->sa->eb.enabled = false;
4038 36345 : stmt *s = stmt_create(be->mvc->sa, st_convert);
4039 36345 : be->mvc->sa->eb.enabled = enabled;
4040 36345 : if(!s) {
4041 0 : freeInstruction(q);
4042 0 : goto bailout;
4043 : }
4044 36345 : s->op1 = v;
4045 36345 : s->nrcols = 0; /* function without arguments returns single value */
4046 36345 : s->key = v->key;
4047 36345 : s->nrcols = v->nrcols;
4048 36345 : s->aggr = v->aggr;
4049 36345 : s->op4.typeval = *t;
4050 36345 : s->nr = getDestVar(q);
4051 36345 : s->q = q;
4052 36345 : s->cand = pushed ? sel : NULL;
4053 36345 : pushInstruction(mb, q);
4054 36345 : if ((!type_has_tz(f) && type_has_tz(t)))
4055 61 : return temporal_convert(be, s, NULL, f, t, false);
4056 : return s;
4057 :
4058 0 : bailout:
4059 0 : if (be->mvc->sa->eb.enabled)
4060 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4061 : return NULL;
4062 : }
4063 :
4064 : stmt *
4065 27062 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
4066 : {
4067 27062 : list *ops = sa_list(be->mvc->sa);
4068 27062 : list_append(ops, op1);
4069 27062 : stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
4070 27062 : if (r && !r->cand)
4071 27062 : r->cand = op1->cand;
4072 27062 : return r;
4073 : }
4074 :
4075 : stmt *
4076 44189 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
4077 : {
4078 44189 : list *ops = sa_list(be->mvc->sa);
4079 44189 : list_append(ops, op1);
4080 44189 : list_append(ops, op2);
4081 44189 : stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
4082 44189 : if (r && !r->cand)
4083 44189 : r->cand = op1->cand?op1->cand:op2->cand;
4084 44189 : return r;
4085 : }
4086 :
4087 : #define LANG_INT_OR_MAL(l) ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
4088 :
4089 : stmt *
4090 216956 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
4091 : {
4092 216956 : MalBlkPtr mb = be->mb;
4093 216956 : InstrPtr q = NULL;
4094 216956 : const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
4095 216957 : sql_subtype *tpe = NULL;
4096 216957 : int push_cands = 0, default_nargs;
4097 216957 : stmt *o = NULL, *card = NULL;
4098 :
4099 216957 : if (ops == NULL)
4100 0 : goto bailout;
4101 :
4102 216957 : if (rows) {
4103 103 : if (sel) /* if there's a candidate list, use it instead of 'rows' */
4104 0 : rows = sel;
4105 : o = rows;
4106 216854 : } else if (list_length(ops->op4.lval)) {
4107 215052 : o = ops->op4.lval->h->data;
4108 642140 : for (node *n = ops->op4.lval->h; n; n = n->next) {
4109 427088 : stmt *c = n->data;
4110 :
4111 427088 : if (c && o->nrcols < c->nrcols)
4112 427088 : o = c;
4113 : }
4114 : }
4115 :
4116 : /* handle nullif */
4117 216956 : if (list_length(ops->op4.lval) == 2 &&
4118 135218 : strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
4119 95 : stmt *e1 = ops->op4.lval->h->data;
4120 95 : stmt *e2 = ops->op4.lval->h->next->data;
4121 95 : int nrcols = 0;
4122 :
4123 95 : nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols;
4124 : /* nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) */
4125 95 : if (strcmp(f->func->base.name, "nullif") == 0) {
4126 95 : const char *mod = (!nrcols)?calcRef:batcalcRef;
4127 95 : sql_subtype *t = tail_type(e1);
4128 95 : int tt = t->type->localtype;
4129 95 : q = newStmt(mb, mod, "==");
4130 95 : if (q == NULL)
4131 0 : goto bailout;
4132 95 : q = pushArgument(mb, q, e1->nr);
4133 95 : q = pushArgument(mb, q, e2->nr);
4134 95 : int nr = getDestVar(q);
4135 95 : pushInstruction(mb, q);
4136 :
4137 95 : q = newStmt(mb, mod, ifthenelseRef);
4138 95 : if (q == NULL)
4139 0 : goto bailout;
4140 95 : q = pushArgument(mb, q, nr);
4141 95 : q = pushNil(mb, q, tt);
4142 95 : q = pushArgument(mb, q, e1->nr);
4143 95 : pushInstruction(mb, q);
4144 : }
4145 95 : push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
4146 : }
4147 95 : if (q == NULL) {
4148 216862 : if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
4149 2 : goto bailout;
4150 216861 : mod = sql_func_mod(f->func);
4151 216861 : fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
4152 216859 : push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
4153 225992 : default_nargs = (f->res && list_length(f->res) ? list_length(f->res) : 1) + list_length(ops->op4.lval) + (o && o->nrcols > 0 ? 6 : 4);
4154 216857 : if (rows) {
4155 103 : card = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(be->mvc, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
4156 103 : default_nargs++;
4157 : }
4158 :
4159 216857 : if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
4160 137113 : sql_subtype *res = f->res->h->data;
4161 :
4162 137113 : q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
4163 137114 : if (q == NULL)
4164 0 : goto bailout;
4165 137114 : if (rows)
4166 103 : q = pushArgument(mb, q, card->nr);
4167 137114 : q = pushStr(mb, q, mod);
4168 137114 : q = pushStr(mb, q, fimp);
4169 137114 : setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
4170 : } else {
4171 79744 : q = newStmtArgs(mb, mod, fimp, default_nargs);
4172 79747 : if (q == NULL)
4173 0 : goto bailout;
4174 :
4175 79747 : if (rows)
4176 0 : q = pushArgument(mb, q, card->nr);
4177 79747 : if (f->res && list_length(f->res)) {
4178 70613 : sql_subtype *res = f->res->h->data;
4179 :
4180 70613 : setVarType(mb, getArg(q, 0), res->type->localtype);
4181 : }
4182 : }
4183 216861 : if (LANG_EXT(f->func->lang)) {
4184 : /* TODO LOADER functions still use information in sql_subfunc struct
4185 : that won't be visible to other sessions if another function uses them.
4186 : It has to be cleaned up */
4187 221 : if (f->func->type == F_LOADER)
4188 25 : q = pushPtr(mb, q, f);
4189 : else
4190 196 : q = pushPtr(mb, q, f->func);
4191 : }
4192 216861 : if (f->func->lang == FUNC_LANG_C) {
4193 35 : q = pushBit(mb, q, 0);
4194 216826 : } else if (f->func->lang == FUNC_LANG_CPP) {
4195 1 : q = pushBit(mb, q, 1);
4196 : }
4197 216861 : if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY ||
4198 : f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) {
4199 221 : q = pushStr(mb, q, f->func->query);
4200 : }
4201 : /* first dynamic output of copy* functions */
4202 216861 : if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
4203 2684 : q = table_func_create_result(mb, q, f->func, f->res);
4204 216861 : if (list_length(ops->op4.lval))
4205 215045 : tpe = tail_type(ops->op4.lval->h->data);
4206 :
4207 643941 : for (node *n = ops->op4.lval->h; n; n = n->next) {
4208 427080 : stmt *op = n->data;
4209 427080 : q = pushArgument(mb, q, op->nr);
4210 : }
4211 : /* push candidate lists if that's the case */
4212 216861 : if (push_cands) {
4213 76913 : for (node *n = ops->op4.lval->h; n; n = n->next) {
4214 50739 : stmt *op = n->data;
4215 :
4216 50739 : if (op->nrcols > 0) {
4217 28472 : if (op->cand && op->cand == sel) {
4218 3818 : q = pushNilBat(mb, q);
4219 : } else {
4220 24654 : q = pushArgument(mb, q, sel->nr);
4221 : }
4222 : }
4223 : }
4224 : }
4225 : /* special case for round function on decimals */
4226 216861 : if (LANG_INT_OR_MAL(f->func->lang) && strcmp(fimp, "round") == 0 && tpe && tpe->type->eclass == EC_DEC && ops->op4.lval->h && ops->op4.lval->h->data) {
4227 48 : q = pushInt(mb, q, tpe->digits);
4228 48 : q = pushInt(mb, q, tpe->scale);
4229 : }
4230 216861 : pushInstruction(mb, q);
4231 : }
4232 :
4233 216956 : stmt *s = stmt_create(be->mvc->sa, st_Nop);
4234 216956 : if(!s) {
4235 0 : goto bailout;
4236 : }
4237 216956 : s->op1 = ops;
4238 216956 : if (o) {
4239 215156 : s->nrcols = o->nrcols;
4240 215156 : s->key = o->key;
4241 215156 : s->aggr = o->aggr;
4242 : } else {
4243 1800 : s->nrcols = 0;
4244 1800 : s->key = 1;
4245 : }
4246 216956 : s->op4.funcval = f;
4247 216956 : s->nr = getDestVar(q);
4248 216956 : s->q = q;
4249 216956 : if (sel && push_cands && s->nrcols)
4250 24659 : s->cand = sel;
4251 : return s;
4252 :
4253 2 : bailout:
4254 2 : if (be->mvc->sa->eb.enabled)
4255 2 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4256 : return NULL;
4257 : }
4258 :
4259 : stmt *
4260 23 : stmt_direct_func(backend *be, InstrPtr q)
4261 : {
4262 23 : if (q) {
4263 23 : stmt *s = stmt_create(be->mvc->sa, st_func);
4264 23 : if(!s) {
4265 : return NULL;
4266 : }
4267 23 : s->flag = op_union;
4268 23 : s->nrcols = 3;
4269 23 : s->nr = getDestVar(q);
4270 23 : s->q = q;
4271 23 : return s;
4272 : }
4273 : return NULL;
4274 : }
4275 :
4276 : stmt *
4277 186 : stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
4278 : {
4279 186 : MalBlkPtr mb = be->mb;
4280 186 : InstrPtr q = NULL;
4281 186 : prop *p = NULL;
4282 :
4283 : /* dump args */
4284 186 : if (ops && ops->nr < 0)
4285 0 : goto bailout;
4286 :
4287 186 : if ((p = find_prop(rel->p, PROP_REMOTE)))
4288 186 : rel->p = prop_remove(rel->p, p);
4289 : /* sql_processrelation may split projections, so make sure the topmost relation only contains references */
4290 186 : rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 1, 1));
4291 186 : if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
4292 0 : goto bailout;
4293 186 : if (p) {
4294 186 : p->p = rel->p;
4295 186 : rel->p = p;
4296 : }
4297 :
4298 186 : if (monet5_create_relational_function(be->mvc, sql_private_module_name, name, rel, ops, NULL, 1) < 0)
4299 0 : goto bailout;
4300 :
4301 186 : int nargs;
4302 186 : sql_rel *r = relational_func_create_result_part1(be->mvc, rel, &nargs);
4303 186 : if (ops)
4304 186 : nargs += list_length(ops->op4.lval);
4305 186 : if (f_union)
4306 0 : q = newStmt(mb, batmalRef, multiplexRef);
4307 : else
4308 186 : q = newStmt(mb, sql_private_module_name, name);
4309 186 : if (q == NULL)
4310 0 : goto bailout;
4311 186 : q = relational_func_create_result_part2(mb, q, r);
4312 186 : if (f_union) {
4313 0 : q = pushStr(mb, q, sql_private_module_name);
4314 0 : q = pushStr(mb, q, name);
4315 : }
4316 186 : if (ops) {
4317 208 : for (node *n = ops->op4.lval->h; n; n = n->next) {
4318 22 : stmt *op = n->data;
4319 :
4320 22 : q = pushArgument(mb, q, op->nr);
4321 : }
4322 : }
4323 :
4324 186 : allocator *sa = be->mvc->sa;
4325 186 : bool enabled = be->mvc->sa->eb.enabled;
4326 186 : be->mvc->sa->eb.enabled = false;
4327 186 : stmt *o = NULL, *s = stmt_create(sa, st_func);
4328 186 : be->mvc->sa->eb.enabled = enabled;
4329 186 : if(!s) {
4330 0 : freeInstruction(q);
4331 0 : goto bailout;
4332 : }
4333 186 : s->op1 = ops;
4334 186 : s->op2 = stmt_atom_string(be, name);
4335 186 : s->op4.rel = rel;
4336 186 : s->flag = f_union;
4337 186 : if (ops && list_length(ops->op4.lval)) {
4338 10 : node *n;
4339 32 : for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
4340 22 : stmt *c = n->data;
4341 :
4342 22 : if (o->nrcols < c->nrcols)
4343 0 : o = c;
4344 : }
4345 : }
4346 :
4347 10 : if (o) {
4348 10 : s->nrcols = o->nrcols;
4349 10 : s->key = o->key;
4350 10 : s->aggr = o->aggr;
4351 : } else {
4352 176 : s->nrcols = 0;
4353 176 : s->key = 1;
4354 : }
4355 186 : s->nr = getDestVar(q);
4356 186 : s->q = q;
4357 186 : pushInstruction(mb, q);
4358 186 : return s;
4359 :
4360 0 : bailout:
4361 0 : if (be->mvc->sa->eb.enabled)
4362 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4363 : return NULL;
4364 : }
4365 :
4366 : stmt *
4367 85034 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
4368 : {
4369 85034 : MalBlkPtr mb = be->mb;
4370 85034 : InstrPtr q = NULL;
4371 85034 : const char *mod, *aggrfunc;
4372 85034 : sql_subtype *res = op->res->h->data;
4373 85034 : int restype = res->type->localtype;
4374 85034 : bool complex_aggr = false;
4375 85034 : int *stmt_nr = NULL;
4376 85034 : int avg = 0;
4377 :
4378 85034 : if (op1->nr < 0)
4379 0 : goto bailout;
4380 85034 : if (backend_create_subfunc(be, op, NULL) < 0)
4381 0 : goto bailout;
4382 85034 : mod = sql_func_mod(op->func);
4383 85034 : aggrfunc = backend_function_imp(be, op->func);
4384 :
4385 85033 : if (LANG_INT_OR_MAL(op->func->lang)) {
4386 84986 : if (strcmp(aggrfunc, "avg") == 0)
4387 : avg = 1;
4388 83616 : if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
4389 76352 : || strcmp(aggrfunc, "str_group_concat") == 0)
4390 : complex_aggr = true;
4391 84986 : if (restype == TYPE_dbl)
4392 1561 : avg = 0;
4393 : }
4394 :
4395 170066 : int argc = 1
4396 85033 : + 2 * avg
4397 85033 : + (LANG_EXT(op->func->lang) != 0)
4398 85033 : + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
4399 85033 : + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
4400 85033 : + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
4401 85033 : + (grp ? 4 : avg + 1);
4402 :
4403 85033 : if (grp) {
4404 6832 : char *aggrF = SA_NEW_ARRAY(be->mvc->sa, char, strlen(aggrfunc) + 4);
4405 6832 : if (!aggrF)
4406 0 : goto bailout;
4407 6832 : stpcpy(stpcpy(aggrF, "sub"), aggrfunc);
4408 6832 : aggrfunc = aggrF;
4409 6832 : if ((grp && grp->nr < 0) || (ext && ext->nr < 0))
4410 0 : goto bailout;
4411 :
4412 6832 : q = newStmtArgs(mb, mod, aggrfunc, argc);
4413 6832 : if (q == NULL)
4414 0 : goto bailout;
4415 6832 : setVarType(mb, getArg(q, 0), newBatType(restype));
4416 6832 : if (avg) { /* for avg also return rest and count */
4417 96 : q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
4418 96 : q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
4419 : }
4420 : } else {
4421 78201 : q = newStmtArgs(mb, mod, aggrfunc, argc);
4422 78201 : if (q == NULL)
4423 0 : goto bailout;
4424 78201 : if (complex_aggr) {
4425 6715 : setVarType(mb, getArg(q, 0), restype);
4426 6715 : if (avg) { /* for avg also return rest and count */
4427 57 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
4428 57 : q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
4429 : }
4430 : }
4431 : }
4432 :
4433 85033 : if (LANG_EXT(op->func->lang))
4434 47 : q = pushPtr(mb, q, op->func);
4435 85033 : if (op->func->lang == FUNC_LANG_R ||
4436 84998 : op->func->lang >= FUNC_LANG_PY ||
4437 : op->func->lang == FUNC_LANG_C ||
4438 : op->func->lang == FUNC_LANG_CPP) {
4439 47 : if (!grp) {
4440 20 : setVarType(mb, getArg(q, 0), restype);
4441 : }
4442 47 : if (op->func->lang == FUNC_LANG_C) {
4443 12 : q = pushBit(mb, q, 0);
4444 35 : } else if (op->func->lang == FUNC_LANG_CPP) {
4445 0 : q = pushBit(mb, q, 1);
4446 : }
4447 47 : q = pushStr(mb, q, op->func->query);
4448 : }
4449 :
4450 85033 : if (op1->type != st_list) {
4451 79168 : q = pushArgument(mb, q, op1->nr);
4452 : } else {
4453 5865 : int i;
4454 5865 : node *n;
4455 :
4456 12130 : for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
4457 6265 : stmt *op = n->data;
4458 :
4459 6265 : if (stmt_nr)
4460 : q = pushArgument(mb, q, stmt_nr[i]);
4461 : else
4462 6265 : q = pushArgument(mb, q, op->nr);
4463 : }
4464 : }
4465 85034 : if (grp) {
4466 6832 : q = pushArgument(mb, q, grp->nr);
4467 6832 : q = pushArgument(mb, q, ext->nr);
4468 6832 : if (LANG_INT_OR_MAL(op->func->lang)) {
4469 6805 : if (avg) /* push nil candidates */
4470 96 : q = pushNilBat(mb, q);
4471 6805 : q = pushBit(mb, q, no_nil);
4472 : }
4473 78202 : } else if (LANG_INT_OR_MAL(op->func->lang) && no_nil && strncmp(aggrfunc, "count", 5) == 0) {
4474 1643 : q = pushBit(mb, q, no_nil);
4475 76559 : } else if (LANG_INT_OR_MAL(op->func->lang) && !nil_if_empty && strncmp(aggrfunc, "sum", 3) == 0) {
4476 0 : q = pushBit(mb, q, FALSE);
4477 76559 : } else if (LANG_INT_OR_MAL(op->func->lang) && avg) { /* push candidates */
4478 57 : q = pushNilBat(mb, q);
4479 57 : q = pushBit(mb, q, no_nil);
4480 : }
4481 :
4482 85034 : bool enabled = be->mvc->sa->eb.enabled;
4483 85034 : be->mvc->sa->eb.enabled = false;
4484 85034 : stmt *s = stmt_create(be->mvc->sa, st_aggr);
4485 85034 : be->mvc->sa->eb.enabled = enabled;
4486 85034 : if(!s) {
4487 0 : freeInstruction(q);
4488 0 : goto bailout;
4489 : }
4490 85034 : s->op1 = op1;
4491 85034 : if (grp) {
4492 6832 : s->op2 = grp;
4493 6832 : s->op3 = ext;
4494 6832 : s->nrcols = 1;
4495 : } else {
4496 78202 : if (!reduce)
4497 0 : s->nrcols = 1;
4498 : }
4499 85034 : s->key = reduce;
4500 85034 : s->aggr = reduce;
4501 85034 : s->flag = no_nil;
4502 85034 : s->op4.funcval = op;
4503 85034 : s->nr = getDestVar(q);
4504 85034 : s->q = q;
4505 85034 : pushInstruction(mb, q);
4506 85034 : return s;
4507 :
4508 0 : bailout:
4509 0 : if (be->mvc->sa->eb.enabled)
4510 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4511 : return NULL;
4512 : }
4513 :
4514 : static stmt *
4515 4936643 : stmt_alias_(backend *be, stmt *op1, int label, const char *tname, const char *alias)
4516 : {
4517 4936643 : assert(label);
4518 4936643 : stmt *s = stmt_create(be->mvc->sa, st_alias);
4519 4936494 : if(!s) {
4520 : return NULL;
4521 : }
4522 4936494 : s->label = label;
4523 4936494 : s->op1 = op1;
4524 4936494 : s->nrcols = op1->nrcols;
4525 4936494 : s->key = op1->key;
4526 4936494 : s->aggr = op1->aggr;
4527 :
4528 4936494 : s->tname = tname;
4529 4936494 : s->cname = alias;
4530 4936494 : s->nr = op1->nr;
4531 4936494 : s->q = op1->q;
4532 4936494 : return s;
4533 : }
4534 :
4535 : stmt *
4536 4372934 : stmt_alias(backend *be, stmt *op1, int label, const char *tname, const char *alias)
4537 : {
4538 : /*
4539 : if (((!op1->tname && !tname) ||
4540 : (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
4541 : op1->cname && strcmp(op1->cname, alias)==0)
4542 : return op1;
4543 : */
4544 4372934 : return stmt_alias_(be, op1, label, tname, alias);
4545 : }
4546 :
4547 : stmt *
4548 563722 : stmt_as(backend *be, stmt *s, stmt *org)
4549 : {
4550 563722 : assert(org->type == st_alias);
4551 563722 : return stmt_alias_(be, s, org->label, org->tname, org->cname);
4552 : }
4553 :
4554 : sql_subtype *
4555 1547500 : tail_type(stmt *st)
4556 : {
4557 8588367 : for (;;) {
4558 8588367 : switch (st->type) {
4559 36649 : case st_const:
4560 36649 : st = st->op2;
4561 36649 : continue;
4562 3374 : case st_uselect:
4563 : case st_semijoin:
4564 : case st_limit:
4565 : case st_limit2:
4566 : case st_sample:
4567 : case st_tunion:
4568 : case st_tdiff:
4569 : case st_tinter:
4570 3374 : return sql_bind_localtype("oid");
4571 587 : case st_uselect2:
4572 587 : if (!st->reduce)
4573 61 : return sql_bind_localtype("bit");
4574 526 : return sql_bind_localtype("oid");
4575 3879557 : case st_append:
4576 : case st_append_bulk:
4577 : case st_replace:
4578 : case st_alias:
4579 : case st_gen_group:
4580 : case st_order:
4581 3879557 : st = st->op1;
4582 3879557 : continue;
4583 0 : case st_list:
4584 0 : st = st->op4.lval->h->data;
4585 0 : continue;
4586 905504 : case st_bat:
4587 905504 : return &st->op4.cval->type;
4588 2019 : case st_idxbat:
4589 2019 : if (hash_index(st->op4.idxval->type)) {
4590 272 : return sql_bind_localtype("lng");
4591 1747 : } else if (oid_index(st->op4.idxval->type)) {
4592 1747 : return sql_bind_localtype("oid");
4593 : }
4594 : /* fall through */
4595 : case st_join:
4596 : case st_join2:
4597 : case st_joinN:
4598 3124704 : if (st->flag == cmp_project) {
4599 3124661 : st = st->op2;
4600 3124661 : continue;
4601 : }
4602 : /* fall through */
4603 : case st_reorder:
4604 : case st_group:
4605 : case st_tid:
4606 : case st_mirror:
4607 15196 : return sql_bind_localtype("oid");
4608 31472 : case st_result:
4609 31472 : return &st->op4.typeval;
4610 0 : case st_table_clear:
4611 0 : return sql_bind_localtype("lng");
4612 154797 : case st_aggr:
4613 : case st_Nop: {
4614 154797 : list *res = st->op4.funcval->res;
4615 :
4616 154797 : if (res && list_length(res) == 1)
4617 154797 : return res->h->data;
4618 :
4619 : return NULL;
4620 : }
4621 151276 : case st_atom:
4622 151276 : return atom_type(st->op4.aval);
4623 280970 : case st_convert:
4624 : case st_temp:
4625 : case st_single:
4626 : case st_rs_column:
4627 280970 : return &st->op4.typeval;
4628 2297 : case st_var:
4629 2297 : if (st->op4.typeval.type)
4630 2297 : return &st->op4.typeval;
4631 : /* fall through */
4632 : case st_exception:
4633 : return NULL;
4634 8 : case st_table:
4635 8 : return sql_bind_localtype("bat");
4636 : default:
4637 0 : assert(0);
4638 : return NULL;
4639 : }
4640 : }
4641 : }
4642 :
4643 : int
4644 6634 : stmt_has_null(stmt *s)
4645 : {
4646 20864 : switch (s->type) {
4647 : case st_aggr:
4648 : case st_semijoin:
4649 : case st_uselect:
4650 : case st_uselect2:
4651 : case st_atom:
4652 : return 0;
4653 8187 : case st_alias:
4654 8187 : return stmt_has_null(s->op1);
4655 6043 : case st_join:
4656 6043 : return stmt_has_null(s->op2);
4657 4212 : case st_bat:
4658 4212 : return s->op4.cval->null;
4659 :
4660 2422 : default:
4661 2422 : return 1;
4662 : }
4663 : }
4664 :
4665 : static const char *
4666 0 : func_name(allocator *sa, const char *n1, const char *n2)
4667 : {
4668 0 : size_t l1 = _strlen(n1), l2;
4669 :
4670 0 : if (!sa)
4671 : return n1;
4672 0 : if (!n2)
4673 0 : return sa_strdup(sa, n1);
4674 0 : l2 = _strlen(n2);
4675 :
4676 0 : if (l2 > 16) { /* only support short names */
4677 0 : char *ns = SA_NEW_ARRAY(sa, char, l2 + 1);
4678 0 : if(!ns)
4679 : return NULL;
4680 0 : snprintf(ns, l2 + 1, "%s", n2);
4681 0 : return ns;
4682 : } else {
4683 0 : char *ns = SA_NEW_ARRAY(sa, char, l1 + l2 + 2), *s = ns;
4684 0 : if(!ns)
4685 : return NULL;
4686 0 : snprintf(ns, l1 + l2 + 2, "%s_%s", n1, n2);
4687 0 : return s;
4688 : }
4689 : }
4690 :
4691 : static const char *_column_name(allocator *sa, stmt *st);
4692 :
4693 : const char *
4694 2654419 : column_name(allocator *sa, stmt *st)
4695 : {
4696 2654419 : if (!st->cname)
4697 0 : st->cname = _column_name(sa, st);
4698 2654419 : return st->cname;
4699 : }
4700 :
4701 : static const char *
4702 0 : _column_name(allocator *sa, stmt *st)
4703 : {
4704 0 : switch (st->type) {
4705 0 : case st_order:
4706 : case st_reorder:
4707 0 : return column_name(sa, st->op1);
4708 0 : case st_const:
4709 : case st_join:
4710 : case st_join2:
4711 : case st_joinN:
4712 0 : return column_name(sa, st->op2);
4713 :
4714 0 : case st_mirror:
4715 : case st_group:
4716 : case st_result:
4717 : case st_append:
4718 : case st_append_bulk:
4719 : case st_replace:
4720 : case st_gen_group:
4721 : case st_semijoin:
4722 : case st_uselect:
4723 : case st_uselect2:
4724 : case st_limit:
4725 : case st_limit2:
4726 : case st_sample:
4727 : case st_tunion:
4728 : case st_tdiff:
4729 : case st_tinter:
4730 : case st_convert:
4731 0 : return column_name(sa, st->op1);
4732 0 : case st_Nop:
4733 : case st_aggr:
4734 : {
4735 0 : const char *cn = column_name(sa, st->op1);
4736 0 : return func_name(sa, st->op4.funcval->func->base.name, cn);
4737 : }
4738 0 : case st_alias:
4739 0 : if (st->op3)
4740 0 : return column_name(sa, st->op3);
4741 : break;
4742 0 : case st_bat:
4743 0 : return st->op4.cval->base.name;
4744 0 : case st_atom:
4745 0 : if (st->op4.aval->data.vtype == TYPE_str)
4746 0 : return atom2string(sa, st->op4.aval);
4747 : /* fall through */
4748 : case st_var:
4749 : case st_temp:
4750 : case st_single:
4751 0 : if (sa)
4752 0 : return sa_strdup(sa, "single_value");
4753 : return "single_value";
4754 :
4755 0 : case st_list:
4756 0 : if (list_length(st->op4.lval))
4757 0 : return column_name(sa, st->op4.lval->h->data);
4758 : /* fall through */
4759 : case st_rs_column:
4760 : return NULL;
4761 : default:
4762 : return NULL;
4763 : }
4764 : return NULL;
4765 : }
4766 :
4767 : const char *
4768 2639071 : table_name(allocator *sa, stmt *st)
4769 : {
4770 2639071 : (void)sa;
4771 2639071 : return st->tname;
4772 : }
4773 :
4774 : const char *
4775 336660 : schema_name(allocator *sa, stmt *st)
4776 : {
4777 3103064 : switch (st->type) {
4778 1193868 : case st_const:
4779 : case st_semijoin:
4780 : case st_join:
4781 : case st_join2:
4782 : case st_joinN:
4783 1193868 : return schema_name(sa, st->op2);
4784 120499 : case st_mirror:
4785 : case st_group:
4786 : case st_result:
4787 : case st_append:
4788 : case st_append_bulk:
4789 : case st_replace:
4790 : case st_gen_group:
4791 : case st_uselect:
4792 : case st_uselect2:
4793 : case st_limit:
4794 : case st_limit2:
4795 : case st_sample:
4796 : case st_tunion:
4797 : case st_tdiff:
4798 : case st_tinter:
4799 : case st_convert:
4800 : case st_Nop:
4801 : case st_aggr:
4802 : /* there are no schema aliases, ie look into the base column */
4803 120499 : if (st->op1)
4804 : return schema_name(sa, st->op1);
4805 : return NULL;
4806 1420790 : case st_alias:
4807 1420790 : return schema_name(sa, st->op1);
4808 201529 : case st_bat:
4809 201529 : return st->op4.cval->t->s->base.name;
4810 : case st_atom:
4811 : return NULL;
4812 : case st_var:
4813 : case st_temp:
4814 : case st_single:
4815 : return NULL;
4816 31367 : case st_list:
4817 31367 : if (list_length(st->op4.lval))
4818 31247 : return schema_name(sa, st->op4.lval->h->data);
4819 : return NULL;
4820 : default:
4821 : return NULL;
4822 : }
4823 : }
4824 :
4825 : stmt *
4826 1118 : stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
4827 : {
4828 1118 : MalBlkPtr mb = be->mb;
4829 1118 : InstrPtr q = NULL;
4830 :
4831 1118 : if (cond->nr < 0)
4832 0 : goto bailout;
4833 1118 : if (anti) {
4834 25 : sql_subtype *bt = sql_bind_localtype("bit");
4835 25 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
4836 25 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
4837 25 : sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
4838 25 : cond = stmt_binop(be,
4839 : stmt_unop(be, cond, NULL, not),
4840 : stmt_unop(be, cond, NULL, isnull), NULL, or);
4841 : }
4842 1118 : if (!loop) { /* if */
4843 1101 : q = newAssignment(mb);
4844 1101 : if (q == NULL)
4845 0 : goto bailout;
4846 1101 : q->barrier = BARRIERsymbol;
4847 1101 : q = pushArgument(mb, q, cond->nr);
4848 : } else { /* while */
4849 17 : int c;
4850 :
4851 17 : if (outer->nr < 0)
4852 0 : goto bailout;
4853 : /* leave barrier */
4854 17 : q = newStmt(mb, calcRef, notRef);
4855 17 : if (q == NULL)
4856 0 : goto bailout;
4857 17 : q = pushArgument(mb, q, cond->nr);
4858 17 : c = getArg(q, 0);
4859 17 : pushInstruction(mb, q);
4860 :
4861 17 : q = newAssignment(mb);
4862 17 : if (q == NULL)
4863 0 : goto bailout;
4864 17 : getArg(q, 0) = outer->nr;
4865 17 : q->barrier = LEAVEsymbol;
4866 17 : q = pushArgument(mb, q, c);
4867 : }
4868 :
4869 1118 : bool enabled = be->mvc->sa->eb.enabled;
4870 1118 : be->mvc->sa->eb.enabled = false;
4871 1118 : stmt *s = stmt_create(be->mvc->sa, st_cond);
4872 1118 : be->mvc->sa->eb.enabled = enabled;
4873 1118 : if(!s) {
4874 0 : freeInstruction(q);
4875 0 : goto bailout;
4876 : }
4877 1118 : s->flag = be->mvc_var; /* keep the mvc_var of the outer context */
4878 1118 : s->loop = loop;
4879 1118 : s->op1 = cond;
4880 1118 : s->nr = getArg(q, 0);
4881 1118 : pushInstruction(mb, q);
4882 1118 : return s;
4883 :
4884 0 : bailout:
4885 0 : if (be->mvc->sa->eb.enabled)
4886 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4887 : return NULL;
4888 : }
4889 :
4890 : stmt *
4891 1118 : stmt_control_end(backend *be, stmt *cond)
4892 : {
4893 1118 : MalBlkPtr mb = be->mb;
4894 1118 : InstrPtr q = NULL;
4895 :
4896 1118 : if (cond->nr < 0)
4897 0 : goto bailout;
4898 :
4899 1118 : if (cond->loop) { /* while */
4900 : /* redo barrier */
4901 17 : q = newAssignment(mb);
4902 17 : if (q == NULL)
4903 0 : goto bailout;
4904 17 : getArg(q, 0) = cond->nr;
4905 17 : q->argc = q->retc = 1;
4906 17 : q->barrier = REDOsymbol;
4907 17 : q = pushBit(mb, q, TRUE);
4908 : } else {
4909 1101 : q = newAssignment(mb);
4910 1101 : if (q == NULL)
4911 0 : goto bailout;
4912 1101 : getArg(q, 0) = cond->nr;
4913 1101 : q->argc = q->retc = 1;
4914 1101 : q->barrier = EXITsymbol;
4915 : }
4916 1118 : be->mvc_var = cond->flag; /* restore old mvc_var from before the barrier */
4917 1118 : bool enabled = be->mvc->sa->eb.enabled;
4918 1118 : be->mvc->sa->eb.enabled = false;
4919 1118 : stmt *s = stmt_create(be->mvc->sa, st_control_end);
4920 1118 : be->mvc->sa->eb.enabled = enabled;
4921 1118 : if(!s) {
4922 0 : freeInstruction(q);
4923 0 : goto bailout;
4924 : }
4925 1118 : s->op1 = cond;
4926 1118 : s->nr = getArg(q, 0);
4927 1118 : pushInstruction(mb, q);
4928 1118 : return s;
4929 :
4930 0 : bailout:
4931 0 : if (be->mvc->sa->eb.enabled)
4932 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
4933 : return NULL;
4934 : }
4935 :
4936 :
4937 : static InstrPtr
4938 206 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
4939 : {
4940 206 : int i;
4941 206 : node *n;
4942 :
4943 206 : if (q == NULL)
4944 : return NULL;
4945 206 : q->retc = q->argc = 0;
4946 1651 : for (i = 0, n = l->h; n; n = n->next, i++) {
4947 1445 : stmt *c = n->data;
4948 :
4949 1445 : q = pushArgument(mb, q, c->nr);
4950 : }
4951 206 : if (q == NULL)
4952 : return NULL;
4953 206 : q->retc = q->argc;
4954 : /* Let's make it a proper assignment */
4955 1651 : for (i = 0, n = l->h; n; n = n->next, i++) {
4956 1445 : stmt *c = n->data;
4957 :
4958 1445 : q = pushArgument(mb, q, c->nr);
4959 : }
4960 : return q;
4961 : }
4962 :
4963 : stmt *
4964 658 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
4965 : {
4966 658 : MalBlkPtr mb = be->mb;
4967 658 : InstrPtr q = NULL;
4968 :
4969 658 : if (val->nr < 0)
4970 0 : goto bailout;
4971 658 : int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
4972 206 : if (args < MAXARG)
4973 : args = MAXARG;
4974 658 : q = newInstructionArgs(mb, NULL, NULL, args);
4975 658 : if (q == NULL)
4976 0 : goto bailout;
4977 658 : q->barrier= RETURNsymbol;
4978 658 : if (val->type == st_table) {
4979 206 : list *l = val->op1->op4.lval;
4980 :
4981 206 : q = dump_cols(mb, l, q);
4982 : } else {
4983 452 : getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
4984 452 : q = pushArgument(mb, q, val->nr);
4985 : }
4986 :
4987 658 : bool enabled = be->mvc->sa->eb.enabled;
4988 658 : be->mvc->sa->eb.enabled = false;
4989 658 : stmt *s = stmt_create(be->mvc->sa, st_return);
4990 658 : be->mvc->sa->eb.enabled = enabled;
4991 658 : if(!s) {
4992 0 : freeInstruction(q);
4993 0 : goto bailout;
4994 : }
4995 658 : s->op1 = val;
4996 658 : s->flag = nr_declared_tables;
4997 658 : s->nr = getDestVar(q);
4998 658 : s->q = q;
4999 658 : pushInstruction(mb, q);
5000 658 : return s;
5001 :
5002 0 : bailout:
5003 0 : if (be->mvc->sa->eb.enabled)
5004 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
5005 : return NULL;
5006 : }
5007 :
5008 : stmt *
5009 1418 : stmt_assign(backend *be, const char *sname, const char *varname, stmt *val, int level)
5010 : {
5011 1418 : MalBlkPtr mb = be->mb;
5012 1418 : InstrPtr q = NULL;
5013 :
5014 1418 : if (val && val->nr < 0)
5015 0 : goto bailout;
5016 1418 : if (level != 0) {
5017 1037 : char *buf, levelstr[16];
5018 :
5019 1037 : if (!val) {
5020 : /* drop declared table */
5021 0 : assert(0);
5022 : }
5023 :
5024 1037 : assert(!sname);
5025 1037 : snprintf(levelstr, sizeof(levelstr), "%d", level);
5026 1037 : buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
5027 1037 : if (!buf)
5028 0 : goto bailout;
5029 1037 : stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
5030 1037 : q = newInstruction(mb, NULL, NULL);
5031 1037 : if (q == NULL) {
5032 0 : goto bailout;
5033 : }
5034 1037 : q->argc = q->retc = 0;
5035 1037 : q = pushArgumentId(mb, q, buf);
5036 1037 : pushInstruction(mb, q);
5037 1037 : q->retc++;
5038 : } else {
5039 381 : assert(sname); /* all global variables have a schema */
5040 381 : q = newStmt(mb, sqlRef, setVariableRef);
5041 381 : if (q == NULL)
5042 0 : goto bailout;
5043 381 : q = pushArgument(mb, q, be->mvc_var);
5044 381 : q = pushStr(mb, q, sname);
5045 381 : q = pushStr(mb, q, varname);
5046 381 : getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
5047 381 : pushInstruction(mb, q);
5048 381 : be->mvc_var = getDestVar(q);
5049 : }
5050 1418 : q = pushArgument(mb, q, val->nr);
5051 :
5052 1418 : bool enabled = be->mvc->sa->eb.enabled;
5053 1418 : be->mvc->sa->eb.enabled = false;
5054 1418 : stmt *s = stmt_create(be->mvc->sa, st_assign);
5055 1418 : be->mvc->sa->eb.enabled = enabled;
5056 1418 : if(!s) {
5057 0 : goto bailout;
5058 : }
5059 1418 : s->op2 = val;
5060 1418 : s->flag = (level << 1);
5061 1418 : s->q = q;
5062 1418 : s->nr = 1;
5063 1418 : return s;
5064 :
5065 0 : bailout:
5066 0 : if (be->mvc->sa->eb.enabled)
5067 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
5068 : return NULL;
5069 : }
5070 :
5071 : stmt *
5072 21384 : const_column(backend *be, stmt *val)
5073 : {
5074 21384 : sql_subtype *ct = tail_type(val);
5075 21384 : MalBlkPtr mb = be->mb;
5076 21384 : InstrPtr q = NULL;
5077 21384 : int tt = ct->type->localtype;
5078 :
5079 21384 : if (val->nr < 0)
5080 0 : goto bailout;
5081 21384 : q = newStmt(mb, batRef, singleRef);
5082 21384 : if (q == NULL)
5083 0 : goto bailout;
5084 21384 : setVarType(mb, getArg(q, 0), newBatType(tt));
5085 21384 : q = pushArgument(mb, q, val->nr);
5086 :
5087 21384 : bool enabled = be->mvc->sa->eb.enabled;
5088 21384 : be->mvc->sa->eb.enabled = false;
5089 21384 : stmt *s = stmt_create(be->mvc->sa, st_single);
5090 21384 : be->mvc->sa->eb.enabled = enabled;
5091 21384 : if(!s) {
5092 0 : freeInstruction(q);
5093 0 : goto bailout;
5094 : }
5095 21384 : s->op1 = val;
5096 21384 : s->op4.typeval = *ct;
5097 21384 : s->nrcols = 1;
5098 :
5099 21384 : s->tname = val->tname;
5100 21384 : s->cname = val->cname;
5101 21384 : s->nr = getDestVar(q);
5102 21384 : s->q = q;
5103 21384 : pushInstruction(mb, q);
5104 21384 : return s;
5105 :
5106 0 : bailout:
5107 0 : if (be->mvc->sa->eb.enabled)
5108 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
5109 : return NULL;
5110 : }
5111 :
5112 : stmt *
5113 10 : stmt_fetch(backend *be, stmt *val)
5114 : {
5115 10 : sql_subtype *ct;
5116 10 : MalBlkPtr mb = be->mb;
5117 10 : InstrPtr q = NULL;
5118 10 : int tt;
5119 :
5120 10 : if (val->nr < 0)
5121 0 : goto bailout;
5122 : /* pick from first column on a table case */
5123 10 : if (val->type == st_table) {
5124 0 : if (list_length(val->op1->op4.lval) > 1)
5125 0 : goto bailout;
5126 0 : val = val->op1->op4.lval->h->data;
5127 : }
5128 10 : ct = tail_type(val);
5129 10 : tt = ct->type->localtype;
5130 :
5131 10 : q = newStmt(mb, algebraRef, fetchRef);
5132 10 : if (q == NULL)
5133 0 : goto bailout;
5134 10 : setVarType(mb, getArg(q, 0), tt);
5135 10 : q = pushArgument(mb, q, val->nr);
5136 10 : q = pushOid(mb, q, 0);
5137 :
5138 10 : bool enabled = be->mvc->sa->eb.enabled;
5139 10 : be->mvc->sa->eb.enabled = false;
5140 10 : stmt *s = stmt_create(be->mvc->sa, st_single);
5141 10 : be->mvc->sa->eb.enabled = enabled;
5142 10 : if(!s) {
5143 0 : freeInstruction(q);
5144 0 : goto bailout;
5145 : }
5146 10 : s->op1 = val;
5147 10 : s->op4.typeval = *ct;
5148 10 : s->nrcols = 0;
5149 :
5150 10 : s->tname = val->tname;
5151 10 : s->cname = val->cname;
5152 10 : s->nr = getDestVar(q);
5153 10 : s->q = q;
5154 10 : pushInstruction(mb, q);
5155 10 : return s;
5156 :
5157 0 : bailout:
5158 0 : if (be->mvc->sa->eb.enabled)
5159 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
5160 : return NULL;
5161 : }
5162 :
5163 : stmt *
5164 1521650 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
5165 : {
5166 1521650 : int label = exp_get_label(exp);
5167 1521647 : const char *name = exp_name(exp);
5168 1521646 : const char *rname = exp_relname(exp);
5169 1521620 : stmt *o = s;
5170 :
5171 1521620 : if (!name && exp_is_atom(exp))
5172 0 : name = sa_strdup(be->mvc->sa, "single_value");
5173 0 : assert(name);
5174 1521620 : s = stmt_alias(be, s, label, rname, name);
5175 1521627 : if (o->flag & OUTER_ZERO)
5176 521 : s->flag |= OUTER_ZERO;
5177 1521627 : return s;
5178 : }
|