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