1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "sql_mem.h"
11#include "sql_stack.h"
12#include "sql_statement.h"
13#include "sql_gencode.h"
14#include "rel_rel.h"
15#include "rel_exp.h"
16#include "rel_prop.h"
17#include "rel_unnest.h"
18#include "rel_optimizer.h"
19
20#include "mal_namespace.h"
21#include "mal_builder.h"
22#include "mal_debugger.h"
23#include "opt_prelude.h"
24
25#include <string.h>
26
27/*
28 * Some utility routines to generate code
29 * The equality operator in MAL is '==' instead of '='.
30 */
31static const char *
32convertMultiplexMod(const char *mod, const char *op)
33{
34 if (strcmp(op, "=") == 0)
35 return "calc";
36 return mod;
37}
38
39static const char *
40convertMultiplexFcn(const char *op)
41{
42 if (strcmp(op, "=") == 0)
43 return "==";
44 return op;
45}
46
47static const char *
48convertOperator(const char *op)
49{
50 if (strcmp(op, "=") == 0)
51 return "==";
52 return op;
53}
54
55static InstrPtr
56multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
57{
58 InstrPtr q = NULL;
59
60 q = newStmt(mb, malRef, multiplexRef);
61 if (q == NULL)
62 return NULL;
63 setVarType(mb, getArg(q, 0), newBatType(rtype));
64 setVarUDFtype(mb, getArg(q, 0));
65 q = pushStr(mb, q, convertMultiplexMod(mod, name));
66 q = pushStr(mb, q, convertMultiplexFcn(name));
67 q = pushArgument(mb, q, o1);
68 q = pushArgument(mb, q, o2);
69 return q;
70}
71
72static InstrPtr
73dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
74{
75 InstrPtr q = NULL;
76
77 if (o1->nr < 0)
78 return NULL;
79 q = newStmt(mb, mod, name);
80 q = pushArgument(mb, q, o1->nr);
81 return q;
82}
83
84static InstrPtr
85dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
86{
87 InstrPtr q = NULL;
88
89 if (o1->nr < 0 || o2->nr < 0)
90 return NULL;
91 q = newStmt(mb, mod, name);
92 q = pushArgument(mb, q, o1->nr);
93 q = pushArgument(mb, q, o2->nr);
94 return q;
95}
96
97static InstrPtr
98pushPtr(MalBlkPtr mb, InstrPtr q, ptr val)
99{
100 int _t;
101 ValRecord cst;
102
103 if (q == NULL)
104 return NULL;
105 cst.vtype= TYPE_ptr;
106 cst.val.pval = val;
107 cst.len = 0;
108 _t = defConstant(mb, TYPE_ptr, &cst);
109 return pushArgument(mb, q, _t);
110}
111
112static InstrPtr
113pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
114{
115 if (t->s)
116 return pushArgument(mb, q, getStrConstant(mb,t->s->base.name));
117 else
118 return pushNil(mb, q, TYPE_str);
119}
120
121void
122create_merge_partitions_accumulator(backend *be)
123{
124 sql_subtype tpe;
125
126 sql_find_subtype(&tpe, "bigint", 0, 0);
127 be->cur_append = constantAtom(be, be->mb, atom_int(be->mvc->sa, &tpe, 0));
128}
129
130int
131add_to_merge_partitions_accumulator(backend *be, int nr)
132{
133 MalBlkPtr mb = be->mb;
134 int help = be->cur_append;
135 InstrPtr q = newStmt(mb, calcRef, "+");
136
137 getArg(q, 0) = be->cur_append = newTmpVariable(mb, TYPE_lng);
138 q = pushArgument(mb, q, help);
139 q = pushArgument(mb, q, nr);
140
141 be->first_statement_generated = true; /* set the first statement as generated */
142
143 return getDestVar(q);
144}
145
146int
147stmt_key(stmt *s)
148{
149 const char *nme = column_name(NULL, s);
150
151 return hash_key(nme);
152}
153
154/* #TODO make proper traversal operations */
155stmt *
156stmt_atom_string(backend *be, const char *S)
157{
158 const char *s = sa_strdup(be->mvc->sa, S);
159 sql_subtype t;
160
161 sql_find_subtype(&t, "varchar", _strlen(s), 0);
162 return stmt_atom(be, atom_string(be->mvc->sa, &t, s));
163}
164
165stmt *
166stmt_atom_string_nil(backend *be)
167{
168 sql_subtype t;
169
170 sql_find_subtype(&t, "clob", 0, 0);
171 return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
172}
173
174stmt *
175stmt_atom_int(backend *be, int i)
176{
177 sql_subtype t;
178
179 sql_find_subtype(&t, "int", 32, 0);
180 return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
181}
182
183stmt *
184stmt_atom_lng(backend *be, lng i)
185{
186 sql_subtype t;
187
188 sql_find_subtype(&t, "bigint", 64, 0);
189 return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
190}
191
192stmt *
193stmt_atom_lng_nil(backend *be)
194{
195 sql_subtype t;
196
197 sql_find_subtype(&t, "bigint", 64, 0);
198 return stmt_atom(be, atom_general(be->mvc->sa, &t, NULL));
199}
200
201stmt *
202stmt_bool(backend *be, int b)
203{
204 sql_subtype t;
205
206 sql_find_subtype(&t, "boolean", 0, 0);
207 if (b) {
208 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
209 } else {
210 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
211 }
212}
213
214static stmt *
215stmt_create(sql_allocator *sa, st_type type)
216{
217 stmt *s = SA_NEW(sa, stmt);
218 if(!s)
219 return NULL;
220
221 s->type = type;
222 s->op1 = NULL;
223 s->op2 = NULL;
224 s->op3 = NULL;
225 s->op4.lval = NULL;
226 s->flag = 0;
227 s->nrcols = 0;
228 s->key = 0;
229 s->aggr = 0;
230 s->nr = 0;
231 s->partition = 0;
232 s->tname = s->cname = NULL;
233 return s;
234}
235
236stmt *
237stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
238{
239 MalBlkPtr mb = be->mb;
240 InstrPtr q = NULL;
241
242 if (s->nr < 0)
243 return NULL;
244 if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
245 return NULL;
246
247 q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
248 if(!q)
249 return NULL;
250
251 /* output variables extent and hist */
252 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
253 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
254 q = pushArgument(mb, q, s->nr);
255 if (grp)
256 q = pushArgument(mb, q, grp->nr);
257 if (q) {
258 stmt *ns = stmt_create(be->mvc->sa, st_group);
259 if (ns == NULL) {
260 freeInstruction(q);
261 return NULL;
262 }
263
264 ns->op1 = s;
265
266 if (grp) {
267 ns->op2 = grp;
268 ns->op3 = ext;
269 ns->op4.stval = cnt;
270 }
271 ns->nrcols = s->nrcols;
272 ns->key = 0;
273 ns->q = q;
274 ns->nr = getDestVar(q);
275 return ns;
276 }
277 return NULL;
278}
279
280stmt *
281stmt_none(backend *be)
282{
283 return stmt_create(be->mvc->sa, st_none);
284}
285
286static int
287create_bat(MalBlkPtr mb, int tt)
288{
289 InstrPtr q = newStmt(mb, batRef, newRef);
290
291 if (q == NULL)
292 return -1;
293 setVarType(mb, getArg(q, 0), newBatType(tt));
294 setVarUDFtype(mb, getArg(q, 0));
295 q = pushType(mb, q, tt);
296 return getDestVar(q);
297}
298
299static int *
300dump_table(sql_allocator *sa, MalBlkPtr mb, sql_table *t)
301{
302 int i = 0;
303 node *n;
304 int *l = SA_NEW_ARRAY(sa, int, list_length(t->columns.set) + 1);
305
306 if (!l)
307 return NULL;
308
309 /* tid column */
310 if ((l[i++] = create_bat(mb, TYPE_oid)) < 0)
311 return NULL;
312
313 for (n = t->columns.set->h; n; n = n->next) {
314 sql_column *c = n->data;
315
316 if ((l[i++] = create_bat(mb, c->type.type->localtype)) < 0)
317 return NULL;
318 }
319 return l;
320}
321
322stmt *
323stmt_var(backend *be, const char *varname, sql_subtype *t, int declare, int level)
324{
325 MalBlkPtr mb = be->mb;
326 InstrPtr q = NULL;
327 char buf[IDLENGTH];
328
329 if (level == 1 ) { /* global */
330 int tt = t->type->localtype;
331
332 q = newStmt(mb, sqlRef, putName("getVariable"));
333 q = pushArgument(mb, q, be->mvc_var);
334 q = pushStr(mb, q, varname);
335 if (q == NULL)
336 return NULL;
337 setVarType(mb, getArg(q, 0), tt);
338 setVarUDFtype(mb, getArg(q, 0));
339 } else if (!declare) {
340 (void) snprintf(buf, sizeof(buf), "A%s", varname);
341 q = newAssignment(mb);
342 q = pushArgumentId(mb, q, buf);
343 } else {
344 int tt;
345
346 tt = t->type->localtype;
347 (void) snprintf(buf, sizeof(buf), "A%s", varname);
348 q = newInstruction(mb, NULL, NULL);
349 if (q == NULL) {
350 return NULL;
351 }
352 q->argc = q->retc = 0;
353 q = pushArgumentId(mb, q, buf);
354 q = pushNil(mb, q, tt);
355 pushInstruction(mb, q);
356 if (q == NULL)
357 return NULL;
358 q->retc++;
359 }
360 if (q) {
361 stmt *s = stmt_create(be->mvc->sa, st_var);
362 if (s == NULL) {
363 freeInstruction(q);
364 return NULL;
365 }
366
367 if (t)
368 s->op4.typeval = *t;
369 else
370 s->op4.typeval.type = NULL;
371 s->flag = declare + (level << 1);
372 s->key = 1;
373 s->q = q;
374 s->nr = getDestVar(q);
375 return s;
376 }
377 return NULL;
378}
379
380stmt *
381stmt_vars(backend *be, const char *varname, sql_table *t, int declare, int level)
382{
383 MalBlkPtr mb = be->mb;
384 InstrPtr q = NULL;
385 int *l;
386
387 (void)varname;
388 /* declared table */
389 if ((l = dump_table(be->mvc->sa, mb, t)) != NULL) {
390 stmt *s = stmt_create(be->mvc->sa, st_var);
391
392 if (s == NULL) {
393 freeInstruction(q);
394 return NULL;
395 }
396
397 t->data = l;
398 /*
399 s->op2 = (stmt*)l;
400 s->op3 = (stmt*)t;
401 */
402 s->flag = declare + (level << 1);
403 s->key = 1;
404 s->nr = l[0];
405 return s;
406 }
407 return NULL;
408}
409
410stmt *
411stmt_varnr(backend *be, int nr, sql_subtype *t)
412{
413 MalBlkPtr mb = be->mb;
414 InstrPtr q = newAssignment(mb);
415
416 if (!q)
417 return NULL;
418 if (be->mvc->argc && be->mvc->args[nr]->varid >= 0) {
419 q = pushArgument(mb, q, be->mvc->args[nr]->varid);
420 } else {
421 char buf[IDLENGTH];
422
423 (void) snprintf(buf, sizeof(buf), "A%d", nr);
424 q = pushArgumentId(mb, q, buf);
425 }
426 if (q) {
427 stmt *s = stmt_create(be->mvc->sa, st_var);
428 if (s == NULL) {
429 freeInstruction(q);
430 return NULL;
431 }
432
433 s->op1 = NULL;
434 if (t)
435 s->op4.typeval = *t;
436 else
437 s->op4.typeval.type = NULL;
438 s->flag = nr;
439 s->key = 1;
440 s->q = q;
441 s->nr = getDestVar(q);
442 return s;
443 }
444 return NULL;
445}
446
447stmt *
448stmt_table(backend *be, stmt *cols, int temp)
449{
450 MalBlkPtr mb = be->mb;
451 InstrPtr q = newAssignment(mb);
452
453 if (cols->nr < 0)
454 return NULL;
455
456 if (cols->type != st_list) {
457 q = newStmt(mb, sqlRef, printRef);
458 q = pushStr(mb, q, "not a valid output list\n");
459 if (q == NULL)
460 return NULL;
461 }
462 if (q) {
463 stmt *s = stmt_create(be->mvc->sa, st_table);
464 if (s == NULL) {
465 freeInstruction(q);
466 return NULL;
467 }
468
469 s->op1 = cols;
470 s->flag = temp;
471 s->nr = cols->nr;
472 s->nrcols = cols->nrcols;
473 return s;
474 }
475 return NULL;
476}
477
478stmt *
479stmt_temp(backend *be, sql_subtype *t)
480{
481 int tt = t->type->localtype;
482 MalBlkPtr mb = be->mb;
483 InstrPtr q = newStmt(mb, batRef, newRef);
484
485 if (q == NULL)
486 return NULL;
487 setVarType(mb, getArg(q, 0), newBatType(tt));
488 setVarUDFtype(mb, getArg(q, 0));
489 q = pushType(mb, q, tt);
490 if (q) {
491 stmt *s = stmt_create(be->mvc->sa, st_temp);
492
493 if (s == NULL) {
494 freeInstruction(q);
495 return NULL;
496 }
497 s->op4.typeval = *t;
498 s->nrcols = 1;
499 s->q = q;
500 s->nr = getDestVar(q);
501 return s;
502 }
503 return NULL;
504}
505
506stmt *
507stmt_tid(backend *be, sql_table *t, int partition)
508{
509 int tt = TYPE_oid;
510 MalBlkPtr mb = be->mb;
511 InstrPtr q;
512
513 if (!t->s && t->data) { /* declared table */
514 stmt *s = stmt_create(be->mvc->sa, st_tid);
515 int *l = t->data;
516
517 assert(partition == 0);
518 s->partition = partition;
519 s->op4.tval = t;
520 s->nrcols = 1;
521 s->nr = l[0];
522 return s;
523 }
524 q = newStmt(mb, sqlRef, tidRef);
525 if (q == NULL)
526 return NULL;
527 setVarType(mb, getArg(q, 0), newBatType(tt));
528 setVarUDFtype(mb, getArg(q, 0));
529 q = pushArgument(mb, q, be->mvc_var);
530 q = pushSchema(mb, q, t);
531 q = pushStr(mb, q, t->base.name);
532 if (q == NULL)
533 return NULL;
534 if (t && (!isRemote(t) && !isMergeTable(t)) && partition) {
535 sql_trans *tr = be->mvc->session->tr;
536 BUN rows = (BUN) store_funcs.count_col(tr, t->columns.set->h->data, 1);
537 setRowCnt(mb,getArg(q,0),rows);
538 if (t->p && 0)
539 setMitosisPartition(q, t->p->base.id);
540 }
541 if (q) {
542 stmt *s = stmt_create(be->mvc->sa, st_tid);
543 if (s == NULL) {
544 freeInstruction(q);
545 return NULL;
546 }
547
548 s->partition = partition;
549 s->op4.tval = t;
550 s->nrcols = 1;
551 s->nr = getDestVar(q);
552 s->q = q;
553 return s;
554 }
555 return NULL;
556}
557
558stmt *
559stmt_bat(backend *be, sql_column *c, int access, int partition)
560{
561 int tt = c->type.type->localtype;
562 MalBlkPtr mb = be->mb;
563 InstrPtr q;
564
565 /* for read access tid.project(col) */
566 if (!c->t->s && c->t->data) { /* declared table */
567 stmt *s = stmt_create(be->mvc->sa, st_bat);
568 int *l = c->t->data;
569
570 assert(partition == 0);
571 s->partition = partition;
572 s->op4.cval = c;
573 s->nrcols = 1;
574 s->flag = access;
575 s->nr = l[c->colnr+1];
576 return s;
577 }
578 q = newStmt(mb, sqlRef, bindRef);
579 if (q == NULL)
580 return NULL;
581 if (access == RD_UPD_ID) {
582 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
583 setVarUDFtype(mb, getArg(q, 0));
584 setVarUDFtype(mb, getArg(q, 1));
585 } else {
586 setVarType(mb, getArg(q, 0), newBatType(tt));
587 setVarUDFtype(mb, getArg(q, 0));
588 }
589 q = pushArgument(mb, q, be->mvc_var);
590 q = pushSchema(mb, q, c->t);
591 q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
592 q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
593 q = pushArgument(mb, q, getIntConstant(mb,access));
594 if (q == NULL)
595 return NULL;
596
597 if (access == RD_UPD_ID) {
598 setVarType(mb, getArg(q, 1), newBatType(tt));
599 setVarUDFtype(mb, getArg(q, 1));
600 }
601 if (access != RD_INS && partition) {
602 sql_trans *tr = be->mvc->session->tr;
603
604 if (c && (!isRemote(c->t) && !isMergeTable(c->t))) {
605 BUN rows = (BUN) store_funcs.count_col(tr, c, 1);
606 setRowCnt(mb,getArg(q,0),rows);
607 if (c->t->p && 0)
608 setMitosisPartition(q, c->t->p->base.id);
609 }
610 }
611 if (q) {
612 stmt *s = stmt_create(be->mvc->sa, st_bat);
613 if (s == NULL) {
614 freeInstruction(q);
615 return NULL;
616 }
617
618 s->partition = partition;
619 s->op4.cval = c;
620 s->nrcols = 1;
621 s->flag = access;
622 s->nr = getDestVar(q);
623 s->q = q;
624 return s;
625 }
626 return NULL;
627}
628
629stmt *
630stmt_idxbat(backend *be, sql_idx *i, int access, int partition)
631{
632 int tt = hash_index(i->type)?TYPE_lng:TYPE_oid;
633 MalBlkPtr mb = be->mb;
634 InstrPtr q = newStmt(mb, sqlRef, bindidxRef);
635
636 if (q == NULL)
637 return NULL;
638
639 if (access == RD_UPD_ID) {
640 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
641 } else {
642 setVarType(mb, getArg(q, 0), newBatType(tt));
643 setVarUDFtype(mb, getArg(q, 0));
644 }
645
646 q = pushArgument(mb, q, be->mvc_var);
647 q = pushSchema(mb, q, i->t);
648 q = pushArgument(mb, q, getStrConstant(mb, i->t->base.name));
649 q = pushArgument(mb, q, getStrConstant(mb, i->base.name));
650 q = pushArgument(mb, q, getIntConstant(mb, access));
651 if (q == NULL)
652 return NULL;
653
654 if (access == RD_UPD_ID) {
655 setVarType(mb, getArg(q, 1), newBatType(tt));
656 setVarUDFtype(mb, getArg(q, 1));
657 }
658 if (access != RD_INS && partition) {
659 sql_trans *tr = be->mvc->session->tr;
660
661 if (i && (!isRemote(i->t) && !isMergeTable(i->t))) {
662 BUN rows = (BUN) store_funcs.count_idx(tr, i, 1);
663 setRowCnt(mb,getArg(q,0),rows);
664 if (i->t->p && 0)
665 setMitosisPartition(q, i->t->p->base.id);
666 }
667 }
668 if (q) {
669 stmt *s = stmt_create(be->mvc->sa, st_idxbat);
670 if (s == NULL) {
671 freeInstruction(q);
672 return NULL;
673 }
674
675 s->partition = partition;
676 s->op4.idxval = i;
677 s->nrcols = 1;
678 s->flag = access;
679 s->nr = getDestVar(q);
680 s->q = q;
681 return s;
682 }
683 return NULL;
684}
685
686stmt *
687stmt_append_col(backend *be, sql_column *c, stmt *b, int fake)
688{
689 MalBlkPtr mb = be->mb;
690 InstrPtr q = NULL;
691
692 if (b->nr < 0)
693 return NULL;
694
695 if (!c->t->s && c->t->data) { /* declared table */
696 int *l = c->t->data;
697
698 if (c->colnr == 0) { /* append to tid column */
699 q = newStmt(mb, sqlRef, "grow");
700 q = pushArgument(mb, q, l[0]);
701 q = pushArgument(mb, q, b->nr);
702 }
703 q = newStmt(mb, batRef, appendRef);
704 q = pushArgument(mb, q, l[c->colnr+1]);
705 q = pushArgument(mb, q, b->nr);
706 q = pushBit(mb, q, TRUE);
707 getArg(q,0) = l[c->colnr+1];
708 } else if (!fake) { /* fake append */
709 q = newStmt(mb, sqlRef, appendRef);
710 q = pushArgument(mb, q, be->mvc_var);
711 if (q == NULL)
712 return NULL;
713 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
714 q = pushSchema(mb, q, c->t);
715 q = pushStr(mb, q, c->t->base.name);
716 q = pushStr(mb, q, c->base.name);
717 q = pushArgument(mb, q, b->nr);
718 if (q == NULL)
719 return NULL;
720 be->mvc_var = getDestVar(q);
721 } else {
722 return b;
723 }
724 if (q) {
725 stmt *s = stmt_create(be->mvc->sa, st_append_col);
726
727 if (s == NULL) {
728 freeInstruction(q);
729 return NULL;
730 }
731 s->op1 = b;
732 s->op4.cval = c;
733 s->q = q;
734 s->nr = getDestVar(q);
735 return s;
736 }
737 return NULL;
738}
739
740stmt *
741stmt_append_idx(backend *be, sql_idx *i, stmt *b)
742{
743 MalBlkPtr mb = be->mb;
744 InstrPtr q = NULL;
745
746 if (b->nr < 0)
747 return NULL;
748
749 q = newStmt(mb, sqlRef, appendRef);
750 q = pushArgument(mb, q, be->mvc_var);
751 if (q == NULL)
752 return NULL;
753 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
754 q = pushSchema(mb, q, i->t);
755 q = pushStr(mb, q, i->t->base.name);
756 q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
757 q = pushArgument(mb, q, b->nr);
758 if (q == NULL)
759 return NULL;
760 be->mvc_var = getDestVar(q);
761 if (q) {
762 stmt *s = stmt_create(be->mvc->sa, st_append_idx);
763 if (s == NULL) {
764 freeInstruction(q);
765 return NULL;
766 }
767
768 s->op1 = b;
769 s->op4.idxval = i;
770 s->q = q;
771 s->nr = getDestVar(q);
772 return s;
773 }
774 return NULL;
775}
776
777stmt *
778stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
779{
780 MalBlkPtr mb = be->mb;
781 InstrPtr q = NULL;
782
783 if (tids->nr < 0 || upd->nr < 0)
784 return NULL;
785
786 if (!c->t->s && c->t->data) { /* declared table */
787 int *l = c->t->data;
788
789 q = newStmt(mb, batRef, updateRef);
790 q = pushArgument(mb, q, l[c->colnr+1]);
791 q = pushArgument(mb, q, tids->nr);
792 q = pushArgument(mb, q, upd->nr);
793 } else {
794 q = newStmt(mb, sqlRef, updateRef);
795 q = pushArgument(mb, q, be->mvc_var);
796 if (q == NULL)
797 return NULL;
798 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
799 q = pushSchema(mb, q, c->t);
800 q = pushStr(mb, q, c->t->base.name);
801 q = pushStr(mb, q, c->base.name);
802 q = pushArgument(mb, q, tids->nr);
803 q = pushArgument(mb, q, upd->nr);
804 if (q == NULL)
805 return NULL;
806 be->mvc_var = getDestVar(q);
807 }
808 if (q){
809 stmt *s = stmt_create(be->mvc->sa, st_update_col);
810
811 if (s == NULL) {
812 freeInstruction(q);
813 return NULL;
814 }
815 s->op1 = tids;
816 s->op2 = upd;
817 s->op4.cval = c;
818 s->q = q;
819 s->nr = getDestVar(q);
820 return s;
821 }
822 return NULL;
823}
824
825
826stmt *
827stmt_update_idx(backend *be, sql_idx *i, stmt *tids, stmt *upd)
828{
829 MalBlkPtr mb = be->mb;
830 InstrPtr q = NULL;
831
832 if (tids->nr < 0 || upd->nr < 0)
833 return NULL;
834
835 q = newStmt(mb, sqlRef, updateRef);
836 q = pushArgument(mb, q, be->mvc_var);
837 if (q == NULL)
838 return NULL;
839 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
840 q = pushSchema(mb, q, i->t);
841 q = pushStr(mb, q, i->t->base.name);
842 q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
843 q = pushArgument(mb, q, tids->nr);
844 q = pushArgument(mb, q, upd->nr);
845 if (q == NULL)
846 return NULL;
847 be->mvc_var = getDestVar(q);
848 if (q) {
849 stmt *s = stmt_create(be->mvc->sa, st_update_idx);
850 if (s == NULL) {
851 freeInstruction(q);
852 return NULL;
853 }
854
855 s->op1 = tids;
856 s->op2 = upd;
857 s->op4.idxval = i;
858 s->q = q;
859 s->nr = getDestVar(q);
860 return s;
861 }
862 return NULL;
863}
864
865stmt *
866stmt_delete(backend *be, sql_table *t, stmt *tids)
867{
868 MalBlkPtr mb = be->mb;
869 InstrPtr q = NULL;
870
871 if (tids->nr < 0)
872 return NULL;
873
874 if (!t->s && t->data) { /* declared table */
875 int *l = t->data;
876
877 q = newStmt(mb, batRef, deleteRef);
878 q = pushArgument(mb, q, l[0]);
879 q = pushArgument(mb, q, tids->nr);
880 } else {
881 q = newStmt(mb, sqlRef, deleteRef);
882 q = pushArgument(mb, q, be->mvc_var);
883 if (q == NULL)
884 return NULL;
885 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
886 q = pushSchema(mb, q, t);
887 q = pushStr(mb, q, t->base.name);
888 q = pushArgument(mb, q, tids->nr);
889 if (q == NULL)
890 return NULL;
891 be->mvc_var = getDestVar(q);
892 }
893 if (q) {
894 stmt *s = stmt_create(be->mvc->sa, st_delete);
895 if (s == NULL) {
896 freeInstruction(q);
897 return NULL;
898 }
899
900 s->op1 = tids;
901 s->op4.tval = t;
902 s->q = q;
903 s->nr = getDestVar(q);
904 return s;
905 }
906 return NULL;
907}
908
909stmt *
910stmt_const(backend *be, stmt *s, stmt *val)
911{
912 InstrPtr q = NULL;
913 MalBlkPtr mb = be->mb;
914
915 if (val)
916 q = dump_2(mb, algebraRef, projectRef, s, val);
917 else
918 q = dump_1(mb, algebraRef, projectRef, s);
919 if (q) {
920 stmt *ns = stmt_create(be->mvc->sa, st_const);
921 if (ns == NULL) {
922 freeInstruction(q);
923 return NULL;
924 }
925
926 ns->op1 = s;
927 ns->op2 = val;
928 ns->nrcols = s->nrcols;
929 ns->key = s->key;
930 ns->aggr = s->aggr;
931 ns->q = q;
932 ns->nr = getDestVar(q);
933 return ns;
934 }
935 return NULL;
936}
937
938stmt *
939stmt_gen_group(backend *be, stmt *gids, stmt *cnts)
940{
941 MalBlkPtr mb = be->mb;
942 InstrPtr q = dump_2(mb, algebraRef, groupbyRef, gids, cnts);
943
944 if (q) {
945 stmt *ns = stmt_create(be->mvc->sa, st_gen_group);
946 if (ns == NULL) {
947 freeInstruction(q);
948 return NULL;
949 }
950
951 ns->op1 = gids;
952 ns->op2 = cnts;
953
954 ns->nrcols = gids->nrcols;
955 ns->key = 0;
956 ns->aggr = 0;
957 ns->q = q;
958 ns->nr = getDestVar(q);
959 return ns;
960 }
961 return NULL;
962}
963
964stmt *
965stmt_mirror(backend *be, stmt *s)
966{
967 MalBlkPtr mb = be->mb;
968 InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
969
970 if (q) {
971 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
972 if (ns == NULL) {
973 freeInstruction(q);
974 return NULL;
975 }
976
977 ns->op1 = s;
978 ns->nrcols = 2;
979 ns->key = s->key;
980 ns->aggr = s->aggr;
981 ns->q = q;
982 ns->nr = getDestVar(q);
983 return ns;
984 }
985 return NULL;
986}
987
988stmt *
989stmt_result(backend *be, stmt *s, int nr)
990{
991 stmt *ns;
992
993 if (s->type == st_join && s->flag == cmp_joined) {
994 if (nr)
995 return s->op2;
996 return s->op1;
997 }
998
999 if (s->op1->nr < 0)
1000 return NULL;
1001
1002 ns = stmt_create(be->mvc->sa, st_result);
1003 if(!ns) {
1004 return NULL;
1005 }
1006 if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
1007 assert(0);
1008 } else if (nr) {
1009 int v = getArg(s->q, nr);
1010
1011 assert(s->q->retc >= nr);
1012 ns->nr = v;
1013 } else {
1014 ns->nr = s->nr;
1015 }
1016 ns->op1 = s;
1017 ns->flag = nr;
1018 ns->nrcols = s->nrcols;
1019 ns->key = s->key;
1020 ns->aggr = s->aggr;
1021 return ns;
1022}
1023
1024
1025/* limit maybe atom nil */
1026stmt *
1027stmt_limit(backend *be, stmt *col, stmt *piv, stmt *gid, stmt *offset, stmt *limit, int distinct, int dir, int nullslast, int last, int order)
1028{
1029 MalBlkPtr mb = be->mb;
1030 InstrPtr q = NULL;
1031 int l, p, g, c;
1032
1033 if (col->nr < 0 || offset->nr < 0 || limit->nr < 0)
1034 return NULL;
1035 if (piv && (piv->nr < 0 || gid->nr < 0))
1036 return NULL;
1037
1038 c = (col) ? col->nr : 0;
1039 p = (piv) ? piv->nr : 0;
1040 g = (gid) ? gid->nr : 0;
1041
1042 /* first insert single value into a bat */
1043 if (col->nrcols == 0) {
1044 int k, tt = tail_type(col)->type->localtype;
1045
1046 q = newStmt(mb, batRef, newRef);
1047 if (q == NULL)
1048 return NULL;
1049 setVarType(mb, getArg(q, 0), newBatType(tt));
1050 setVarUDFtype(mb, getArg(q, 0));
1051 q = pushType(mb, q, tt);
1052 if (q == NULL)
1053 return NULL;
1054 k = getDestVar(q);
1055
1056 q = newStmt(mb, batRef, appendRef);
1057 q = pushArgument(mb, q, k);
1058 q = pushArgument(mb, q, c);
1059 if (q == NULL)
1060 return NULL;
1061 c = k;
1062 }
1063 if (order) {
1064 int topn = 0;
1065
1066 q = newStmt(mb, calcRef, "+");
1067 q = pushArgument(mb, q, offset->nr);
1068 q = pushArgument(mb, q, limit->nr);
1069 if (q == NULL)
1070 return NULL;
1071 topn = getDestVar(q);
1072
1073 q = newStmt(mb, algebraRef, firstnRef);
1074 if (!last) /* we need the groups for the next firstn */
1075 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1076 q = pushArgument(mb, q, c);
1077 if (p)
1078 q = pushArgument(mb, q, p);
1079 if (g)
1080 q = pushArgument(mb, q, g);
1081 q = pushArgument(mb, q, topn);
1082 q = pushBit(mb, q, dir);
1083 q = pushBit(mb, q, nullslast);
1084 q = pushBit(mb, q, distinct != 0);
1085
1086 if (q == NULL)
1087 return NULL;
1088 l = getArg(q, 0);
1089 l = getDestVar(q);
1090 } else {
1091 int len;
1092
1093 q = newStmt(mb, calcRef, "+");
1094 q = pushArgument(mb, q, offset->nr);
1095 q = pushArgument(mb, q, limit->nr);
1096 if (q == NULL)
1097 return NULL;
1098 len = getDestVar(q);
1099
1100 /* since both arguments of algebra.subslice are
1101 inclusive correct the LIMIT value by
1102 subtracting 1 */
1103 q = newStmt(mb, calcRef, "-");
1104 q = pushArgument(mb, q, len);
1105 q = pushInt(mb, q, 1);
1106 if (q == NULL)
1107 return NULL;
1108 len = getDestVar(q);
1109
1110 q = newStmt(mb, algebraRef, subsliceRef);
1111 q = pushArgument(mb, q, c);
1112 q = pushArgument(mb, q, offset->nr);
1113 q = pushArgument(mb, q, len);
1114 if (q == NULL)
1115 return NULL;
1116 l = getDestVar(q);
1117 }
1118 /* retrieve the single values again */
1119 if (col->nrcols == 0) {
1120 q = newStmt(mb, algebraRef, findRef);
1121 q = pushArgument(mb, q, l);
1122 q = pushOid(mb, q, 0);
1123 if (q == NULL)
1124 return NULL;
1125 l = getDestVar(q);
1126 }
1127 if (q) {
1128 stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
1129 if (ns == NULL) {
1130 freeInstruction(q);
1131 return NULL;
1132 }
1133
1134 ns->op1 = col;
1135 ns->op2 = offset;
1136 ns->op3 = limit;
1137 ns->nrcols = col->nrcols;
1138 ns->key = col->key;
1139 ns->aggr = col->aggr;
1140 ns->q = q;
1141 ns->nr = l;
1142 return ns;
1143 }
1144 return NULL;
1145}
1146
1147stmt *
1148stmt_sample(backend *be, stmt *s, stmt *sample, stmt *seed)
1149{
1150 MalBlkPtr mb = be->mb;
1151 InstrPtr q = NULL;
1152
1153 if (s->nr < 0 || sample->nr < 0)
1154 return NULL;
1155 q = newStmt(mb, sampleRef, subuniformRef);
1156 q = pushArgument(mb, q, s->nr);
1157 q = pushArgument(mb, q, sample->nr);
1158
1159 if (seed) {
1160 if (seed->nr < 0)
1161 return NULL;
1162
1163 q = pushArgument(mb, q, seed->nr);
1164 }
1165
1166 if (q) {
1167 stmt *ns = stmt_create(be->mvc->sa, st_sample);
1168 if (ns == NULL) {
1169 freeInstruction(q);
1170 return NULL;
1171 }
1172
1173 ns->op1 = s;
1174 ns->op2 = sample;
1175
1176 if (seed) {
1177 ns->op3 = seed;
1178 }
1179
1180 ns->nrcols = s->nrcols;
1181 ns->key = s->key;
1182 ns->aggr = s->aggr;
1183 ns->flag = 0;
1184 ns->q = q;
1185 ns->nr = getDestVar(q);
1186 return ns;
1187 }
1188 return NULL;
1189}
1190
1191
1192stmt *
1193stmt_order(backend *be, stmt *s, int direction, int nullslast)
1194{
1195 MalBlkPtr mb = be->mb;
1196 InstrPtr q = NULL;
1197
1198 if (s->nr < 0)
1199 return NULL;
1200 q = newStmt(mb, algebraRef, sortRef);
1201 /* both ordered result and oid's order en subgroups */
1202 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1203 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1204 q = pushArgument(mb, q, s->nr);
1205 q = pushBit(mb, q, !direction);
1206 q = pushBit(mb, q, nullslast);
1207 q = pushBit(mb, q, FALSE);
1208 if (q == NULL)
1209 return NULL;
1210
1211 if (q) {
1212 stmt *ns = stmt_create(be->mvc->sa, st_order);
1213 if (ns == NULL) {
1214 freeInstruction(q);
1215 return NULL;
1216 }
1217
1218 ns->op1 = s;
1219 ns->flag = direction;
1220 ns->nrcols = s->nrcols;
1221 ns->key = s->key;
1222 ns->aggr = s->aggr;
1223 ns->q = q;
1224 ns->nr = getDestVar(q);
1225 return ns;
1226 }
1227 return NULL;
1228}
1229
1230stmt *
1231stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
1232{
1233 MalBlkPtr mb = be->mb;
1234 InstrPtr q = NULL;
1235
1236 if (s->nr < 0 || orderby_ids->nr < 0 || orderby_grp->nr < 0)
1237 return NULL;
1238 q = newStmt(mb, algebraRef, sortRef);
1239 /* both ordered result and oid's order en subgroups */
1240 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1241 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1242 q = pushArgument(mb, q, s->nr);
1243 q = pushArgument(mb, q, orderby_ids->nr);
1244 q = pushArgument(mb, q, orderby_grp->nr);
1245 q = pushBit(mb, q, !direction);
1246 q = pushBit(mb, q, nullslast);
1247 q = pushBit(mb, q, FALSE);
1248 if (q == NULL)
1249 return NULL;
1250 if (q) {
1251 stmt *ns = stmt_create(be->mvc->sa, st_reorder);
1252 if (ns == NULL) {
1253 freeInstruction(q);
1254 return NULL;
1255 }
1256
1257 ns->op1 = s;
1258 ns->op2 = orderby_ids;
1259 ns->op3 = orderby_grp;
1260 ns->flag = direction;
1261 ns->nrcols = s->nrcols;
1262 ns->key = s->key;
1263 ns->aggr = s->aggr;
1264 ns->nr = getDestVar(q);
1265 ns->q = q;
1266 return ns;
1267 }
1268 return NULL;
1269}
1270
1271stmt *
1272stmt_atom(backend *be, atom *a)
1273{
1274 MalBlkPtr mb = be->mb;
1275 InstrPtr q = newStmt(mb, calcRef, atom_type(a)->type->base.name);
1276
1277 if (!q)
1278 return NULL;
1279 if (atom_null(a)) {
1280 q = pushNil(mb, q, atom_type(a)->type->localtype);
1281 } else {
1282 int k;
1283 if((k = constantAtom(be, mb, a)) == -1) {
1284 freeInstruction(q);
1285 return NULL;
1286 }
1287
1288 q = pushArgument(mb, q, k);
1289 }
1290 /* digits of the result timestamp/daytime */
1291 if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
1292 q = pushInt(mb, q, atom_type(a)->digits);
1293 if (q) {
1294 stmt *s = stmt_create(be->mvc->sa, st_atom);
1295 if (s == NULL) {
1296 freeInstruction(q);
1297 return NULL;
1298 }
1299
1300 s->op4.aval = a;
1301 s->key = 1; /* values are also unique */
1302 s->q = q;
1303 s->nr = getDestVar(q);
1304 return s;
1305 }
1306 return NULL;
1307}
1308
1309stmt *
1310stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
1311{
1312 MalBlkPtr mb = be->mb;
1313 InstrPtr q = NULL;
1314 const char *mod, *op;
1315 node *n;
1316 int k;
1317
1318 if (backend_create_subfunc(be, f, NULL) < 0)
1319 return NULL;
1320 op = sql_func_imp(f->func);
1321 mod = sql_func_mod(f->func);
1322
1323 if (rops->nrcols >= 1) {
1324 bit need_not = FALSE;
1325
1326 q = newStmt(mb, malRef, multiplexRef);
1327 setVarType(mb, getArg(q, 0), newBatType(TYPE_bit));
1328 setVarUDFtype(mb, getArg(q, 0));
1329 q = pushStr(mb, q, convertMultiplexMod(mod, op));
1330 q = pushStr(mb, q, convertMultiplexFcn(op));
1331 for (n = lops->op4.lval->h; n; n = n->next) {
1332 stmt *op = n->data;
1333
1334 q = pushArgument(mb, q, op->nr);
1335 }
1336 for (n = rops->op4.lval->h; n; n = n->next) {
1337 stmt *op = n->data;
1338
1339 q = pushArgument(mb, q, op->nr);
1340 }
1341 k = getDestVar(q);
1342
1343 q = newStmt(mb, algebraRef, selectRef);
1344 q = pushArgument(mb, q, k);
1345 if (sub)
1346 q = pushArgument(mb, q, sub->nr);
1347 q = pushBit(mb, q, !need_not);
1348 q = pushBit(mb, q, !need_not);
1349 q = pushBit(mb, q, TRUE);
1350 q = pushBit(mb, q, TRUE);
1351 q = pushBit(mb, q, anti);
1352 } else {
1353 node *n;
1354
1355 op = sa_strconcat(be->mvc->sa, op, selectRef);
1356 q = newStmt(mb, mod, convertOperator(op));
1357 // push pointer to the SQL structure into the MAL call
1358 // allows getting argument names for example
1359 if (LANG_EXT(f->func->lang))
1360 q = pushPtr(mb, q, f); // nothing to see here, please move along
1361 // f->query contains the R code to be run
1362 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
1363 q = pushStr(mb, q, f->func->query);
1364
1365 for (n = lops->op4.lval->h; n; n = n->next) {
1366 stmt *op = n->data;
1367
1368 q = pushArgument(mb, q, op->nr);
1369 }
1370 /* candidate lists */
1371 if (sub)
1372 q = pushArgument(mb, q, sub->nr);
1373 else
1374 q = pushNil(mb, q, TYPE_bat);
1375
1376 for (n = rops->op4.lval->h; n; n = n->next) {
1377 stmt *op = n->data;
1378
1379 q = pushArgument(mb, q, op->nr);
1380 }
1381
1382 q = pushBit(mb, q, anti);
1383 }
1384
1385 if (q) {
1386 stmt *s = stmt_create(be->mvc->sa, st_uselect);
1387 if (s == NULL) {
1388 freeInstruction(q);
1389 return NULL;
1390 }
1391
1392 s->op1 = lops;
1393 s->op2 = rops;
1394 s->op3 = sub;
1395 s->flag = cmp_filter;
1396 s->nrcols = (lops->nrcols == 2) ? 2 : 1;
1397 s->nr = getDestVar(q);
1398 s->q = q;
1399 return s;
1400 }
1401 return NULL;
1402}
1403
1404stmt *
1405stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti)
1406{
1407 MalBlkPtr mb = be->mb;
1408 InstrPtr q = NULL;
1409 int l, r;
1410
1411 if (op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
1412 return NULL;
1413 l = op1->nr;
1414 r = op2->nr;
1415
1416 if (op2->nrcols >= 1) {
1417 bit need_not = FALSE;
1418 const char *mod = calcRef;
1419 const char *op = "=";
1420 int k;
1421
1422 switch (cmptype) {
1423 case mark_in:
1424 case mark_notin:
1425 case cmp_equal:
1426 case cmp_equal_nil:
1427 op = "=";
1428 break;
1429 case cmp_notequal:
1430 op = "!=";
1431 break;
1432 case cmp_lt:
1433 op = "<";
1434 break;
1435 case cmp_lte:
1436 op = "<=";
1437 break;
1438 case cmp_gt:
1439 op = ">";
1440 break;
1441 case cmp_gte:
1442 op = ">=";
1443 break;
1444 default:
1445 fprintf(stderr, "!SQL Unknown operator");
1446 }
1447
1448 if ((q = multiplex2(mb, mod, convertOperator(op), l, r, TYPE_bit)) == NULL)
1449 return NULL;
1450 if (cmptype == cmp_equal_nil)
1451 q = pushBit(mb, q, TRUE);
1452 k = getDestVar(q);
1453
1454 q = newStmt(mb, algebraRef, selectRef);
1455 q = pushArgument(mb, q, k);
1456 if (sub)
1457 q = pushArgument(mb, q, sub->nr);
1458 q = pushBit(mb, q, !need_not);
1459 q = pushBit(mb, q, !need_not);
1460 q = pushBit(mb, q, TRUE);
1461 q = pushBit(mb, q, TRUE);
1462 q = pushBit(mb, q, anti);
1463 if (q == NULL)
1464 return NULL;
1465 k = getDestVar(q);
1466 } else {
1467 assert (cmptype != cmp_filter);
1468 if (cmptype == cmp_equal_nil) {
1469 q = newStmt(mb, algebraRef, selectRef);
1470 q = pushArgument(mb, q, l);
1471 if (sub)
1472 q = pushArgument(mb, q, sub->nr);
1473 q = pushArgument(mb, q, r);
1474 q = pushArgument(mb, q, r);
1475 q = pushBit(mb, q, TRUE);
1476 q = pushBit(mb, q, TRUE);
1477 q = pushBit(mb, q, anti);
1478 } else {
1479 q = newStmt(mb, algebraRef, thetaselectRef);
1480 q = pushArgument(mb, q, l);
1481 if (sub)
1482 q = pushArgument(mb, q, sub->nr);
1483 q = pushArgument(mb, q, r);
1484 switch (cmptype) {
1485 case mark_in:
1486 case mark_notin: /* we use a anti join, todo handle null (not) in empty semantics */
1487 case cmp_equal:
1488 q = pushStr(mb, q, anti?"!=":"==");
1489 break;
1490 case cmp_notequal:
1491 q = pushStr(mb, q, anti?"==":"!=");
1492 break;
1493 case cmp_lt:
1494 q = pushStr(mb, q, anti?">=":"<");
1495 break;
1496 case cmp_lte:
1497 q = pushStr(mb, q, anti?">":"<=");
1498 break;
1499 case cmp_gt:
1500 q = pushStr(mb, q, anti?"<=":">");
1501 break;
1502 case cmp_gte:
1503 q = pushStr(mb, q, anti?"<":">=");
1504 break;
1505 default:
1506 fprintf(stderr, "!SQL2MAL: error impossible select compare\n");
1507 if (q)
1508 freeInstruction(q);
1509 q = NULL;
1510 }
1511 }
1512 if (q == NULL)
1513 return NULL;
1514 }
1515 if (q) {
1516 stmt *s = stmt_create(be->mvc->sa, st_uselect);
1517 if (s == NULL) {
1518 freeInstruction(q);
1519 return NULL;
1520 }
1521
1522 s->op1 = op1;
1523 s->op2 = op2;
1524 s->op3 = sub;
1525 s->flag = cmptype;
1526 s->nrcols = (op1->nrcols == 2) ? 2 : 1;
1527 s->nr = getDestVar(q);
1528 s->q = q;
1529 return s;
1530 }
1531 return NULL;
1532}
1533
1534/*
1535static int
1536range_join_convertable(stmt *s, stmt **base, stmt **L, stmt **H)
1537{
1538 int ls = 0, hs = 0;
1539 stmt *l = NULL, *h = NULL;
1540 stmt *bl = s->op2, *bh = s->op3;
1541 int tt = tail_type(s->op2)->type->localtype;
1542
1543#ifdef HAVE_HGE
1544 if (tt > TYPE_hge)
1545#else
1546 if (tt > TYPE_lng)
1547#endif
1548 return 0;
1549 if (s->op2->type == st_Nop && list_length(s->op2->op1->op4.lval) == 2) {
1550 bl = s->op2->op1->op4.lval->h->data;
1551 l = s->op2->op1->op4.lval->t->data;
1552 }
1553 if (s->op3->type == st_Nop && list_length(s->op3->op1->op4.lval) == 2) {
1554 bh = s->op3->op1->op4.lval->h->data;
1555 h = s->op3->op1->op4.lval->t->data;
1556 }
1557
1558 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) {
1559 *base = bl;
1560 *L = l;
1561 *H = h;
1562 return 1;
1563 }
1564 return 0;
1565}
1566
1567static int
1568argumentZero(MalBlkPtr mb, int tpe)
1569{
1570 ValRecord cst;
1571 str msg;
1572
1573 cst.vtype = TYPE_int;
1574 cst.val.ival = 0;
1575 msg = convertConstant(tpe, &cst);
1576 if( msg)
1577 freeException(msg); // will not be called
1578 return defConstant(mb, tpe, &cst);
1579}
1580*/
1581
1582
1583static InstrPtr
1584select2_join2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int swapped, int type)
1585{
1586 MalBlkPtr mb = be->mb;
1587 InstrPtr p, q;
1588 int l;
1589 const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
1590
1591 if (op1->nr < 0 && (sub && sub->nr < 0))
1592 return NULL;
1593 l = op1->nr;
1594 if (((cmp & CMP_BETWEEN && cmp & CMP_SYMMETRIC) || (cmp & CMP_BETWEEN && anti) || op2->nrcols > 0 || op3->nrcols > 0) && (type == st_uselect2)) {
1595 int k;
1596
1597 if (op2->nr < 0 || op3->nr < 0)
1598 return NULL;
1599
1600 p = newStmt(mb, batcalcRef, betweenRef);
1601 p = pushArgument(mb, p, l);
1602 p = pushArgument(mb, p, op2->nr);
1603 p = pushArgument(mb, p, op3->nr);
1604 p = pushBit(mb, p, (cmp & CMP_SYMMETRIC) != 0); /* symmetric */
1605 p = pushBit(mb, p, (cmp & 1) != 0); /* lo inclusive */
1606 p = pushBit(mb, p, (cmp & 2) != 0); /* hi inclusive */
1607 p = pushBit(mb, p, FALSE); /* nils_false */
1608 p = pushBit(mb, p, (anti)?TRUE:FALSE); /* anti */
1609 k = getDestVar(p);
1610
1611 q = newStmt(mb, algebraRef, selectRef);
1612 q = pushArgument(mb, q, k);
1613 if (sub)
1614 q = pushArgument(mb, q, sub->nr);
1615 q = pushBit(mb, q, TRUE);
1616 q = pushBit(mb, q, TRUE);
1617 q = pushBit(mb, q, TRUE);
1618 q = pushBit(mb, q, TRUE);
1619 q = pushBit(mb, q, FALSE);
1620 if (q == NULL)
1621 return NULL;
1622 } else {
1623 /* if st_join2 try to convert to bandjoin */
1624 /* ie check if we subtract/add a constant, to the
1625 same column */
1626 /* move this optimization into the relational phase! */
1627 /*
1628 stmt *base, *low = NULL, *high = NULL;
1629 if (type == st_join2 && range_join_convertable(s, &base, &low, &high)) {
1630 int tt = tail_type(base)->type->localtype;
1631
1632 if ((rs = _dumpstmt(sql, mb, base)) < 0)
1633 return -1;
1634 if (low) {
1635 if ((r1 = _dumpstmt(sql, mb, low)) < 0)
1636 return -1;
1637 } else
1638 r1 = argumentZero(mb, tt);
1639 if (high) {
1640 if ((r2 = _dumpstmt(sql, mb, high)) < 0)
1641 return -1;
1642 } else
1643 r2 = argumentZero(mb, tt);
1644 cmd = bandjoinRef;
1645 }
1646 */
1647
1648 int r1 = op2->nr;
1649 int r2 = op3->nr;
1650 int rs = 0;
1651 /*
1652 if (!rs) {
1653 r1 = op2->nr;
1654 r2 = op3->nr;
1655 }
1656 */
1657 q = newStmt(mb, algebraRef, cmd);
1658 if (type == st_join2)
1659 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1660 q = pushArgument(mb, q, l);
1661 if (sub) /* only for uselect2 */
1662 q = pushArgument(mb, q, sub->nr);
1663 if (rs) {
1664 q = pushArgument(mb, q, rs);
1665 } else {
1666 q = pushArgument(mb, q, r1);
1667 q = pushArgument(mb, q, r2);
1668 }
1669 if (type == st_join2) {
1670 q = pushNil(mb, q, TYPE_bat);
1671 q = pushNil(mb, q, TYPE_bat);
1672 }
1673
1674 switch (cmp & 3) {
1675 case 0:
1676 q = pushBit(mb, q, FALSE);
1677 q = pushBit(mb, q, FALSE);
1678 break;
1679 case 1:
1680 q = pushBit(mb, q, TRUE);
1681 q = pushBit(mb, q, FALSE);
1682 break;
1683 case 2:
1684 q = pushBit(mb, q, FALSE);
1685 q = pushBit(mb, q, TRUE);
1686 break;
1687 case 3:
1688 q = pushBit(mb, q, TRUE);
1689 q = pushBit(mb, q, TRUE);
1690 break;
1691 }
1692 q = pushBit(mb, q, anti);
1693 if (type == st_uselect2) {
1694 if (cmp & CMP_BETWEEN)
1695 q = pushBit(mb, q, TRUE); /* all nil's are != */
1696 } else
1697 q = pushBit(mb, q, FALSE);
1698 if (type == st_join2)
1699 q = pushNil(mb, q, TYPE_lng); /* estimate */
1700 if (q == NULL)
1701 return NULL;
1702 if (swapped) {
1703 InstrPtr r = newInstruction(mb, NULL, NULL);
1704 if (r == NULL)
1705 return NULL;
1706 getArg(r, 0) = newTmpVariable(mb, TYPE_any);
1707 r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
1708 r = pushArgument(mb, r, getArg(q,1));
1709 r = pushArgument(mb, r, getArg(q,0));
1710 pushInstruction(mb, r);
1711 q = r;
1712 }
1713 }
1714 return q;
1715}
1716
1717stmt *
1718stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti)
1719{
1720 InstrPtr q = select2_join2(be, op1, op2, op3, cmp, sub, anti, 0, st_uselect2);
1721
1722 if (q) {
1723 stmt *s = stmt_create(be->mvc->sa, st_uselect2);
1724 if (s == NULL) {
1725 freeInstruction(q);
1726 return NULL;
1727 }
1728
1729 s->op1 = op1;
1730 s->op2 = op2;
1731 s->op3 = op3;
1732 s->op4.stval = sub;
1733 s->flag = cmp;
1734 s->nrcols = (op1->nrcols == 2) ? 2 : 1;
1735 s->nr = getDestVar(q);
1736 s->q = q;
1737 return s;
1738 }
1739 return NULL;
1740}
1741
1742stmt *
1743stmt_tunion(backend *be, stmt *op1, stmt *op2)
1744{
1745 InstrPtr q = NULL;
1746 MalBlkPtr mb = be->mb;
1747
1748 q = dump_2(mb, batRef, mergecandRef, op1, op2);
1749 if (q) {
1750 stmt *s = stmt_create(be->mvc->sa, st_tunion);
1751 if (s == NULL) {
1752 freeInstruction(q);
1753 return NULL;
1754 }
1755
1756 s->op1 = op1;
1757 s->op2 = op2;
1758 s->nrcols = op1->nrcols;
1759 s->key = op1->key;
1760 s->aggr = op1->aggr;
1761 s->nr = getDestVar(q);
1762 s->q = q;
1763 return s;
1764 }
1765 return NULL;
1766}
1767
1768stmt *
1769stmt_tdiff(backend *be, stmt *op1, stmt *op2)
1770{
1771 InstrPtr q = NULL;
1772 MalBlkPtr mb = be->mb;
1773
1774 if (op1->nr < 0 || op2->nr < 0)
1775 return NULL;
1776 q = newStmt(mb, algebraRef, differenceRef);
1777 q = pushArgument(mb, q, op1->nr); /* left */
1778 q = pushArgument(mb, q, op2->nr); /* right */
1779 q = pushNil(mb, q, TYPE_bat); /* left candidate */
1780 q = pushNil(mb, q, TYPE_bat); /* right candidate */
1781 q = pushBit(mb, q, FALSE); /* nil matches */
1782 q = pushBit(mb, q, FALSE); /* do not clear nils */
1783 q = pushNil(mb, q, TYPE_lng); /* estimate */
1784
1785 if (q) {
1786 stmt *s = stmt_create(be->mvc->sa, st_tdiff);
1787 if (s == NULL) {
1788 freeInstruction(q);
1789 return NULL;
1790 }
1791
1792 s->op1 = op1;
1793 s->op2 = op2;
1794 s->nrcols = op1->nrcols;
1795 s->key = op1->key;
1796 s->aggr = op1->aggr;
1797 s->nr = getDestVar(q);
1798 s->q = q;
1799 return s;
1800 }
1801 return NULL;
1802}
1803
1804stmt *
1805stmt_tdiff2(backend *be, stmt *op1, stmt *op2)
1806{
1807 InstrPtr q = NULL;
1808 MalBlkPtr mb = be->mb;
1809
1810 if (op1->nr < 0 || op2->nr < 0)
1811 return NULL;
1812 q = newStmt(mb, algebraRef, differenceRef);
1813 q = pushArgument(mb, q, op1->nr); /* left */
1814 q = pushArgument(mb, q, op2->nr); /* right */
1815 q = pushNil(mb, q, TYPE_bat); /* left candidate */
1816 q = pushNil(mb, q, TYPE_bat); /* right candidate */
1817 q = pushBit(mb, q, FALSE); /* nil matches */
1818 q = pushBit(mb, q, TRUE); /* clear nils */
1819 q = pushNil(mb, q, TYPE_lng); /* estimate */
1820
1821 if (q) {
1822 stmt *s = stmt_create(be->mvc->sa, st_tdiff);
1823 if (s == NULL) {
1824 freeInstruction(q);
1825 return NULL;
1826 }
1827
1828 s->op1 = op1;
1829 s->op2 = op2;
1830 s->nrcols = op1->nrcols;
1831 s->key = op1->key;
1832 s->aggr = op1->aggr;
1833 s->nr = getDestVar(q);
1834 s->q = q;
1835 return s;
1836 }
1837 return NULL;
1838}
1839
1840stmt *
1841stmt_tinter(backend *be, stmt *op1, stmt *op2)
1842{
1843 InstrPtr q = NULL;
1844 MalBlkPtr mb = be->mb;
1845
1846 if (op1->nr < 0 || op2->nr < 0)
1847 return NULL;
1848 q = newStmt(mb, algebraRef, intersectRef);
1849 q = pushArgument(mb, q, op1->nr); /* left */
1850 q = pushArgument(mb, q, op2->nr); /* right */
1851 q = pushNil(mb, q, TYPE_bat); /* left candidate */
1852 q = pushNil(mb, q, TYPE_bat); /* right candidate */
1853 q = pushBit(mb, q, FALSE); /* nil matches */
1854 q = pushNil(mb, q, TYPE_lng); /* estimate */
1855
1856 if (q) {
1857 stmt *s = stmt_create(be->mvc->sa, st_tinter);
1858
1859 s->op1 = op1;
1860 s->op2 = op2;
1861 s->nrcols = op1->nrcols;
1862 s->key = op1->key;
1863 s->aggr = op1->aggr;
1864 s->nr = getDestVar(q);
1865 s->q = q;
1866 return s;
1867 }
1868 return NULL;
1869}
1870
1871stmt *
1872stmt_join(backend *be, stmt *op1, stmt *op2, int anti, comp_type cmptype)
1873{
1874 MalBlkPtr mb = be->mb;
1875 InstrPtr q = NULL;
1876 int left = (cmptype == cmp_left);
1877 const char *sjt = "join";
1878
1879 (void)anti;
1880
1881 if (left) {
1882 cmptype = cmp_equal;
1883 sjt = "leftjoin";
1884 }
1885 if (op1->nr < 0 || op2->nr < 0)
1886 return NULL;
1887
1888 switch (cmptype) {
1889 case mark_in:
1890 case mark_notin: /* we use a anti join, todo handle null (not) in empty */
1891 case cmp_equal:
1892 q = newStmt(mb, algebraRef, sjt);
1893 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1894 q = pushArgument(mb, q, op1->nr);
1895 q = pushArgument(mb, q, op2->nr);
1896 q = pushNil(mb, q, TYPE_bat);
1897 q = pushNil(mb, q, TYPE_bat);
1898 q = pushBit(mb, q, FALSE);
1899 q = pushNil(mb, q, TYPE_lng);
1900 if (q == NULL)
1901 return NULL;
1902 break;
1903 case cmp_equal_nil: /* nil == nil */
1904 q = newStmt(mb, algebraRef, sjt);
1905 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1906 q = pushArgument(mb, q, op1->nr);
1907 q = pushArgument(mb, q, op2->nr);
1908 q = pushNil(mb, q, TYPE_bat);
1909 q = pushNil(mb, q, TYPE_bat);
1910 q = pushBit(mb, q, TRUE);
1911 q = pushNil(mb, q, TYPE_lng);
1912 if (q == NULL)
1913 return NULL;
1914 break;
1915 case cmp_notequal:
1916 q = newStmt(mb, algebraRef, antijoinRef);
1917 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1918 q = pushArgument(mb, q, op1->nr);
1919 q = pushArgument(mb, q, op2->nr);
1920 q = pushNil(mb, q, TYPE_bat);
1921 q = pushNil(mb, q, TYPE_bat);
1922 q = pushBit(mb, q, FALSE);
1923 q = pushNil(mb, q, TYPE_lng);
1924 if (q == NULL)
1925 return NULL;
1926 break;
1927 case cmp_lt:
1928 case cmp_lte:
1929 case cmp_gt:
1930 case cmp_gte:
1931 q = newStmt(mb, algebraRef, thetajoinRef);
1932 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1933 q = pushArgument(mb, q, op1->nr);
1934 q = pushArgument(mb, q, op2->nr);
1935 q = pushNil(mb, q, TYPE_bat);
1936 q = pushNil(mb, q, TYPE_bat);
1937 if (cmptype == cmp_lt)
1938 q = pushInt(mb, q, -1);
1939 else if (cmptype == cmp_lte)
1940 q = pushInt(mb, q, -2);
1941 else if (cmptype == cmp_gt)
1942 q = pushInt(mb, q, 1);
1943 else if (cmptype == cmp_gte)
1944 q = pushInt(mb, q, 2);
1945 q = pushBit(mb, q, TRUE);
1946 q = pushNil(mb, q, TYPE_lng);
1947 if (q == NULL)
1948 return NULL;
1949 break;
1950 case cmp_all: /* aka cross table */
1951 q = newStmt(mb, algebraRef, crossRef);
1952 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
1953 q = pushArgument(mb, q, op1->nr);
1954 q = pushArgument(mb, q, op2->nr);
1955 if (q == NULL)
1956 return NULL;
1957 break;
1958 case cmp_joined:
1959 q = op1->q;
1960 break;
1961 default:
1962 fprintf(stderr, "!SQL2MAL: error impossible\n");
1963 }
1964 if (q) {
1965 stmt *s = stmt_create(be->mvc->sa, st_join);
1966
1967 s->op1 = op1;
1968 s->op2 = op2;
1969 s->flag = cmptype;
1970 s->key = 0;
1971 s->nrcols = 2;
1972 s->nr = getDestVar(q);
1973 s->q = q;
1974 return s;
1975 }
1976 return NULL;
1977}
1978
1979static InstrPtr
1980stmt_project_join(backend *be, stmt *op1, stmt *op2, stmt *ins)
1981{
1982 MalBlkPtr mb = be->mb;
1983 InstrPtr q = NULL;
1984
1985 if (op1->nr < 0 || op2->nr < 0)
1986 return NULL;
1987 /* delta bat */
1988 if (ins) {
1989 int uval = getArg(op2->q, 1);
1990
1991 if (ins->nr < 0)
1992 return NULL;
1993 q = newStmt(mb, sqlRef, deltaRef);
1994 q = pushArgument(mb, q, op1->nr);
1995 q = pushArgument(mb, q, op2->nr);
1996 q = pushArgument(mb, q, uval);
1997 q = pushArgument(mb, q, ins->nr);
1998 } else {
1999 /* projections, ie left is void headed */
2000 q = newStmt(mb, algebraRef, projectionRef);
2001 q = pushArgument(mb, q, op1->nr);
2002 q = pushArgument(mb, q, op2->nr);
2003 if (q == NULL)
2004 return NULL;
2005 /*
2006 if (s->key) {
2007 q = newStmt(mb, batRef, putName("setKey"));
2008 q = pushArgument(mb, q, s->nr);
2009 q = pushBit(mb, q, TRUE);
2010 }
2011 */
2012
2013 }
2014 return q;
2015}
2016
2017stmt *
2018stmt_project(backend *be, stmt *op1, stmt *op2)
2019{
2020 InstrPtr q = stmt_project_join(be, op1, op2, NULL);
2021 if (q) {
2022 stmt *s = stmt_create(be->mvc->sa, st_join);
2023
2024 s->op1 = op1;
2025 s->op2 = op2;
2026 s->flag = cmp_project;
2027 s->key = 0;
2028 s->nrcols = MAX(op1->nrcols,op2->nrcols);
2029 s->nr = getDestVar(q);
2030 s->q = q;
2031 return s;
2032 }
2033 return NULL;
2034}
2035
2036stmt *
2037stmt_project_delta(backend *be, stmt *col, stmt *upd, stmt *ins)
2038{
2039 InstrPtr q = stmt_project_join(be, col, upd, ins);
2040 if (q) {
2041 stmt *s = stmt_create(be->mvc->sa, st_join);
2042
2043 s->op1 = col;
2044 s->op2 = upd;
2045 s->op3 = ins;
2046 s->flag = cmp_project;
2047 s->key = 0;
2048 s->nrcols = 2;
2049 s->nr = getDestVar(q);
2050 s->q = q;
2051 return s;
2052 }
2053 return NULL;
2054}
2055
2056stmt *
2057stmt_left_project(backend *be, stmt *op1, stmt *op2, stmt *op3)
2058{
2059 MalBlkPtr mb = be->mb;
2060 InstrPtr q = NULL;
2061 if (op1->nr < 0 || op2->nr < 0 || op3->nr < 0)
2062 return NULL;
2063
2064 q = newStmt(mb, sqlRef, projectRef);
2065 q = pushArgument(mb, q, op1->nr);
2066 q = pushArgument(mb, q, op2->nr);
2067 q = pushArgument(mb, q, op3->nr);
2068
2069 if (q){
2070 stmt *s = stmt_create(be->mvc->sa, st_join);
2071
2072 s->op1 = op1;
2073 s->op2 = op2;
2074 s->op3 = op3;
2075 s->flag = cmp_left_project;
2076 s->key = 0;
2077 s->nrcols = 2;
2078 s->nr = getDestVar(q);
2079 s->q = q;
2080 return s;
2081 }
2082 return NULL;
2083}
2084
2085stmt *
2086stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int swapped)
2087{
2088 InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, swapped, st_join2);
2089 if (q) {
2090 stmt *s = stmt_create(be->mvc->sa, st_join2);
2091
2092 s->op1 = l;
2093 s->op2 = ra;
2094 s->op3 = rb;
2095 s->flag = cmp;
2096 s->nrcols = 2;
2097 s->nr = getDestVar(q);
2098 s->q = q;
2099 return s;
2100 }
2101 return NULL;
2102}
2103
2104stmt *
2105stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
2106{
2107 MalBlkPtr mb = be->mb;
2108 InstrPtr q = NULL;
2109 const char *mod, *fimp;
2110 node *n;
2111
2112 (void)anti;
2113 if (backend_create_subfunc(be, op, NULL) < 0)
2114 return NULL;
2115 mod = sql_func_mod(op->func);
2116 fimp = sql_func_imp(op->func);
2117 fimp = sa_strconcat(be->mvc->sa, fimp, "join");
2118
2119 /* filter qualifying tuples, return oids of h and tail */
2120 q = newStmt(mb, mod, fimp);
2121 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
2122 for (n = l->op4.lval->h; n; n = n->next) {
2123 stmt *op = n->data;
2124
2125 q = pushArgument(mb, q, op->nr);
2126 }
2127
2128 for (n = r->op4.lval->h; n; n = n->next) {
2129 stmt *op = n->data;
2130
2131 q = pushArgument(mb, q, op->nr);
2132 }
2133 q = pushNil(mb, q, TYPE_bat); /* candidate lists */
2134 q = pushNil(mb, q, TYPE_bat); /* candidate lists */
2135 q = pushBit(mb, q, TRUE); /* nil_matches */
2136 q = pushNil(mb, q, TYPE_lng); /* estimate */
2137
2138 if (swapped) {
2139 InstrPtr r = newInstruction(mb, NULL, NULL);
2140 if (r == NULL)
2141 return NULL;
2142 getArg(r, 0) = newTmpVariable(mb, TYPE_any);
2143 r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
2144 r = pushArgument(mb, r, getArg(q,1));
2145 r = pushArgument(mb, r, getArg(q,0));
2146 pushInstruction(mb, r);
2147 q = r;
2148 }
2149
2150 if (q) {
2151 stmt *s = stmt_create(be->mvc->sa, st_joinN);
2152
2153 s->op1 = l;
2154 s->op2 = r;
2155 s->op4.funcval = op;
2156 s->nrcols = 2;
2157 if (swapped)
2158 s->flag |= SWAPPED;
2159 s->nr = getDestVar(q);
2160 s->q = q;
2161 return s;
2162 }
2163 return NULL;
2164}
2165
2166stmt *
2167stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
2168{
2169 InstrPtr q = NULL;
2170
2171 if (rs->nr < 0)
2172 return NULL;
2173 q = rs->q;
2174 if (q) {
2175 stmt *s = stmt_create(be->mvc->sa, st_rs_column);
2176
2177 s->op1 = rs;
2178 s->op4.typeval = *tpe;
2179 s->flag = i;
2180 s->nrcols = 1;
2181 s->key = 0;
2182 s->q = q;
2183 s->nr = getArg(q, s->flag);
2184 return s;
2185 }
2186 return NULL;
2187}
2188
2189/*
2190 * The dump_header produces a sequence of instructions for
2191 * the front-end to prepare presentation of a result table.
2192 *
2193 * A secondary scheme is added to assemblt all information
2194 * in columns first. Then it can be returned to the environment.
2195 */
2196#define NEWRESULTSET
2197
2198#define meta(P, Id, Tpe, Args) \
2199P = newStmtArgs(mb, batRef, packRef, Args);\
2200Id = getArg(P,0);\
2201setVarType(mb, Id, newBatType(Tpe));\
2202setVarFixed(mb, Id);\
2203list = pushArgument(mb, list, Id);
2204
2205#define metaInfo(P,Tpe,Val)\
2206P = push##Tpe(mb, P, Val);
2207
2208
2209static int
2210dump_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)
2211{
2212 node *n;
2213 bool error = false;
2214 int ret = -1;
2215 int args;
2216
2217 // gather the meta information
2218 int tblId, nmeId, tpeId, lenId, scaleId;
2219 InstrPtr list;
2220 InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
2221
2222 args = 4;
2223 for (n = l->h; n; n = n->next) args ++;
2224
2225 list = newInstruction(mb, sqlRef, export_tableRef);
2226 getArg(list,0) = newTmpVariable(mb,TYPE_int);
2227 if( file >= 0){
2228 list = pushArgument(mb, list, file);
2229 list = pushStr(mb, list, format);
2230 list = pushStr(mb, list, sep);
2231 list = pushStr(mb, list, rsep);
2232 list = pushStr(mb, list, ssep);
2233 list = pushStr(mb, list, ns);
2234 list = pushInt(mb, list, onclient);
2235 }
2236 meta(tblPtr, tblId, TYPE_str, args);
2237 meta(nmePtr, nmeId, TYPE_str, args);
2238 meta(tpePtr, tpeId, TYPE_str, args);
2239 meta(lenPtr, lenId, TYPE_int, args);
2240 meta(scalePtr, scaleId, TYPE_int, args);
2241 if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
2242 return -1;
2243
2244 for (n = l->h; n; n = n->next) {
2245 stmt *c = n->data;
2246 sql_subtype *t = tail_type(c);
2247 const char *tname = table_name(sql->sa, c);
2248 const char *sname = schema_name(sql->sa, c);
2249 const char *_empty = "";
2250 const char *tn = (tname) ? tname : _empty;
2251 const char *sn = (sname) ? sname : _empty;
2252 const char *cn = column_name(sql->sa, c);
2253 const char *ntn = sql_escape_ident(tn);
2254 const char *nsn = sql_escape_ident(sn);
2255 size_t fqtnl;
2256 char *fqtn = NULL;
2257
2258 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
2259 fqtn = NEW_ARRAY(char, fqtnl);
2260 if(fqtn) {
2261 snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
2262 metaInfo(tblPtr, Str, fqtn);
2263 metaInfo(nmePtr, Str, cn);
2264 metaInfo(tpePtr, Str, (t->type->localtype == TYPE_void ? "char" : t->type->sqlname));
2265 metaInfo(lenPtr, Int, t->digits);
2266 metaInfo(scalePtr, Int, t->scale);
2267 list = pushArgument(mb, list, c->nr);
2268 _DELETE(fqtn);
2269 } else
2270 error = true;
2271 } else
2272 error = true;
2273 c_delete(ntn);
2274 c_delete(nsn);
2275 if(error)
2276 return -1;
2277 }
2278 ret = getArg(list,0);
2279 pushInstruction(mb,list);
2280 return ret;
2281}
2282
2283
2284stmt *
2285stmt_export(backend *be, stmt *t, const char *sep, const char *rsep, const char *ssep, const char *null_string, int onclient, stmt *file)
2286{
2287 MalBlkPtr mb = be->mb;
2288 InstrPtr q = NULL;
2289 int fnr;
2290 list *l;
2291
2292 if (t->nr < 0)
2293 return NULL;
2294 l = t->op4.lval;
2295 if (file) {
2296 if (file->nr < 0)
2297 return NULL;
2298 fnr = file->nr;
2299 } else {
2300 q = newAssignment(mb);
2301 q = pushStr(mb,q,"stdout");
2302 fnr = getArg(q,0);
2303 }
2304 if (t->type == st_list) {
2305 if (dump_export_header(be->mvc, mb, l, fnr, "csv", sep, rsep, ssep, null_string, onclient) < 0)
2306 return NULL;
2307 } else {
2308 q = newStmt(mb, sqlRef, raiseRef);
2309 q = pushStr(mb, q, "not a valid output list\n");
2310 if (q == NULL)
2311 return NULL;
2312 }
2313 if (q) {
2314 stmt *s = stmt_create(be->mvc->sa, st_export);
2315 if(!s) {
2316 freeInstruction(q);
2317 return NULL;
2318 }
2319 s->op1 = t;
2320 s->op2 = file;
2321 s->q = q;
2322 s->nr = 1;
2323 return s;
2324 }
2325 return NULL;
2326}
2327
2328stmt *
2329stmt_trans(backend *be, int type, stmt *chain, stmt *name)
2330{
2331 MalBlkPtr mb = be->mb;
2332 InstrPtr q = NULL;
2333
2334 if (chain->nr < 0)
2335 return NULL;
2336
2337 switch(type){
2338 case ddl_release:
2339 q = newStmt(mb, sqlRef, transaction_releaseRef);
2340 break;
2341 case ddl_commit:
2342 q = newStmt(mb, sqlRef, transaction_commitRef);
2343 break;
2344 case ddl_rollback:
2345 q = newStmt(mb, sqlRef, transaction_rollbackRef);
2346 break;
2347 case ddl_trans:
2348 q = newStmt(mb, sqlRef, transaction_beginRef);
2349 break;
2350 default:
2351 fprintf(stderr, "!SQL transaction unknown type");
2352 }
2353 q = pushArgument(mb, q, chain->nr);
2354 if (name)
2355 q = pushArgument(mb, q, name->nr);
2356 else
2357 q = pushNil(mb, q, TYPE_str);
2358 if (q) {
2359 stmt *s = stmt_create(be->mvc->sa, st_trans);
2360 if(!s) {
2361 freeInstruction(q);
2362 return NULL;
2363 }
2364 s->op1 = chain;
2365 s->op2 = name;
2366 s->flag = type;
2367 s->q = q;
2368 s->nr = getDestVar(q);
2369 return s;
2370 }
2371 return NULL;
2372}
2373
2374stmt *
2375stmt_catalog(backend *be, int type, stmt *args)
2376{
2377 MalBlkPtr mb = be->mb;
2378 InstrPtr q = NULL;
2379 node *n;
2380
2381 if (args->nr < 0)
2382 return NULL;
2383
2384 /* cast them into properly named operations */
2385 switch(type){
2386 case ddl_create_seq: q = newStmt(mb, sqlcatalogRef, create_seqRef); break;
2387 case ddl_alter_seq: q = newStmt(mb, sqlcatalogRef, alter_seqRef); break;
2388 case ddl_drop_seq: q = newStmt(mb, sqlcatalogRef, drop_seqRef); break;
2389 case ddl_create_schema: q = newStmt(mb, sqlcatalogRef, create_schemaRef); break;
2390 case ddl_drop_schema: q = newStmt(mb, sqlcatalogRef, drop_schemaRef); break;
2391 case ddl_create_table: q = newStmt(mb, sqlcatalogRef, create_tableRef); break;
2392 case ddl_create_view: q = newStmt(mb, sqlcatalogRef, create_viewRef); break;
2393 case ddl_drop_table: q = newStmt(mb, sqlcatalogRef, drop_tableRef); break;
2394 case ddl_drop_view: q = newStmt(mb, sqlcatalogRef, drop_viewRef); break;
2395 case ddl_drop_constraint: q = newStmt(mb, sqlcatalogRef, drop_constraintRef); break;
2396 case ddl_alter_table: q = newStmt(mb, sqlcatalogRef, alter_tableRef); break;
2397 case ddl_create_type: q = newStmt(mb, sqlcatalogRef, create_typeRef); break;
2398 case ddl_drop_type: q = newStmt(mb, sqlcatalogRef, drop_typeRef); break;
2399 case ddl_grant_roles: q = newStmt(mb, sqlcatalogRef, grant_rolesRef); break;
2400 case ddl_revoke_roles: q = newStmt(mb, sqlcatalogRef, revoke_rolesRef); break;
2401 case ddl_grant: q = newStmt(mb, sqlcatalogRef, grantRef); break;
2402 case ddl_revoke: q = newStmt(mb, sqlcatalogRef, revokeRef); break;
2403 case ddl_grant_func: q = newStmt(mb, sqlcatalogRef, grant_functionRef); break;
2404 case ddl_revoke_func: q = newStmt(mb, sqlcatalogRef, revoke_functionRef); break;
2405 case ddl_create_user: q = newStmt(mb, sqlcatalogRef, create_userRef); break;
2406 case ddl_drop_user: q = newStmt(mb, sqlcatalogRef, drop_userRef); break;
2407 case ddl_alter_user: q = newStmt(mb, sqlcatalogRef, alter_userRef); break;
2408 case ddl_rename_user: q = newStmt(mb, sqlcatalogRef, rename_userRef); break;
2409 case ddl_create_role: q = newStmt(mb, sqlcatalogRef, create_roleRef); break;
2410 case ddl_drop_role: q = newStmt(mb, sqlcatalogRef, drop_roleRef); break;
2411 case ddl_drop_index: q = newStmt(mb, sqlcatalogRef, drop_indexRef); break;
2412 case ddl_drop_function: q = newStmt(mb, sqlcatalogRef, drop_functionRef); break;
2413 case ddl_create_function: q = newStmt(mb, sqlcatalogRef, create_functionRef); break;
2414 case ddl_create_trigger: q = newStmt(mb, sqlcatalogRef, create_triggerRef); break;
2415 case ddl_drop_trigger: q = newStmt(mb, sqlcatalogRef, drop_triggerRef); break;
2416 case ddl_alter_table_add_table: q = newStmt(mb, sqlcatalogRef, alter_add_tableRef); break;
2417 case ddl_alter_table_del_table: q = newStmt(mb, sqlcatalogRef, alter_del_tableRef); break;
2418 case ddl_alter_table_set_access:q = newStmt(mb, sqlcatalogRef, alter_set_tableRef); break;
2419 case ddl_alter_table_add_range_partition: q = newStmt(mb, sqlcatalogRef, alter_add_range_partitionRef); break;
2420 case ddl_alter_table_add_list_partition: q = newStmt(mb, sqlcatalogRef, alter_add_value_partitionRef); break;
2421 case ddl_comment_on: q = newStmt(mb, sqlcatalogRef, comment_onRef); break;
2422 case ddl_rename_schema: q = newStmt(mb, sqlcatalogRef, rename_schemaRef); break;
2423 case ddl_rename_table: q = newStmt(mb, sqlcatalogRef, rename_tableRef); break;
2424 case ddl_rename_column: q = newStmt(mb, sqlcatalogRef, rename_columnRef); break;
2425 default:
2426 fprintf(stderr, "!SQL catalog operation unknown\n");
2427 }
2428 // pass all arguments as before
2429 for (n = args->op4.lval->h; n; n = n->next) {
2430 stmt *c = n->data;
2431
2432 q = pushArgument(mb, q, c->nr);
2433 }
2434 if (q) {
2435 stmt *s = stmt_create(be->mvc->sa, st_catalog);
2436 if(!s) {
2437 freeInstruction(q);
2438 return NULL;
2439 }
2440 s->op1 = args;
2441 s->flag = type;
2442 s->q = q;
2443 s->nr = getDestVar(q);
2444 return s;
2445 }
2446 return NULL;
2447}
2448
2449void
2450stmt_set_nrcols(stmt *s)
2451{
2452 int nrcols = 0;
2453 int key = 1;
2454 node *n;
2455 list *l = s->op4.lval;
2456
2457 assert(s->type == st_list);
2458 for (n = l->h; n; n = n->next) {
2459 stmt *f = n->data;
2460
2461 if (!f)
2462 continue;
2463 if (f->nrcols > nrcols)
2464 nrcols = f->nrcols;
2465 key &= f->key;
2466 s->nr = f->nr;
2467 }
2468 s->nrcols = nrcols;
2469 s->key = key;
2470}
2471
2472stmt *
2473stmt_list(backend *be, list *l)
2474{
2475 stmt *s = stmt_create(be->mvc->sa, st_list);
2476 if(!s) {
2477 return NULL;
2478 }
2479 s->op4.lval = l;
2480 stmt_set_nrcols(s);
2481 return s;
2482}
2483
2484static InstrPtr
2485dump_header(mvc *sql, MalBlkPtr mb, stmt *s, list *l)
2486{
2487 node *n;
2488 bool error = false;
2489 // gather the meta information
2490 int tblId, nmeId, tpeId, lenId, scaleId;
2491 int args;
2492 InstrPtr list;
2493 InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
2494
2495 args = 4;
2496 for (n = l->h; n; n = n->next) args++;
2497
2498 list = newInstruction(mb,sqlRef, resultSetRef);
2499 if(!list) {
2500 return NULL;
2501 }
2502 getArg(list,0) = newTmpVariable(mb,TYPE_int);
2503 meta(tblPtr, tblId, TYPE_str, args);
2504 meta(nmePtr, nmeId, TYPE_str, args);
2505 meta(tpePtr, tpeId, TYPE_str, args);
2506 meta(lenPtr, lenId, TYPE_int, args);
2507 meta(scalePtr, scaleId, TYPE_int, args);
2508 if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
2509 return NULL;
2510
2511 (void) s;
2512
2513 for (n = l->h; n; n = n->next) {
2514 stmt *c = n->data;
2515 sql_subtype *t = tail_type(c);
2516 const char *tname = table_name(sql->sa, c);
2517 const char *sname = schema_name(sql->sa, c);
2518 const char *_empty = "";
2519 const char *tn = (tname) ? tname : _empty;
2520 const char *sn = (sname) ? sname : _empty;
2521 const char *cn = column_name(sql->sa, c);
2522 const char *ntn = sql_escape_ident(tn);
2523 const char *nsn = sql_escape_ident(sn);
2524 size_t fqtnl;
2525 char *fqtn = NULL;
2526
2527 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
2528 fqtn = NEW_ARRAY(char, fqtnl);
2529 if(fqtn) {
2530 snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
2531 metaInfo(tblPtr,Str,fqtn);
2532 metaInfo(nmePtr,Str,cn);
2533 metaInfo(tpePtr,Str,(t->type->localtype == TYPE_void ? "char" : t->type->sqlname));
2534 metaInfo(lenPtr,Int,t->digits);
2535 metaInfo(scalePtr,Int,t->scale);
2536 list = pushArgument(mb,list,c->nr);
2537 _DELETE(fqtn);
2538 } else
2539 error = true;
2540 } else
2541 error = true;
2542 c_delete(ntn);
2543 c_delete(nsn);
2544 if (error)
2545 return NULL;
2546 }
2547 pushInstruction(mb,list);
2548 return list;
2549}
2550
2551stmt *
2552stmt_output(backend *be, stmt *lst)
2553{
2554 MalBlkPtr mb = be->mb;
2555 InstrPtr q = NULL;
2556 list *l = lst->op4.lval;
2557
2558 int cnt = list_length(l), ok = 0;
2559 stmt *first;
2560 node *n;
2561
2562 n = l->h;
2563 first = n->data;
2564
2565 /* single value result, has a fast exit */
2566 if (cnt == 1 && first->nrcols <= 0 ){
2567 stmt *c = n->data;
2568 sql_subtype *t = tail_type(c);
2569 const char *tname = table_name(be->mvc->sa, c);
2570 const char *sname = schema_name(be->mvc->sa, c);
2571 const char *_empty = "";
2572 const char *tn = (tname) ? tname : _empty;
2573 const char *sn = (sname) ? sname : _empty;
2574 const char *cn = column_name(be->mvc->sa, c);
2575 const char *ntn = sql_escape_ident(tn);
2576 const char *nsn = sql_escape_ident(sn);
2577 size_t fqtnl;
2578 char *fqtn = NULL;
2579
2580 if(ntn && nsn) {
2581 fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
2582 fqtn = NEW_ARRAY(char, fqtnl);
2583 if(fqtn) {
2584 ok = 1;
2585 snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
2586
2587 q = newStmt(mb, sqlRef, resultSetRef);
2588 getArg(q,0) = newTmpVariable(mb,TYPE_int);
2589 if (q) {
2590 q = pushStr(mb, q, fqtn);
2591 q = pushStr(mb, q, cn);
2592 q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->sqlname);
2593 q = pushInt(mb, q, t->digits);
2594 q = pushInt(mb, q, t->scale);
2595 q = pushInt(mb, q, t->type->eclass);
2596 q = pushArgument(mb, q, c->nr);
2597 }
2598 }
2599 }
2600 c_delete(ntn);
2601 c_delete(nsn);
2602 _DELETE(fqtn);
2603 if(!ok)
2604 return NULL;
2605 } else {
2606 if ((q = dump_header(be->mvc, mb, lst, l)) == NULL)
2607 return NULL;
2608 }
2609 if (q) {
2610 stmt *s = stmt_create(be->mvc->sa, st_output);
2611
2612 s->op1 = lst;
2613 s->nr = getDestVar(q);
2614 s->q = q;
2615 return s;
2616 }
2617 return NULL;
2618}
2619
2620stmt *
2621stmt_affected_rows(backend *be, stmt *l)
2622{
2623 MalBlkPtr mb = be->mb;
2624 InstrPtr q = NULL;
2625
2626 if (l->nr < 0)
2627 return NULL;
2628 q = newStmt(mb, sqlRef, affectedRowsRef);
2629 q = pushArgument(mb, q, be->mvc_var);
2630 if (q == NULL)
2631 return NULL;
2632 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
2633 q = pushArgument(mb, q, l->nr);
2634 if (q == NULL)
2635 return NULL;
2636 be->mvc_var = getDestVar(q);
2637 if (q) {
2638 stmt *s = stmt_create(be->mvc->sa, st_affected_rows);
2639 if(!s) {
2640 freeInstruction(q);
2641 return NULL;
2642 }
2643 s->op1 = l;
2644 s->nr = getDestVar(q);
2645 s->q = q;
2646 return s;
2647 }
2648 return NULL;
2649}
2650
2651stmt *
2652stmt_append(backend *be, stmt *c, stmt *a)
2653{
2654 MalBlkPtr mb = be->mb;
2655 InstrPtr q = NULL;
2656
2657 if (c->nr < 0 || a->nr < 0)
2658 return NULL;
2659 q = newStmt(mb, batRef, appendRef);
2660 q = pushArgument(mb, q, c->nr);
2661 q = pushArgument(mb, q, a->nr);
2662 q = pushBit(mb, q, TRUE);
2663 if (q) {
2664 stmt *s = stmt_create(be->mvc->sa, st_append);
2665 if(!s) {
2666 freeInstruction(q);
2667 return NULL;
2668 }
2669 s->op1 = c;
2670 s->op2 = a;
2671 s->nrcols = c->nrcols;
2672 s->key = c->key;
2673 s->nr = getDestVar(q);
2674 s->q = q;
2675 return s;
2676 }
2677 return NULL;
2678}
2679
2680stmt *
2681stmt_table_clear(backend *be, sql_table *t)
2682{
2683 MalBlkPtr mb = be->mb;
2684 InstrPtr q = NULL;
2685
2686 if (!t->s && t->data) { /* declared table */
2687 int *l = t->data;
2688 int cnt = list_length(t->columns.set)+1, i;
2689
2690 for (i = 0; i < cnt; i++) {
2691 q = newStmt(mb, batRef, "clear");
2692 q = pushArgument(mb, q, l[i]);
2693 l[i] = getDestVar(q);
2694 }
2695 } else {
2696 q = newStmt(mb, sqlRef, clear_tableRef);
2697 q = pushSchema(mb, q, t);
2698 q = pushStr(mb, q, t->base.name);
2699 }
2700 if (q) {
2701 stmt *s = stmt_create(be->mvc->sa, st_table_clear);
2702
2703 if(!s) {
2704 freeInstruction(q);
2705 return NULL;
2706 }
2707 s->op4.tval = t;
2708 s->nrcols = 0;
2709 s->nr = getDestVar(q);
2710 s->q = q;
2711 return s;
2712 }
2713 return NULL;
2714}
2715
2716stmt *
2717stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
2718{
2719 MalBlkPtr mb = be->mb;
2720 InstrPtr q = NULL;
2721
2722 if (cond->nr < 0)
2723 return NULL;
2724
2725 /* if(bit(l)) { error(r);} ==raising an exception */
2726 q = newStmt(mb, sqlRef, assertRef);
2727 q = pushArgument(mb, q, cond->nr);
2728 q = pushStr(mb, q, errstr);
2729 if (q) {
2730 stmt *s = stmt_create(be->mvc->sa, st_exception);
2731 if(!s) {
2732 freeInstruction(q);
2733 return NULL;
2734 }
2735 assert(cond);
2736 s->op1 = cond;
2737 (void)errcode;
2738 s->nrcols = 0;
2739 s->q = q;
2740 s->nr = getDestVar(q);
2741 return s;
2742 }
2743 return NULL;
2744}
2745
2746stmt *
2747stmt_convert(backend *be, stmt *v, sql_subtype *f, sql_subtype *t, stmt *sel)
2748{
2749 MalBlkPtr mb = be->mb;
2750 InstrPtr q = NULL;
2751 const char *convert = t->type->base.name;
2752 /* convert types and make sure they are rounded up correctly */
2753
2754 if (v->nr < 0)
2755 return NULL;
2756
2757 if (t->type->localtype == f->type->localtype &&
2758 (t->type->eclass == f->type->eclass ||
2759 (EC_VARCHAR(f->type->eclass) && EC_VARCHAR(t->type->eclass))) &&
2760 !EC_INTERVAL(f->type->eclass) &&
2761 f->type->eclass != EC_DEC &&
2762 (t->digits == 0 || f->digits == t->digits) &&
2763 type_has_tz(t) == type_has_tz(f)) {
2764 return v;
2765 }
2766
2767 /* external types have sqlname convert functions,
2768 these can generate errors (fromstr cannot) */
2769 if (t->type->eclass == EC_EXTERNAL)
2770 convert = t->type->sqlname;
2771
2772 if (t->type->eclass == EC_MONTH)
2773 convert = "month_interval";
2774 else if (t->type->eclass == EC_SEC)
2775 convert = "second_interval";
2776
2777 /* Lookup the sql convert function, there is no need
2778 * for single value vs bat, this is handled by the
2779 * mal function resolution */
2780 if (v->nrcols == 0) { /* simple calc */
2781 q = newStmt(mb, calcRef, convert);
2782 } else if (v->nrcols > 0 &&
2783 (t->type->localtype > TYPE_str || f->type->eclass == EC_DEC || t->type->eclass == EC_DEC || EC_INTERVAL(t->type->eclass) || EC_TEMP(t->type->eclass) || (EC_VARCHAR(t->type->eclass) && !(f->type->eclass == EC_STRING && t->digits == 0)))) {
2784 int type = t->type->localtype;
2785
2786 q = newStmt(mb, malRef, multiplexRef);
2787 if (q == NULL)
2788 return NULL;
2789 setVarType(mb, getArg(q, 0), newBatType(type));
2790 setVarUDFtype(mb, getArg(q, 0));
2791 q = pushStr(mb, q, convertMultiplexMod(calcRef, convert));
2792 q = pushStr(mb, q, convertMultiplexFcn(convert));
2793 } else
2794 q = newStmt(mb, batcalcRef, convert);
2795
2796 /* convert to string is complex, we need full type info and mvc for the timezone */
2797 if (EC_VARCHAR(t->type->eclass) && !(f->type->eclass == EC_STRING && t->digits == 0)) {
2798 q = pushInt(mb, q, f->type->eclass);
2799 q = pushInt(mb, q, f->digits);
2800 q = pushInt(mb, q, f->scale);
2801 q = pushInt(mb, q, type_has_tz(f));
2802 } else if (f->type->eclass == EC_DEC) {
2803 /* scale of the current decimal */
2804 q = pushInt(mb, q, f->scale);
2805 } else if (f->type->eclass == EC_SEC && t->type->eclass == EC_FLT) {
2806 /* scale of the current decimal */
2807 q = pushInt(mb, q, 3);
2808 }
2809 q = pushArgument(mb, q, v->nr);
2810 if (sel && v->nrcols && f->type->eclass != EC_DEC && !EC_TEMP_FRAC(t->type->eclass) && !EC_INTERVAL(t->type->eclass))
2811 q = pushArgument(mb, q, sel->nr);
2812
2813 if (t->type->eclass == EC_DEC || EC_TEMP_FRAC(t->type->eclass) || EC_INTERVAL(t->type->eclass)) {
2814 /* digits, scale of the result decimal */
2815 q = pushInt(mb, q, t->digits);
2816 if (!EC_TEMP_FRAC(t->type->eclass))
2817 q = pushInt(mb, q, t->scale);
2818 }
2819 /* convert to string, give error on to large strings */
2820 if (EC_VARCHAR(t->type->eclass) && !(f->type->eclass == EC_STRING && t->digits == 0))
2821 q = pushInt(mb, q, t->digits);
2822 /* convert a string to a time(stamp) with time zone */
2823 if (EC_VARCHAR(f->type->eclass) && EC_TEMP_FRAC(t->type->eclass) && type_has_tz(t))
2824 q = pushInt(mb, q, type_has_tz(t));
2825 if (t->type->eclass == EC_GEOM) {
2826 /* push the type and coordinates of the column */
2827 q = pushInt(mb, q, t->digits);
2828 /* push the SRID of the whole columns */
2829 q = pushInt(mb, q, t->scale);
2830 /* push the type and coordinates of the inserted value */
2831 //q = pushInt(mb, q, f->digits);
2832 /* push the SRID of the inserted value */
2833 //q = pushInt(mb, q, f->scale);
2834 /* we decided to create the EWKB type also used by PostGIS and has the SRID provided by the user inside alreay */
2835 /* push the SRID provided for this value */
2836 /* GEOS library is able to store in the returned wkb the type an
2837 * number if coordinates but not the SRID so SRID should be provided
2838 * from this level */
2839/* if(be->argc > 1)
2840 f->scale = ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival;
2841
2842 q = pushInt(mb, q, f->digits);
2843 q = pushInt(mb, q, f->scale);
2844*/ //q = pushInt(mb, q, ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival);
2845 }
2846 if (q) {
2847 stmt *s = stmt_create(be->mvc->sa, st_convert);
2848 if(!s) {
2849 freeInstruction(q);
2850 return NULL;
2851 }
2852 s->op1 = v;
2853 s->op2 = sel;
2854 s->nrcols = 0; /* function without arguments returns single value */
2855 s->key = v->key;
2856 s->nrcols = v->nrcols;
2857 s->aggr = v->aggr;
2858 s->op4.typeval = *t;
2859 s->nr = getDestVar(q);
2860 s->q = q;
2861 return s;
2862 }
2863 return NULL;
2864}
2865
2866stmt *
2867stmt_unop(backend *be, stmt *op1, sql_subfunc *op)
2868{
2869 list *ops = sa_list(be->mvc->sa);
2870 list_append(ops, op1);
2871 return stmt_Nop(be, stmt_list(be, ops), op);
2872}
2873
2874stmt *
2875stmt_binop(backend *be, stmt *op1, stmt *op2, sql_subfunc *op)
2876{
2877 list *ops = sa_list(be->mvc->sa);
2878 list_append(ops, op1);
2879 list_append(ops, op2);
2880 return stmt_Nop(be, stmt_list(be, ops), op);
2881}
2882
2883stmt *
2884stmt_Nop(backend *be, stmt *ops, sql_subfunc *f)
2885{
2886 MalBlkPtr mb = be->mb;
2887 InstrPtr q = NULL;
2888 const char *mod, *fimp;
2889 sql_subtype *tpe = NULL;
2890 int special = 0;
2891
2892 node *n;
2893 stmt *o = NULL;
2894
2895 if (list_length(ops->op4.lval)) {
2896 for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
2897 stmt *c = n->data;
2898
2899 if (o->nrcols < c->nrcols)
2900 o = c;
2901 }
2902 }
2903
2904 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
2905 return NULL;
2906 mod = sql_func_mod(f->func);
2907 fimp = sql_func_imp(f->func);
2908 if (o && o->nrcols > 0 && f->func->type != F_LOADER) {
2909 sql_subtype *res = f->res->h->data;
2910 fimp = convertMultiplexFcn(fimp);
2911 q = NULL;
2912 if (strcmp(fimp, "rotate_xor_hash") == 0 &&
2913 strcmp(mod, calcRef) == 0 &&
2914 (q = newStmt(mb, mkeyRef, putName("bulk_rotate_xor_hash"))) == NULL)
2915 return NULL;
2916 if (!q) {
2917 if (f->func->type == F_UNION)
2918 q = newStmt(mb, batmalRef, multiplexRef);
2919 else
2920 q = newStmt(mb, malRef, multiplexRef);
2921 if (q == NULL)
2922 return NULL;
2923 setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
2924 setVarUDFtype(mb, getArg(q, 0));
2925 q = pushStr(mb, q, mod);
2926 q = pushStr(mb, q, fimp);
2927 } else {
2928 setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
2929 setVarUDFtype(mb, getArg(q, 0));
2930 }
2931 } else {
2932 fimp = convertOperator(fimp);
2933 q = newStmt(mb, mod, fimp);
2934
2935 if (f->res && list_length(f->res)) {
2936 sql_subtype *res = f->res->h->data;
2937
2938 setVarType(mb, getArg(q, 0), res->type->localtype);
2939 setVarUDFtype(mb, getArg(q, 0));
2940 }
2941 }
2942 if (LANG_EXT(f->func->lang))
2943 q = pushPtr(mb, q, f);
2944 if (f->func->lang == FUNC_LANG_C) {
2945 q = pushBit(mb, q, 0);
2946 } else if (f->func->lang == FUNC_LANG_CPP) {
2947 q = pushBit(mb, q, 1);
2948 }
2949 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY ||
2950 f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) {
2951 q = pushStr(mb, q, f->func->query);
2952 }
2953 /* first dynamic output of copy* functions */
2954 if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
2955 q = table_func_create_result(mb, q, f->func, f->res);
2956 if (list_length(ops->op4.lval))
2957 tpe = tail_type(ops->op4.lval->h->data);
2958 if (strcmp(fimp, "round") == 0 && tpe && tpe->type->eclass == EC_DEC)
2959 special = 1;
2960
2961 for (n = ops->op4.lval->h; n; n = n->next) {
2962 stmt *op = n->data;
2963
2964 q = pushArgument(mb, q, op->nr);
2965 if (special) {
2966 q = pushInt(mb, q, tpe->digits);
2967 setVarUDFtype(mb, getArg(q, q->argc-1));
2968 q = pushInt(mb, q, tpe->scale);
2969 setVarUDFtype(mb, getArg(q, q->argc-1));
2970 }
2971 special = 0;
2972 }
2973
2974 if (q) {
2975 stmt *s = stmt_create(be->mvc->sa, st_Nop);
2976 if(!s) {
2977 freeInstruction(q);
2978 return NULL;
2979 }
2980 s->op1 = ops;
2981 if (o) {
2982 s->nrcols = o->nrcols;
2983 s->key = o->key;
2984 s->aggr = o->aggr;
2985 } else {
2986 s->nrcols = 0;
2987 s->key = 1;
2988 }
2989 s->op4.funcval = f;
2990 s->nr = getDestVar(q);
2991 s->q = q;
2992 return s;
2993 }
2994 return NULL;
2995}
2996
2997stmt *
2998stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
2999{
3000 MalBlkPtr mb = be->mb;
3001 InstrPtr q = NULL;
3002 const char *mod = "user";
3003 node *n;
3004 prop *p = NULL;
3005
3006 /* dump args */
3007 if (ops && ops->nr < 0)
3008 return NULL;
3009
3010 p = find_prop(rel->p, PROP_REMOTE);
3011 if (p)
3012 rel->p = prop_remove(rel->p, p);
3013 rel = rel_unnest(be->mvc, rel);
3014 rel = rel_optimizer(be->mvc, rel, 0);
3015 if (p) {
3016 p->p = rel->p;
3017 rel->p = p;
3018 }
3019
3020 if (monet5_create_relational_function(be->mvc, mod, name, rel, ops, NULL, 1) < 0)
3021 return NULL;
3022
3023 if (f_union)
3024 q = newStmt(mb, batmalRef, multiplexRef);
3025 else
3026 q = newStmt(mb, mod, name);
3027 q = relational_func_create_result(be->mvc, mb, q, rel);
3028 if (f_union) {
3029 q = pushStr(mb, q, mod);
3030 q = pushStr(mb, q, name);
3031 }
3032 if (ops) {
3033 for (n = ops->op4.lval->h; n; n = n->next) {
3034 stmt *op = n->data;
3035
3036 q = pushArgument(mb, q, op->nr);
3037 }
3038 }
3039
3040 if (q) {
3041 node *n;
3042 sql_allocator *sa = be->mvc->sa;
3043 stmt *o = NULL, *s = stmt_create(sa, st_func);
3044 if(!s) {
3045 freeInstruction(q);
3046 return NULL;
3047 }
3048 s->op1 = ops;
3049 s->op2 = stmt_atom_string(be, name);
3050 s->op4.rel = rel;
3051 s->flag = f_union;
3052 if (ops && list_length(ops->op4.lval)) {
3053 for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
3054 stmt *c = n->data;
3055
3056 if (o->nrcols < c->nrcols)
3057 o = c;
3058 }
3059 }
3060
3061 if (o) {
3062 s->nrcols = o->nrcols;
3063 s->key = o->key;
3064 s->aggr = o->aggr;
3065 } else {
3066 s->nrcols = 0;
3067 s->key = 1;
3068 }
3069 s->nr = getDestVar(q);
3070 s->q = q;
3071 return s;
3072 }
3073 return NULL;
3074}
3075
3076stmt *
3077stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subaggr *op, int reduce, int no_nil, int nil_if_empty)
3078{
3079 MalBlkPtr mb = be->mb;
3080 InstrPtr q = NULL;
3081 const char *mod, *aggrfunc;
3082 char aggrF[64];
3083 sql_subtype *res = op->res->h->data;
3084 int restype = res->type->localtype;
3085 bool complex_aggr = false;
3086 bool abort_on_error;
3087 int *stmt_nr = NULL;
3088
3089 if (op1->nr < 0)
3090 return NULL;
3091 if (backend_create_subaggr(be, op) < 0)
3092 return NULL;
3093 mod = op->aggr->mod;
3094 aggrfunc = op->aggr->imp;
3095
3096 if (strcmp(aggrfunc, "avg") == 0 || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
3097 || strcmp(aggrfunc, "str_group_concat") == 0)
3098 complex_aggr = true;
3099 /* some "sub" aggregates have an extra argument "abort_on_error" */
3100 abort_on_error = complex_aggr || strncmp(aggrfunc, "stdev", 5) == 0 || strncmp(aggrfunc, "variance", 8) == 0;
3101
3102 if (ext) {
3103 snprintf(aggrF, 64, "sub%s", aggrfunc);
3104 aggrfunc = aggrF;
3105 if (grp->nr < 0 || ext->nr < 0)
3106 return NULL;
3107
3108 q = newStmt(mb, mod, aggrfunc);
3109 if (q == NULL)
3110 return NULL;
3111 setVarType(mb, getArg(q, 0), newBatType(restype));
3112 setVarUDFtype(mb, getArg(q, 0));
3113 } else {
3114 q = newStmt(mb, mod, aggrfunc);
3115 if (q == NULL)
3116 return NULL;
3117 if (complex_aggr) {
3118 setVarType(mb, getArg(q, 0), restype);
3119 setVarUDFtype(mb, getArg(q, 0));
3120 }
3121 }
3122
3123 if (LANG_EXT(op->aggr->lang))
3124 q = pushPtr(mb, q, op->aggr);
3125 if (op->aggr->lang == FUNC_LANG_R ||
3126 op->aggr->lang >= FUNC_LANG_PY ||
3127 op->aggr->lang == FUNC_LANG_C ||
3128 op->aggr->lang == FUNC_LANG_CPP) {
3129 if (!grp) {
3130 setVarType(mb, getArg(q, 0), restype);
3131 setVarUDFtype(mb, getArg(q, 0));
3132 }
3133 if (op->aggr->lang == FUNC_LANG_C) {
3134 q = pushBit(mb, q, 0);
3135 } else if (op->aggr->lang == FUNC_LANG_CPP) {
3136 q = pushBit(mb, q, 1);
3137 }
3138 q = pushStr(mb, q, op->aggr->query);
3139 }
3140
3141 if (op1->type != st_list) {
3142 q = pushArgument(mb, q, op1->nr);
3143 } else {
3144 int i;
3145 node *n;
3146
3147 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
3148 stmt *op = n->data;
3149
3150 if (stmt_nr)
3151 q = pushArgument(mb, q, stmt_nr[i]);
3152 else
3153 q = pushArgument(mb, q, op->nr);
3154 }
3155 }
3156 if (grp) {
3157 q = pushArgument(mb, q, grp->nr);
3158 q = pushArgument(mb, q, ext->nr);
3159 if (q == NULL)
3160 return NULL;
3161 q = pushBit(mb, q, no_nil);
3162 if (abort_on_error)
3163 q = pushBit(mb, q, TRUE);
3164 } else if (no_nil && strncmp(aggrfunc, "count", 5) == 0) {
3165 q = pushBit(mb, q, no_nil);
3166 } else if (!nil_if_empty && strncmp(aggrfunc, "sum", 3) == 0) {
3167 q = pushBit(mb, q, FALSE);
3168 }
3169 if (q) {
3170 stmt *s = stmt_create(be->mvc->sa, st_aggr);
3171 if(!s) {
3172 freeInstruction(q);
3173 return NULL;
3174 }
3175 s->op1 = op1;
3176 if (grp) {
3177 s->op2 = grp;
3178 s->op3 = ext;
3179 s->nrcols = 1;
3180 } else {
3181 if (!reduce)
3182 s->nrcols = 1;
3183 }
3184 s->key = reduce;
3185 s->aggr = reduce;
3186 s->flag = no_nil;
3187 s->op4.aggrval = op;
3188 s->nr = getDestVar(q);
3189 s->q = q;
3190 return s;
3191 }
3192 return NULL;
3193}
3194
3195static stmt *
3196stmt_alias_(backend *be, stmt *op1, const char *tname, const char *alias)
3197{
3198 stmt *s = stmt_create(be->mvc->sa, st_alias);
3199 if(!s) {
3200 return NULL;
3201 }
3202 s->op1 = op1;
3203 s->nrcols = op1->nrcols;
3204 s->key = op1->key;
3205 s->aggr = op1->aggr;
3206
3207 s->tname = tname;
3208 s->cname = alias;
3209 s->nr = op1->nr;
3210 s->q = op1->q;
3211 return s;
3212}
3213
3214stmt *
3215stmt_alias(backend *be, stmt *op1, const char *tname, const char *alias)
3216{
3217 if (((!op1->tname && !tname) ||
3218 (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
3219 op1->cname && strcmp(op1->cname, alias)==0)
3220 return op1;
3221 return stmt_alias_(be, op1, tname, alias);
3222}
3223
3224sql_subtype *
3225tail_type(stmt *st)
3226{
3227 for (;;) {
3228 switch (st->type) {
3229 case st_const:
3230 st = st->op2;
3231 continue;
3232
3233 case st_uselect:
3234 case st_uselect2:
3235 case st_limit:
3236 case st_limit2:
3237 case st_sample:
3238 case st_tunion:
3239 case st_tdiff:
3240 case st_tinter:
3241 case st_append:
3242 case st_alias:
3243 case st_gen_group:
3244 case st_order:
3245 st = st->op1;
3246 continue;
3247
3248 case st_list:
3249 st = st->op4.lval->h->data;
3250 continue;
3251
3252 case st_bat:
3253 return &st->op4.cval->type;
3254 case st_idxbat:
3255 if (hash_index(st->op4.idxval->type)) {
3256 return sql_bind_localtype("lng");
3257 } else if (st->op4.idxval->type == join_idx) {
3258 return sql_bind_localtype("oid");
3259 }
3260 /* fall through */
3261 case st_join:
3262 case st_join2:
3263 case st_joinN:
3264 if (st->flag == cmp_project) {
3265 st = st->op2;
3266 continue;
3267 }
3268 /* fall through */
3269 case st_reorder:
3270 case st_group:
3271 case st_result:
3272 case st_tid:
3273 case st_mirror:
3274 return sql_bind_localtype("oid");
3275 case st_table_clear:
3276 return sql_bind_localtype("lng");
3277
3278 case st_aggr: {
3279 list *res = st->op4.aggrval->res;
3280
3281 if (res && list_length(res) == 1)
3282 return res->h->data;
3283
3284 return NULL;
3285 }
3286 case st_Nop: {
3287 list *res = st->op4.funcval->res;
3288
3289 if (res && list_length(res) == 1)
3290 return res->h->data;
3291 return NULL;
3292 }
3293 case st_atom:
3294 return atom_type(st->op4.aval);
3295 case st_convert:
3296 case st_temp:
3297 case st_single:
3298 case st_rs_column:
3299 return &st->op4.typeval;
3300 case st_var:
3301 if (st->op4.typeval.type)
3302 return &st->op4.typeval;
3303 /* fall through */
3304 case st_exception:
3305 return NULL;
3306 case st_table:
3307 return sql_bind_localtype("bat");
3308 default:
3309 assert(0);
3310 return NULL;
3311 }
3312 }
3313}
3314
3315int
3316stmt_has_null(stmt *s)
3317{
3318 switch (s->type) {
3319 case st_aggr:
3320 case st_Nop:
3321 case st_uselect:
3322 case st_uselect2:
3323 case st_atom:
3324 return 0;
3325 case st_join:
3326 return stmt_has_null(s->op2);
3327 case st_bat:
3328 return s->op4.cval->null;
3329
3330 default:
3331 return 1;
3332 }
3333}
3334
3335static const char *
3336func_name(sql_allocator *sa, const char *n1, const char *n2)
3337{
3338 size_t l1 = _strlen(n1), l2;
3339
3340 if (!sa)
3341 return n1;
3342 if (!n2)
3343 return sa_strdup(sa, n1);
3344 l2 = _strlen(n2);
3345
3346 if (l2 > 16) { /* only support short names */
3347 char *ns = SA_NEW_ARRAY(sa, char, l2 + 1);
3348 if(!ns)
3349 return NULL;
3350 snprintf(ns, l2 + 1, "%s", n2);
3351 return ns;
3352 } else {
3353 char *ns = SA_NEW_ARRAY(sa, char, l1 + l2 + 2), *s = ns;
3354 if(!ns)
3355 return NULL;
3356 snprintf(ns, l1 + l2 + 2, "%s_%s", n1, n2);
3357 return s;
3358 }
3359}
3360
3361const char *_column_name(sql_allocator *sa, stmt *st);
3362
3363const char *
3364column_name(sql_allocator *sa, stmt *st)
3365{
3366 if (!st->cname)
3367 st->cname = _column_name(sa, st);
3368 return st->cname;
3369}
3370
3371const char *
3372_column_name(sql_allocator *sa, stmt *st)
3373{
3374 switch (st->type) {
3375 case st_order:
3376 case st_reorder:
3377 return column_name(sa, st->op1);
3378 case st_const:
3379 case st_join:
3380 case st_join2:
3381 case st_joinN:
3382 return column_name(sa, st->op2);
3383
3384 case st_mirror:
3385 case st_group:
3386 case st_result:
3387 case st_append:
3388 case st_gen_group:
3389 case st_uselect:
3390 case st_uselect2:
3391 case st_limit:
3392 case st_limit2:
3393 case st_sample:
3394 case st_tunion:
3395 case st_tdiff:
3396 case st_tinter:
3397 case st_convert:
3398 return column_name(sa, st->op1);
3399 case st_Nop:
3400 {
3401 const char *cn = column_name(sa, st->op1);
3402 return func_name(sa, st->op4.funcval->func->base.name, cn);
3403 }
3404 case st_aggr:
3405 {
3406 const char *cn = column_name(sa, st->op1);
3407 return func_name(sa, st->op4.aggrval->aggr->base.name, cn);
3408 }
3409 case st_alias:
3410 if (st->op3)
3411 return column_name(sa, st->op3);
3412 break;
3413 case st_bat:
3414 return st->op4.cval->base.name;
3415 case st_atom:
3416 if (st->op4.aval->data.vtype == TYPE_str)
3417 return atom2string(sa, st->op4.aval);
3418 /* fall through */
3419 case st_var:
3420 case st_temp:
3421 case st_single:
3422 if (sa)
3423 return sa_strdup(sa, "single_value");
3424 return "single_value";
3425
3426 case st_list:
3427 if (list_length(st->op4.lval))
3428 return column_name(sa, st->op4.lval->h->data);
3429 /* fall through */
3430 case st_rs_column:
3431 return NULL;
3432 default:
3433 return NULL;
3434 }
3435 return NULL;
3436}
3437
3438const char *_table_name(sql_allocator *sa, stmt *st);
3439
3440const char *
3441table_name(sql_allocator *sa, stmt *st)
3442{
3443 if (!st->tname)
3444 st->tname = _table_name(sa, st);
3445 return st->tname;
3446}
3447
3448const char *
3449_table_name(sql_allocator *sa, stmt *st)
3450{
3451 switch (st->type) {
3452 case st_const:
3453 case st_join:
3454 case st_join2:
3455 case st_joinN:
3456 case st_append:
3457 return table_name(sa, st->op2);
3458 case st_mirror:
3459 case st_group:
3460 case st_result:
3461 case st_gen_group:
3462 case st_uselect:
3463 case st_uselect2:
3464 case st_limit:
3465 case st_limit2:
3466 case st_sample:
3467 case st_tunion:
3468 case st_tdiff:
3469 case st_tinter:
3470 case st_aggr:
3471 return table_name(sa, st->op1);
3472
3473 case st_table_clear:
3474 return st->op4.tval->base.name;
3475 case st_idxbat:
3476 case st_bat:
3477 case st_tid:
3478 return st->op4.cval->t->base.name;
3479 case st_alias:
3480 if (st->tname)
3481 return st->tname;
3482 else
3483 /* there are no table aliases, ie look into the base column */
3484 return table_name(sa, st->op1);
3485 case st_atom:
3486 if (st->op4.aval->data.vtype == TYPE_str && st->op4.aval->data.val.sval && _strlen(st->op4.aval->data.val.sval))
3487 return st->op4.aval->data.val.sval;
3488 return NULL;
3489
3490 case st_list:
3491 if (list_length(st->op4.lval) && st->op4.lval->h)
3492 return table_name(sa, st->op4.lval->h->data);
3493 return NULL;
3494
3495 case st_var:
3496 case st_temp:
3497 case st_single:
3498 default:
3499 return NULL;
3500 }
3501}
3502
3503const char *
3504schema_name(sql_allocator *sa, stmt *st)
3505{
3506 switch (st->type) {
3507 case st_const:
3508 case st_join:
3509 case st_join2:
3510 case st_joinN:
3511 return schema_name(sa, st->op2);
3512 case st_mirror:
3513 case st_group:
3514 case st_result:
3515 case st_append:
3516 case st_gen_group:
3517 case st_uselect:
3518 case st_uselect2:
3519 case st_limit:
3520 case st_limit2:
3521 case st_sample:
3522 case st_tunion:
3523 case st_tdiff:
3524 case st_tinter:
3525 case st_convert:
3526 case st_Nop:
3527 case st_aggr:
3528 return schema_name(sa, st->op1);
3529 case st_alias:
3530 /* there are no schema aliases, ie look into the base column */
3531 return schema_name(sa, st->op1);
3532 case st_bat:
3533 return st->op4.cval->t->s->base.name;
3534 case st_atom:
3535 return NULL;
3536 case st_var:
3537 case st_temp:
3538 case st_single:
3539 return NULL;
3540 case st_list:
3541 if (list_length(st->op4.lval))
3542 return schema_name(sa, st->op4.lval->h->data);
3543 return NULL;
3544 default:
3545 return NULL;
3546 }
3547}
3548
3549stmt *
3550stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
3551{
3552 MalBlkPtr mb = be->mb;
3553 InstrPtr q = NULL;
3554
3555 if (cond->nr < 0)
3556 return NULL;
3557 if (anti) {
3558 sql_subtype *bt = sql_bind_localtype("bit");
3559 sql_subfunc *not = sql_bind_func(be->mvc->sa, NULL, "not", bt, NULL, F_FUNC);
3560 sql_subfunc *or = sql_bind_func(be->mvc->sa, NULL, "or", bt, bt, F_FUNC);
3561 sql_subfunc *isnull = sql_bind_func(be->mvc->sa, NULL, "isnull", bt, NULL, F_FUNC);
3562 cond = stmt_binop(be,
3563 stmt_unop(be, cond, not),
3564 stmt_unop(be, cond, isnull), or);
3565 }
3566 if (!loop) { /* if */
3567 q = newAssignment(mb);
3568 if (q == NULL)
3569 return NULL;
3570 q->barrier = BARRIERsymbol;
3571 q = pushArgument(mb, q, cond->nr);
3572 if (q == NULL)
3573 return NULL;
3574 } else { /* while */
3575 int c;
3576
3577 if (outer->nr < 0)
3578 return NULL;
3579 /* leave barrier */
3580 q = newStmt(mb, calcRef, notRef);
3581 q = pushArgument(mb, q, cond->nr);
3582 if (q == NULL)
3583 return NULL;
3584 c = getArg(q, 0);
3585
3586 q = newAssignment(mb);
3587 if (q == NULL)
3588 return NULL;
3589 getArg(q, 0) = outer->nr;
3590 q->barrier = LEAVEsymbol;
3591 q = pushArgument(mb, q, c);
3592 if (q == NULL)
3593 return NULL;
3594 }
3595 if (q){
3596 stmt *s = stmt_create(be->mvc->sa, st_cond);
3597 if(!s) {
3598 freeInstruction(q);
3599 return NULL;
3600 }
3601 s->flag = loop;
3602 s->op1 = cond;
3603 s->nr = getArg(q, 0);
3604 return s;
3605 }
3606 return NULL;
3607}
3608
3609stmt *
3610stmt_control_end(backend *be, stmt *cond)
3611{
3612 MalBlkPtr mb = be->mb;
3613 InstrPtr q = NULL;
3614
3615 if (cond->nr < 0)
3616 return NULL;
3617
3618 if (cond->flag) { /* while */
3619 /* redo barrier */
3620 q = newAssignment(mb);
3621 if (q == NULL)
3622 return NULL;
3623 getArg(q, 0) = cond->nr;
3624 q->argc = q->retc = 1;
3625 q->barrier = REDOsymbol;
3626 q = pushBit(mb, q, TRUE);
3627 if (q == NULL)
3628 return NULL;
3629 } else {
3630 q = newAssignment(mb);
3631 if (q == NULL)
3632 return NULL;
3633 getArg(q, 0) = cond->nr;
3634 q->argc = q->retc = 1;
3635 q->barrier = EXITsymbol;
3636 }
3637 q = newStmt(mb, sqlRef, mvcRef);
3638 if (q == NULL)
3639 return NULL;
3640 be->mvc_var = getDestVar(q);
3641 if (q){
3642 stmt *s = stmt_create(be->mvc->sa, st_control_end);
3643 if(!s) {
3644 freeInstruction(q);
3645 return NULL;
3646 }
3647 s->op1 = cond;
3648 s->nr = getArg(q, 0);
3649 return s;
3650 }
3651 return NULL;
3652}
3653
3654
3655static InstrPtr
3656dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
3657{
3658 int i;
3659 node *n;
3660
3661 if (q == NULL)
3662 return NULL;
3663 q->retc = q->argc = 0;
3664 for (i = 0, n = l->h; n; n = n->next, i++) {
3665 stmt *c = n->data;
3666
3667 q = pushArgument(mb, q, c->nr);
3668 }
3669 if (q == NULL)
3670 return NULL;
3671 q->retc = q->argc;
3672 /* Lets make it a propper assignment */
3673 for (i = 0, n = l->h; n; n = n->next, i++) {
3674 stmt *c = n->data;
3675
3676 q = pushArgument(mb, q, c->nr);
3677 }
3678 return q;
3679}
3680
3681stmt *
3682stmt_return(backend *be, stmt *val, int nr_declared_tables)
3683{
3684 MalBlkPtr mb = be->mb;
3685 InstrPtr q = NULL;
3686
3687 if (val->nr < 0)
3688 return NULL;
3689 q = newInstruction(mb, NULL, NULL);
3690 if (q == NULL)
3691 return NULL;
3692 q->barrier= RETURNsymbol;
3693 if (val->type == st_table) {
3694 list *l = val->op1->op4.lval;
3695
3696 q = dump_cols(mb, l, q);
3697 } else {
3698 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
3699 q = pushArgument(mb, q, val->nr);
3700 }
3701 if (q == NULL)
3702 return NULL;
3703 pushInstruction(mb, q);
3704 if (q) {
3705 stmt *s = stmt_create(be->mvc->sa, st_return);
3706 if(!s) {
3707 freeInstruction(q);
3708 return NULL;
3709 }
3710 s->op1 = val;
3711 s->flag = nr_declared_tables;
3712 s->nr = getDestVar(q);
3713 s->q = q;
3714 return s;
3715 }
3716 return NULL;
3717}
3718
3719stmt *
3720stmt_assign(backend *be, const char *varname, stmt *val, int level)
3721{
3722 MalBlkPtr mb = be->mb;
3723 InstrPtr q = NULL;
3724
3725 if (val && val->nr < 0)
3726 return NULL;
3727 if (level != 1) {
3728 char buf[IDLENGTH];
3729
3730 if (!val) {
3731 /* drop declared table */
3732 assert(0);
3733 }
3734 (void) snprintf(buf, sizeof(buf), "A%s", varname);
3735 q = newInstruction(mb, NULL, NULL);
3736 if (q == NULL) {
3737 return NULL;
3738 }
3739 q->argc = q->retc = 0;
3740 q = pushArgumentId(mb, q, buf);
3741 if (q == NULL)
3742 return NULL;
3743 pushInstruction(mb, q);
3744 if (mb->errors)
3745 return NULL;
3746 q->retc++;
3747 } else {
3748 q = newStmt(mb, sqlRef, setVariableRef);
3749 q = pushArgument(mb, q, be->mvc_var);
3750 q = pushStr(mb, q, varname);
3751 if (q == NULL)
3752 return NULL;
3753 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
3754 be->mvc_var = getDestVar(q);
3755 }
3756 q = pushArgument(mb, q, val->nr);
3757 if (q){
3758 stmt *s = stmt_create(be->mvc->sa, st_assign);
3759 if(!s) {
3760 freeInstruction(q);
3761 return NULL;
3762 }
3763 s->op2 = val;
3764 s->flag = (level << 1);
3765 s->q = q;
3766 s->nr = 1;
3767 return s;
3768 }
3769 return NULL;
3770}
3771
3772stmt *
3773const_column(backend *be, stmt *val)
3774{
3775 sql_subtype *ct = tail_type(val);
3776 MalBlkPtr mb = be->mb;
3777 InstrPtr q = NULL;
3778 int tt = ct->type->localtype;
3779
3780 if (val->nr < 0)
3781 return NULL;
3782 q = newStmt(mb, sqlRef, singleRef);
3783 if (q == NULL)
3784 return NULL;
3785 setVarType(mb, getArg(q, 0), newBatType(tt));
3786 q = pushArgument(mb, q, val->nr);
3787 if (q) {
3788 stmt *s = stmt_create(be->mvc->sa, st_single);
3789 if(!s) {
3790 freeInstruction(q);
3791 return NULL;
3792 }
3793 s->op1 = val;
3794 s->op4.typeval = *ct;
3795 s->nrcols = 1;
3796
3797 s->tname = val->tname;
3798 s->cname = val->cname;
3799 s->nr = getDestVar(q);
3800 s->q = q;
3801 return s;
3802 }
3803 return NULL;
3804}
3805
3806stmt *
3807stmt_fetch(backend *be, stmt *val)
3808{
3809 sql_subtype *ct = tail_type(val);
3810 MalBlkPtr mb = be->mb;
3811 InstrPtr q = NULL;
3812 int tt = ct->type->localtype;
3813
3814 if (val->nr < 0)
3815 return NULL;
3816 q = newStmt(mb, algebraRef, fetchRef);
3817 if (q == NULL)
3818 return NULL;
3819 setVarType(mb, getArg(q, 0), tt);
3820 q = pushArgument(mb, q, val->nr);
3821 q = pushOid(mb, q, 0);
3822 if (q) {
3823 stmt *s = stmt_create(be->mvc->sa, st_single);
3824 if(!s) {
3825 freeInstruction(q);
3826 return NULL;
3827 }
3828 s->op1 = val;
3829 s->op4.typeval = *ct;
3830 s->nrcols = 0;
3831
3832 s->tname = val->tname;
3833 s->cname = val->cname;
3834 s->nr = getDestVar(q);
3835 s->q = q;
3836 return s;
3837 }
3838 return NULL;
3839}
3840