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
11#include "rel_bin.h"
12#include "rel_rel.h"
13#include "rel_exp.h"
14#include "rel_psm.h"
15#include "rel_prop.h"
16#include "rel_select.h"
17#include "rel_updates.h"
18#include "rel_unnest.h"
19#include "rel_optimizer.h"
20#include "sql_env.h"
21#include "sql_optimizer.h"
22
23#define OUTER_ZERO 64
24
25static stmt * exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel);
26static stmt * rel_bin(backend *be, sql_rel *rel);
27static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
28
29static stmt *check_types(backend *be, sql_subtype *ct, stmt *s, check_type tpe);
30
31static stmt *
32stmt_selectnil( backend *be, stmt *col)
33{
34 sql_subtype *t = tail_type(col);
35 stmt *n = stmt_atom(be, atom_general(be->mvc->sa, t, NULL));
36 stmt *nn = stmt_uselect2(be, col, n, n, 3, NULL, 0);
37 return nn;
38}
39
40static stmt *
41sql_unop_(backend *be, sql_schema *s, const char *fname, stmt *rs)
42{
43 mvc *sql = be->mvc;
44 sql_subtype *rt = NULL;
45 sql_subfunc *f = NULL;
46
47 if (!s)
48 s = sql->session->schema;
49 rt = tail_type(rs);
50 f = sql_bind_func(sql->sa, s, fname, rt, NULL, F_FUNC);
51 /* try to find the function without a type, and convert
52 * the value to the type needed by this function!
53 */
54 if (!f && (f = sql_find_func(sql->sa, s, fname, 1, F_FUNC, NULL)) != NULL) {
55 sql_arg *a = f->func->ops->h->data;
56
57 rs = check_types(be, &a->type, rs, type_equal);
58 if (!rs)
59 f = NULL;
60 }
61 if (f) {
62 /*
63 if (f->func->res.scale == INOUT) {
64 f->res.digits = rt->digits;
65 f->res.scale = rt->scale;
66 }
67 */
68 return stmt_unop(be, rs, f);
69 } else if (rs) {
70 char *type = tail_type(rs)->type->sqlname;
71
72 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such unary operator '%s(%s)'", fname, type);
73 }
74 return NULL;
75}
76
77static stmt *
78refs_find_rel(list *refs, sql_rel *rel)
79{
80 node *n;
81
82 for(n=refs->h; n; n = n->next->next) {
83 sql_rel *ref = n->data;
84 stmt *s = n->next->data;
85
86 if (rel == ref)
87 return s;
88 }
89 return NULL;
90}
91
92static void
93print_stmtlist(sql_allocator *sa, stmt *l)
94{
95 node *n;
96 if (l) {
97 for (n = l->op4.lval->h; n; n = n->next) {
98 const char *rnme = table_name(sa, n->data);
99 const char *nme = column_name(sa, n->data);
100
101 fprintf(stderr, "%s.%s\n", rnme ? rnme : "(null!)", nme ? nme : "(null!)");
102 }
103 }
104}
105
106static stmt *
107list_find_column(backend *be, list *l, const char *rname, const char *name )
108{
109 stmt *res = NULL;
110 node *n;
111
112 if (!l)
113 return NULL;
114 MT_lock_set(&l->ht_lock);
115 if (!l->ht && list_length(l) > HASH_MIN_SIZE) {
116 l->ht = hash_new(l->sa, MAX(list_length(l), l->expected_cnt), (fkeyvalue)&stmt_key);
117 if (l->ht == NULL) {
118 MT_lock_unset(&l->ht_lock);
119 return NULL;
120 }
121
122 for (n = l->h; n; n = n->next) {
123 const char *nme = column_name(be->mvc->sa, n->data);
124 if (nme) {
125 int key = hash_key(nme);
126
127 if (hash_add(l->ht, key, n->data) == NULL) {
128 MT_lock_unset(&l->ht_lock);
129 return NULL;
130 }
131 }
132 }
133 }
134 if (l->ht) {
135 int key = hash_key(name);
136 sql_hash_e *e = l->ht->buckets[key&(l->ht->size-1)];
137
138 if (rname) {
139 for (; e; e = e->chain) {
140 stmt *s = e->value;
141 const char *rnme = table_name(be->mvc->sa, s);
142 const char *nme = column_name(be->mvc->sa, s);
143
144 if (rnme && strcmp(rnme, rname) == 0 &&
145 strcmp(nme, name) == 0) {
146 res = s;
147 break;
148 }
149 }
150 } else {
151 for (; e; e = e->chain) {
152 stmt *s = e->value;
153 const char *nme = column_name(be->mvc->sa, s);
154
155 if (nme && strcmp(nme, name) == 0) {
156 res = s;
157 break;
158 }
159 }
160 }
161 MT_lock_unset(&l->ht_lock);
162 if (!res)
163 return NULL;
164 return res;
165 }
166 MT_lock_unset(&l->ht_lock);
167 if (rname) {
168 for (n = l->h; n; n = n->next) {
169 const char *rnme = table_name(be->mvc->sa, n->data);
170 const char *nme = column_name(be->mvc->sa, n->data);
171
172 if (rnme && strcmp(rnme, rname) == 0 &&
173 strcmp(nme, name) == 0) {
174 res = n->data;
175 break;
176 }
177 }
178 } else {
179 for (n = l->h; n; n = n->next) {
180 const char *nme = column_name(be->mvc->sa, n->data);
181
182 if (nme && strcmp(nme, name) == 0) {
183 res = n->data;
184 break;
185 }
186 }
187 }
188 if (!res)
189 return NULL;
190 return res;
191}
192
193static stmt *
194bin_find_column( backend *be, stmt *sub, const char *rname, const char *name )
195{
196 return list_find_column( be, sub->op4.lval, rname, name);
197}
198
199static list *
200bin_find_columns( backend *be, stmt *sub, const char *name )
201{
202 node *n;
203 list *l = sa_list(be->mvc->sa);
204
205 for (n = sub->op4.lval->h; n; n = n->next) {
206 const char *nme = column_name(be->mvc->sa, n->data);
207
208 if (strcmp(nme, name) == 0)
209 append(l, n->data);
210 }
211 if (list_length(l))
212 return l;
213 return NULL;
214}
215
216static stmt *column(backend *be, stmt *val )
217{
218 if (val->nrcols == 0)
219 return const_column(be, val);
220 return val;
221}
222
223static stmt *create_const_column(backend *be, stmt *val )
224{
225 if (val->nrcols == 0)
226 val = const_column(be, val);
227 return stmt_append(be, stmt_temp(be, tail_type(val)), val);
228}
229
230static stmt *
231bin_first_column(backend *be, stmt *sub )
232{
233 node *n = sub->op4.lval->h;
234 stmt *c = n->data;
235
236 if (c->nrcols == 0)
237 return const_column(be, c);
238 return c;
239}
240
241static stmt *
242row2cols(backend *be, stmt *sub)
243{
244 if (sub->nrcols == 0 && sub->key) {
245 node *n;
246 list *l = sa_list(be->mvc->sa);
247
248 for (n = sub->op4.lval->h; n; n = n->next) {
249 stmt *sc = n->data;
250 const char *cname = column_name(be->mvc->sa, sc);
251 const char *tname = table_name(be->mvc->sa, sc);
252
253 sc = column(be, sc);
254 list_append(l, stmt_alias(be, sc, tname, cname));
255 }
256 sub = stmt_list(be, l);
257 }
258 return sub;
259}
260
261static stmt*
262distinct_value_list(backend *be, list *vals, stmt ** last_null_value)
263{
264 node *n;
265 stmt *s;
266
267 /* create bat append values */
268 s = stmt_temp(be, exp_subtype(vals->h->data));
269 for( n = vals->h; n; n = n->next) {
270 sql_exp *e = n->data;
271 stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL);
272
273 if (exp_is_null(be->mvc, e))
274 *last_null_value = i;
275
276 if (!i)
277 return NULL;
278
279 s = stmt_append(be, s, i);
280 }
281
282 // Probably faster to filter out the values directly in the underlying list of atoms.
283 // But for now use groupby to filter out duplicate values.
284
285 stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
286 stmt* ext = stmt_result(be, groupby, 1);
287
288 return stmt_project(be, ext, s);
289}
290
291static stmt *
292stmt_selectnonil( backend *be, stmt *col, stmt *s )
293{
294 sql_subtype *t = tail_type(col);
295 stmt *n = stmt_atom(be, atom_general(be->mvc->sa, t, NULL));
296 stmt *nn = stmt_uselect2(be, col, n, n, 3, s, 1);
297 return nn;
298}
299
300static stmt *
301handle_in_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int in, int use_r)
302{
303 mvc *sql = be->mvc;
304 node *n;
305 stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL);
306
307 if(!c)
308 return NULL;
309
310 if (c->nrcols == 0) {
311 sql_subtype *bt = sql_bind_localtype("bit");
312 sql_subfunc *cmp = (in)
313 ?sql_bind_func(sql->sa, sql->session->schema, "=", tail_type(c), tail_type(c), F_FUNC)
314 :sql_bind_func(sql->sa, sql->session->schema, "<>", tail_type(c), tail_type(c), F_FUNC);
315 sql_subfunc *a = (in)?sql_bind_func(sql->sa, sql->session->schema, "or", bt, bt, F_FUNC)
316 :sql_bind_func(sql->sa, sql->session->schema, "and", bt, bt, F_FUNC);
317
318 for( n = nl->h; n; n = n->next) {
319 sql_exp *e = n->data;
320 stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL);
321 if(!i)
322 return NULL;
323
324 i = stmt_binop(be, c, i, cmp);
325 if (s)
326 s = stmt_binop(be, s, i, a);
327 else
328 s = i;
329
330 }
331 if (sel)
332 s = stmt_uselect(be,
333 stmt_const(be, bin_first_column(be, left), s),
334 stmt_bool(be, 1), cmp_equal, sel, 0);
335 } else if (list_length(nl) < 16) {
336 comp_type cmp = (in)?cmp_equal:cmp_notequal;
337
338 if (!in)
339 s = sel;
340 for( n = nl->h; n; n = n->next) {
341 sql_exp *e = n->data;
342 stmt *i = exp_bin(be, use_r?e->r:e, left, right, grp, ext, cnt, NULL);
343 if(!i)
344 return NULL;
345
346 if (in) {
347 i = stmt_uselect(be, c, i, cmp, sel, 0);
348 if (s)
349 s = stmt_tunion(be, s, i);
350 else
351 s = i;
352 } else {
353 s = stmt_uselect(be, c, i, cmp, s, 0);
354 }
355 }
356 } else {
357 // TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
358 // For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
359 // make sure that this behavior is replicated by the sql optimizer and not handle_in_exps.
360
361 stmt* last_null_value = NULL; // CORNER CASE ALERT: See description below.
362
363 // The actual in-value-list should not contain duplicates to ensure that final join results are unique.
364 s = distinct_value_list(be, nl, &last_null_value);
365
366 if (last_null_value) {
367 // The actual in-value-list should not contain null values.
368 s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
369 }
370
371 s = stmt_join(be, c, s, in, cmp_left);
372 s = stmt_result(be, s, 0);
373
374 if (!in) {
375 if (last_null_value) {
376 // CORNER CASE ALERT:
377 // In case of a not-in-expression with the associated in-value-list containing a null value,
378 // the entire in-predicate is forced to always return false, i.e. an empty candidate list.
379 // This is similar to postgres behavior.
380 // TODO: However I do not think this behavior is in accordance with SQL standard 2003.
381
382 // Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
383 //list* singleton_bat = sa_list(sql->sa);
384 // list_append(singleton_bat, null_value);
385 s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0);
386 return s;
387 }
388 else {
389 // BACK TO HAPPY FLOW:
390 // Make sure that null values are never returned.
391 stmt* non_nulls;
392 non_nulls = stmt_selectnonil(be, c, NULL);
393 s = stmt_tdiff(be, non_nulls, s);
394 s = stmt_project(be, s, non_nulls);
395 }
396 }
397
398 if (sel) {
399 stmt* oid_intersection;
400 oid_intersection = stmt_tinter(be, s, sel);
401 s = stmt_project(be, oid_intersection, s);
402 s = stmt_result(be, s, 0);
403 }
404 }
405 return s;
406}
407
408static stmt *
409value_list(backend *be, list *vals, stmt *left, stmt *sel)
410{
411 node *n;
412 stmt *s;
413 sql_subtype *type = exp_subtype(vals->h->data);
414
415 if (!type)
416 return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
417 /* create bat append values */
418 s = stmt_temp(be, type);
419 for( n = vals->h; n; n = n->next) {
420 sql_exp *e = n->data;
421 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel);
422
423 if (!i)
424 return NULL;
425
426 if (list_length(vals) == 1)
427 return i;
428 s = stmt_append(be, s, i);
429 }
430 return s;
431}
432
433static stmt *
434exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
435{
436 mvc *sql = be->mvc;
437 node *n;
438 list *nl = sa_list(sql->sa);
439
440 for( n = exps->h; n; n = n->next) {
441 sql_exp *e = n->data;
442 stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel);
443 if(!i)
444 return NULL;
445
446 if (n->next && i->type == st_table) /* relational statement */
447 l = i->op1;
448 else
449 append(nl, i);
450 }
451 return stmt_list(be, nl);
452}
453
454static stmt *
455exp_count_no_nil_arg( sql_exp *e, stmt *ext, sql_exp *ae, stmt *as )
456{
457 /* small optimization, ie use candidates directly on count(*) */
458 if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
459 /* skip alias statements */
460 while (as->type == st_alias)
461 as = as->op1;
462 /* use candidate */
463 if (as && as->type == st_join && as->flag == cmp_project) {
464 if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
465 as = as->op1;
466 }
467 }
468 return as;
469}
470
471stmt *
472exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
473{
474 mvc *sql = be->mvc;
475 stmt *s = NULL;
476
477 if (THRhighwater())
478 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
479
480 if (!e) {
481 assert(0);
482 return NULL;
483 }
484
485 switch(e->type) {
486 case e_psm:
487 if (e->flag & PSM_SET) {
488 stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel);
489 if(!r)
490 return NULL;
491 if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
492 r = stmt_fetch(be, r);
493 return stmt_assign(be, exp_name(e), r, GET_PSM_LEVEL(e->flag));
494 } else if (e->flag & PSM_VAR) {
495 if (e->f)
496 return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
497 else
498 return stmt_var(be, exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
499 } else if (e->flag & PSM_RETURN) {
500 sql_exp *l = e->l;
501 stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel);
502
503 if (!r)
504 return NULL;
505 /* handle table returning functions */
506 if (l->type == e_psm && l->flag & PSM_REL) {
507 stmt *lst = r->op1;
508 //if (r->type == st_table && lst->nrcols == 0 && lst->key) {
509 if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
510 node *n;
511 list *l = sa_list(sql->sa);
512
513 for(n=lst->op4.lval->h; n; n = n->next)
514 list_append(l, const_column(be, (stmt*)n->data));
515 r = stmt_list(be, l);
516 }
517 if (r->type == st_list)
518 r = stmt_table(be, r, 1);
519 }
520 return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
521 } else if (e->flag & PSM_WHILE) {
522 /* while is a if - block true with leave statement
523 * needed because the condition needs to be inside this outer block */
524 stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
525 stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel);
526 stmt *wstmt;
527
528 if(!cond)
529 return NULL;
530 wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
531
532 if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
533 return NULL;
534 (void)stmt_control_end(be, wstmt);
535 return stmt_control_end(be, ifstmt);
536 } else if (e->flag & PSM_IF) {
537 stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel);
538 stmt *ifstmt, *res;
539
540 if(!cond)
541 return NULL;
542 ifstmt = stmt_cond(be, cond, NULL, 0, 0);
543 if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
544 return NULL;
545 res = stmt_control_end(be, ifstmt);
546 if (e->f) {
547 stmt *elsestmt = stmt_cond(be, cond, NULL, 0, 1);
548
549 if (!exp_list(be, e->f, left, right, grp, ext, cnt, sel))
550 return NULL;
551 res = stmt_control_end(be, elsestmt);
552 }
553 return res;
554 } else if (e->flag & PSM_REL) {
555 sql_rel *rel = e->l;
556 stmt *r = rel_bin(be, rel);
557
558 if (!r)
559 return NULL;
560 if (is_modify(rel->op) || is_ddl(rel->op))
561 return r;
562 return stmt_table(be, r, 1);
563 } else if (e->flag & PSM_EXCEPTION) {
564 stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel);
565 return stmt_exception(be, cond, (const char *) e->r, 0);
566 }
567 break;
568 case e_atom: {
569 if (e->l) { /* literals */
570 atom *a = e->l;
571 s = stmt_atom(be, atom_dup(sql->sa, a));
572 } else if (e->r) { /* parameters */
573 s = stmt_var(be, sa_strdup(sql->sa, e->r), e->tpe.type?&e->tpe:NULL, 0, e->flag);
574 } else if (e->f) { /* values */
575 s = value_list(be, e->f, left, sel);
576 } else { /* arguments */
577 s = stmt_varnr(be, e->flag, e->tpe.type?&e->tpe:NULL);
578 }
579 } break;
580 case e_convert: {
581 /* if input is type any NULL or column of nulls, change type */
582 list *tps = e->r;
583 sql_subtype *from = tps->h->data;
584 sql_subtype *to = tps->h->next->data;
585 stmt *l;
586
587 if (from->type->localtype == 0) {
588 l = stmt_atom(be, atom_general(sql->sa, to, NULL));
589 } else {
590 l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel);
591 }
592 if (!l)
593 return NULL;
594 s = stmt_convert(be, l, from, to, NULL);
595 } break;
596 case e_func: {
597 node *en;
598 list *l = sa_list(sql->sa), *exps = e->l;
599 sql_subfunc *f = e->f;
600 stmt *rows = NULL, *cond_execution = NULL;
601 char name[16], *nme = NULL;
602
603 if (f->func->side_effect && left) {
604 if (!exps || list_empty(exps))
605 append(l,
606 stmt_const(be,
607 bin_first_column(be, left),
608 stmt_atom_int(be, 0)));
609 else if (exps_card(exps) < CARD_MULTI) {
610 rows = bin_first_column(be, left);
611 }
612 }
613 assert(!e->r);
614 if (exps) {
615 int nrcols = 0;
616 for (en = exps->h; en; en = en->next) {
617 sql_exp *e = en->data;
618 stmt *es;
619
620 es = exp_bin(be, e, left, right, grp, ext, cnt, sel);
621
622 if (!es)
623 return NULL;
624
625 if (rows && en == exps->h && f->func->type != F_LOADER)
626 es = stmt_const(be, rows, es);
627 else if(f->func->type == F_ANALYTIC && es->nrcols == 0) {
628 if(en == exps->h)
629 es = stmt_const(be, bin_first_column(be, left), es); /* ensure the first argument is a column */
630 if((!strcmp(f->func->base.name, "window_bound"))
631 && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next)
632 es = stmt_const(be, bin_first_column(be, left), es);
633 }
634 /* last argument is condition, change into candidate list */
635 if (f->func->type != F_ANALYTIC && !en->next && !f->func->varres && !f->func->vararg && list_length(exps) > list_length(f->func->ops)) {
636 if (es->nrcols) {
637 if (!nrcols) {
638 node *n;
639 list *nl = sa_list(sql->sa);
640 for (n = l->h; n; n = n->next) {
641 stmt *s = n->data;
642 s = stmt_const(be, es, s);
643 list_append(nl, s);
644 }
645 l = nl;
646
647 }
648 es = stmt_uselect(be, es, stmt_bool(be,1), cmp_equal, NULL, 0);
649 } else /* need a condition */
650 cond_execution = es;
651 }
652 if (es->nrcols > nrcols)
653 nrcols = es->nrcols;
654 if (!cond_execution)
655 list_append(l,es);
656 }
657 if (sel && strcmp(sql_func_mod(f->func), "calc") == 0 && nrcols && strcmp(sql_func_imp(f->func), "ifthenelse") != 0)
658 list_append(l,sel);
659 }
660 if (cond_execution) {
661 /* var_x = nil; */
662 nme = number2name(name, sizeof(name), ++sql->label);
663 (void)stmt_var(be, nme, exp_subtype(e), 1, 2);
664 /* if_barrier ... */
665 cond_execution = stmt_cond(be, cond_execution, NULL, 0, 0);
666 }
667 if (f->func->rel)
668 s = stmt_func(be, stmt_list(be, l), sa_strdup(sql->sa, f->func->base.name), f->func->rel, (f->func->type == F_UNION));
669 else
670 s = stmt_Nop(be, stmt_list(be, l), e->f);
671 if (!s)
672 return NULL;
673 if (cond_execution) {
674 /* var_x = s */
675 (void)stmt_assign(be, nme, s, 2);
676 /* endif_barrier */
677 (void)stmt_control_end(be, cond_execution);
678 s = stmt_var(be, nme, exp_subtype(e), 0, 2);
679 }
680 } break;
681 case e_aggr: {
682 list *attr = e->l;
683 stmt *as = NULL;
684 sql_subaggr *a = e->f;
685
686 assert(sel == NULL);
687 if (attr && attr->h) {
688 node *en;
689 list *l = sa_list(sql->sa);
690
691 for (en = attr->h; en; en = en->next) {
692 sql_exp *at = en->data;
693
694 as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel);
695
696 if (as && as->nrcols <= 0 && left && (a->aggr->base.name[0] != 'm' || en->next || en == attr->h))
697 as = stmt_const(be, bin_first_column(be, left), as);
698 if (en == attr->h && !en->next && exp_aggr_is_count(e))
699 as = exp_count_no_nil_arg(e, ext, at, as);
700 /* insert single value into a column */
701 if (as && as->nrcols <= 0 && !left && (a->aggr->base.name[0] != 'm' || en->next || en == attr->h))
702 as = const_column(be, as);
703
704 if (!as)
705 return NULL;
706 if (need_distinct(e)){
707 stmt *g = stmt_group(be, as, grp, ext, cnt, 1);
708 stmt *next = stmt_result(be, g, 1);
709
710 as = stmt_project(be, next, as);
711 if (grp)
712 grp = stmt_project(be, next, grp);
713 }
714 append(l, as);
715 }
716 as = stmt_list(be, l);
717 } else {
718 /* count(*) may need the default group (relation) and
719 and/or an attribute to count */
720 if (grp) {
721 as = grp;
722 } else if (left) {
723 as = bin_first_column(be, left);
724 as = exp_count_no_nil_arg(e, ext, NULL, as);
725 } else {
726 /* create dummy single value in a column */
727 as = stmt_atom_lng(be, 0);
728 as = const_column(be, as);
729 }
730 }
731 s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e) );
732 if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
733 s->flag |= OUTER_ZERO;
734 } break;
735 case e_column: {
736 if (right) /* check relation names */
737 s = bin_find_column(be, right, e->l, e->r);
738 if (!s && left)
739 s = bin_find_column(be, left, e->l, e->r);
740 if (s && grp)
741 s = stmt_project(be, ext, s);
742 if (!s && right) {
743 fprintf(stderr, "could not find %s.%s\n", (char*)e->l, (char*)e->r);
744 print_stmtlist(sql->sa, left);
745 print_stmtlist(sql->sa, right);
746 if (!s) {
747 fprintf(stderr, "query: '%s'\n", sql->query);
748 }
749 assert(s);
750 return NULL;
751 }
752 } break;
753 case e_cmp: {
754 stmt *l = NULL, *r = NULL, *r2 = NULL;
755 int swapped = 0, is_select = 0;
756 sql_exp *re = e->r, *re2 = e->f;
757
758 /* general predicate, select and join */
759 if (get_cmp(e) == cmp_filter) {
760 list *args;
761 list *ops;
762 node *n;
763 int first = 1;
764
765 ops = sa_list(sql->sa);
766 args = e->l;
767 for( n = args->h; n; n = n->next ) {
768 s = NULL;
769 if (!swapped)
770 s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL);
771 if (!s && (first || swapped)) {
772 s = exp_bin(be, n->data, right, NULL, grp, ext, cnt, NULL);
773 swapped = 1;
774 }
775 if (!s)
776 return s;
777 if (s->nrcols == 0 && first)
778 s = stmt_const(be, bin_first_column(be, swapped?right:left), s);
779 list_append(ops, s);
780 first = 0;
781 }
782 l = stmt_list(be, ops);
783 ops = sa_list(sql->sa);
784 args = e->r;
785 for( n = args->h; n; n = n->next ) {
786 s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL);
787 if (!s)
788 return s;
789 list_append(ops, s);
790 }
791 r = stmt_list(be, ops);
792
793 if (left && right && exps_card(e->r) > CARD_ATOM) {
794 sql_subfunc *f = e->f;
795 return stmt_genjoin(be, l, r, f, is_anti(e), swapped);
796 }
797 assert(!swapped);
798 s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
799 return s;
800 }
801 if (e->flag == cmp_in || e->flag == cmp_notin) {
802 return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), 0);
803 }
804 if (get_cmp(e) == cmp_or && (!right || right->nrcols == 1)) {
805 sql_subtype *bt = sql_bind_localtype("bit");
806 list *l = e->l;
807 node *n;
808 stmt *sel1 = NULL, *sel2 = NULL;
809 int anti = is_anti(e);
810
811 sel1 = sel;
812 sel2 = sel;
813 for( n = l->h; n; n = n->next ) {
814 sql_exp *c = n->data;
815 stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
816
817 /* propagate the anti flag */
818 if (anti)
819 set_anti(c);
820 s = exp_bin(be, c, left, right, grp, ext, cnt, sin);
821 if (!s)
822 return s;
823
824 if (!sin && sel1 && sel1->nrcols == 0 && s->nrcols == 0) {
825 sql_subfunc *f = sql_bind_func(sql->sa, sql->session->schema, anti?"or":"and", bt, bt, F_FUNC);
826 assert(f);
827 s = stmt_binop(be, sel1, s, f);
828 } else if (sel1 && (sel1->nrcols == 0 || s->nrcols == 0)) {
829 stmt *predicate = bin_first_column(be, left);
830
831 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
832 if (s->nrcols == 0)
833 s = stmt_uselect(be, predicate, s, cmp_equal, sel1, anti);
834 else
835 s = stmt_uselect(be, predicate, sel1, cmp_equal, s, anti);
836 }
837 sel1 = s;
838 }
839 l = e->r;
840 for( n = l->h; n; n = n->next ) {
841 sql_exp *c = n->data;
842 stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
843
844 /* propagate the anti flag */
845 if (anti)
846 set_anti(c);
847 s = exp_bin(be, c, left, right, grp, ext, cnt, sin);
848 if (!s)
849 return s;
850
851 if (!sin && sel2 && sel2->nrcols == 0 && s->nrcols == 0) {
852 sql_subfunc *f = sql_bind_func(sql->sa, sql->session->schema, anti?"or":"and", bt, bt, F_FUNC);
853 assert(f);
854 s = stmt_binop(be, sel2, s, f);
855 } else if (sel2 && (sel2->nrcols == 0 || s->nrcols == 0)) {
856 stmt *predicate = bin_first_column(be, left);
857
858 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
859 if (s->nrcols == 0)
860 s = stmt_uselect(be, predicate, s, cmp_equal, sel2, anti);
861 else
862 s = stmt_uselect(be, predicate, sel2, cmp_equal, s, anti);
863 }
864 sel2 = s;
865 }
866 if (sel1->nrcols == 0 && sel2->nrcols == 0) {
867 sql_subfunc *f = sql_bind_func(sql->sa, sql->session->schema, anti?"and":"or", bt, bt, F_FUNC);
868 assert(f);
869 return stmt_binop(be, sel1, sel2, f);
870 }
871 if (sel1->nrcols == 0) {
872 stmt *predicate = bin_first_column(be, left);
873
874 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
875 sel1 = stmt_uselect(be, predicate, sel1, cmp_equal, NULL, 0/*anti*/);
876 }
877 if (sel2->nrcols == 0) {
878 stmt *predicate = bin_first_column(be, left);
879
880 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
881 sel2 = stmt_uselect(be, predicate, sel2, cmp_equal, NULL, 0/*anti*/);
882 }
883 if (anti)
884 return stmt_project(be, stmt_tinter(be, sel1, sel2), sel1);
885 return stmt_tunion(be, sel1, sel2);
886 }
887 if (get_cmp(e) == cmp_or && right) { /* join */
888 assert(0);
889 }
890
891 /* mark use of join indices */
892 if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
893 sql->opt_stats[0]++;
894
895 if (!l) {
896 l = exp_bin(be, e->l, left, NULL, grp, ext, cnt, sel);
897 swapped = 0;
898 }
899 if (!l && right) {
900 l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel);
901 swapped = 1;
902 }
903 if (swapped || !right)
904 r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel);
905 else
906 r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel);
907 if (!r && !swapped) {
908 r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel);
909 is_select = 1;
910 }
911 if (!r && swapped) {
912 r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel);
913 is_select = 1;
914 }
915 if (re2)
916 r2 = exp_bin(be, re2, left, right, grp, ext, cnt, sel);
917
918 if (!l || !r || (re2 && !r2)) {
919 //assert(0);
920 fprintf(stderr, "query: '%s'\n", sql->query);
921 return NULL;
922 }
923
924 /*
925 if (left && right && !is_select &&
926 ((l->nrcols && (r->nrcols || (r2 && r2->nrcols))) ||
927 re->card > CARD_ATOM ||
928 (re2 && re2->card > CARD_ATOM))) {
929 */
930 (void)is_select;
931 if (left && right) {
932 if (l->nrcols == 0)
933 l = stmt_const(be, bin_first_column(be, swapped?right:left), l);
934 if (r->nrcols == 0)
935 r = stmt_const(be, bin_first_column(be, swapped?left:right), r);
936 if (r2 && r2->nrcols == 0)
937 r2 = stmt_const(be, bin_first_column(be, swapped?left:right), r2);
938 if (r2) {
939 s = stmt_join2(be, l, r, r2, (comp_type)e->flag, is_anti(e), swapped);
940 } else if (swapped) {
941 s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag));
942 } else {
943 s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag);
944 }
945 } else {
946 if (r2) {
947 if (l->nrcols == 0 && r->nrcols == 0 && r2->nrcols == 0) {
948 sql_subtype *bt = sql_bind_localtype("bit");
949 sql_subfunc *lf = sql_bind_func(sql->sa, sql->session->schema,
950 compare_func(range2lcompare(e->flag), 0),
951 tail_type(l), tail_type(r), F_FUNC);
952 sql_subfunc *rf = sql_bind_func(sql->sa, sql->session->schema,
953 compare_func(range2rcompare(e->flag), 0),
954 tail_type(l), tail_type(r), F_FUNC);
955 sql_subfunc *a = sql_bind_func(sql->sa, sql->session->schema,
956 "and", bt, bt, F_FUNC);
957
958 if (is_atom(re->type) && re->l && atom_null((atom*)re->l) &&
959 is_atom(re2->type) && re2->l && atom_null((atom*)re2->l)) {
960 s = sql_unop_(be, NULL, "isnull", l);
961 } else {
962 assert(lf && rf && a);
963 s = stmt_binop(be,
964 stmt_binop(be, l, r, lf),
965 stmt_binop(be, l, r2, rf), a);
966 }
967 if (is_anti(e)) {
968 sql_subfunc *a = sql_bind_func(sql->sa, sql->session->schema, "not", bt, NULL, F_FUNC);
969 s = stmt_unop(be, s, a);
970 }
971 } else if (((e->flag&3) != 3) /* both sides closed use between implementation */ && l->nrcols > 0 && r->nrcols > 0 && r2->nrcols > 0) {
972 s = stmt_uselect(be, l, r, range2lcompare(e->flag),
973 stmt_uselect(be, l, r2, range2rcompare(e->flag), sel, is_anti(e)), is_anti(e));
974 } else {
975 s = stmt_uselect2(be, l, r, r2, (comp_type)e->flag, sel, is_anti(e));
976 }
977 } else {
978 /* value compare or select */
979 if (l->nrcols == 0 && r->nrcols == 0 && (e->flag == mark_in || e->flag == mark_notin)) {
980 sql_subfunc *f = sql_bind_func(sql->sa, sql->session->schema, "=", tail_type(l), tail_type(l), F_FUNC);
981 assert(f);
982 s = stmt_binop(be, l, r, f);
983 } else if (l->nrcols == 0 && r->nrcols == 0) {
984 sql_subfunc *f = sql_bind_func(sql->sa, sql->session->schema,
985 compare_func((comp_type)get_cmp(e), is_anti(e)),
986 tail_type(l), tail_type(l), F_FUNC);
987 assert(f);
988 s = stmt_binop(be, l, r, f);
989 } else {
990 /* this can still be a join (as relational algebra and single value subquery results still means joins */
991 s = stmt_uselect(be, l, r, (comp_type)get_cmp(e), sel, is_anti(e));
992 }
993 }
994 }
995 } break;
996 default:
997 ;
998 }
999 return s;
1000}
1001
1002static stmt *
1003stmt_col( backend *be, sql_column *c, stmt *del)
1004{
1005 stmt *sc = stmt_bat(be, c, RDONLY, del?del->partition:0);
1006
1007 if (isTable(c->t) && c->t->access != TABLE_READONLY &&
1008 (!isNew(c) || !isNew(c->t) /* alter */) &&
1009 (c->t->persistence == SQL_PERSIST || c->t->persistence == SQL_DECLARED_TABLE) && !c->t->commit_action) {
1010 stmt *i = stmt_bat(be, c, RD_INS, 0);
1011 stmt *u = stmt_bat(be, c, RD_UPD_ID, del?del->partition:0);
1012 sc = stmt_project_delta(be, sc, u, i);
1013 sc = stmt_project(be, del, sc);
1014 } else if (del) { /* always handle the deletes */
1015 sc = stmt_project(be, del, sc);
1016 }
1017 return sc;
1018}
1019
1020static stmt *
1021stmt_idx( backend *be, sql_idx *i, stmt *del)
1022{
1023 stmt *sc = stmt_idxbat(be, i, RDONLY, del?del->partition:0);
1024
1025 if (isTable(i->t) && i->t->access != TABLE_READONLY &&
1026 (!isNew(i) || !isNew(i->t) /* alter */) &&
1027 (i->t->persistence == SQL_PERSIST || i->t->persistence == SQL_DECLARED_TABLE) && !i->t->commit_action) {
1028 stmt *ic = stmt_idxbat(be, i, RD_INS, 0);
1029 stmt *u = stmt_idxbat(be, i, RD_UPD_ID, del?del->partition:0);
1030 sc = stmt_project_delta(be, sc, u, ic);
1031 sc = stmt_project(be, del, sc);
1032 } else if (del) { /* always handle the deletes */
1033 sc = stmt_project(be, del, sc);
1034 }
1035 return sc;
1036}
1037
1038#if 0
1039static stmt *
1040check_table_types(backend *be, list *types, stmt *s, check_type tpe)
1041{
1042 mvc *sql = be->mvc;
1043 //const char *tname;
1044 stmt *tab = s;
1045 int temp = 0;
1046
1047 if (s->type != st_table) {
1048 return sql_error(
1049 sql, 03,
1050 SQLSTATE(42000) "single value and complex type are not equal");
1051 }
1052 tab = s->op1;
1053 temp = s->flag;
1054 if (tab->type == st_var) {
1055 sql_table *tbl = NULL;//tail_type(tab)->comp_type;
1056 stmt *dels = stmt_tid(be, tbl, 0);
1057 node *n, *m;
1058 list *l = sa_list(sql->sa);
1059
1060 stack_find_var(sql, tab->op1->op4.aval->data.val.sval);
1061
1062 for (n = types->h, m = tbl->columns.set->h;
1063 n && m; n = n->next, m = m->next)
1064 {
1065 sql_subtype *ct = n->data;
1066 sql_column *dtc = m->data;
1067 stmt *dtcs = stmt_col(be, dtc, dels);
1068 stmt *r = check_types(be, ct, dtcs, tpe);
1069 if (!r)
1070 return NULL;
1071 //r = stmt_alias(be, r, tbl->base.name, c->base.name);
1072 list_append(l, r);
1073 }
1074 return stmt_table(be, stmt_list(be, l), temp);
1075 } else if (tab->type == st_list) {
1076 node *n, *m;
1077 list *l = sa_list(sql->sa);
1078 for (n = types->h, m = tab->op4.lval->h;
1079 n && m; n = n->next, m = m->next)
1080 {
1081 sql_subtype *ct = n->data;
1082 stmt *r = check_types(be, ct, m->data, tpe);
1083 if (!r)
1084 return NULL;
1085 //tname = table_name(sql->sa, r);
1086 //r = stmt_alias(be, r, tname, c->base.name);
1087 list_append(l, r);
1088 }
1089 return stmt_table(be, stmt_list(be, l), temp);
1090 } else { /* single column/value */
1091 stmt *r;
1092 sql_subtype *st = tail_type(tab), *ct;
1093
1094 if (list_length(types) != 1) {
1095 stmt *res = sql_error(
1096 sql, 03,
1097 SQLSTATE(42000) "single value of type %s and complex type are not equal",
1098 st->type->sqlname
1099 );
1100 return res;
1101 }
1102 ct = types->h->data;
1103 r = check_types(be, ct, tab, tpe);
1104 //tname = table_name(sql->sa, r);
1105 //r = stmt_alias(be, r, tname, c->base.name);
1106 return stmt_table(be, r, temp);
1107 }
1108}
1109#endif
1110
1111static void
1112sql_convert_arg(mvc *sql, int nr, sql_subtype *rt)
1113{
1114 atom *a = sql_bind_arg(sql, nr);
1115
1116 if (atom_null(a)) {
1117 if (a->data.vtype != rt->type->localtype) {
1118 a->data.vtype = rt->type->localtype;
1119 VALset(&a->data, a->data.vtype, (ptr) ATOMnilptr(a->data.vtype));
1120 }
1121 }
1122 a->tpe = *rt;
1123}
1124
1125/* try to do an inplace convertion
1126 *
1127 * inplace conversion is only possible if the s is an variable.
1128 * This is only done to be able to map more cached queries onto the same
1129 * interface.
1130 */
1131static stmt *
1132inplace_convert(backend *be, sql_subtype *ct, stmt *s)
1133{
1134 atom *a;
1135
1136 /* exclude named variables */
1137 if (s->type != st_var || (s->op1 && s->op1->op4.aval->data.val.sval) ||
1138 (ct->scale && ct->type->eclass != EC_FLT))
1139 return s;
1140
1141 a = sql_bind_arg(be->mvc, s->flag);
1142 if (atom_cast(be->mvc->sa, a, ct)) {
1143 stmt *r = stmt_varnr(be, s->flag, ct);
1144 sql_convert_arg(be->mvc, s->flag, ct);
1145 return r;
1146 }
1147 return s;
1148}
1149
1150static int
1151stmt_set_type_param(mvc *sql, sql_subtype *type, stmt *param)
1152{
1153 if (!type || !param || param->type != st_var)
1154 return -1;
1155
1156 if (set_type_param(sql, type, param->flag) == 0) {
1157 param->op4.typeval = *type;
1158 return 0;
1159 }
1160 return -1;
1161}
1162
1163/* check_types tries to match the ct type with the type of s if they don't
1164 * match s is converted. Returns NULL on failure.
1165 */
1166static stmt *
1167check_types(backend *be, sql_subtype *ct, stmt *s, check_type tpe)
1168{
1169 mvc *sql = be->mvc;
1170 int c = 0;
1171 sql_subtype *t = NULL, *st = NULL;
1172
1173 st = tail_type(s);
1174 if ((!st || !st->type) && stmt_set_type_param(sql, ct, s) == 0) {
1175 return s;
1176 } else if (!st) {
1177 return sql_error(sql, 02, SQLSTATE(42000) "statement has no type information");
1178 }
1179
1180 /* first try cheap internal (inplace) convertions ! */
1181 s = inplace_convert(be, ct, s);
1182 t = st = tail_type(s);
1183
1184 /* check if the types are the same */
1185 if (t && subtype_cmp(t, ct) != 0) {
1186 t = NULL;
1187 }
1188
1189 if (!t) { /* try to convert if needed */
1190 if (EC_INTERVAL(st->type->eclass) && (ct->type->eclass == EC_NUM || ct->type->eclass == EC_POS) && ct->digits < st->digits) {
1191 s = NULL; /* conversion from interval to num depends on the number of digits */
1192 } else {
1193 c = sql_type_convert(st->type->eclass, ct->type->eclass);
1194 if (!c || (c == 2 && tpe == type_set) || (c == 3 && tpe != type_cast)) {
1195 s = NULL;
1196 } else {
1197 s = stmt_convert(be, s, st, ct, NULL);
1198 }
1199 }
1200 }
1201 if (!s) {
1202 stmt *res = sql_error(
1203 sql, 03,
1204 SQLSTATE(42000) "types %s(%u,%u) (%s) and %s(%u,%u) (%s) are not equal",
1205 st->type->sqlname,
1206 st->digits,
1207 st->scale,
1208 st->type->base.name,
1209 ct->type->sqlname,
1210 ct->digits,
1211 ct->scale,
1212 ct->type->base.name
1213 );
1214 return res;
1215 }
1216 return s;
1217}
1218
1219static stmt *
1220sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
1221{
1222 mvc *sql = be->mvc;
1223 list *sl = sa_list(sql->sa);
1224 list *tl = sa_list(sql->sa);
1225 sql_subfunc *f = NULL;
1226
1227 list_append(sl, a1);
1228 list_append(tl, tail_type(a1));
1229 list_append(sl, a2);
1230 list_append(tl, tail_type(a2));
1231 list_append(sl, a3);
1232 list_append(tl, tail_type(a3));
1233 if (a4) {
1234 list_append(sl, a4);
1235 list_append(tl, tail_type(a4));
1236 }
1237
1238 f = sql_bind_func_(sql->sa, sql->session->schema, fname, tl, F_FUNC);
1239 if (f)
1240 return stmt_Nop(be, stmt_list(be, sl), f);
1241 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: no such operator '%s'", fname);
1242}
1243
1244static stmt *
1245rel_parse_value(backend *be, char *query, char emode)
1246{
1247 mvc *m = be->mvc;
1248 mvc o = *m;
1249 stmt *s = NULL;
1250 buffer *b;
1251 char *n;
1252 size_t len = _strlen(query);
1253 exp_kind ek = {type_value, card_value, FALSE};
1254 stream *sr;
1255 bstream *bs;
1256
1257 m->qc = NULL;
1258
1259 m->caching = 0;
1260 m->emode = emode;
1261 b = (buffer*)GDKmalloc(sizeof(buffer));
1262 n = GDKmalloc(len + 1 + 1);
1263 if (b == NULL || n == NULL) {
1264 GDKfree(b);
1265 GDKfree(n);
1266 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1267 }
1268 snprintf(n, len + 2, "%s\n", query);
1269 query = n;
1270 len++;
1271 buffer_init(b, query, len);
1272 sr = buffer_rastream(b, "sqlstatement");
1273 if (sr == NULL) {
1274 buffer_destroy(b);
1275 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1276 }
1277 bs = bstream_create(sr, b->len);
1278 if(bs == NULL) {
1279 buffer_destroy(b);
1280 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
1281 }
1282 scanner_init(&m->scanner, bs, NULL);
1283 m->scanner.mode = LINE_1;
1284 bstream_next(m->scanner.rs);
1285
1286 m->params = NULL;
1287 /*m->args = NULL;*/
1288 m->argc = 0;
1289 m->sym = NULL;
1290 m->errstr[0] = '\0';
1291
1292 (void) sqlparse(m); /* blindly ignore errors */
1293
1294 /* get out the single value as we don't want an enclosing projection! */
1295 if (m->sym->token == SQL_SELECT) {
1296 SelectNode *sn = (SelectNode *)m->sym;
1297 if (sn->selection->h->data.sym->token == SQL_COLUMN || sn->selection->h->data.sym->token == SQL_IDENT) {
1298 int is_last = 0;
1299 sql_rel *rel = NULL;
1300 sql_query *query = query_create(m);
1301 sql_exp *e = rel_value_exp2(query, &rel, sn->selection->h->data.sym->data.lval->h->data.sym, sql_sel, ek, &is_last);
1302
1303 if (!rel)
1304 s = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL);
1305 }
1306 }
1307 GDKfree(query);
1308 GDKfree(b);
1309 bstream_destroy(m->scanner.rs);
1310
1311 m->sym = NULL;
1312 o.vars = m->vars; /* may have been realloc'ed */
1313 o.sizevars = m->sizevars;
1314 o.query = m->query;
1315 if (m->session->status || m->errstr[0]) {
1316 int status = m->session->status;
1317
1318 memcpy(o.errstr, m->errstr, sizeof(o.errstr));
1319 *m = o;
1320 m->session->status = status;
1321 } else {
1322 *m = o;
1323 }
1324 return s;
1325}
1326
1327
1328static stmt *
1329stmt_rename(backend *be, sql_rel *rel, sql_exp *exp, stmt *s )
1330{
1331 const char *name = exp_name(exp);
1332 const char *rname = exp_relname(exp);
1333 stmt *o = s;
1334
1335 (void)rel;
1336 if (!name && exp->type == e_column && exp->r)
1337 name = exp->r;
1338 if (!name)
1339 name = column_name(be->mvc->sa, s);
1340 if (!rname && exp->type == e_column && exp->l)
1341 rname = exp->l;
1342 if (!rname)
1343 rname = table_name(be->mvc->sa, s);
1344 s = stmt_alias(be, s, rname, name);
1345 if (o->flag & OUTER_ZERO)
1346 s->flag |= OUTER_ZERO;
1347 return s;
1348}
1349
1350static stmt *
1351rel2bin_sql_table(backend *be, sql_table *t)
1352{
1353 mvc *sql = be->mvc;
1354 list *l = sa_list(sql->sa);
1355 node *n;
1356 stmt *dels = stmt_tid(be, t, 0);
1357
1358 for (n = t->columns.set->h; n; n = n->next) {
1359 sql_column *c = n->data;
1360 stmt *sc = stmt_col(be, c, dels);
1361
1362 list_append(l, sc);
1363 }
1364 /* TID column */
1365 if (t->columns.set->h) {
1366 /* tid function sql.tid(t) */
1367 const char *rnme = t->base.name;
1368
1369 stmt *sc = dels?dels:stmt_tid(be, t, 0);
1370 sc = stmt_alias(be, sc, rnme, TID);
1371 list_append(l, sc);
1372 }
1373 if (t->idxs.set) {
1374 for (n = t->idxs.set->h; n; n = n->next) {
1375 sql_idx *i = n->data;
1376 stmt *sc = stmt_idx(be, i, dels);
1377 const char *rnme = t->base.name;
1378
1379 /* index names are prefixed, to make them independent */
1380 sc = stmt_alias(be, sc, rnme, sa_strconcat(sql->sa, "%", i->base.name));
1381 list_append(l, sc);
1382 }
1383 }
1384 return stmt_list(be, l);
1385}
1386
1387static stmt *
1388rel2bin_basetable(backend *be, sql_rel *rel)
1389{
1390 mvc *sql = be->mvc;
1391 sql_table *t = rel->l;
1392 sql_column *c = rel->r;
1393 list *l = sa_list(sql->sa);
1394 stmt *dels;
1395 node *en;
1396
1397 if (!t && c)
1398 t = c->t;
1399
1400 dels = stmt_tid(be, t, rel->flag == REL_PARTITION);
1401
1402 /* add aliases */
1403 assert(rel->exps);
1404 for( en = rel->exps->h; en; en = en->next ) {
1405 sql_exp *exp = en->data;
1406 const char *rname = exp_relname(exp)?exp_relname(exp):exp->l;
1407 const char *oname = exp->r;
1408 stmt *s = NULL;
1409
1410 if (is_func(exp->type)) {
1411 list *exps = exp->l;
1412 sql_exp *cexp = exps->h->data;
1413 const char *cname = cexp->r;
1414 list *l = sa_list(sql->sa);
1415
1416 c = find_sql_column(t, cname);
1417 s = stmt_col(be, c, dels);
1418 append(l, s);
1419 if (exps->h->next) {
1420 sql_exp *at = exps->h->next->data;
1421 stmt *u = exp_bin(be, at, NULL, NULL, NULL, NULL, NULL, NULL);
1422 if(!u)
1423 return NULL;
1424
1425 append(l, u);
1426 }
1427 s = stmt_Nop(be, stmt_list(be, l), exp->f);
1428 } else if (oname[0] == '%' && strcmp(oname, TID) == 0) {
1429 /* tid function sql.tid(t) */
1430 const char *rnme = t->base.name;
1431
1432 s = dels?dels:stmt_tid(be, t, 0);
1433 s = stmt_alias(be, s, rnme, TID);
1434 } else if (oname[0] == '%') {
1435 sql_idx *i = find_sql_idx(t, oname+1);
1436
1437 /* do not include empty indices in the plan */
1438 if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
1439 continue;
1440 s = stmt_idx(be, i, dels);
1441 } else {
1442 sql_column *c = find_sql_column(t, oname);
1443
1444 s = stmt_col(be, c, dels);
1445 }
1446 s->tname = rname;
1447 s->cname = exp_name(exp);
1448 list_append(l, s);
1449 }
1450 return stmt_list(be, l);
1451}
1452
1453static int
1454alias_cmp( stmt *s, const char *nme )
1455{
1456 return strcmp(s->cname, nme);
1457}
1458
1459static list* exps2bin_args(backend *be, list *exps, list *args);
1460
1461static list *
1462exp2bin_args(backend *be, sql_exp *e, list *args)
1463{
1464 mvc *sql = be->mvc;
1465
1466 if (THRhighwater())
1467 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1468
1469 if (!e)
1470 return args;
1471 switch(e->type){
1472 case e_column:
1473 case e_psm:
1474 return args;
1475 case e_cmp:
1476 if (get_cmp(e) == cmp_or || get_cmp(e) == cmp_filter) {
1477 args = exps2bin_args(be, e->l, args);
1478 args = exps2bin_args(be, e->r, args);
1479 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
1480 args = exp2bin_args(be, e->l, args);
1481 args = exps2bin_args(be, e->r, args);
1482 } else {
1483 args = exp2bin_args(be, e->l, args);
1484 args = exp2bin_args(be, e->r, args);
1485 if (e->f)
1486 args = exp2bin_args(be, e->f, args);
1487 }
1488 return args;
1489 case e_convert:
1490 if (e->l)
1491 return exp2bin_args(be, e->l, args);
1492 break;
1493 case e_aggr:
1494 case e_func:
1495 if (e->l)
1496 return exps2bin_args(be, e->l, args);
1497 break;
1498 case e_atom:
1499 if (e->l) {
1500 return args;
1501 } else if (e->f) {
1502 return exps2bin_args(be, e->f, args);
1503 } else if (e->r) {
1504 char nme[64];
1505
1506 snprintf(nme, 64, "A%s", (char*)e->r);
1507 if (!list_find(args, nme, (fcmp)&alias_cmp)) {
1508 stmt *s = stmt_var(be, e->r, &e->tpe, 0, 0);
1509
1510 s = stmt_alias(be, s, NULL, sa_strdup(sql->sa, nme));
1511 list_append(args, s);
1512 }
1513 } else {
1514 char nme[16];
1515
1516 snprintf(nme, 16, "A%d", e->flag);
1517 if (!list_find(args, nme, (fcmp)&alias_cmp)) {
1518 atom *a = sql->args[e->flag];
1519 stmt *s = stmt_varnr(be, e->flag, &a->tpe);
1520
1521 s = stmt_alias(be, s, NULL, sa_strdup(sql->sa, nme));
1522 list_append(args, s);
1523 }
1524 }
1525 }
1526 return args;
1527}
1528
1529static list *
1530exps2bin_args(backend *be, list *exps, list *args)
1531{
1532 node *n;
1533
1534 if (!exps)
1535 return args;
1536 for (n = exps->h; n; n = n->next)
1537 args = exp2bin_args(be, n->data, args);
1538 return args;
1539}
1540
1541static list *
1542rel2bin_args(backend *be, sql_rel *rel, list *args)
1543{
1544 if (THRhighwater())
1545 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1546
1547 if (!rel)
1548 return args;
1549 switch(rel->op) {
1550 case op_basetable:
1551 case op_table:
1552 break;
1553 case op_join:
1554 case op_left:
1555 case op_right:
1556 case op_full:
1557
1558 case op_semi:
1559 case op_anti:
1560
1561 case op_union:
1562 case op_inter:
1563 case op_except:
1564 args = rel2bin_args(be, rel->l, args);
1565 args = rel2bin_args(be, rel->r, args);
1566 break;
1567 case op_groupby:
1568 if (rel->r)
1569 args = exps2bin_args(be, rel->r, args);
1570 /* fall through */
1571 case op_project:
1572 case op_select:
1573 case op_topn:
1574 case op_sample:
1575 if (rel->exps)
1576 args = exps2bin_args(be, rel->exps, args);
1577 args = rel2bin_args(be, rel->l, args);
1578 break;
1579 case op_ddl:
1580 args = rel2bin_args(be, rel->l, args);
1581 if (rel->r)
1582 args = rel2bin_args(be, rel->r, args);
1583 break;
1584 case op_insert:
1585 case op_update:
1586 case op_delete:
1587 case op_truncate:
1588 args = rel2bin_args(be, rel->r, args);
1589 break;
1590 }
1591 return args;
1592}
1593
1594typedef struct trigger_input {
1595 sql_table *t;
1596 stmt *tids;
1597 stmt **updates;
1598 int type; /* insert 1, update 2, delete 3, truncate 4 */
1599 const char *on;
1600 const char *nn;
1601} trigger_input;
1602
1603static stmt *
1604rel2bin_table(backend *be, sql_rel *rel, list *refs)
1605{
1606 mvc *sql = be->mvc;
1607 list *l;
1608 stmt *sub = NULL, *osub = NULL;
1609 node *en, *n;
1610 sql_exp *op = rel->r;
1611
1612 if (rel->flag == 2) {
1613 trigger_input *ti = rel->l;
1614 l = sa_list(sql->sa);
1615
1616 for(n = ti->t->columns.set->h; n; n = n->next) {
1617 sql_column *c = n->data;
1618
1619 if (ti->type == 2) { /* updates */
1620 stmt *s = stmt_col(be, c, ti->tids);
1621 append(l, stmt_alias(be, s, ti->on, c->base.name));
1622 }
1623 if (ti->updates[c->colnr]) {
1624 append(l, stmt_alias(be, ti->updates[c->colnr], ti->nn, c->base.name));
1625 } else {
1626 stmt *s = stmt_col(be, c, ti->tids);
1627 append(l, stmt_alias(be, s, ti->nn, c->base.name));
1628 assert(ti->type != 1);
1629 }
1630 }
1631 sub = stmt_list(be, l);
1632 return sub;
1633 } else if (op) {
1634 int i;
1635 sql_subfunc *f = op->f;
1636 stmt *psub = NULL;
1637
1638 if (rel->l) { /* first construct the sub relation */
1639 sql_rel *l = rel->l;
1640 if (l->op == op_ddl) {
1641 sql_table *t = rel_ddl_table_get(l);
1642
1643 if (t)
1644 sub = rel2bin_sql_table(be, t);
1645 } else {
1646 sub = subrel_bin(be, rel->l, refs);
1647 }
1648 if (!sub)
1649 return NULL;
1650 }
1651
1652 psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL); /* table function */
1653 if (!f || !psub) {
1654 assert(0);
1655 return NULL;
1656 }
1657 l = sa_list(sql->sa);
1658 if (f->func->res) {
1659 if (f->func->varres) {
1660 for(i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++ ) {
1661 sql_exp *exp = en->data;
1662 sql_subtype *st = n->data;
1663 const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
1664 stmt *s = stmt_rs_column(be, psub, i, st);
1665
1666 s = stmt_alias(be, s, rnme, exp_name(exp));
1667 list_append(l, s);
1668 }
1669 } else {
1670 for(i = 0, n = f->func->res->h; n; n = n->next, i++ ) {
1671 sql_arg *a = n->data;
1672 stmt *s = stmt_rs_column(be, psub, i, &a->type);
1673 const char *rnme = exp_find_rel_name(op);
1674
1675 s = stmt_alias(be, s, rnme, a->name);
1676 list_append(l, s);
1677 }
1678 if (list_length(f->res) == list_length(f->func->res) + 1) {
1679 /* add missing %TID% column */
1680 sql_subtype *t = f->res->t->data;
1681 stmt *s = stmt_rs_column(be, psub, i, t);
1682 const char *rnme = exp_find_rel_name(op);
1683
1684 s = stmt_alias(be, s, rnme, TID);
1685 list_append(l, s);
1686 }
1687 }
1688 }
1689 if (!rel->flag && sub && sub->nrcols) {
1690 assert(0);
1691 list_merge(l, sub->op4.lval, NULL);
1692 osub = sub;
1693 }
1694 sub = stmt_list(be, l);
1695 } else if (rel->l) { /* handle sub query via function */
1696 int i;
1697 char name[16], *nme;
1698 sql_rel *fr;
1699
1700 nme = number2name(name, sizeof(name), ++sql->remote);
1701
1702 l = rel2bin_args(be, rel->l, sa_list(sql->sa));
1703 if(!l)
1704 return NULL;
1705 sub = stmt_list(be, l);
1706 sub = stmt_func(be, sub, sa_strdup(sql->sa, nme), rel->l, 0);
1707 fr = rel->l;
1708 l = sa_list(sql->sa);
1709 for(i = 0, n = rel->exps->h; n; n = n->next, i++ ) {
1710 sql_exp *c = n->data;
1711 stmt *s = stmt_rs_column(be, sub, i, exp_subtype(c));
1712 const char *nme = exp_name(c);
1713 const char *rnme = NULL;
1714
1715 s = stmt_alias(be, s, rnme, nme);
1716 if (fr->card <= CARD_ATOM) /* single value, get result from bat */
1717 s = stmt_fetch(be, s);
1718 list_append(l, s);
1719 }
1720 sub = stmt_list(be, l);
1721 }
1722 if (!sub) {
1723 assert(0);
1724 return NULL;
1725 }
1726 l = sa_list(sql->sa);
1727 for( en = rel->exps->h; en; en = en->next ) {
1728 sql_exp *exp = en->data;
1729 const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
1730 stmt *s;
1731
1732 /* no relation names */
1733 if (exp->l)
1734 exp->l = NULL;
1735 s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL);
1736
1737 if (!s) {
1738 assert(0);
1739 return NULL;
1740 }
1741 if (sub && sub->nrcols >= 1 && s->nrcols == 0)
1742 s = stmt_const(be, bin_first_column(be, sub), s);
1743 s = stmt_alias(be, s, rnme, exp_name(exp));
1744 list_append(l, s);
1745 }
1746 if (osub && osub->nrcols)
1747 list_merge(l, osub->op4.lval, NULL);
1748 sub = stmt_list(be, l);
1749 return sub;
1750}
1751
1752static stmt *
1753rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en )
1754{
1755 mvc *sql = be->mvc;
1756 node *n;
1757 sql_subtype *it = sql_bind_localtype("int");
1758 sql_subtype *lng = sql_bind_localtype("lng");
1759 stmt *h = NULL;
1760 stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
1761 sql_exp *e = en->data;
1762 sql_exp *l = e->l;
1763 stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
1764 int swap_exp = 0, swap_rel = 0;
1765 comp_type comp = cmp_equal;
1766
1767 if (!idx) {
1768 swap_exp = 1;
1769 l = e->r;
1770 idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
1771 }
1772 if (!idx && right) {
1773 swap_exp = 0;
1774 swap_rel = 1;
1775 l = e->l;
1776 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
1777 }
1778 if (!idx && right) {
1779 swap_exp = 1;
1780 swap_rel = 1;
1781 l = e->r;
1782 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
1783 }
1784 if (!idx)
1785 return NULL;
1786 /* should be in key order! */
1787 for( en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next ) {
1788 sql_exp *e = en->data;
1789 stmt *s = NULL;
1790
1791 if (e->type == e_cmp && e->flag == cmp_equal) {
1792 sql_exp *ee = (swap_exp)?e->l:e->r;
1793 if (swap_rel)
1794 s = exp_bin(be, ee, left, NULL, NULL, NULL, NULL, NULL);
1795 else
1796 s = exp_bin(be, ee, right, NULL, NULL, NULL, NULL, NULL);
1797 }
1798
1799 if (!s)
1800 return NULL;
1801 if (h) {
1802 sql_subfunc *xor = sql_bind_func_result3(sql->sa, sql->session->schema, "rotate_xor_hash", lng, it, tail_type(s), lng);
1803
1804 h = stmt_Nop(be, stmt_list(be, list_append( list_append(
1805 list_append(sa_list(sql->sa), h), bits), s)), xor);
1806 comp = cmp_equal_nil;
1807 } else {
1808 sql_subfunc *hf = sql_bind_func_result(sql->sa, sql->session->schema, "hash", tail_type(s), NULL, lng);
1809
1810 h = stmt_unop(be, s, hf);
1811 }
1812 }
1813 if (h && h->nrcols) {
1814 if (!swap_rel) {
1815 return stmt_join(be, idx, h, 0, comp);
1816 } else {
1817 return stmt_join(be, h, idx, 0, comp);
1818 }
1819 } else {
1820 return stmt_uselect(be, idx, h, comp, NULL, 0);
1821 }
1822}
1823
1824static stmt *
1825join_hash_key( backend *be, list *l )
1826{
1827 mvc *sql = be->mvc;
1828 node *m;
1829 sql_subtype *it, *lng;
1830 stmt *h = NULL;
1831 stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
1832
1833 it = sql_bind_localtype("int");
1834 lng = sql_bind_localtype("lng");
1835 for (m = l->h; m; m = m->next) {
1836 stmt *s = m->data;
1837
1838 if (h) {
1839 sql_subfunc *xor = sql_bind_func_result3(sql->sa, sql->session->schema, "rotate_xor_hash", lng, it, tail_type(s), lng);
1840
1841 h = stmt_Nop(be, stmt_list(be, list_append( list_append( list_append(sa_list(sql->sa), h), bits), s )), xor);
1842 } else {
1843 sql_subfunc *hf = sql_bind_func_result(sql->sa, sql->session->schema, "hash", tail_type(s), NULL, lng);
1844 h = stmt_unop(be, s, hf);
1845 }
1846 }
1847 return h;
1848}
1849
1850static stmt *
1851releqjoin( backend *be, list *l1, list *l2, int used_hash, comp_type cmp_op, int need_left )
1852{
1853 mvc *sql = be->mvc;
1854 node *n1 = l1->h, *n2 = l2->h;
1855 stmt *l, *r, *res;
1856
1857 if (list_length(l1) <= 1) {
1858 l = l1->h->data;
1859 r = l2->h->data;
1860 r = stmt_join(be, l, r, 0, cmp_op);
1861 if (need_left)
1862 r->flag = cmp_left;
1863 return r;
1864 }
1865 if (used_hash) {
1866 l = n1->data;
1867 r = n2->data;
1868 n1 = n1->next;
1869 n2 = n2->next;
1870 res = stmt_join(be, l, r, 0, cmp_op);
1871 } else { /* need hash */
1872 l = join_hash_key(be, l1);
1873 r = join_hash_key(be, l2);
1874 res = stmt_join(be, l, r, 0, cmp_op == cmp_equal ? cmp_equal_nil : cmp_op);
1875 }
1876 if (need_left)
1877 res->flag = cmp_left;
1878 l = stmt_result(be, res, 0);
1879 r = stmt_result(be, res, 1);
1880 for (; n1 && n2; n1 = n1->next, n2 = n2->next) {
1881 stmt *ld = n1->data;
1882 stmt *rd = n2->data;
1883 stmt *le = stmt_project(be, l, ld );
1884 stmt *re = stmt_project(be, r, rd );
1885 /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
1886 sql_subfunc *f = NULL;
1887 stmt * cmp;
1888 list *ops;
1889
1890 f = sql_bind_func(sql->sa, sql->session->schema, "=", tail_type(le), tail_type(le), F_FUNC);
1891 assert(f);
1892
1893 ops = sa_list(be->mvc->sa);
1894 list_append(ops, le);
1895 list_append(ops, re);
1896 if (cmp_op == cmp_equal_nil)
1897 list_append(ops, stmt_bool(be, 1));
1898 cmp = stmt_Nop(be, stmt_list(be, ops), f);
1899 cmp = stmt_uselect(be, cmp, stmt_bool(be, 1), cmp_equal, NULL, 0);
1900 l = stmt_project(be, cmp, l );
1901 r = stmt_project(be, cmp, r );
1902 }
1903 res = stmt_join(be, l, r, 0, cmp_joined);
1904 return res;
1905}
1906
1907static stmt *
1908rel2bin_join(backend *be, sql_rel *rel, list *refs)
1909{
1910 mvc *sql = be->mvc;
1911 list *l;
1912 node *en = NULL, *n;
1913 stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr;
1914 stmt *ld = NULL, *rd = NULL;
1915 int need_left = (rel->flag == LEFT_JOIN);
1916
1917 if (rel->l) /* first construct the left sub relation */
1918 left = subrel_bin(be, rel->l, refs);
1919 if (rel->r) /* first construct the right sub relation */
1920 right = subrel_bin(be, rel->r, refs);
1921 if (!left || !right)
1922 return NULL;
1923 left = row2cols(be, left);
1924 right = row2cols(be, right);
1925 /*
1926 * split in 2 steps,
1927 * first cheap join(s) (equality or idx)
1928 * second selects/filters
1929 */
1930 if (!list_empty(rel->exps)) {
1931 int used_hash = 0;
1932 int idx = 0, i;
1933 list *jexps = sa_list(sql->sa);
1934 list *lje = sa_list(sql->sa);
1935 list *rje = sa_list(sql->sa);
1936 char *handled = SA_ZNEW_ARRAY(sql->sa, char, list_length(rel->exps));
1937
1938 /* get equi-joins/filters first */
1939 if (list_length(rel->exps) > 1) {
1940 for( en = rel->exps->h, i=0; en; en = en->next, i++) {
1941 sql_exp *e = en->data;
1942 if (e->type == e_cmp && (e->flag == cmp_equal || e->flag == cmp_filter)) {
1943 if ( !((rel_find_exp(rel->l, e->l) && rel_find_exp(rel->l, e->r)) ||
1944 (rel_find_exp(rel->r, e->l) && rel_find_exp(rel->r, e->r)))) {
1945 append(jexps, e);
1946 handled[i] = 1;
1947 }
1948 }
1949 }
1950 if (list_empty(jexps)) {
1951 stmt *l = bin_first_column(be, left);
1952 stmt *r = bin_first_column(be, right);
1953 join = stmt_join(be, l, r, 0, cmp_all);
1954 }
1955 for( en = rel->exps->h, i=0; en; en = en->next, i++) {
1956 sql_exp *e = en->data;
1957 if (!handled[i])
1958 append(jexps, e);
1959 }
1960 rel->exps = jexps;
1961 }
1962
1963 /* generate a relational join */
1964 if (join)
1965 en = rel->exps->h;
1966 else
1967 for( en = rel->exps->h; en; en = en->next ) {
1968 int join_idx = sql->opt_stats[0];
1969 sql_exp *e = en->data;
1970 stmt *s = NULL;
1971 prop *p;
1972
1973 /* only handle simple joins here */
1974 if ((exp_has_func(e) && get_cmp(e) != cmp_filter) ||
1975 get_cmp(e) == cmp_or || (e->f && e->anti) ||
1976 (e->type == e_cmp && e->flag == cmp_equal &&
1977 ((rel_find_exp(rel->l, e->l) && rel_find_exp(rel->l, e->r)) ||
1978 (rel_find_exp(rel->r, e->l) && rel_find_exp(rel->r, e->r)))) ) {
1979 if (!join && !list_length(lje)) {
1980 stmt *l = bin_first_column(be, left);
1981 stmt *r = bin_first_column(be, right);
1982 join = stmt_join(be, l, r, 0, cmp_all);
1983 }
1984 break;
1985 }
1986 if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
1987 (join && e->flag == cmp_filter)))
1988 break;
1989 if (e->type == e_cmp && e->flag == cmp_equal &&
1990 ((rel_find_exp(rel->l, e->l) && rel_find_exp(rel->l, e->r)) ||
1991 (rel_find_exp(rel->r, e->l) && rel_find_exp(rel->r, e->r)))) {
1992 break;
1993 }
1994
1995 /* handle possible index lookups */
1996 /* expressions are in index order ! */
1997 if (!join &&
1998 (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
1999 sql_idx *i = p->value;
2000
2001 join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
2002 if (s) {
2003 list_append(lje, s->op1);
2004 list_append(rje, s->op2);
2005 used_hash = 1;
2006 }
2007 }
2008
2009 s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL);
2010 if (!s) {
2011 assert(0);
2012 return NULL;
2013 }
2014 if (join_idx != sql->opt_stats[0])
2015 idx = 1;
2016
2017 if (s->type != st_join &&
2018 s->type != st_join2 &&
2019 s->type != st_joinN) {
2020 /* predicate */
2021 if (!list_length(lje) && s->nrcols == 0) {
2022 stmt *l = bin_first_column(be, left);
2023 stmt *r = bin_first_column(be, right);
2024
2025 l = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, NULL, 0);
2026 join = stmt_join(be, l, r, 0, cmp_all);
2027 continue;
2028 }
2029 if (!join) {
2030 stmt *l = bin_first_column(be, left);
2031 stmt *r = bin_first_column(be, right);
2032 join = stmt_join(be, l, r, 0, cmp_all);
2033 }
2034 break;
2035 }
2036
2037 if (!join)
2038 join = s;
2039 list_append(lje, s->op1);
2040 list_append(rje, s->op2);
2041 }
2042 if (list_length(lje) > 1) {
2043 join = releqjoin(be, lje, rje, used_hash, cmp_equal, need_left);
2044 } else if (!join) {
2045 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal);
2046 if (need_left)
2047 join->flag = cmp_left;
2048 }
2049 } else {
2050 stmt *l = bin_first_column(be, left);
2051 stmt *r = bin_first_column(be, right);
2052 join = stmt_join(be, l, r, 0, cmp_all);
2053 }
2054 jl = stmt_result(be, join, 0);
2055 jr = stmt_result(be, join, 1);
2056 if (en) {
2057 stmt *sub, *sel = NULL;
2058 list *nl;
2059
2060 /* construct relation */
2061 nl = sa_list(sql->sa);
2062
2063 /* first project using equi-joins */
2064 for( n = left->op4.lval->h; n; n = n->next ) {
2065 stmt *c = n->data;
2066 const char *rnme = table_name(sql->sa, c);
2067 const char *nme = column_name(sql->sa, c);
2068 stmt *s = stmt_project(be, jl, column(be, c) );
2069
2070 s = stmt_alias(be, s, rnme, nme);
2071 list_append(nl, s);
2072 }
2073 for( n = right->op4.lval->h; n; n = n->next ) {
2074 stmt *c = n->data;
2075 const char *rnme = table_name(sql->sa, c);
2076 const char *nme = column_name(sql->sa, c);
2077 stmt *s = stmt_project(be, jr, column(be, c) );
2078
2079 s = stmt_alias(be, s, rnme, nme);
2080 list_append(nl, s);
2081 }
2082 sub = stmt_list(be, nl);
2083
2084 /* continue with non equi-joins */
2085 for( ; en; en = en->next ) {
2086 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel);
2087
2088 if (!s) {
2089 assert(0);
2090 return NULL;
2091 }
2092 if (s->nrcols == 0) {
2093 stmt *l = bin_first_column(be, sub);
2094 s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0);
2095 }
2096 sel = s;
2097 }
2098 /* recreate join output */
2099 jl = stmt_project(be, sel, jl);
2100 jr = stmt_project(be, sel, jr);
2101 }
2102
2103 /* construct relation */
2104 l = sa_list(sql->sa);
2105
2106 if (rel->op == op_left || rel->op == op_full) {
2107 /* we need to add the missing oid's */
2108 ld = stmt_mirror(be, bin_first_column(be, left));
2109 ld = stmt_tdiff(be, ld, jl);
2110 }
2111 if (rel->op == op_right || rel->op == op_full) {
2112 /* we need to add the missing oid's */
2113 rd = stmt_mirror(be, bin_first_column(be, right));
2114 rd = stmt_tdiff(be, rd, jr);
2115 }
2116
2117 for( n = left->op4.lval->h; n; n = n->next ) {
2118 stmt *c = n->data;
2119 const char *rnme = table_name(sql->sa, c);
2120 const char *nme = column_name(sql->sa, c);
2121 stmt *s = stmt_project(be, jl, column(be, c) );
2122
2123 /* as append isn't save, we append to a new copy */
2124 if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
2125 s = create_const_column(be, s);
2126 if (rel->op == op_left || rel->op == op_full)
2127 s = stmt_append(be, s, stmt_project(be, ld, c));
2128 if (rel->op == op_right || rel->op == op_full)
2129 s = stmt_append(be, s, stmt_const(be, rd, (c->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(sql->sa, tail_type(c), NULL))));
2130
2131 s = stmt_alias(be, s, rnme, nme);
2132 list_append(l, s);
2133 }
2134 for( n = right->op4.lval->h; n; n = n->next ) {
2135 stmt *c = n->data;
2136 const char *rnme = table_name(sql->sa, c);
2137 const char *nme = column_name(sql->sa, c);
2138 stmt *s = stmt_project(be, jr, column(be, c) );
2139
2140 /* as append isn't save, we append to a new copy */
2141 if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
2142 s = create_const_column(be, s);
2143 if (rel->op == op_left || rel->op == op_full)
2144 s = stmt_append(be, s, stmt_const(be, ld, (c->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(sql->sa, tail_type(c), NULL))));
2145 if (rel->op == op_right || rel->op == op_full)
2146 s = stmt_append(be, s, stmt_project(be, rd, c));
2147
2148 s = stmt_alias(be, s, rnme, nme);
2149 list_append(l, s);
2150 }
2151 return stmt_list(be, l);
2152}
2153
2154static int
2155exp_is_mark(sql_exp *e)
2156{
2157 if (e->type == e_cmp &&
2158 (e->flag == mark_in || e->flag == mark_notin ||
2159 e->flag == mark_exists || e->flag == mark_notexists))
2160 return 1;
2161 return 0;
2162}
2163
2164static stmt *
2165rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
2166{
2167 mvc *sql = be->mvc;
2168 list *l, *jexps = NULL, *mexps = NULL;
2169 node *en = NULL, *n;
2170 stmt *left = NULL, *right = NULL, *join = NULL;
2171
2172 if (rel->l) /* first construct the left sub relation */
2173 left = subrel_bin(be, rel->l, refs);
2174 if (rel->r) /* first construct the right sub relation */
2175 right = subrel_bin(be, rel->r, refs);
2176 if (!left || !right)
2177 return NULL;
2178 left = row2cols(be, left);
2179 right = row2cols(be, right);
2180
2181 if (rel->exps) {
2182 jexps = sa_list(sql->sa);
2183 mexps = sa_list(sql->sa);
2184
2185 for( en = rel->exps->h; en; en = en->next ) {
2186 sql_exp *e = en->data;
2187
2188 if (e->type != e_cmp)
2189 assert(0);
2190 if (exp_is_mark(e))
2191 append(mexps, e);
2192 else
2193 append(jexps, e);
2194 }
2195 }
2196 /* handle join-ing conditions first */
2197 if (!list_empty(jexps)) {
2198 // assert(0);
2199 if (list_empty(mexps))
2200 mexps = jexps;
2201 }
2202 /* handle mark conditions second */
2203 if (!list_empty(mexps)) {
2204 assert(list_length(mexps) == 1);
2205 for( en = mexps->h; en; en = en->next ) {
2206 sql_exp *e = en->data;
2207 stmt *ls = exp_bin(be, e->l, left, right, NULL, NULL, NULL, NULL);
2208 stmt *rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL);
2209
2210 if (ls->nrcols == 0)
2211 ls = stmt_const(be, bin_first_column(be, left), ls);
2212 if (rs->nrcols == 0)
2213 rs = stmt_const(be, bin_first_column(be, right), rs);
2214 join = stmt_tdiff2(be, ls, rs);
2215 }
2216 }
2217
2218 /* construct relation */
2219 l = sa_list(sql->sa);
2220
2221 /* project all the left columns */
2222 for( n = left->op4.lval->h; n; n = n->next ) {
2223 stmt *c = n->data;
2224 const char *rnme = table_name(sql->sa, c);
2225 const char *nme = column_name(sql->sa, c);
2226 stmt *s = stmt_project(be, join, column(be, c));
2227
2228 s = stmt_alias(be, s, rnme, nme);
2229 list_append(l, s);
2230 }
2231 return stmt_list(be, l);
2232}
2233
2234static stmt *
2235rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
2236{
2237 mvc *sql = be->mvc;
2238 list *l;
2239 node *en = NULL, *n;
2240 stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c;
2241
2242 if (rel->op == op_anti && !list_empty(rel->exps) && list_length(rel->exps) == 1 && ((sql_exp*)rel->exps->h->data)->flag == mark_notin)
2243 return rel2bin_antijoin(be, rel, refs);
2244
2245 if (rel->l) /* first construct the left sub relation */
2246 left = subrel_bin(be, rel->l, refs);
2247 if (rel->r) /* first construct the right sub relation */
2248 right = subrel_bin(be, rel->r, refs);
2249 if (!left || !right)
2250 return NULL;
2251 left = row2cols(be, left);
2252 right = row2cols(be, right);
2253 /*
2254 * split in 2 steps,
2255 * first cheap join(s) (equality or idx)
2256 * second selects/filters
2257 */
2258 if (rel->exps) {
2259 int idx = 0;
2260 list *jexps = sa_list(sql->sa);
2261 list *lje = sa_list(sql->sa);
2262 list *rje = sa_list(sql->sa);
2263
2264 /* get equi-joins/filters first */
2265 if (list_length(rel->exps) > 1) {
2266 for( en = rel->exps->h; en; en = en->next ) {
2267 sql_exp *e = en->data;
2268 if (e->type == e_cmp && (e->flag == cmp_equal || e->flag == cmp_filter))
2269 list_append(jexps, e);
2270 }
2271 for( en = rel->exps->h; en; en = en->next ) {
2272 sql_exp *e = en->data;
2273 if (e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter))
2274 list_append(jexps, e);
2275 }
2276 rel->exps = jexps;
2277 }
2278
2279 for( en = rel->exps->h; en; en = en->next ) {
2280 int join_idx = sql->opt_stats[0];
2281 sql_exp *e = en->data;
2282 stmt *s = NULL;
2283
2284 /* only handle simple joins here */
2285 if ((exp_has_func(e) && get_cmp(e) != cmp_filter) ||
2286 get_cmp(e) == cmp_or || (e->f && e->anti)) {
2287 if (!join && !list_length(lje)) {
2288 stmt *l = bin_first_column(be, left);
2289 stmt *r = bin_first_column(be, right);
2290 join = stmt_join(be, l, r, 0, cmp_all);
2291 }
2292 break;
2293 }
2294 if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
2295 (join && e->flag == cmp_filter)))
2296 break;
2297
2298 s = exp_bin(be, en->data, left, right, NULL, NULL, NULL, NULL);
2299 if (!s) {
2300 assert(0);
2301 return NULL;
2302 }
2303 if (join_idx != sql->opt_stats[0])
2304 idx = 1;
2305 /* stop on first non equality join */
2306 if (!join) {
2307 if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
2308 if (!en->next && (s->type == st_uselect || s->type == st_uselect2))
2309 join = s;
2310 else
2311 break;
2312 }
2313 join = s;
2314 } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
2315 /* handle select expressions */
2316 break;
2317 }
2318 if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
2319 list_append(lje, s->op1);
2320 list_append(rje, s->op2);
2321 }
2322 }
2323 if (list_length(lje) > 1) {
2324 join = releqjoin(be, lje, rje, 0 /* no hash used */, cmp_equal, 0);
2325 } else if (!join && list_length(lje) == list_length(rje) && list_length(lje)) {
2326 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal);
2327 } else if (!join) {
2328 stmt *l = bin_first_column(be, left);
2329 stmt *r = bin_first_column(be, right);
2330 join = stmt_join(be, l, r, 0, cmp_all);
2331 }
2332 } else {
2333 stmt *l = bin_first_column(be, left);
2334 stmt *r = bin_first_column(be, right);
2335 join = stmt_join(be, l, r, 0, cmp_all);
2336 }
2337 jl = stmt_result(be, join, 0);
2338 if (en) {
2339 stmt *sub, *sel = NULL;
2340 list *nl;
2341
2342 jr = stmt_result(be, join, 1);
2343 /* construct relation */
2344 nl = sa_list(sql->sa);
2345
2346 /* first project after equi-joins */
2347 for( n = left->op4.lval->h; n; n = n->next ) {
2348 stmt *c = n->data;
2349 const char *rnme = table_name(sql->sa, c);
2350 const char *nme = column_name(sql->sa, c);
2351 stmt *s = stmt_project(be, jl, column(be, c) );
2352
2353 s = stmt_alias(be, s, rnme, nme);
2354 list_append(nl, s);
2355 }
2356 for( n = right->op4.lval->h; n; n = n->next ) {
2357 stmt *c = n->data;
2358 const char *rnme = table_name(sql->sa, c);
2359 const char *nme = column_name(sql->sa, c);
2360 stmt *s = stmt_project(be, jr, column(be, c) );
2361
2362 s = stmt_alias(be, s, rnme, nme);
2363 list_append(nl, s);
2364 }
2365 sub = stmt_list(be, nl);
2366
2367 /* continue with non equi-joins */
2368 for( ; en; en = en->next ) {
2369 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel);
2370
2371 if (!s) {
2372 assert(0);
2373 return NULL;
2374 }
2375 if (s->nrcols == 0) {
2376 stmt *l = bin_first_column(be, sub);
2377 s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0);
2378 }
2379 sel = s;
2380 }
2381 /* recreate join output */
2382 jl = stmt_project(be, sel, jl);
2383 }
2384
2385 /* construct relation */
2386 l = sa_list(sql->sa);
2387
2388 /* We did a full join, thats too much.
2389 Reduce this using difference and intersect */
2390 c = stmt_mirror(be, left->op4.lval->h->data);
2391 if (rel->op == op_anti) {
2392 join = stmt_tdiff(be, c, jl);
2393 } else {
2394 join = stmt_tinter(be, c, jl);
2395 }
2396
2397 /* project all the left columns */
2398 for( n = left->op4.lval->h; n; n = n->next ) {
2399 stmt *c = n->data;
2400 const char *rnme = table_name(sql->sa, c);
2401 const char *nme = column_name(sql->sa, c);
2402 stmt *s = stmt_project(be, join, column(be, c));
2403
2404 s = stmt_alias(be, s, rnme, nme);
2405 list_append(l, s);
2406 }
2407 return stmt_list(be, l);
2408}
2409
2410static stmt *
2411rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
2412{
2413 mvc *sql = be->mvc;
2414 node *n;
2415 stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
2416 list *rl = sa_list(sql->sa), *tids;
2417
2418 /* single values are unique */
2419 if (s->key && s->nrcols == 0)
2420 return s;
2421
2422 /* Use 'all' tid columns */
2423 if (/* DISABLES CODE */ (0) && (tids = bin_find_columns(be, s, TID)) != NULL) {
2424 for (n = tids->h; n; n = n->next) {
2425 stmt *t = n->data;
2426
2427 g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
2428 grp = stmt_result(be, g, 0);
2429 ext = stmt_result(be, g, 1);
2430 cnt = stmt_result(be, g, 2);
2431 }
2432 } else {
2433 for (n = s->op4.lval->h; n; n = n->next) {
2434 stmt *t = n->data;
2435
2436 g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
2437 grp = stmt_result(be, g, 0);
2438 ext = stmt_result(be, g, 1);
2439 cnt = stmt_result(be, g, 2);
2440 }
2441 }
2442 if (!ext)
2443 return NULL;
2444
2445 for (n = s->op4.lval->h; n; n = n->next) {
2446 stmt *t = n->data;
2447
2448 list_append(rl, stmt_project(be, ext, t));
2449 }
2450
2451 if (distinct)
2452 *distinct = ext;
2453 s = stmt_list(be, rl);
2454 return s;
2455}
2456
2457static stmt *
2458rel_rename(backend *be, sql_rel *rel, stmt *sub)
2459{
2460 if (rel->exps) {
2461 node *en, *n;
2462 list *l = sa_list(be->mvc->sa);
2463
2464 for( en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next ) {
2465 sql_exp *exp = en->data;
2466 stmt *s = n->data;
2467
2468 if (!s) {
2469 assert(0);
2470 return NULL;
2471 }
2472 s = stmt_rename(be, rel, exp, s);
2473 list_append(l, s);
2474 }
2475 sub = stmt_list(be, l);
2476 }
2477 return sub;
2478}
2479
2480static stmt *
2481rel2bin_union(backend *be, sql_rel *rel, list *refs)
2482{
2483 mvc *sql = be->mvc;
2484 list *l;
2485 node *n, *m;
2486 stmt *left = NULL, *right = NULL, *sub;
2487
2488 if (rel->l) /* first construct the left sub relation */
2489 left = subrel_bin(be, rel->l, refs);
2490 if (rel->r) /* first construct the right sub relation */
2491 right = subrel_bin(be, rel->r, refs);
2492 if (!left || !right)
2493 return NULL;
2494
2495 /* construct relation */
2496 l = sa_list(sql->sa);
2497 for( n = left->op4.lval->h, m = right->op4.lval->h; n && m;
2498 n = n->next, m = m->next ) {
2499 stmt *c1 = n->data;
2500 stmt *c2 = m->data;
2501 const char *rnme = table_name(sql->sa, c1);
2502 const char *nme = column_name(sql->sa, c1);
2503 stmt *s;
2504
2505 s = stmt_append(be, create_const_column(be, c1), c2);
2506 s = stmt_alias(be, s, rnme, nme);
2507 list_append(l, s);
2508 }
2509 sub = stmt_list(be, l);
2510
2511 sub = rel_rename(be, rel, sub);
2512 if (need_distinct(rel))
2513 sub = rel2bin_distinct(be, sub, NULL);
2514 return sub;
2515}
2516
2517static stmt *
2518rel2bin_except(backend *be, sql_rel *rel, list *refs)
2519{
2520 mvc *sql = be->mvc;
2521 sql_subtype *lng = sql_bind_localtype("lng");
2522 list *stmts;
2523 node *n, *m;
2524 stmt *left = NULL, *right = NULL, *sub;
2525 sql_subfunc *min;
2526
2527 stmt *lg = NULL, *rg = NULL;
2528 stmt *lgrp = NULL, *rgrp = NULL;
2529 stmt *lext = NULL, *rext = NULL, *next = NULL;
2530 stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
2531 stmt *s, *lm, *rm;
2532 list *lje = sa_list(sql->sa);
2533 list *rje = sa_list(sql->sa);
2534
2535 if (rel->l) /* first construct the left sub relation */
2536 left = subrel_bin(be, rel->l, refs);
2537 if (rel->r) /* first construct the right sub relation */
2538 right = subrel_bin(be, rel->r, refs);
2539 if (!left || !right)
2540 return NULL;
2541 left = row2cols(be, left);
2542 right = row2cols(be, right);
2543
2544 /*
2545 * The multi column except is handled using group by's and
2546 * group size counts on both sides of the intersect. We then
2547 * return for each group of L with min(L.count,R.count),
2548 * number of rows.
2549 */
2550 for (n = left->op4.lval->h; n; n = n->next) {
2551 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
2552 lgrp = stmt_result(be, lg, 0);
2553 lext = stmt_result(be, lg, 1);
2554 lcnt = stmt_result(be, lg, 2);
2555 }
2556 for (n = right->op4.lval->h; n; n = n->next) {
2557 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
2558 rgrp = stmt_result(be, rg, 0);
2559 rext = stmt_result(be, rg, 1);
2560 rcnt = stmt_result(be, rg, 2);
2561 }
2562
2563 if (!lg || !rg)
2564 return NULL;
2565
2566 if (need_distinct(rel)) {
2567 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
2568 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
2569 }
2570
2571 /* now find the matching groups */
2572 for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
2573 stmt *l = column(be, n->data);
2574 stmt *r = column(be, m->data);
2575
2576 l = stmt_project(be, lext, l);
2577 r = stmt_project(be, rext, r);
2578 list_append(lje, l);
2579 list_append(rje, r);
2580 }
2581 s = releqjoin(be, lje, rje, 1 /* cannot use hash */, cmp_equal_nil, 0);
2582 lm = stmt_result(be, s, 0);
2583 rm = stmt_result(be, s, 1);
2584
2585 s = stmt_mirror(be, lext);
2586 s = stmt_tdiff(be, s, lm);
2587
2588 /* first we find those missing in R */
2589 next = stmt_project(be, s, lext);
2590 ncnt = stmt_project(be, s, lcnt);
2591 zero = stmt_const(be, s, stmt_atom_lng(be, 0));
2592
2593 /* ext, lcount, rcount */
2594 lext = stmt_project(be, lm, lext);
2595 lcnt = stmt_project(be, lm, lcnt);
2596 rcnt = stmt_project(be, rm, rcnt);
2597
2598 /* append those missing in L */
2599 lext = stmt_append(be, lext, next);
2600 lcnt = stmt_append(be, lcnt, ncnt);
2601 rcnt = stmt_append(be, rcnt, zero);
2602
2603 min = sql_bind_func(sql->sa, sql->session->schema, "sql_sub", lng, lng, F_FUNC);
2604 s = stmt_binop(be, lcnt, rcnt, min); /* use count */
2605
2606 /* now we have gid,cnt, blowup to full groupsizes */
2607 s = stmt_gen_group(be, lext, s);
2608
2609 /* project columns of left hand expression */
2610 stmts = sa_list(sql->sa);
2611 for (n = left->op4.lval->h; n; n = n->next) {
2612 stmt *c1 = column(be, n->data);
2613 const char *rnme = NULL;
2614 const char *nme = column_name(sql->sa, c1);
2615
2616 /* retain name via the stmt_alias */
2617 c1 = stmt_project(be, s, c1);
2618
2619 rnme = table_name(sql->sa, c1);
2620 c1 = stmt_alias(be, c1, rnme, nme);
2621 list_append(stmts, c1);
2622 }
2623 sub = stmt_list(be, stmts);
2624 return rel_rename(be, rel, sub);
2625}
2626
2627static stmt *
2628rel2bin_inter(backend *be, sql_rel *rel, list *refs)
2629{
2630 mvc *sql = be->mvc;
2631 sql_subtype *lng = sql_bind_localtype("lng");
2632 list *stmts;
2633 node *n, *m;
2634 stmt *left = NULL, *right = NULL, *sub;
2635 sql_subfunc *min;
2636
2637 stmt *lg = NULL, *rg = NULL;
2638 stmt *lgrp = NULL, *rgrp = NULL;
2639 stmt *lext = NULL, *rext = NULL;
2640 stmt *lcnt = NULL, *rcnt = NULL;
2641 stmt *s, *lm, *rm;
2642 list *lje = sa_list(sql->sa);
2643 list *rje = sa_list(sql->sa);
2644
2645 if (rel->l) /* first construct the left sub relation */
2646 left = subrel_bin(be, rel->l, refs);
2647 if (rel->r) /* first construct the right sub relation */
2648 right = subrel_bin(be, rel->r, refs);
2649 if (!left || !right)
2650 return NULL;
2651 left = row2cols(be, left);
2652
2653 /*
2654 * The multi column intersect is handled using group by's and
2655 * group size counts on both sides of the intersect. We then
2656 * return for each group of L with min(L.count,R.count),
2657 * number of rows.
2658 */
2659 for (n = left->op4.lval->h; n; n = n->next) {
2660 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
2661 lgrp = stmt_result(be, lg, 0);
2662 lext = stmt_result(be, lg, 1);
2663 lcnt = stmt_result(be, lg, 2);
2664 }
2665 for (n = right->op4.lval->h; n; n = n->next) {
2666 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
2667 rgrp = stmt_result(be, rg, 0);
2668 rext = stmt_result(be, rg, 1);
2669 rcnt = stmt_result(be, rg, 2);
2670 }
2671
2672 if (!lg || !rg)
2673 return NULL;
2674
2675 if (need_distinct(rel)) {
2676 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
2677 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
2678 }
2679
2680 /* now find the matching groups */
2681 for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
2682 stmt *l = column(be, n->data);
2683 stmt *r = column(be, m->data);
2684
2685 l = stmt_project(be, lext, l);
2686 r = stmt_project(be, rext, r);
2687 list_append(lje, l);
2688 list_append(rje, r);
2689 }
2690 s = releqjoin(be, lje, rje, 1 /* cannot use hash */, cmp_equal_nil, 0);
2691 lm = stmt_result(be, s, 0);
2692 rm = stmt_result(be, s, 1);
2693
2694 /* ext, lcount, rcount */
2695 lext = stmt_project(be, lm, lext);
2696 lcnt = stmt_project(be, lm, lcnt);
2697 rcnt = stmt_project(be, rm, rcnt);
2698
2699 min = sql_bind_func(sql->sa, sql->session->schema, "sql_min", lng, lng, F_FUNC);
2700 s = stmt_binop(be, lcnt, rcnt, min);
2701
2702 /* now we have gid,cnt, blowup to full groupsizes */
2703 s = stmt_gen_group(be, lext, s);
2704
2705 /* project columns of left hand expression */
2706 stmts = sa_list(sql->sa);
2707 for (n = left->op4.lval->h; n; n = n->next) {
2708 stmt *c1 = column(be, n->data);
2709 const char *rnme = NULL;
2710 const char *nme = column_name(sql->sa, c1);
2711
2712 /* retain name via the stmt_alias */
2713 c1 = stmt_project(be, s, c1);
2714
2715 rnme = table_name(sql->sa, c1);
2716 c1 = stmt_alias(be, c1, rnme, nme);
2717 list_append(stmts, c1);
2718 }
2719 sub = stmt_list(be, stmts);
2720 return rel_rename(be, rel, sub);
2721}
2722
2723static stmt *
2724sql_reorder(backend *be, stmt *order, stmt *s)
2725{
2726 list *l = sa_list(be->mvc->sa);
2727 node *n;
2728
2729 for (n = s->op4.lval->h; n; n = n->next) {
2730 stmt *sc = n->data;
2731 const char *cname = column_name(be->mvc->sa, sc);
2732 const char *tname = table_name(be->mvc->sa, sc);
2733
2734 sc = stmt_project(be, order, sc);
2735 sc = stmt_alias(be, sc, tname, cname );
2736 list_append(l, sc);
2737 }
2738 return stmt_list(be, l);
2739}
2740
2741static sql_exp*
2742topn_limit( sql_rel *rel )
2743{
2744 if (rel->exps) {
2745 sql_exp *limit = rel->exps->h->data;
2746
2747 return limit;
2748 }
2749 return NULL;
2750}
2751
2752static sql_exp*
2753topn_offset( sql_rel *rel )
2754{
2755 if (rel->exps && list_length(rel->exps) > 1) {
2756 sql_exp *offset = rel->exps->h->next->data;
2757
2758 return offset;
2759 }
2760 return NULL;
2761}
2762
2763static stmt *
2764rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
2765{
2766 mvc *sql = be->mvc;
2767 list *pl;
2768 node *en, *n;
2769 stmt *sub = NULL, *psub = NULL;
2770 stmt *l = NULL;
2771
2772 if (topn) {
2773 sql_exp *le = topn_limit(topn);
2774 sql_exp *oe = topn_offset(topn);
2775
2776 if (!le) { /* Don't push only offset */
2777 topn = NULL;
2778 } else {
2779 l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL);
2780 if(!l)
2781 return NULL;
2782 if (oe) {
2783 sql_subtype *lng = sql_bind_localtype("lng");
2784 sql_subfunc *add = sql_bind_func_result(sql->sa, sql->session->schema, "sql_add", lng, lng, lng);
2785 stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL);
2786 if(!o)
2787 return NULL;
2788 l = stmt_binop(be, l, o, add);
2789 }
2790 }
2791 }
2792
2793 if (!rel->exps)
2794 return stmt_none(be);
2795
2796 if (rel->l) { /* first construct the sub relation */
2797 sql_rel *l = rel->l;
2798 if (l->op == op_ddl) {
2799 sql_table *t = rel_ddl_table_get(l);
2800
2801 if (t)
2802 sub = rel2bin_sql_table(be, t);
2803 } else {
2804 sub = subrel_bin(be, rel->l, refs);
2805 }
2806 if (!sub)
2807 return NULL;
2808 }
2809
2810 pl = sa_list(sql->sa);
2811 if (sub)
2812 pl->expected_cnt = list_length(sub->op4.lval);
2813 psub = stmt_list(be, pl);
2814 for( en = rel->exps->h; en; en = en->next ) {
2815 sql_exp *exp = en->data;
2816 stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL);
2817
2818 if (!s) /* try with own projection as well */
2819 s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL);
2820 if (!s) /* error */
2821 return NULL;
2822 /* single value with limit */
2823 if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
2824 s = const_column(be, s);
2825 else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
2826 s = stmt_const(be, bin_first_column(be, sub), s);
2827
2828 s = stmt_rename(be, rel, exp, s);
2829 column_name(sql->sa, s); /* save column name */
2830 list_append(pl, s);
2831 }
2832 stmt_set_nrcols(psub);
2833
2834 /* In case of a topn
2835 if both order by and distinct: then get first order by col
2836 do topn on it. Project all again! Then rest
2837 */
2838 if (topn && rel->r) {
2839 list *oexps = rel->r, *npl = sa_list(sql->sa);
2840 /* distinct, topn returns atleast N (unique groups) */
2841 int distinct = need_distinct(rel);
2842 stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
2843
2844 for (n=oexps->h; n; n = n->next) {
2845 sql_exp *orderbycole = n->data;
2846 int last = (n->next == NULL);
2847
2848 stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL);
2849
2850 if (!orderbycolstmt)
2851 return NULL;
2852
2853 /* handle constants */
2854 if (orderbycolstmt->nrcols == 0 && !last) /* no need to sort on constant */
2855 continue;
2856 orderbycolstmt = column(be, orderbycolstmt);
2857 if (!limit) { /* topn based on a single column */
2858 limit = stmt_limit(be, orderbycolstmt, NULL, NULL, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
2859 } else { /* topn based on 2 columns */
2860 limit = stmt_limit(be, orderbycolstmt, lpiv, lgid, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
2861 }
2862 if (!limit)
2863 return NULL;
2864 lpiv = limit;
2865 if (!last) {
2866 lpiv = stmt_result(be, limit, 0);
2867 lgid = stmt_result(be, limit, 1);
2868 }
2869 }
2870
2871 limit = lpiv;
2872 for ( n=pl->h ; n; n = n->next)
2873 list_append(npl, stmt_project(be, limit, column(be, n->data)));
2874 psub = stmt_list(be, npl);
2875
2876 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
2877 pl = sub->op4.lval;
2878 npl = sa_list(sql->sa);
2879 for ( n=pl->h ; n; n = n->next) {
2880 list_append(npl, stmt_project(be, limit, column(be, n->data)));
2881 }
2882 sub = stmt_list(be, npl);
2883 }
2884 if (need_distinct(rel)) {
2885 stmt *distinct = NULL;
2886 psub = rel2bin_distinct(be, psub, &distinct);
2887 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
2888 if (sub && distinct) {
2889 list *npl = sa_list(sql->sa);
2890
2891 pl = sub->op4.lval;
2892 for ( n=pl->h ; n; n = n->next)
2893 list_append(npl, stmt_project(be, distinct, column(be, n->data)));
2894 sub = stmt_list(be, npl);
2895 }
2896 }
2897 if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
2898 list *oexps = rel->r;
2899 stmt *orderby_ids = NULL, *orderby_grp = NULL;
2900
2901 for (en = oexps->h; en; en = en->next) {
2902 stmt *orderby = NULL;
2903 sql_exp *orderbycole = en->data;
2904 stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL);
2905
2906 if (!orderbycolstmt) {
2907 assert(0);
2908 return NULL;
2909 }
2910 /* single values don't need sorting */
2911 if (orderbycolstmt->nrcols == 0)
2912 continue;
2913 if (orderby_ids)
2914 orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
2915 else
2916 orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
2917 orderby_ids = stmt_result(be, orderby, 1);
2918 orderby_grp = stmt_result(be, orderby, 2);
2919 }
2920 if (orderby_ids)
2921 psub = sql_reorder(be, orderby_ids, psub);
2922 }
2923 return psub;
2924}
2925
2926static stmt *
2927rel2bin_predicate(backend *be)
2928{
2929 return const_column(be, stmt_bool(be, 1));
2930}
2931
2932static stmt *
2933rel2bin_select(backend *be, sql_rel *rel, list *refs)
2934{
2935 mvc *sql = be->mvc;
2936 list *l;
2937 node *en, *n;
2938 stmt *sub = NULL, *sel = NULL;
2939 stmt *predicate = NULL;
2940
2941 if (rel->l) { /* first construct the sub relation */
2942 sub = subrel_bin(be, rel->l, refs);
2943 if (!sub)
2944 return NULL;
2945 sub = row2cols(be, sub);
2946 }
2947 if (!sub && !predicate)
2948 predicate = rel2bin_predicate(be);
2949 /*
2950 else if (!predicate)
2951 predicate = stmt_const(be, bin_first_column(be, sub), stmt_bool(be, 1));
2952 */
2953 if (!rel->exps || !rel->exps->h) {
2954 if (sub)
2955 return sub;
2956 if (predicate)
2957 return predicate;
2958 return stmt_const(be, bin_first_column(be, sub), stmt_bool(be, 1));
2959 }
2960 if (!sub && predicate) {
2961 list *l = sa_list(sql->sa);
2962 assert(predicate);
2963 append(l, predicate);
2964 sub = stmt_list(be, l);
2965 }
2966 /* handle possible index lookups */
2967 /* expressions are in index order ! */
2968 if (sub && (en = rel->exps->h) != NULL) {
2969 sql_exp *e = en->data;
2970 prop *p;
2971
2972 if ((p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
2973 sql_idx *i = p->value;
2974
2975 sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, en);
2976 }
2977 }
2978 for( en = rel->exps->h; en; en = en->next ) {
2979 sql_exp *e = en->data;
2980 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel);
2981
2982 if (!s) {
2983 assert(0);
2984 return NULL;
2985 }
2986 if (s->nrcols == 0){
2987 if (!predicate && sub)
2988 predicate = stmt_const(be, bin_first_column(be, sub), stmt_bool(be, 1));
2989 if (e->type != e_cmp) {
2990 sql_subtype *bt = sql_bind_localtype("bit");
2991
2992 s = stmt_convert(be, s, exp_subtype(e), bt, NULL);
2993 }
2994 sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0);
2995 } else if (e->type != e_cmp) {
2996 sel = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0);
2997 } else {
2998 sel = s;
2999 }
3000 }
3001
3002 /* construct relation */
3003 l = sa_list(sql->sa);
3004 if (sub && sel) {
3005 for( n = sub->op4.lval->h; n; n = n->next ) {
3006 stmt *col = n->data;
3007
3008 if (col->nrcols == 0) /* constant */
3009 col = stmt_const(be, sel, col);
3010 else
3011 col = stmt_project(be, sel, col);
3012 list_append(l, col);
3013 }
3014 }
3015 return stmt_list(be, l);
3016}
3017
3018static stmt *
3019rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
3020{
3021 mvc *sql = be->mvc;
3022 list *l, *aggrs, *gbexps = sa_list(sql->sa);
3023 node *n, *en;
3024 stmt *sub = NULL, *cursub;
3025 stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
3026
3027 if (rel->l) { /* first construct the sub relation */
3028 sub = subrel_bin(be, rel->l, refs);
3029 if (!sub)
3030 return NULL;
3031 }
3032
3033 if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
3034 list *newl = sa_list(sql->sa);
3035 node *n;
3036
3037 for(n=sub->op4.lval->h; n; n = n->next) {
3038 const char *cname = column_name(sql->sa, n->data);
3039 const char *tname = table_name(sql->sa, n->data);
3040 stmt *s = column(be, n->data);
3041
3042 s = stmt_alias(be, s, tname, cname );
3043 append(newl, s);
3044 }
3045 sub = stmt_list(be, newl);
3046 }
3047
3048 /* groupby columns */
3049
3050 /* Keep groupby columns, sub that they can be lookup in the aggr list */
3051 if (rel->r) {
3052 list *exps = rel->r;
3053
3054 for( en = exps->h; en; en = en->next ) {
3055 sql_exp *e = en->data;
3056 stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL);
3057
3058 if (!gbcol) {
3059 assert(0);
3060 return NULL;
3061 }
3062 if (!gbcol->nrcols)
3063 gbcol = stmt_const(be, bin_first_column(be, sub), gbcol);
3064 groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
3065 grp = stmt_result(be, groupby, 0);
3066 ext = stmt_result(be, groupby, 1);
3067 cnt = stmt_result(be, groupby, 2);
3068 gbcol = stmt_alias(be, gbcol, exp_find_rel_name(e), exp_name(e));
3069 list_append(gbexps, gbcol);
3070 }
3071 }
3072 /* now aggregate */
3073 l = sa_list(sql->sa);
3074 aggrs = rel->exps;
3075 cursub = stmt_list(be, l);
3076 for( n = aggrs->h; n; n = n->next ) {
3077 sql_exp *aggrexp = n->data;
3078
3079 stmt *aggrstmt = NULL;
3080
3081 /* first look in the current aggr list (l) and group by column list */
3082 if (l && !aggrstmt && aggrexp->type == e_column)
3083 aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
3084 if (gbexps && !aggrstmt && aggrexp->type == e_column) {
3085 aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
3086 if (aggrstmt && groupby) {
3087 aggrstmt = stmt_project(be, ext, aggrstmt);
3088 if (list_length(gbexps) == 1)
3089 aggrstmt->key = 1;
3090 }
3091 }
3092
3093 if (!aggrstmt)
3094 aggrstmt = exp_bin(be, aggrexp, sub, NULL, grp, ext, cnt, NULL);
3095 /* maybe the aggr uses intermediate results of this group by,
3096 therefore we pass the group by columns too
3097 */
3098 if (!aggrstmt)
3099 aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL);
3100 if (!aggrstmt) {
3101 assert(0);
3102 return NULL;
3103 }
3104
3105 aggrstmt = stmt_rename(be, rel, aggrexp, aggrstmt);
3106 list_append(l, aggrstmt);
3107 }
3108 stmt_set_nrcols(cursub);
3109 return cursub;
3110}
3111
3112static stmt *
3113rel2bin_topn(backend *be, sql_rel *rel, list *refs)
3114{
3115 mvc *sql = be->mvc;
3116 sql_exp *oe = NULL, *le = NULL;
3117 stmt *sub = NULL, *l = NULL, *o = NULL;
3118 node *n;
3119
3120 if (rel->l) { /* first construct the sub relation */
3121 sql_rel *rl = rel->l;
3122
3123 if (rl->op == op_project) {
3124 sub = rel2bin_project(be, rl, refs, rel);
3125 } else {
3126 sub = subrel_bin(be, rl, refs);
3127 }
3128 }
3129 if (!sub)
3130 return NULL;
3131
3132 le = topn_limit(rel);
3133 oe = topn_offset(rel);
3134
3135 n = sub->op4.lval->h;
3136 if (n) {
3137 stmt *limit = NULL, *sc = n->data;
3138 const char *cname = column_name(sql->sa, sc);
3139 const char *tname = table_name(sql->sa, sc);
3140 list *newl = sa_list(sql->sa);
3141
3142 if (le)
3143 l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL);
3144 if (oe)
3145 o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL);
3146
3147 if (!l)
3148 l = stmt_atom_lng_nil(be);
3149 if (!o)
3150 o = stmt_atom_lng(be, 0);
3151 if (!l || !o)
3152 return NULL;
3153
3154 sc = column(be, sc);
3155 limit = stmt_limit(be, stmt_alias(be, sc, tname, cname), NULL, NULL, o, l, 0,0,0,0,0);
3156
3157 for ( ; n; n = n->next) {
3158 stmt *sc = n->data;
3159 const char *cname = column_name(sql->sa, sc);
3160 const char *tname = table_name(sql->sa, sc);
3161
3162 sc = column(be, sc);
3163 sc = stmt_project(be, limit, sc);
3164 list_append(newl, stmt_alias(be, sc, tname, cname));
3165 }
3166 sub = stmt_list(be, newl);
3167 }
3168 return sub;
3169}
3170
3171static stmt *
3172rel2bin_sample(backend *be, sql_rel *rel, list *refs)
3173{
3174 mvc *sql = be->mvc;
3175 list *newl;
3176 stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
3177 node *n;
3178
3179 if (rel->l) /* first construct the sub relation */
3180 sub = subrel_bin(be, rel->l, refs);
3181 if (!sub)
3182 return NULL;
3183
3184 n = sub->op4.lval->h;
3185 newl = sa_list(sql->sa);
3186
3187 if (n) {
3188 stmt *sc = n->data;
3189 const char *cname = column_name(sql->sa, sc);
3190 const char *tname = table_name(sql->sa, sc);
3191
3192 sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL);
3193 if (!sample_size)
3194 sample_size = stmt_atom_lng_nil(be);
3195
3196 if (rel->exps->cnt == 2) {
3197 seed = exp_bin(be, rel->exps->h->next->data, NULL, NULL, NULL, NULL, NULL, NULL);
3198 if(!seed)
3199 return NULL;
3200 }
3201
3202 sc = column(be, sc);
3203 sample = stmt_sample(be, stmt_alias(be, sc, tname, cname),sample_size, seed);
3204
3205 for ( ; n; n = n->next) {
3206 stmt *sc = n->data;
3207 const char *cname = column_name(sql->sa, sc);
3208 const char *tname = table_name(sql->sa, sc);
3209
3210 sc = column(be, sc);
3211 sc = stmt_project(be, sample, sc);
3212 list_append(newl, stmt_alias(be, sc, tname, cname));
3213 }
3214 }
3215 sub = stmt_list(be, newl);
3216 return sub;
3217}
3218
3219stmt *
3220sql_parse(backend *be, sql_allocator *sa, const char *query, char mode)
3221{
3222 mvc *m = be->mvc;
3223 mvc *o = NULL;
3224 stmt *sq = NULL;
3225 buffer *b;
3226 char *nquery;
3227 size_t len = _strlen(query);
3228 stream *buf;
3229 bstream * bst;
3230
3231 if (THRhighwater())
3232 return sql_error(m, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
3233
3234 o = MNEW(mvc);
3235 if (!o)
3236 return NULL;
3237 *o = *m;
3238
3239 m->qc = NULL;
3240
3241 m->caching = 0;
3242 m->emode = mode;
3243 be->depth++;
3244
3245 b = (buffer*)GDKmalloc(sizeof(buffer));
3246 if (b == 0) {
3247 *m = *o;
3248 GDKfree(o);
3249 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
3250 }
3251 nquery = GDKmalloc(len + 1 + 1);
3252 if (nquery == 0) {
3253 *m = *o;
3254 GDKfree(o);
3255 GDKfree(b);
3256 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
3257 }
3258 snprintf(nquery, len + 2, "%s\n", query);
3259 len++;
3260 buffer_init(b, nquery, len);
3261 buf = buffer_rastream(b, "sqlstatement");
3262 if(buf == NULL) {
3263 *m = *o;
3264 GDKfree(o);
3265 GDKfree(b);
3266 GDKfree(nquery);
3267 be->depth--;
3268 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
3269 }
3270 if((bst = bstream_create(buf, b->len)) == NULL) {
3271 close_stream(buf);
3272 *m = *o;
3273 GDKfree(o);
3274 GDKfree(b);
3275 GDKfree(nquery);
3276 be->depth--;
3277 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
3278 }
3279 scanner_init( &m->scanner, bst, NULL);
3280 m->scanner.mode = LINE_1;
3281 bstream_next(m->scanner.rs);
3282
3283 m->params = NULL;
3284 m->argc = 0;
3285 m->sym = NULL;
3286 m->errstr[0] = '\0';
3287 m->errstr[ERRSIZE-1] = '\0';
3288
3289 /* create private allocator */
3290 m->sa = (sa)?sa:sa_create();
3291 if (!m->sa) {
3292 bstream_destroy(bst);
3293 *m = *o;
3294 GDKfree(o);
3295 GDKfree(b);
3296 GDKfree(nquery);
3297 be->depth--;
3298 return sql_error(m, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
3299 }
3300
3301 if (sqlparse(m) || !m->sym) {
3302 /* oops an error */
3303 snprintf(m->errstr, ERRSIZE, "An error occurred when executing "
3304 "internal query: %s", nquery);
3305 } else {
3306 sql_query *query = query_create(m);
3307 sql_rel *r = rel_semantic(query, m->sym);
3308
3309 if (r && (r = rel_unnest(m,r)) != NULL && (r = rel_optimizer(m, r, 1)) != NULL)
3310 sq = rel_bin(be, r);
3311 }
3312
3313 GDKfree(nquery);
3314 GDKfree(b);
3315 bstream_destroy(m->scanner.rs);
3316 be->depth--;
3317 if (m->sa && m->sa != sa)
3318 sa_destroy(m->sa);
3319 m->sym = NULL;
3320 {
3321 int status = m->session->status;
3322 int sizevars = m->sizevars, topvars = m->topvars;
3323 sql_var *vars = m->vars;
3324 /* cascade list maybe removed */
3325 list *cascade_action = m->cascade_action;
3326
3327 strcpy(o->errstr, m->errstr);
3328 *m = *o;
3329 m->sizevars = sizevars;
3330 m->topvars = topvars;
3331 m->vars = vars;
3332 m->session->status = status;
3333 m->cascade_action = cascade_action;
3334 }
3335 _DELETE(o);
3336 return sq;
3337}
3338
3339static stmt *
3340insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
3341{
3342 mvc *sql = be->mvc;
3343/* pkey's cannot have NULLs, ukeys however can
3344 current implementation switches on 'NOT NULL' on primary key columns */
3345
3346 char *msg = NULL;
3347 stmt *res;
3348
3349 sql_subtype *lng = sql_bind_localtype("lng");
3350 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
3351 sql_subtype *bt = sql_bind_localtype("bit");
3352 stmt *dels = stmt_tid(be, k->t, 0);
3353 sql_subfunc *ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
3354
3355 if (list_length(k->columns) > 1) {
3356 node *m;
3357 stmt *s = list_fetch(inserts, 0), *ins = s;
3358 sql_subaggr *sum;
3359 stmt *ssum = NULL;
3360 stmt *col = NULL;
3361
3362 s = ins;
3363 /* 1st stage: find out if original contains same values */
3364 if (s->key && s->nrcols == 0) {
3365 s = NULL;
3366 if (k->idx && hash_index(k->idx->type))
3367 s = stmt_uselect(be, stmt_idx(be, k->idx, dels), idx_inserts, cmp_equal_nil, s, 0);
3368 for (m = k->columns->h; m; m = m->next) {
3369 sql_kc *c = m->data;
3370 stmt *cs = list_fetch(inserts, c->c->colnr);
3371
3372 col = stmt_col(be, c->c, dels);
3373 if ((k->type == ukey) && stmt_has_null(col)) {
3374 stmt *nn = stmt_selectnonil(be, col, s);
3375 s = stmt_uselect( be, col, cs, cmp_equal, nn, 0);
3376 } else {
3377 s = stmt_uselect( be, col, cs, cmp_equal, s, 0);
3378 }
3379 }
3380 } else {
3381 list *lje = sa_list(sql->sa);
3382 list *rje = sa_list(sql->sa);
3383 if (k->idx && hash_index(k->idx->type)) {
3384 list_append(lje, stmt_idx(be, k->idx, dels));
3385 list_append(rje, idx_inserts);
3386 }
3387 for (m = k->columns->h; m; m = m->next) {
3388 sql_kc *c = m->data;
3389 stmt *cs = list_fetch(inserts, c->c->colnr);
3390
3391 col = stmt_col(be, c->c, dels);
3392 list_append(lje, col);
3393 list_append(rje, cs);
3394 }
3395 s = releqjoin(be, lje, rje, 1 /* hash used */, cmp_equal, 0);
3396 s = stmt_result(be, s, 0);
3397 }
3398 s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), ne);
3399
3400 /* 2e stage: find out if inserted are unique */
3401 if ((!idx_inserts && ins->nrcols) || (idx_inserts && idx_inserts->nrcols)) { /* insert columns not atoms */
3402 sql_subfunc *or = sql_bind_func_result(sql->sa, sql->session->schema, "or", bt, bt, bt);
3403 stmt *orderby_ids = NULL, *orderby_grp = NULL;
3404
3405 /* implementation uses sort key check */
3406 for (m = k->columns->h; m; m = m->next) {
3407 sql_kc *c = m->data;
3408 stmt *orderby;
3409 stmt *cs = list_fetch(inserts, c->c->colnr);
3410
3411 if (orderby_grp)
3412 orderby = stmt_reorder(be, cs, 1, 0, orderby_ids, orderby_grp);
3413 else
3414 orderby = stmt_order(be, cs, 1, 0);
3415 orderby_ids = stmt_result(be, orderby, 1);
3416 orderby_grp = stmt_result(be, orderby, 2);
3417 }
3418
3419 if (!orderby_grp || !orderby_ids)
3420 return NULL;
3421
3422 sum = sql_bind_aggr(sql->sa, sql->session->schema, "not_unique", tail_type(orderby_grp));
3423 ssum = stmt_aggr(be, orderby_grp, NULL, NULL, sum, 1, 0, 1);
3424 /* combine results */
3425 s = stmt_binop(be, s, ssum, or);
3426 }
3427
3428 if (k->type == pkey) {
3429 msg = sa_message(sql->sa, "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
3430 } else {
3431 msg = sa_message(sql->sa, "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
3432 }
3433 res = stmt_exception(be, s, msg, 00001);
3434 } else { /* single column key */
3435 sql_kc *c = k->columns->h->data;
3436 stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
3437
3438 s = stmt_col(be, c->c, dels);
3439 if ((k->type == ukey) && stmt_has_null(s)) {
3440 stmt *nn = stmt_selectnonil(be, s, NULL);
3441 s = stmt_project(be, nn, s);
3442 }
3443 if (h->nrcols) {
3444 s = stmt_join(be, s, h, 0, cmp_equal);
3445 /* s should be empty */
3446 s = stmt_result(be, s, 0);
3447 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
3448 } else {
3449 s = stmt_uselect(be, s, h, cmp_equal, NULL, 0);
3450 /* s should be empty */
3451 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
3452 }
3453 /* s should be empty */
3454 s = stmt_binop(be, s, stmt_atom_lng(be, 0), ne);
3455
3456 /* 2e stage: find out if inserts are unique */
3457 if (h->nrcols) { /* insert multiple atoms */
3458 sql_subaggr *sum;
3459 stmt *count_sum = NULL;
3460 sql_subfunc *or = sql_bind_func_result(sql->sa, sql->session->schema, "or", bt, bt, bt);
3461 stmt *ssum, *ss;
3462
3463 stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
3464
3465 /* inserted vaules may be null */
3466 if ((k->type == ukey) && stmt_has_null(ins)) {
3467 stmt *nn = stmt_selectnonil(be, ins, NULL);
3468 ins = stmt_project(be, nn, ins);
3469 }
3470
3471 g = stmt_group(be, ins, NULL, NULL, NULL, 1);
3472 ss = stmt_result(be, g, 2); /* use count */
3473 /* (count(ss) <> sum(ss)) */
3474 sum = sql_bind_aggr(sql->sa, sql->session->schema, "sum", lng);
3475 ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
3476 ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, NULL, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
3477 count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, ne);
3478
3479 /* combine results */
3480 s = stmt_binop(be, s, count_sum, or);
3481 }
3482 if (k->type == pkey) {
3483 msg = sa_message( sql->sa,"INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
3484 } else {
3485 msg = sa_message(sql->sa, "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
3486 }
3487 res = stmt_exception(be, s, msg, 00001);
3488 }
3489 return res;
3490}
3491
3492static stmt *
3493insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
3494{
3495 mvc *sql = be->mvc;
3496 char *msg = NULL;
3497 stmt *cs = list_fetch(inserts, 0), *s = cs;
3498 sql_subtype *lng = sql_bind_localtype("lng");
3499 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
3500 sql_subtype *bt = sql_bind_localtype("bit");
3501 sql_subfunc *ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
3502
3503 if (pin && list_length(pin->op4.lval))
3504 s = pin->op4.lval->h->data;
3505 if (s->key && s->nrcols == 0) {
3506 s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 1), ne);
3507 } else {
3508 /* releqjoin.count <> inserts[col1].count */
3509 s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 0, 1), stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), ne);
3510 }
3511
3512 /* s should be empty */
3513 msg = sa_message(sql->sa, "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
3514 return stmt_exception(be, s, msg, 00001);
3515}
3516
3517static stmt *
3518sql_insert_key(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
3519{
3520 /* int insert = 1;
3521 * while insert and has u/pkey and not defered then
3522 * if u/pkey values exist then
3523 * insert = 0
3524 * while insert and has fkey and not defered then
3525 * find id of corresponding u/pkey
3526 * if (!found)
3527 * insert = 0
3528 * if insert
3529 * insert values
3530 * insert fkey/pkey index
3531 */
3532 if (k->type == pkey || k->type == ukey) {
3533 return insert_check_ukey(be, inserts, k, idx_inserts );
3534 } else { /* foreign keys */
3535 return insert_check_fkey(be, inserts, k, idx_inserts, pin );
3536 }
3537}
3538
3539static int
3540sql_stack_add_inserted( mvc *sql, const char *name, sql_table *t, stmt **updates)
3541{
3542 /* Put single relation of updates and old values on to the stack */
3543 sql_rel *r = NULL;
3544 node *n;
3545 list *exps = sa_list(sql->sa);
3546 trigger_input *ti = SA_NEW(sql->sa, trigger_input);
3547
3548 ti->t = t;
3549 ti->tids = NULL;
3550 ti->updates = updates;
3551 ti->type = 1;
3552 ti->nn = name;
3553 for (n = t->columns.set->h; n; n = n->next) {
3554 sql_column *c = n->data;
3555 sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, 0);
3556
3557 append(exps, ne);
3558 }
3559 r = rel_table_func(sql->sa, NULL, NULL, exps, 2);
3560 r->l = ti;
3561
3562 return stack_push_rel_view(sql, name, r) ? 1 : 0;
3563}
3564
3565static int
3566sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
3567{
3568 mvc *sql = be->mvc;
3569 node *n;
3570 int res = 1;
3571
3572 if (!t->triggers.set)
3573 return res;
3574
3575 for (n = t->triggers.set->h; n; n = n->next) {
3576 sql_trigger *trigger = n->data;
3577
3578 if(!stack_push_frame(sql, "OLD-NEW"))
3579 return 0;
3580 if (trigger->event == 0 && trigger->time == time) {
3581 const char *n = trigger->new_name;
3582
3583 /* add name for the 'inserted' to the stack */
3584 if (!n) n = "new";
3585
3586 if(!sql_stack_add_inserted(sql, n, t, updates)) {
3587 stack_pop_frame(sql);
3588 return 0;
3589 }
3590 if (!sql_parse(be, sql->sa, trigger->statement, m_instantiate)) {
3591 stack_pop_frame(sql);
3592 return 0;
3593 }
3594 }
3595 stack_pop_frame(sql);
3596 }
3597 return res;
3598}
3599
3600static void
3601sql_insert_check_null(backend *be, sql_table *t, list *inserts)
3602{
3603 mvc *sql = be->mvc;
3604 node *m, *n;
3605 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
3606
3607 for (n = t->columns.set->h, m = inserts->h; n && m;
3608 n = n->next, m = m->next) {
3609 stmt *i = m->data;
3610 sql_column *c = n->data;
3611
3612 if (!c->null) {
3613 stmt *s = i;
3614 char *msg = NULL;
3615
3616 if (!(s->key && s->nrcols == 0)) {
3617 s = stmt_selectnil(be, i);
3618 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
3619 } else {
3620 sql_subfunc *isnil = sql_bind_func(sql->sa, sql->session->schema, "isnull", &c->type, NULL, F_FUNC);
3621
3622 s = stmt_unop(be, i, isnil);
3623 }
3624 msg = sa_message(sql->sa, "INSERT INTO: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
3625 (void)stmt_exception(be, s, msg, 00001);
3626 }
3627 }
3628}
3629
3630static stmt **
3631table_update_stmts(mvc *sql, sql_table *t, int *Len)
3632{
3633 *Len = list_length(t->columns.set);
3634 return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
3635}
3636
3637static stmt *
3638rel2bin_insert(backend *be, sql_rel *rel, list *refs)
3639{
3640 mvc *sql = be->mvc;
3641 list *l;
3642 stmt *inserts = NULL, *insert = NULL, *s, *ddl = NULL, *pin = NULL, **updates, *ret = NULL;
3643 int idx_ins = 0, constraint = 1, len = 0;
3644 node *n, *m;
3645 sql_rel *tr = rel->l, *prel = rel->r;
3646 sql_table *t = NULL;
3647
3648 if ((rel->flag&UPD_NO_CONSTRAINT))
3649 constraint = 0;
3650 if ((rel->flag&UPD_COMP)) { /* special case ! */
3651 idx_ins = 1;
3652 prel = rel->l;
3653 rel = rel->r;
3654 tr = rel->l;
3655 }
3656
3657 if (tr->op == op_basetable) {
3658 t = tr->l;
3659 } else {
3660 ddl = subrel_bin(be, tr, refs);
3661 if (!ddl)
3662 return NULL;
3663 t = rel_ddl_table_get(tr);
3664 }
3665
3666 if (rel->r) /* first construct the inserts relation */
3667 inserts = subrel_bin(be, rel->r, refs);
3668
3669 if (!inserts)
3670 return NULL;
3671
3672 if (idx_ins)
3673 pin = refs_find_rel(refs, prel);
3674
3675 if (constraint && !be->first_statement_generated)
3676 sql_insert_check_null(be, (be->cur_append && t->p) ? t->p : t, inserts->op4.lval);
3677
3678 l = sa_list(sql->sa);
3679
3680 updates = table_update_stmts(sql, t, &len);
3681 for (n = t->columns.set->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
3682 sql_column *c = n->data;
3683
3684 updates[c->colnr] = m->data;
3685 }
3686
3687/* before */
3688 if (be->cur_append && !be->first_statement_generated) {
3689 for(sql_table *up = t->p ; up ; up = up->p) {
3690 if (!sql_insert_triggers(be, up, updates, 0))
3691 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", up->base.name);
3692 }
3693 }
3694 if (!sql_insert_triggers(be, t, updates, 0))
3695 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
3696
3697 if (t->idxs.set)
3698 for (n = t->idxs.set->h; n && m; n = n->next, m = m->next) {
3699 stmt *is = m->data;
3700 sql_idx *i = n->data;
3701
3702 if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
3703 continue;
3704 if (hash_index(i->type) && list_length(i->columns) <= 1)
3705 is = NULL;
3706 if (i->key && constraint) {
3707 stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
3708
3709 list_append(l, ckeys);
3710 }
3711 if (!insert)
3712 insert = is;
3713 if (is)
3714 is = stmt_append_idx(be, i, is);
3715 }
3716
3717 for (n = t->columns.set->h, m = inserts->op4.lval->h;
3718 n && m; n = n->next, m = m->next) {
3719
3720 stmt *ins = m->data;
3721 sql_column *c = n->data;
3722
3723 insert = stmt_append_col(be, c, ins, rel->flag&UPD_LOCKED);
3724 append(l,insert);
3725 }
3726 if (!insert)
3727 return NULL;
3728
3729 if (be->cur_append && !be->first_statement_generated) {
3730 for(sql_table *up = t->p ; up ; up = up->p) {
3731 if (!sql_insert_triggers(be, up, updates, 1))
3732 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", up->base.name);
3733 }
3734 }
3735 if (!sql_insert_triggers(be, t, updates, 1))
3736 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
3737 if (ddl) {
3738 ret = ddl;
3739 list_prepend(l, ddl);
3740 } else {
3741 if (insert->op1->nrcols == 0) {
3742 s = stmt_atom_lng(be, 1);
3743 } else {
3744 s = stmt_aggr(be, insert->op1, NULL, NULL, sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL), 1, 0, 1);
3745 }
3746 ret = s;
3747 }
3748
3749 if (be->cur_append) //building the total number of rows affected across all tables
3750 ret->nr = add_to_merge_partitions_accumulator(be, ret->nr);
3751
3752 if (ddl)
3753 return stmt_list(be, l);
3754 else
3755 return ret;
3756}
3757
3758static int
3759is_idx_updated(sql_idx * i, stmt **updates)
3760{
3761 int update = 0;
3762 node *m;
3763
3764 for (m = i->columns->h; m; m = m->next) {
3765 sql_kc *ic = m->data;
3766
3767 if (updates[ic->c->colnr]) {
3768 update = 1;
3769 break;
3770 }
3771 }
3772 return update;
3773}
3774
3775static int
3776first_updated_col(stmt **updates, int cnt)
3777{
3778 int i;
3779
3780 for (i = 0; i < cnt; i++) {
3781 if (updates[i])
3782 return i;
3783 }
3784 return -1;
3785}
3786
3787static stmt *
3788update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol)
3789{
3790 mvc *sql = be->mvc;
3791 char *msg = NULL;
3792 stmt *res = NULL;
3793
3794 sql_subtype *lng = sql_bind_localtype("lng");
3795 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
3796 sql_subtype *bt = sql_bind_localtype("bit");
3797 sql_subfunc *ne;
3798
3799 (void)tids;
3800 ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
3801 if (list_length(k->columns) > 1) {
3802 stmt *dels = stmt_tid(be, k->t, 0);
3803 node *m;
3804 stmt *s = NULL;
3805
3806 /* 1st stage: find out if original (without the updated)
3807 do not contain the same values as the updated values.
3808 This is done using a relation join and a count (which
3809 should be zero)
3810 */
3811 if (!isNew(k)) {
3812 stmt *nu_tids = stmt_tdiff(be, dels, tids); /* not updated ids */
3813 list *lje = sa_list(sql->sa);
3814 list *rje = sa_list(sql->sa);
3815
3816 if (k->idx && hash_index(k->idx->type)) {
3817 list_append(lje, stmt_idx(be, k->idx, nu_tids));
3818 list_append(rje, idx_updates);
3819 }
3820 for (m = k->columns->h; m; m = m->next) {
3821 sql_kc *c = m->data;
3822 stmt *upd;
3823
3824 assert(updates);
3825 if (updates[c->c->colnr]) {
3826 upd = updates[c->c->colnr];
3827 } else {
3828 upd = stmt_project(be, tids, stmt_col(be, c->c, dels));
3829 }
3830 list_append(lje, stmt_col(be, c->c, nu_tids));
3831 list_append(rje, upd);
3832 }
3833 s = releqjoin(be, lje, rje, 1 /* hash used */, cmp_equal, 0);
3834 s = stmt_result(be, s, 0);
3835 s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), ne);
3836 }
3837
3838 /* 2e stage: find out if the updated are unique */
3839 if (!updates || updates[updcol]->nrcols) { /* update columns not atoms */
3840 sql_subaggr *sum;
3841 stmt *count_sum = NULL, *ssum;
3842 stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
3843 stmt *cand = NULL;
3844 stmt *ss;
3845 sql_subfunc *or = sql_bind_func_result(sql->sa, sql->session->schema, "or", bt, bt, bt);
3846
3847 /* also take the hopefully unique hash keys, to reduce
3848 (re)group costs */
3849 if (k->idx && hash_index(k->idx->type)) {
3850 g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
3851 grp = stmt_result(be, g, 0);
3852 ext = stmt_result(be, g, 1);
3853 Cnt = stmt_result(be, g, 2);
3854
3855 /* continue only with groups with a cnt > 1 */
3856 cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0);
3857 /* project cand on ext and Cnt */
3858 Cnt = stmt_project(be, cand, Cnt);
3859 ext = stmt_project(be, cand, ext);
3860
3861 /* join groups with extend to retrieve all oid's of the original
3862 * bat that belong to a group with Cnt >1 */
3863 g = stmt_join(be, grp, ext, 0, cmp_equal);
3864 cand = stmt_result(be, g, 0);
3865 grp = stmt_project(be, cand, grp);
3866 }
3867
3868 for (m = k->columns->h; m; m = m->next) {
3869 sql_kc *c = m->data;
3870 stmt *upd;
3871
3872 if (updates && updates[c->c->colnr]) {
3873 upd = updates[c->c->colnr];
3874 /*
3875 } else if (updates) {
3876 //assert(0);
3877 //upd = updates[updcol]->op1;
3878 //upd = stmt_project(be, upd, stmt_col(be, c->c, dels));
3879 upd = stmt_project(be, tids, stmt_col(be, c->c, dels));
3880 */
3881 } else {
3882 upd = stmt_project(be, tids, stmt_col(be, c->c, dels));
3883 }
3884
3885 /* apply cand list first */
3886 if (cand)
3887 upd = stmt_project(be, cand, upd);
3888
3889 /* remove nulls */
3890 if ((k->type == ukey) && stmt_has_null(upd)) {
3891 stmt *nn = stmt_selectnonil(be, upd, NULL);
3892 upd = stmt_project(be, nn, upd);
3893 if (grp)
3894 grp = stmt_project(be, nn, grp);
3895 if (cand)
3896 cand = stmt_project(be, nn, cand);
3897 }
3898
3899 /* apply group by on groups with Cnt > 1 */
3900 g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
3901 grp = stmt_result(be, g, 0);
3902 ext = stmt_result(be, g, 1);
3903 Cnt = stmt_result(be, g, 2);
3904 }
3905 ss = Cnt; /* use count */
3906 /* (count(ss) <> sum(ss)) */
3907 sum = sql_bind_aggr(sql->sa, sql->session->schema, "sum", lng);
3908 ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
3909 ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, NULL, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
3910 count_sum = stmt_binop(be, stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), check_types(be, lng, ssum, type_equal), ne);
3911
3912 /* combine results */
3913 if (s)
3914 s = stmt_binop(be, s, count_sum, or);
3915 else
3916 s = count_sum;
3917 }
3918
3919 if (k->type == pkey) {
3920 msg = sa_message(sql->sa, "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
3921 } else {
3922 msg = sa_message(sql->sa, "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
3923 }
3924 res = stmt_exception(be, s, msg, 00001);
3925 } else { /* single column key */
3926 stmt *dels = stmt_tid(be, k->t, 0);
3927 sql_kc *c = k->columns->h->data;
3928 stmt *s = NULL, *h = NULL, *o;
3929
3930 /* s should be empty */
3931 if (!isNew(k)) {
3932 stmt *nu_tids = stmt_tdiff(be, dels, tids); /* not updated ids */
3933 assert (updates);
3934
3935 h = updates[c->c->colnr];
3936 o = stmt_col(be, c->c, nu_tids);
3937 s = stmt_join(be, o, h, 0, cmp_equal);
3938 s = stmt_result(be, s, 0);
3939 s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), ne);
3940 }
3941
3942 /* 2e stage: find out if updated are unique */
3943 if (!h || h->nrcols) { /* update columns not atoms */
3944 sql_subaggr *sum;
3945 stmt *count_sum = NULL;
3946 sql_subfunc *or = sql_bind_func_result(sql->sa, sql->session->schema, "or", bt, bt, bt);
3947 stmt *ssum, *ss;
3948 stmt *upd;
3949 stmt *g;
3950
3951 if (updates) {
3952 upd = updates[c->c->colnr];
3953 } else {
3954 upd = stmt_col(be, c->c, dels);
3955 }
3956
3957 /* remove nulls */
3958 if ((k->type == ukey) && stmt_has_null(upd)) {
3959 stmt *nn = stmt_selectnonil(be, upd, NULL);
3960 upd = stmt_project(be, nn, upd);
3961 }
3962
3963 g = stmt_group(be, upd, NULL, NULL, NULL, 1);
3964 ss = stmt_result(be, g, 2); /* use count */
3965
3966 /* (count(ss) <> sum(ss)) */
3967 sum = sql_bind_aggr(sql->sa, sql->session->schema, "sum", lng);
3968 ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
3969 ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, NULL, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
3970 count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, ne);
3971
3972 /* combine results */
3973 if (s)
3974 s = stmt_binop(be, s, count_sum, or);
3975 else
3976 s = count_sum;
3977 }
3978
3979 if (k->type == pkey) {
3980 msg = sa_message(sql->sa, "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
3981 } else {
3982 msg = sa_message(sql->sa, "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
3983 }
3984 res = stmt_exception(be, s, msg, 00001);
3985 }
3986 return res;
3987}
3988
3989/*
3990 A referential constraint is satisfied if one of the following con-
3991 ditions is true, depending on the <match option> specified in the
3992 <referential constraint definition>:
3993
3994 - If no <match type> was specified then, for each row R1 of the
3995 referencing table, either at least one of the values of the
3996 referencing columns in R1 shall be a null value, or the value of
3997 each referencing column in R1 shall be equal to the value of the
3998 corresponding referenced column in some row of the referenced
3999 table.
4000
4001 - If MATCH FULL was specified then, for each row R1 of the refer-
4002 encing table, either the value of every referencing column in R1
4003 shall be a null value, or the value of every referencing column
4004 in R1 shall not be null and there shall be some row R2 of the
4005 referenced table such that the value of each referencing col-
4006 umn in R1 is equal to the value of the corresponding referenced
4007 column in R2.
4008
4009 - If MATCH PARTIAL was specified then, for each row R1 of the
4010 referencing table, there shall be some row R2 of the refer-
4011 enced table such that the value of each referencing column in
4012 R1 is either null or is equal to the value of the corresponding
4013 referenced column in R2.
4014*/
4015
4016static stmt *
4017update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
4018{
4019 mvc *sql = be->mvc;
4020 char *msg = NULL;
4021 stmt *s, *cur, *null = NULL, *cntnulls;
4022 sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
4023 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
4024 sql_subfunc *ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
4025 sql_subfunc *or = sql_bind_func_result(sql->sa, sql->session->schema, "or", bt, bt, bt);
4026 node *m;
4027
4028 if (!idx_updates)
4029 return NULL;
4030 /* releqjoin.count <> updates[updcol].count */
4031 if (pup && list_length(pup->op4.lval)) {
4032 cur = pup->op4.lval->h->data;
4033 } else if (updates) {
4034 cur = updates[updcol];
4035 } else {
4036 sql_kc *c = k->columns->h->data;
4037 stmt *dels = stmt_tid(be, k->t, 0);
4038 assert(0);
4039 cur = stmt_col(be, c->c, dels);
4040 }
4041 s = stmt_binop(be, stmt_aggr(be, idx_updates, NULL, NULL, cnt, 1, 0, 1), stmt_aggr(be, cur, NULL, NULL, cnt, 1, 0, 1), ne);
4042
4043 for (m = k->columns->h; m; m = m->next) {
4044 sql_kc *c = m->data;
4045
4046 /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
4047 /* Currently only the default MATCH SIMPLE is supported */
4048 if (c->c->null) {
4049 stmt *upd, *nn;
4050
4051 if (updates && updates[c->c->colnr]) {
4052 upd = updates[c->c->colnr];
4053 } else if (updates && updcol >= 0) {
4054 assert(0);
4055 //upd = updates[updcol]->op1;
4056 //upd = stmt_project(be, upd, stmt_col(be, c->c, tids));
4057 upd = stmt_col(be, c->c, tids);
4058 } else { /* created idx/key using alter */
4059 upd = stmt_col(be, c->c, tids);
4060 }
4061 nn = stmt_selectnil(be, upd);
4062 if (null)
4063 null = stmt_tunion(be, null, nn);
4064 else
4065 null = nn;
4066 }
4067 }
4068 if (null) {
4069 cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
4070 } else {
4071 cntnulls = stmt_atom_lng(be, 0);
4072 }
4073 s = stmt_binop(be, s,
4074 stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls , ne), or);
4075
4076 /* s should be empty */
4077 msg = sa_message(sql->sa, "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
4078 return stmt_exception(be, s, msg, 00001);
4079}
4080
4081static stmt *
4082join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
4083{
4084 mvc *sql = be->mvc;
4085 char *msg = NULL;
4086 int nulls = 0;
4087 node *m, *o;
4088 sql_key *rk = &((sql_fkey*)k)->rkey->k;
4089 stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
4090 stmt *null = NULL, *rows;
4091 sql_subtype *lng = sql_bind_localtype("lng");
4092 sql_subtype *bt = sql_bind_localtype("bit");
4093 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
4094 sql_subfunc *ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
4095 list *lje = sa_list(sql->sa);
4096 list *rje = sa_list(sql->sa);
4097
4098 fdels = stmt_tid(be, k->idx->t, 0);
4099 rows = stmt_idx(be, k->idx, fdels);
4100
4101 rows = stmt_join(be, rows, tids, 0, cmp_equal); /* join over the join index */
4102 rows = stmt_result(be, rows, 0);
4103
4104 for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
4105 sql_kc *fc = m->data;
4106 sql_kc *c = o->data;
4107 stmt *upd, *col;
4108
4109 if (updates[c->c->colnr]) {
4110 upd = updates[c->c->colnr];
4111 } else {
4112 assert(0);
4113 //upd = updates[updcol]->op1;
4114 upd = stmt_project(be, tids, stmt_col(be, c->c, dels));
4115 }
4116 if (c->c->null) { /* new nulls (MATCH SIMPLE) */
4117 stmt *nn = stmt_selectnil(be, upd);
4118 if (null)
4119 null = stmt_tunion(be, null, nn);
4120 else
4121 null = nn;
4122 nulls = 1;
4123 }
4124 col = stmt_col(be, fc->c, rows);
4125 list_append(lje, upd);
4126 list_append(rje, col);
4127 }
4128 s = releqjoin(be, lje, rje, 1 /* hash used */, cmp_equal, 0);
4129 s = stmt_result(be, s, 0);
4130
4131 /* add missing nulls */
4132 cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
4133 if (nulls) {
4134 sql_subfunc *add = sql_bind_func_result(sql->sa, sql->session->schema, "sql_add", lng, lng, lng);
4135 cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), add);
4136 }
4137
4138 /* releqjoin.count <> updates[updcol].count */
4139 s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), ne);
4140
4141 /* s should be empty */
4142 msg = sa_message(sql->sa, "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
4143 return stmt_exception(be, s, msg, 00001);
4144}
4145
4146static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
4147
4148static stmt*
4149sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
4150{
4151 mvc *sql = be->mvc;
4152 list *l = NULL;
4153 int len = 0;
4154 node *m, *o;
4155 sql_key *rk = &((sql_fkey*)k)->rkey->k;
4156 stmt **new_updates;
4157 sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
4158
4159 new_updates = table_update_stmts(sql, t, &len);
4160 for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
4161 sql_kc *fc = m->data;
4162 stmt *upd = NULL;
4163
4164 if (action == ACT_SET_DEFAULT) {
4165 if (fc->c->def) {
4166 stmt *sq;
4167 char *msg, *typestr = subtype2string2(&fc->c->type);
4168 if(!typestr)
4169 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
4170 msg = sa_message(sql->sa, "select cast(%s as %s);", fc->c->def, typestr);
4171 _DELETE(typestr);
4172 sq = rel_parse_value(be, msg, sql->emode);
4173 if (!sq)
4174 return NULL;
4175 upd = sq;
4176 } else {
4177 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
4178 }
4179 } else {
4180 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
4181 }
4182
4183 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
4184 return NULL;
4185
4186 if (upd->nrcols <= 0)
4187 upd = stmt_const(be, ftids, upd);
4188
4189 new_updates[fc->c->colnr] = upd;
4190 }
4191 if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
4192 return NULL;
4193 return stmt_list(be, l);
4194}
4195
4196static stmt*
4197sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
4198{
4199 mvc *sql = be->mvc;
4200 list *l = NULL;
4201 int len = 0;
4202 node *m, *o;
4203 sql_key *rk = &((sql_fkey*)k)->rkey->k;
4204 stmt **new_updates;
4205 stmt *rows;
4206 sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
4207 stmt *ftids, *upd_ids;
4208
4209 ftids = stmt_tid(be, k->idx->t, 0);
4210 rows = stmt_idx(be, k->idx, ftids);
4211
4212 rows = stmt_join(be, rows, utids, 0, cmp_equal); /* join over the join index */
4213 upd_ids = stmt_result(be, rows, 1);
4214 rows = stmt_result(be, rows, 0);
4215 rows = stmt_project(be, rows, ftids);
4216
4217 new_updates = table_update_stmts(sql, t, &len);
4218 for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
4219 sql_kc *fc = m->data;
4220 sql_kc *c = o->data;
4221 stmt *upd = NULL;
4222
4223 if (!updates[c->c->colnr]) {
4224 continue;
4225 } else if (action == ACT_CASCADE) {
4226 upd = updates[c->c->colnr];
4227 } else if (action == ACT_SET_DEFAULT) {
4228 if (fc->c->def) {
4229 stmt *sq;
4230 char *msg, *typestr = subtype2string2(&fc->c->type);
4231 if(!typestr)
4232 return sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
4233 msg = sa_message(sql->sa, "select cast(%s as %s);", fc->c->def, typestr);
4234 _DELETE(typestr);
4235 sq = rel_parse_value(be, msg, sql->emode);
4236 if (!sq)
4237 return NULL;
4238 upd = sq;
4239 } else {
4240 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
4241 }
4242 } else if (action == ACT_SET_NULL) {
4243 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
4244 }
4245
4246 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
4247 return NULL;
4248
4249 if (upd->nrcols <= 0)
4250 upd = stmt_const(be, upd_ids, upd);
4251 else
4252 upd = stmt_project(be, upd_ids, upd);
4253
4254 new_updates[fc->c->colnr] = upd;
4255 }
4256
4257 if ((l = sql_update(be, t, rows, new_updates)) == NULL)
4258 return NULL;
4259 return stmt_list(be, l);
4260}
4261
4262
4263static int
4264cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
4265{
4266 sql_ukey *uk = (sql_ukey*)k;
4267
4268 if (uk->keys && list_length(uk->keys) > 0) {
4269 node *n;
4270 for(n = uk->keys->h; n; n = n->next) {
4271 sql_key *fk = n->data;
4272
4273 /* All rows of the foreign key table which are
4274 affected by the primary key update should all
4275 match one of the updated primary keys again.
4276 */
4277 switch (((sql_fkey*)fk)->on_update) {
4278 case ACT_NO_ACTION:
4279 break;
4280 case ACT_SET_NULL:
4281 case ACT_SET_DEFAULT:
4282 case ACT_CASCADE:
4283 if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update))
4284 return -1;
4285 break;
4286 default: /*RESTRICT*/
4287 if (!join_updated_pkey(be, fk, tids, updates))
4288 return -1;
4289 }
4290 }
4291 }
4292 return 0;
4293}
4294
4295static void
4296sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
4297{
4298 stmt *ckeys;
4299
4300 if (k->type == pkey || k->type == ukey) {
4301 ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
4302 } else { /* foreign keys */
4303 ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
4304 }
4305 list_append(l, ckeys);
4306}
4307
4308static stmt *
4309hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
4310{
4311 mvc *sql = be->mvc;
4312 /* calculate new value */
4313 node *m;
4314 sql_subtype *it, *lng;
4315 int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
4316 stmt *h = NULL, *tids;
4317
4318 if (list_length(i->columns) <= 1)
4319 return NULL;
4320
4321 tids = stmt_tid(be, i->t, 0);
4322 it = sql_bind_localtype("int");
4323 lng = sql_bind_localtype("lng");
4324 for (m = i->columns->h; m; m = m->next ) {
4325 sql_kc *c = m->data;
4326 stmt *upd;
4327
4328 if (updates && updates[c->c->colnr]) {
4329 upd = updates[c->c->colnr];
4330 } else if (updates && updcol >= 0) {
4331 assert(0);
4332 //upd = updates[updcol]->op1;
4333 //upd = rows;
4334 //upd = stmt_project(be, upd, stmt_col(be, c->c, tids));
4335 upd = stmt_col(be, c->c, rows);
4336 } else { /* created idx/key using alter */
4337 upd = stmt_col(be, c->c, tids);
4338 }
4339
4340 if (h && i->type == hash_idx) {
4341 sql_subfunc *xor = sql_bind_func_result3(sql->sa, sql->session->schema, "rotate_xor_hash", lng, it, &c->c->type, lng);
4342
4343 h = stmt_Nop(be, stmt_list( be, list_append( list_append(
4344 list_append(sa_list(sql->sa), h),
4345 stmt_atom_int(be, bits)), upd)),
4346 xor);
4347 } else if (h) {
4348 stmt *h2;
4349 sql_subfunc *lsh = sql_bind_func_result(sql->sa, sql->session->schema, "left_shift", lng, it, lng);
4350 sql_subfunc *lor = sql_bind_func_result(sql->sa, sql->session->schema, "bit_or", lng, lng, lng);
4351 sql_subfunc *hf = sql_bind_func_result(sql->sa, sql->session->schema, "hash", &c->c->type, NULL, lng);
4352
4353 h = stmt_binop(be, h, stmt_atom_int(be, bits), lsh);
4354 h2 = stmt_unop(be, upd, hf);
4355 h = stmt_binop(be, h, h2, lor);
4356 } else {
4357 sql_subfunc *hf = sql_bind_func_result(sql->sa, sql->session->schema, "hash", &c->c->type, NULL, lng);
4358 h = stmt_unop(be, upd, hf);
4359 if (i->type == oph_idx)
4360 break;
4361 }
4362 }
4363 return h;
4364}
4365
4366static stmt *
4367join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
4368{
4369 mvc *sql = be->mvc;
4370 node *m, *o;
4371 sql_key *rk = &((sql_fkey *) i->key)->rkey->k;
4372 stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
4373 list *lje = sa_list(sql->sa);
4374 list *rje = sa_list(sql->sa);
4375
4376 for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
4377 sql_kc *c = m->data;
4378 sql_kc *rc = o->data;
4379 stmt *upd;
4380
4381 if (updates && updates[c->c->colnr]) {
4382 upd = updates[c->c->colnr];
4383 } else if (updates && updcol >= 0) {
4384 assert(0);
4385 //upd = updates[updcol]->op1;
4386 //upd = stmt_project(be, upd, stmt_col(be, c->c, ftids));
4387 upd = stmt_col(be, c->c, ftids);
4388 } else { /* created idx/key using alter */
4389 upd = stmt_col(be, c->c, ftids);
4390 }
4391
4392 list_append(lje, check_types(be, &rc->c->type, upd, type_equal));
4393 list_append(rje, stmt_col(be, rc->c, ptids));
4394 }
4395 s = releqjoin(be, lje, rje, 0 /* use hash */, cmp_equal, 0);
4396 l = stmt_result(be, s, 0);
4397 r = stmt_result(be, s, 1);
4398 r = stmt_project(be, r, ptids);
4399 return stmt_left_project(be, ftids, l, r);
4400}
4401
4402static int
4403cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
4404{
4405 mvc *sql = be->mvc;
4406 node *n;
4407
4408 if (!t->idxs.set)
4409 return 0;
4410
4411 for (n = t->idxs.set->h; n; n = n->next) {
4412 sql_idx *i = n->data;
4413
4414 /* check if update is needed,
4415 * ie atleast on of the idx columns is updated
4416 */
4417 if (is_idx_updated(i, updates) == 0)
4418 continue;
4419
4420 if (i->key) {
4421 if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
4422 sql_key *k = i->key;
4423 int *local_id = SA_NEW(sql->sa, int);
4424 if (!sql->cascade_action)
4425 sql->cascade_action = sa_list(sql->sa);
4426 *local_id = i->key->base.id;
4427 list_append(sql->cascade_action, local_id);
4428 if (k->type == pkey || k->type == ukey) {
4429 if (cascade_ukey(be, updates, k, rows))
4430 return -1;
4431 }
4432 }
4433 }
4434 }
4435 return 0;
4436}
4437
4438static list *
4439update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
4440{
4441 mvc *sql = be->mvc;
4442 node *n;
4443 int updcol;
4444 list *idx_updates = sa_list(sql->sa);
4445
4446 if (!t->idxs.set)
4447 return idx_updates;
4448
4449 updcol = first_updated_col(updates, list_length(t->columns.set));
4450 for (n = t->idxs.set->h; n; n = n->next) {
4451 sql_idx *i = n->data;
4452 stmt *is = NULL;
4453
4454 /* check if update is needed,
4455 * ie atleast on of the idx columns is updated
4456 */
4457 if (is_idx_updated(i, updates) == 0)
4458 continue;
4459
4460 if (hash_index(i->type)) {
4461 is = hash_update(be, i, rows, updates, updcol);
4462 } else if (i->type == join_idx) {
4463 if (updcol < 0)
4464 return NULL;
4465 is = join_idx_update(be, i, rows, updates, updcol);
4466 }
4467 if (i->key)
4468 sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
4469 if (is)
4470 list_append(idx_updates, stmt_update_idx(be, i, rows, is));
4471 }
4472 return idx_updates;
4473}
4474
4475static int
4476sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
4477{
4478 /* Put single relation of updates and old values on to the stack */
4479 sql_rel *r = NULL;
4480 node *n;
4481 list *exps = sa_list(sql->sa);
4482 trigger_input *ti = SA_NEW(sql->sa, trigger_input);
4483
4484 ti->t = t;
4485 ti->tids = tids;
4486 ti->updates = updates;
4487 ti->type = 2;
4488 ti->on = on;
4489 ti->nn = nn;
4490 for (n = t->columns.set->h; n; n = n->next) {
4491 sql_column *c = n->data;
4492
4493 if (updates[c->colnr]) {
4494 sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, 0);
4495 sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, 0);
4496
4497 append(exps, oe);
4498 append(exps, ne);
4499 } else {
4500 sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, 0);
4501 sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, 0);
4502
4503 append(exps, oe);
4504 append(exps, ne);
4505 }
4506 }
4507 r = rel_table_func(sql->sa, NULL, NULL, exps, 2);
4508 r->l = ti;
4509
4510 /* put single table into the stack with 2 names, needed for the psm code */
4511 if(!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
4512 return 0;
4513 return 1;
4514}
4515
4516static int
4517sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time )
4518{
4519 mvc *sql = be->mvc;
4520 node *n;
4521 int res = 1;
4522
4523 if (!t->triggers.set)
4524 return res;
4525
4526 for (n = t->triggers.set->h; n; n = n->next) {
4527 sql_trigger *trigger = n->data;
4528
4529 if(!stack_push_frame(sql, "OLD-NEW"))
4530 return 0;
4531 if (trigger->event == 2 && trigger->time == time) {
4532 /* add name for the 'inserted' to the stack */
4533 const char *n = trigger->new_name;
4534 const char *o = trigger->old_name;
4535
4536 if (!n) n = "new";
4537 if (!o) o = "old";
4538
4539 if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
4540 stack_pop_frame(sql);
4541 return 0;
4542 }
4543
4544 if (!sql_parse(be, sql->sa, trigger->statement, m_instantiate)) {
4545 stack_pop_frame(sql);
4546 return 0;
4547 }
4548 }
4549 stack_pop_frame(sql);
4550 }
4551 return res;
4552}
4553
4554static void
4555sql_update_check_null(backend *be, sql_table *t, stmt **updates)
4556{
4557 mvc *sql = be->mvc;
4558 node *n;
4559 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
4560
4561 for (n = t->columns.set->h; n; n = n->next) {
4562 sql_column *c = n->data;
4563
4564 if (updates[c->colnr] && !c->null) {
4565 stmt *s = updates[c->colnr];
4566 char *msg = NULL;
4567
4568 if (!(s->key && s->nrcols == 0)) {
4569 s = stmt_selectnil(be, updates[c->colnr]);
4570 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
4571 } else {
4572 sql_subfunc *isnil = sql_bind_func(sql->sa, sql->session->schema, "isnull", &c->type, NULL, F_FUNC);
4573
4574 s = stmt_unop(be, updates[c->colnr], isnil);
4575 }
4576 msg = sa_message(sql->sa, "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
4577 (void)stmt_exception(be, s, msg, 00001);
4578 }
4579 }
4580}
4581
4582/* updates: an array of table width, per column holds the values for the to be updated rows */
4583static list *
4584sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
4585{
4586 mvc *sql = be->mvc;
4587 list *idx_updates = NULL;
4588 int i, nr_cols = list_length(t->columns.set);
4589 list *l = sa_list(sql->sa);
4590 node *n;
4591
4592 if (!be->first_statement_generated)
4593 sql_update_check_null(be, (be->cur_append && t->p) ? t->p : t, updates);
4594
4595 /* check keys + get idx */
4596 idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
4597 if (!idx_updates) {
4598 assert(0);
4599 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
4600 }
4601
4602/* before */
4603 if (be->cur_append && !be->first_statement_generated) {
4604 for(sql_table *up = t->p ; up ; up = up->p) {
4605 if (!sql_update_triggers(be, up, rows, updates, 0))
4606 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", up->base.name);
4607 }
4608 }
4609 if (!sql_update_triggers(be, t, rows, updates, 0))
4610 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
4611
4612/* apply updates */
4613 for (i = 0, n = t->columns.set->h; i < nr_cols && n; i++, n = n->next) {
4614 sql_column *c = n->data;
4615
4616 if (updates[i])
4617 append(l, stmt_update_col(be, c, rows, updates[i]));
4618 }
4619 if (cascade_updates(be, t, rows, updates))
4620 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
4621
4622/* after */
4623 if (be->cur_append && !be->first_statement_generated) {
4624 for(sql_table *up = t->p ; up ; up = up->p) {
4625 if (!sql_update_triggers(be, up, rows, updates, 1))
4626 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", up->base.name);
4627 }
4628 }
4629 if (!sql_update_triggers(be, t, rows, updates, 1))
4630 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
4631
4632/* cascade ?? */
4633 return l;
4634}
4635
4636/* updates with empty list is alter with create idx or keys */
4637static stmt *
4638rel2bin_update(backend *be, sql_rel *rel, list *refs)
4639{
4640 mvc *sql = be->mvc;
4641 stmt *update = NULL, **updates = NULL, *tids, *s, *ddl = NULL, *pup = NULL, *cnt;
4642 list *l = sa_list(sql->sa);
4643 int nr_cols, updcol, idx_ups = 0;
4644 node *m;
4645 sql_rel *tr = rel->l, *prel = rel->r;
4646 sql_table *t = NULL;
4647
4648 if ((rel->flag&UPD_COMP)) { /* special case ! */
4649 idx_ups = 1;
4650 prel = rel->l;
4651 rel = rel->r;
4652 tr = rel->l;
4653 }
4654 if (tr->op == op_basetable) {
4655 t = tr->l;
4656 } else {
4657 ddl = subrel_bin(be, tr, refs);
4658 if (!ddl)
4659 return NULL;
4660 t = rel_ddl_table_get(tr);
4661
4662 /* no columns to update (probably an new pkey!) */
4663 if (!rel->exps)
4664 return ddl;
4665 }
4666
4667 if (rel->r) /* first construct the update relation */
4668 update = subrel_bin(be, rel->r, refs);
4669
4670 if (!update)
4671 return NULL;
4672
4673 if (idx_ups)
4674 pup = refs_find_rel(refs, prel);
4675
4676 updates = table_update_stmts(sql, t, &nr_cols);
4677 tids = update->op4.lval->h->data;
4678
4679 /* lookup the updates */
4680 for (m = rel->exps->h; m; m = m->next) {
4681 sql_exp *ce = m->data;
4682 sql_column *c = find_sql_column(t, exp_name(ce));
4683
4684 if (c)
4685 updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
4686 }
4687 if (!be->first_statement_generated)
4688 sql_update_check_null(be, (be->cur_append && t->p) ? t->p : t, updates);
4689
4690 /* check keys + get idx */
4691 updcol = first_updated_col(updates, list_length(t->columns.set));
4692 for (m = rel->exps->h; m; m = m->next) {
4693 sql_exp *ce = m->data;
4694 sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
4695 stmt *update_idx, *is = NULL;
4696
4697 if (i) {
4698 if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
4699 continue;
4700
4701 update_idx = bin_find_column(be, update, ce->l, ce->r);
4702 if (update_idx)
4703 is = update_idx;
4704 if (hash_index(i->type) && list_length(i->columns) <= 1) {
4705 is = NULL;
4706 update_idx = NULL;
4707 }
4708 if (i->key)
4709 sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
4710 if (is)
4711 list_append(l, stmt_update_idx(be, i, tids, is));
4712 }
4713 }
4714
4715/* before */
4716 if (be->cur_append && !be->first_statement_generated) {
4717 for(sql_table *up = t->p ; up ; up = up->p) {
4718 if (!sql_update_triggers(be, up, tids, updates, 0))
4719 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", up->base.name);
4720 }
4721 }
4722 if (!sql_update_triggers(be, t, tids, updates, 0))
4723 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
4724
4725/* apply the update */
4726 for (m = rel->exps->h; m; m = m->next) {
4727 sql_exp *ce = m->data;
4728 sql_column *c = find_sql_column(t, exp_name(ce));
4729
4730 if (c)
4731 append(l, stmt_update_col(be, c, tids, updates[c->colnr]));
4732 }
4733
4734 if (cascade_updates(be, t, tids, updates))
4735 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
4736
4737/* after */
4738 if (be->cur_append && !be->first_statement_generated) {
4739 for(sql_table *up = t->p ; up ; up = up->p) {
4740 if (!sql_update_triggers(be, up, tids, updates, 1))
4741 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", up->base.name);
4742 }
4743 }
4744 if (!sql_update_triggers(be, t, tids, updates, 1))
4745 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
4746
4747 if (ddl) {
4748 list_prepend(l, ddl);
4749 cnt = stmt_list(be, l);
4750 } else {
4751 s = stmt_aggr(be, tids, NULL, NULL, sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL), 1, 0, 1);
4752 cnt = s;
4753 }
4754
4755 if (be->cur_append) //building the total number of rows affected across all tables
4756 cnt->nr = add_to_merge_partitions_accumulator(be, cnt->nr);
4757
4758 if (sql->cascade_action)
4759 sql->cascade_action = NULL;
4760 return cnt;
4761}
4762
4763static int
4764sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, int type)
4765{
4766 /* Put single relation of updates and old values on to the stack */
4767 sql_rel *r = NULL;
4768 node *n;
4769 list *exps = sa_list(sql->sa);
4770 trigger_input *ti = SA_NEW(sql->sa, trigger_input);
4771
4772 ti->t = t;
4773 ti->tids = tids;
4774 ti->updates = NULL;
4775 ti->type = type;
4776 ti->nn = name;
4777 for (n = t->columns.set->h; n; n = n->next) {
4778 sql_column *c = n->data;
4779 sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, 0);
4780
4781 append(exps, ne);
4782 }
4783 r = rel_table_func(sql->sa, NULL, NULL, exps, 2);
4784 r->l = ti;
4785
4786 return stack_push_rel_view(sql, name, r) ? 1 : 0;
4787}
4788
4789static int
4790sql_delete_triggers(backend *be, sql_table *t, stmt *tids, int time, int firing_type, int internal_type)
4791{
4792 mvc *sql = be->mvc;
4793 node *n;
4794 int res = 1;
4795
4796 if (!t->triggers.set)
4797 return res;
4798
4799 for (n = t->triggers.set->h; n; n = n->next) {
4800 sql_trigger *trigger = n->data;
4801
4802 if(!stack_push_frame(sql, "OLD-NEW"))
4803 return 0;
4804 if (trigger->event == firing_type && trigger->time == time) {
4805 /* add name for the 'deleted' to the stack */
4806 const char *o = trigger->old_name;
4807
4808 if (!o) o = "old";
4809
4810 if(!sql_stack_add_deleted(sql, o, t, tids, internal_type)) {
4811 stack_pop_frame(sql);
4812 return 0;
4813 }
4814
4815 if (!sql_parse(be, sql->sa, trigger->statement, m_instantiate)) {
4816 stack_pop_frame(sql);
4817 return 0;
4818 }
4819 }
4820 stack_pop_frame(sql);
4821 }
4822 return res;
4823}
4824
4825static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
4826
4827static stmt *
4828sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
4829{
4830 sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
4831 return sql_delete(be, t, ftids);
4832}
4833
4834static void
4835sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
4836{
4837 mvc *sql = be->mvc;
4838 sql_ukey *uk = (sql_ukey*)k;
4839
4840 if (uk->keys && list_length(uk->keys) > 0) {
4841 sql_subtype *lng = sql_bind_localtype("lng");
4842 sql_subtype *bt = sql_bind_localtype("bit");
4843 node *n;
4844 for(n = uk->keys->h; n; n = n->next) {
4845 char *msg = NULL;
4846 sql_subaggr *cnt = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL);
4847 sql_subfunc *ne = sql_bind_func_result(sql->sa, sql->session->schema, "<>", lng, lng, bt);
4848 sql_key *fk = n->data;
4849 stmt *s, *tids;
4850
4851 tids = stmt_tid(be, fk->idx->t, 0);
4852 s = stmt_idx(be, fk->idx, tids);
4853 s = stmt_join(be, s, utids, 0, cmp_equal); /* join over the join index */
4854 s = stmt_result(be, s, 0);
4855 tids = stmt_project(be, s, tids);
4856 if(cascade) { //for truncate statements with the cascade option
4857 s = sql_delete_cascade_Fkeys(be, fk, tids);
4858 list_prepend(l, s);
4859 } else {
4860 switch (((sql_fkey*)fk)->on_delete) {
4861 case ACT_NO_ACTION:
4862 break;
4863 case ACT_SET_NULL:
4864 case ACT_SET_DEFAULT:
4865 s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
4866 list_prepend(l, s);
4867 break;
4868 case ACT_CASCADE:
4869 s = sql_delete_cascade_Fkeys(be, fk, tids);
4870 list_prepend(l, s);
4871 break;
4872 default: /*RESTRICT*/
4873 /* The overlap between deleted primaries and foreign should be empty */
4874 s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), ne);
4875 msg = sa_message(sql->sa, "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
4876 s = stmt_exception(be, s, msg, 00001);
4877 list_prepend(l, s);
4878 }
4879 }
4880 }
4881 }
4882}
4883
4884static int
4885sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
4886{
4887 mvc *sql = be->mvc;
4888 int res = 1;
4889 node *n;
4890
4891 if (!t->keys.set)
4892 return res;
4893
4894 for (n = t->keys.set->h; n; n = n->next) {
4895 sql_key *k = n->data;
4896
4897 if (k->type == pkey || k->type == ukey) {
4898 if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
4899 int *local_id = SA_NEW(sql->sa, int);
4900 if (!sql->cascade_action)
4901 sql->cascade_action = sa_list(sql->sa);
4902
4903 *local_id = k->base.id;
4904 list_append(sql->cascade_action, local_id);
4905 sql_delete_ukey(be, rows, k, l, which, cascade);
4906 }
4907 }
4908 }
4909 return res;
4910}
4911
4912static stmt *
4913sql_delete(backend *be, sql_table *t, stmt *rows)
4914{
4915 mvc *sql = be->mvc;
4916 stmt *v = NULL, *s = NULL;
4917 list *l = sa_list(sql->sa);
4918
4919 if (rows) {
4920 v = rows;
4921 } else { /* delete all */
4922 v = stmt_tid(be, t, 0);
4923 }
4924
4925/* before */
4926 if (be->cur_append && !be->first_statement_generated) {
4927 for(sql_table *up = t->p ; up ; up = up->p) {
4928 if (!sql_delete_triggers(be, up, v, 0, 1, 3))
4929 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", up->base.name);
4930 }
4931 }
4932 if (!sql_delete_triggers(be, t, v, 0, 1, 3))
4933 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
4934
4935 if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
4936 return sql_error(sql, 02, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
4937
4938 if (rows) {
4939 sql_subtype to;
4940
4941 sql_find_subtype(&to, "oid", 0, 0);
4942 list_append(l, stmt_delete(be, t, rows));
4943 } else { /* delete all */
4944 /* first column */
4945 s = stmt_table_clear(be, t);
4946 list_append(l, s);
4947 }
4948
4949/* after */
4950 if (be->cur_append && !be->first_statement_generated) {
4951 for(sql_table *up = t->p ; up ; up = up->p) {
4952 if (!sql_delete_triggers(be, up, v, 1, 1, 3))
4953 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", up->base.name);
4954 }
4955 }
4956 if (!sql_delete_triggers(be, t, v, 1, 1, 3))
4957 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
4958 if (rows)
4959 s = stmt_aggr(be, rows, NULL, NULL, sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL), 1, 0, 1);
4960 if (be->cur_append) //building the total number of rows affected across all tables
4961 s->nr = add_to_merge_partitions_accumulator(be, s->nr);
4962 return s;
4963}
4964
4965static stmt *
4966rel2bin_delete(backend *be, sql_rel *rel, list *refs)
4967{
4968 mvc *sql = be->mvc;
4969 stmt *rows = NULL, *stdelete = NULL;
4970 sql_rel *tr = rel->l;
4971 sql_table *t = NULL;
4972
4973 if (tr->op == op_basetable)
4974 t = tr->l;
4975 else
4976 assert(0/*ddl statement*/);
4977
4978 if (rel->r) { /* first construct the deletes relation */
4979 rows = subrel_bin(be, rel->r, refs);
4980 if (!rows)
4981 return NULL;
4982 }
4983 if (rows && rows->type == st_list) {
4984 stmt *s = rows;
4985 rows = s->op4.lval->h->data;
4986 }
4987 stdelete = sql_delete(be, t, rows);
4988 if (sql->cascade_action)
4989 sql->cascade_action = NULL;
4990 return stdelete;
4991}
4992
4993struct tablelist {
4994 sql_table *table;
4995 struct tablelist* next;
4996};
4997
4998static void //inspect the other tables recursively for foreign key dependencies
4999check_for_foreign_key_references(mvc *sql, struct tablelist* list, struct tablelist* next_append, sql_table *t, int cascade, int *error) {
5000 node *n;
5001 int found;
5002 struct tablelist* new_node, *node_check;
5003
5004 if (*error)
5005 return;
5006
5007 if (t->keys.set) { /* Check for foreign key references */
5008 for (n = t->keys.set->h; n; n = n->next) {
5009 sql_key *k = n->data;
5010
5011 if (k->type == ukey || k->type == pkey) {
5012 sql_ukey *uk = (sql_ukey *) k;
5013
5014 if (uk->keys && list_length(uk->keys)) {
5015 node *l = uk->keys->h;
5016
5017 for (; l; l = l->next) {
5018 k = l->data;
5019 /* make sure it is not a self referencing key */
5020 if (k->t != t && !cascade) {
5021 node *n = t->columns.set->h;
5022 sql_column *c = n->data;
5023 size_t n_rows = store_funcs.count_col(sql->session->tr, c, 1);
5024 size_t n_deletes = store_funcs.count_del(sql->session->tr, c->t);
5025 assert (n_rows >= n_deletes);
5026 if(n_rows - n_deletes > 0) {
5027 sql_error(sql, 02, SQLSTATE(23000) "TRUNCATE: FOREIGN KEY %s.%s depends on %s", k->t->base.name, k->base.name, t->base.name);
5028 *error = 1;
5029 return;
5030 }
5031 } else if (k->t != t) {
5032 found = 0;
5033 for (node_check = list; node_check; node_check = node_check->next) {
5034 if (node_check->table == k->t)
5035 found = 1;
5036 }
5037 if (!found) {
5038 if ((new_node = MNEW(struct tablelist)) == NULL) {
5039 sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
5040 *error = 1;
5041 return;
5042 }
5043 new_node->table = k->t;
5044 new_node->next = NULL;
5045 next_append->next = new_node;
5046 check_for_foreign_key_references(sql, list, new_node, k->t, cascade, error);
5047 }
5048 }
5049 }
5050 }
5051 }
5052 }
5053 }
5054}
5055
5056static stmt *
5057sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
5058{
5059 mvc *sql = be->mvc;
5060 list *l = sa_list(sql->sa);
5061 stmt *v, *ret = NULL, *other = NULL;
5062 const char *next_value_for = "next value for \"sys\".\"seq_";
5063 char *seq_name = NULL;
5064 str seq_pos = NULL;
5065 sql_column *col = NULL;
5066 sql_sequence *seq = NULL;
5067 sql_schema *sche = NULL;
5068 sql_table *next = NULL;
5069 sql_trans *tr = sql->session->tr;
5070 node *n = NULL;
5071 int error = 0;
5072 struct tablelist* new_list = MNEW(struct tablelist), *list_node, *aux;
5073
5074 if (!new_list) {
5075 sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
5076 error = 1;
5077 goto finalize;
5078 }
5079
5080 new_list->table = t;
5081 new_list->next = NULL;
5082 check_for_foreign_key_references(sql, new_list, new_list, t, cascade, &error);
5083 if (error)
5084 goto finalize;
5085
5086 for (list_node = new_list; list_node; list_node = list_node->next) {
5087 next = list_node->table;
5088 sche = next->s;
5089
5090 if (restart_sequences) { /* restart the sequences if it's the case */
5091 for (n = next->columns.set->h; n; n = n->next) {
5092 col = n->data;
5093 if (col->def && (seq_pos = strstr(col->def, next_value_for))) {
5094 seq_name = _STRDUP(seq_pos + (strlen(next_value_for) - strlen("seq_")));
5095 if (!seq_name) {
5096 sql_error(sql, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
5097 error = 1;
5098 goto finalize;
5099 }
5100 seq_name[strlen(seq_name)-1] = '\0';
5101 seq = find_sql_sequence(sche, seq_name);
5102 if (seq) {
5103 if (!sql_trans_sequence_restart(tr, seq, seq->start)) {
5104 sql_error(sql, 02, SQLSTATE(HY005) "Could not restart sequence %s.%s", sche->base.name, seq_name);
5105 error = 1;
5106 goto finalize;
5107 }
5108 seq->base.wtime = sche->base.wtime = tr->wtime = tr->wstime;
5109 tr->schema_updates++;
5110 }
5111 _DELETE(seq_name);
5112 }
5113 }
5114 }
5115
5116 v = stmt_tid(be, next, 0);
5117
5118 /* before */
5119 if (be->cur_append && !be->first_statement_generated) {
5120 for (sql_table *up = t->p ; up ; up = up->p) {
5121 if (!sql_delete_triggers(be, up, v, 0, 3, 4)) {
5122 sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", up->base.name);
5123 error = 1;
5124 goto finalize;
5125 }
5126 }
5127 }
5128 if (!sql_delete_triggers(be, next, v, 0, 3, 4)) {
5129 sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
5130 error = 1;
5131 goto finalize;
5132 }
5133
5134 if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
5135 sql_error(sql, 02, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
5136 error = 1;
5137 goto finalize;
5138 }
5139
5140 other = stmt_table_clear(be, next);
5141 list_append(l, other);
5142 if (next == t)
5143 ret = other;
5144
5145 /* after */
5146 if (be->cur_append && !be->first_statement_generated) {
5147 for (sql_table *up = t->p ; up ; up = up->p) {
5148 if (!sql_delete_triggers(be, up, v, 1, 3, 4)) {
5149 sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", up->base.name);
5150 error = 1;
5151 goto finalize;
5152 }
5153 }
5154 }
5155 if (!sql_delete_triggers(be, next, v, 1, 3, 4)) {
5156 sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
5157 error = 1;
5158 goto finalize;
5159 }
5160
5161 if (be->cur_append) //building the total number of rows affected across all tables
5162 other->nr = add_to_merge_partitions_accumulator(be, other->nr);
5163 }
5164
5165finalize:
5166 for (list_node = new_list; list_node;) {
5167 aux = list_node->next;
5168 _DELETE(list_node);
5169 list_node = aux;
5170 }
5171
5172 if (error)
5173 return NULL;
5174 return ret;
5175}
5176
5177#define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
5178#define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
5179
5180static stmt *
5181rel2bin_truncate(backend *be, sql_rel *rel)
5182{
5183 mvc *sql = be->mvc;
5184 stmt *truncate = NULL;
5185 sql_rel *tr = rel->l;
5186 sql_table *t = NULL;
5187 node *n = NULL;
5188 int restart_sequences, cascade;
5189
5190 if (tr->op == op_basetable)
5191 t = tr->l;
5192 else
5193 assert(0/*ddl statement*/);
5194
5195 n = rel->exps->h;
5196 restart_sequences = E_ATOM_INT(n->data);
5197 cascade = E_ATOM_INT(n->next->data);
5198
5199 truncate = sql_truncate(be, t, restart_sequences, cascade);
5200 if (sql->cascade_action)
5201 sql->cascade_action = NULL;
5202 return truncate;
5203}
5204
5205static stmt *
5206rel2bin_output(backend *be, sql_rel *rel, list *refs)
5207{
5208 mvc *sql = be->mvc;
5209 node *n;
5210 const char *tsep, *rsep, *ssep, *ns;
5211 const char *fn = NULL;
5212 int onclient = 0;
5213 stmt *s = NULL, *fns = NULL;
5214 list *slist = sa_list(sql->sa);
5215
5216 if (rel->l) /* first construct the sub relation */
5217 s = subrel_bin(be, rel->l, refs);
5218 if (!s)
5219 return NULL;
5220
5221 if (!rel->exps)
5222 return s;
5223 n = rel->exps->h;
5224 tsep = sa_strdup(sql->sa, E_ATOM_STRING(n->data));
5225 rsep = sa_strdup(sql->sa, E_ATOM_STRING(n->next->data));
5226 ssep = sa_strdup(sql->sa, E_ATOM_STRING(n->next->next->data));
5227 ns = sa_strdup(sql->sa, E_ATOM_STRING(n->next->next->next->data));
5228
5229 if (n->next->next->next->next) {
5230 fn = E_ATOM_STRING(n->next->next->next->next->data);
5231 fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
5232 onclient = E_ATOM_INT(n->next->next->next->next->next->data);
5233 }
5234 list_append(slist, stmt_export(be, s, tsep, rsep, ssep, ns, onclient, fns));
5235 if (s->type == st_list && ((stmt*)s->op4.lval->h->data)->nrcols != 0) {
5236 stmt *cnt = stmt_aggr(be, s->op4.lval->h->data, NULL, NULL, sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL), 1, 0, 1);
5237 return cnt;
5238 } else {
5239 return stmt_atom_lng(be, 1);
5240 }
5241}
5242
5243static stmt *
5244rel2bin_list(backend *be, sql_rel *rel, list *refs)
5245{
5246 mvc *sql = be->mvc;
5247 stmt *l = NULL, *r = NULL;
5248 list *slist = sa_list(sql->sa);
5249
5250 (void)refs;
5251
5252 if (find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create affected rows accumulator */
5253 create_merge_partitions_accumulator(be);
5254
5255 if (rel->l) /* first construct the sub relation */
5256 l = subrel_bin(be, rel->l, refs);
5257 if (rel->r) /* first construct the sub relation */
5258 r = subrel_bin(be, rel->r, refs);
5259 if (!l || !r)
5260 return NULL;
5261 list_append(slist, l);
5262 list_append(slist, r);
5263 return stmt_list(be, slist);
5264}
5265
5266static stmt *
5267rel2bin_psm(backend *be, sql_rel *rel)
5268{
5269 mvc *sql = be->mvc;
5270 node *n;
5271 list *l = sa_list(sql->sa);
5272 stmt *sub = NULL;
5273
5274 for (n = rel->exps->h; n; n = n->next) {
5275 sql_exp *e = n->data;
5276 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL);
5277 if(!s)
5278 return NULL;
5279
5280 if (s && s->type == st_table) /* relational statement */
5281 sub = s->op1;
5282 else
5283 append(l, s);
5284 }
5285 return stmt_list(be, l);
5286}
5287
5288static stmt *
5289rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
5290{
5291 stmt *l = NULL, *r = NULL;
5292 node *n = NULL;
5293 list *slist = sa_list(be->mvc->sa);
5294
5295 if (rel->l) /* first construct the sub relation */
5296 l = subrel_bin(be, rel->l, refs);
5297 if (rel->r) /* first construct the sub relation */
5298 r = subrel_bin(be, rel->r, refs);
5299
5300 assert(rel->exps);
5301 assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
5302
5303 if (rel->exps) {
5304 for (n = rel->exps->h; n; n = n->next) {
5305 sql_exp *e = n->data;
5306 stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL);
5307 append(slist, s);
5308 }
5309 }
5310 return stmt_catalog(be, rel->flag, stmt_list(be, slist));
5311}
5312
5313static stmt *
5314rel2bin_exception(backend *be, sql_rel *rel, list *refs)
5315{
5316 stmt *l = NULL, *r = NULL;
5317 node *n = NULL;
5318 list *slist = sa_list(be->mvc->sa);
5319
5320 if (find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create affected rows accumulator */
5321 create_merge_partitions_accumulator(be);
5322
5323 if (rel->l) /* first construct the sub relation */
5324 l = subrel_bin(be, rel->l, refs);
5325 if (rel->r) /* first construct the sub relation */
5326 r = subrel_bin(be, rel->r, refs);
5327
5328 if (rel->exps) {
5329 for (n = rel->exps->h; n; n = n->next) {
5330 sql_exp *e = n->data;
5331 stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL);
5332 append(slist, s);
5333 }
5334 } else { //if there is no exception condition, just generate a statement list
5335 list_append(slist, l);
5336 list_append(slist, r);
5337 }
5338 return stmt_list(be, slist);
5339}
5340
5341static stmt *
5342rel2bin_seq(backend *be, sql_rel *rel, list *refs)
5343{
5344 mvc *sql = be->mvc;
5345 node *en = rel->exps->h;
5346 stmt *restart, *sname, *seq, *seqname, *sl = NULL;
5347 list *l = sa_list(sql->sa);
5348
5349 if (rel->l) { /* first construct the sub relation */
5350 sl = subrel_bin(be, rel->l, refs);
5351 if(!sl)
5352 return NULL;
5353 }
5354
5355 restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL);
5356 sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL);
5357 seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL);
5358 seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL);
5359 if (!restart || !sname || !seqname || !seq)
5360 return NULL;
5361
5362 (void)refs;
5363 append(l, sname);
5364 append(l, seqname);
5365 append(l, seq);
5366 append(l, restart);
5367 return stmt_catalog(be, rel->flag, stmt_list(be, l));
5368}
5369
5370static stmt *
5371rel2bin_trans(backend *be, sql_rel *rel, list *refs)
5372{
5373 node *en = rel->exps->h;
5374 stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5375 stmt *name = NULL;
5376
5377 if (!chain)
5378 return NULL;
5379
5380 (void)refs;
5381 if (en->next) {
5382 name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL);
5383 if (!name)
5384 return NULL;
5385 }
5386 return stmt_trans(be, rel->flag, chain, name);
5387}
5388
5389static stmt *
5390rel2bin_catalog(backend *be, sql_rel *rel, list *refs)
5391{
5392 mvc *sql = be->mvc;
5393 node *en = rel->exps->h;
5394 stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5395 stmt *sname = NULL, *name = NULL, *ifexists = NULL;
5396 list *l = sa_list(sql->sa);
5397
5398 if (!action)
5399 return NULL;
5400
5401 (void)refs;
5402 en = en->next;
5403 sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5404 if (!sname)
5405 return NULL;
5406 if (en->next) {
5407 name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL);
5408 if (!name)
5409 return NULL;
5410 } else {
5411 name = stmt_atom_string_nil(be);
5412 }
5413 if (en->next && en->next->next) {
5414 ifexists = exp_bin(be, en->next->next->data, NULL, NULL, NULL, NULL, NULL, NULL);
5415 if (!ifexists)
5416 return NULL;
5417 } else {
5418 ifexists = stmt_atom_int(be, 0);
5419 }
5420 append(l, sname);
5421 append(l, name);
5422 append(l, ifexists);
5423 append(l, action);
5424 return stmt_catalog(be, rel->flag, stmt_list(be, l));
5425}
5426
5427static stmt *
5428rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
5429{
5430 mvc *sql = be->mvc;
5431 node *en = rel->exps->h;
5432 stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5433 stmt *table = NULL, *sname, *tname = NULL, *ifexists = NULL;
5434 list *l = sa_list(sql->sa);
5435
5436 if (!action)
5437 return NULL;
5438
5439 (void)refs;
5440 en = en->next;
5441 sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5442 if (!sname)
5443 return NULL;
5444 en = en->next;
5445 if (en) {
5446 tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5447 if (!tname)
5448 return NULL;
5449 en = en->next;
5450 }
5451 append(l, sname);
5452 assert(tname);
5453 append(l, tname);
5454 if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
5455 if (en) {
5456 table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5457 if (!table)
5458 return NULL;
5459 }
5460 append(l, table);
5461 } else {
5462 if (en) {
5463 ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5464 if (!ifexists)
5465 return NULL;
5466 } else {
5467 ifexists = stmt_atom_int(be, 0);
5468 }
5469 append(l, ifexists);
5470 }
5471 append(l, action);
5472 return stmt_catalog(be, rel->flag, stmt_list(be, l));
5473}
5474
5475static stmt *
5476rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
5477{
5478 mvc *sql = be->mvc;
5479 node *en;
5480 list *l = sa_list(sql->sa);
5481
5482 (void)refs;
5483 for (en = rel->exps->h; en; en = en->next) {
5484 stmt *es = NULL;
5485
5486 if (en->data) {
5487 es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL);
5488 if (!es)
5489 return NULL;
5490 } else {
5491 es = stmt_atom_string_nil(be);
5492 }
5493 append(l,es);
5494 }
5495 return stmt_catalog(be, rel->flag, stmt_list(be, l));
5496}
5497
5498static stmt *
5499rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
5500{
5501 mvc *sql = be->mvc;
5502 stmt *s = NULL;
5503
5504 switch (rel->flag) {
5505 case ddl_output:
5506 s = rel2bin_output(be, rel, refs);
5507 sql->type = Q_TABLE;
5508 break;
5509 case ddl_list:
5510 s = rel2bin_list(be, rel, refs);
5511 break;
5512 case ddl_psm:
5513 s = rel2bin_psm(be, rel);
5514 break;
5515 case ddl_exception:
5516 s = rel2bin_exception(be, rel, refs);
5517 sql->type = Q_UPDATE;
5518 break;
5519 case ddl_create_seq:
5520 case ddl_alter_seq:
5521 s = rel2bin_seq(be, rel, refs);
5522 sql->type = Q_SCHEMA;
5523 break;
5524 case ddl_alter_table_add_range_partition:
5525 case ddl_alter_table_add_list_partition:
5526 s = rel2bin_partition_limits(be, rel, refs);
5527 sql->type = Q_SCHEMA;
5528 break;
5529 case ddl_release:
5530 case ddl_commit:
5531 case ddl_rollback:
5532 case ddl_trans:
5533 s = rel2bin_trans(be, rel, refs);
5534 sql->type = Q_TRANS;
5535 break;
5536 case ddl_create_schema:
5537 case ddl_drop_schema:
5538 s = rel2bin_catalog(be, rel, refs);
5539 sql->type = Q_SCHEMA;
5540 break;
5541 case ddl_create_table:
5542 case ddl_drop_table:
5543 case ddl_create_view:
5544 case ddl_drop_view:
5545 case ddl_drop_constraint:
5546 case ddl_alter_table:
5547 s = rel2bin_catalog_table(be, rel, refs);
5548 sql->type = Q_SCHEMA;
5549 break;
5550 case ddl_drop_seq:
5551 case ddl_create_type:
5552 case ddl_drop_type:
5553 case ddl_drop_index:
5554 case ddl_create_function:
5555 case ddl_drop_function:
5556 case ddl_create_trigger:
5557 case ddl_drop_trigger:
5558 case ddl_grant_roles:
5559 case ddl_revoke_roles:
5560 case ddl_grant:
5561 case ddl_revoke:
5562 case ddl_grant_func:
5563 case ddl_revoke_func:
5564 case ddl_create_user:
5565 case ddl_drop_user:
5566 case ddl_alter_user:
5567 case ddl_rename_user:
5568 case ddl_create_role:
5569 case ddl_drop_role:
5570 case ddl_alter_table_add_table:
5571 case ddl_alter_table_del_table:
5572 case ddl_alter_table_set_access:
5573 case ddl_comment_on:
5574 case ddl_rename_schema:
5575 case ddl_rename_table:
5576 case ddl_rename_column:
5577 s = rel2bin_catalog2(be, rel, refs);
5578 sql->type = Q_SCHEMA;
5579 break;
5580 default:
5581 assert(0);
5582 }
5583 return s;
5584}
5585
5586static stmt *
5587subrel_bin(backend *be, sql_rel *rel, list *refs)
5588{
5589 mvc *sql = be->mvc;
5590 stmt *s = NULL;
5591
5592 if (THRhighwater())
5593 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");;
5594
5595 if (!rel)
5596 return s;
5597 if (rel_is_ref(rel)) {
5598 s = refs_find_rel(refs, rel);
5599 /* needs a proper fix!! */
5600 if (s)
5601 return s;
5602 }
5603 switch (rel->op) {
5604 case op_basetable:
5605 s = rel2bin_basetable(be, rel);
5606 sql->type = Q_TABLE;
5607 break;
5608 case op_table:
5609 s = rel2bin_table(be, rel, refs);
5610 sql->type = Q_TABLE;
5611 break;
5612 case op_join:
5613 case op_left:
5614 case op_right:
5615 case op_full:
5616 s = rel2bin_join(be, rel, refs);
5617 sql->type = Q_TABLE;
5618 break;
5619 case op_semi:
5620 case op_anti:
5621 s = rel2bin_semijoin(be, rel, refs);
5622 sql->type = Q_TABLE;
5623 break;
5624 case op_union:
5625 s = rel2bin_union(be, rel, refs);
5626 sql->type = Q_TABLE;
5627 break;
5628 case op_except:
5629 s = rel2bin_except(be, rel, refs);
5630 sql->type = Q_TABLE;
5631 break;
5632 case op_inter:
5633 s = rel2bin_inter(be, rel, refs);
5634 sql->type = Q_TABLE;
5635 break;
5636 case op_project:
5637 s = rel2bin_project(be, rel, refs, NULL);
5638 sql->type = Q_TABLE;
5639 break;
5640 case op_select:
5641 s = rel2bin_select(be, rel, refs);
5642 sql->type = Q_TABLE;
5643 break;
5644 case op_groupby:
5645 s = rel2bin_groupby(be, rel, refs);
5646 sql->type = Q_TABLE;
5647 break;
5648 case op_topn:
5649 s = rel2bin_topn(be, rel, refs);
5650 sql->type = Q_TABLE;
5651 break;
5652 case op_sample:
5653 s = rel2bin_sample(be, rel, refs);
5654 sql->type = Q_TABLE;
5655 break;
5656 case op_insert:
5657 s = rel2bin_insert(be, rel, refs);
5658 if (sql->type == Q_TABLE)
5659 sql->type = Q_UPDATE;
5660 break;
5661 case op_update:
5662 s = rel2bin_update(be, rel, refs);
5663 if (sql->type == Q_TABLE)
5664 sql->type = Q_UPDATE;
5665 break;
5666 case op_delete:
5667 s = rel2bin_delete(be, rel, refs);
5668 if (sql->type == Q_TABLE)
5669 sql->type = Q_UPDATE;
5670 break;
5671 case op_truncate:
5672 s = rel2bin_truncate(be, rel);
5673 if (sql->type == Q_TABLE)
5674 sql->type = Q_UPDATE;
5675 break;
5676 case op_ddl:
5677 s = rel2bin_ddl(be, rel, refs);
5678 break;
5679 }
5680 if (s && rel_is_ref(rel)) {
5681 list_append(refs, rel);
5682 list_append(refs, s);
5683 }
5684 return s;
5685}
5686
5687stmt *
5688rel_bin(backend *be, sql_rel *rel)
5689{
5690 mvc *sql = be->mvc;
5691 list *refs = sa_list(sql->sa);
5692 sql_query_t sqltype = sql->type;
5693 stmt *s = subrel_bin(be, rel, refs);
5694
5695 if (sqltype == Q_SCHEMA)
5696 sql->type = sqltype; /* reset */
5697
5698 return s;
5699}
5700
5701stmt *
5702output_rel_bin(backend *be, sql_rel *rel )
5703{
5704 mvc *sql = be->mvc;
5705 list *refs = sa_list(sql->sa);
5706 sql_query_t sqltype = sql->type;
5707 stmt *s;
5708
5709 if (refs == NULL)
5710 return NULL;
5711 s = subrel_bin(be, rel, refs);
5712 if (sqltype == Q_SCHEMA)
5713 sql->type = sqltype; /* reset */
5714
5715 if (!is_ddl(rel->op) && s && s->type != st_none && sql->type == Q_TABLE)
5716 s = stmt_output(be, s);
5717 if (sqltype == Q_UPDATE && s && (s->type != st_list || be->cur_append)) {
5718 if (be->cur_append) { /* finish the output bat */
5719 s->nr = be->cur_append;
5720 be->cur_append = 0;
5721 be->first_statement_generated = false;
5722 }
5723 s = stmt_affected_rows(be, s);
5724 }
5725 return s;
5726}
5727