Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 :
15 : #include "rel_bin.h"
16 : #include "rel_rel.h"
17 : #include "rel_basetable.h"
18 : #include "rel_exp.h"
19 : #include "rel_dump.h"
20 : #include "rel_psm.h"
21 : #include "rel_prop.h"
22 : #include "rel_select.h"
23 : #include "rel_updates.h"
24 : #include "rel_predicates.h"
25 : #include "rel_file_loader.h"
26 : #include "sql_env.h"
27 : #include "sql_optimizer.h"
28 : #include "sql_gencode.h"
29 : #include "mal_builder.h"
30 : #include "opt_prelude.h"
31 :
32 : static stmt * rel_bin(backend *be, sql_rel *rel);
33 : static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
34 :
35 : static stmt *check_types(backend *be, sql_subtype *fromtype, stmt *s, check_type tpe);
36 :
37 : static void
38 44775 : clean_mal_statements(backend *be, int oldstop, int oldvtop)
39 : {
40 44775 : MSresetInstructions(be->mb, oldstop);
41 44778 : freeVariables(be->client, be->mb, NULL, oldvtop);
42 44776 : be->mvc->session->status = 0; /* clean possible generated error */
43 44776 : be->mvc->errstr[0] = '\0';
44 44776 : }
45 :
46 : static int
47 107249 : add_to_rowcount_accumulator(backend *be, int nr)
48 : {
49 107249 : if (be->silent)
50 : return 0;
51 :
52 107122 : if (be->rowcount == 0) {
53 106849 : be->rowcount = nr;
54 106849 : return 0;
55 : }
56 :
57 273 : InstrPtr q = newStmt(be->mb, calcRef, plusRef);
58 273 : if (q == NULL) {
59 0 : if (be->mvc->sa->eb.enabled)
60 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
61 : return -1;
62 : }
63 273 : q = pushArgument(be->mb, q, be->rowcount);
64 273 : q = pushArgument(be->mb, q, nr);
65 273 : pushInstruction(be->mb, q);
66 :
67 273 : be->rowcount = getDestVar(q);
68 273 : return 0;
69 : }
70 :
71 : static stmt *
72 12677 : stmt_selectnil(backend *be, stmt *col)
73 : {
74 12677 : sql_subtype *t = tail_type(col);
75 12677 : return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, NULL, 0, 1);
76 : }
77 :
78 : static stmt *
79 5782 : sql_unop_(backend *be, const char *fname, stmt *rs)
80 : {
81 5782 : mvc *sql = be->mvc;
82 5782 : sql_subtype *rt = NULL;
83 5782 : sql_subfunc *f = NULL;
84 :
85 5782 : rt = tail_type(rs);
86 5782 : f = sql_bind_func(sql, "sys", fname, rt, NULL, F_FUNC, true, true);
87 : /* try to find the function without a type, and convert
88 : * the value to the type needed by this function!
89 : */
90 5782 : if (!f && (f = sql_find_func(sql, "sys", fname, 1, F_FUNC, true, NULL)) != NULL) {
91 0 : sql_arg *a = f->func->ops->h->data;
92 :
93 0 : sql->session->status = 0;
94 0 : sql->errstr[0] = '\0';
95 0 : rs = check_types(be, &a->type, rs, type_equal);
96 0 : if (!rs)
97 : f = NULL;
98 : }
99 : if (f) {
100 : /*
101 : if (f->func->res.scale == INOUT) {
102 : f->res.digits = rt->digits;
103 : f->res.scale = rt->scale;
104 : }
105 : */
106 5782 : return stmt_unop(be, rs, NULL, f);
107 0 : } else if (rs) {
108 0 : char *type = tail_type(rs)->type->base.name;
109 :
110 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such unary operator '%s(%s)'", fname, type);
111 : }
112 : return NULL;
113 : }
114 :
115 : static stmt *
116 15589 : refs_find_rel(list *refs, sql_rel *rel)
117 : {
118 15589 : node *n;
119 :
120 19585 : for (n=refs->h; n; n = n->next->next) {
121 10939 : sql_rel *ref = n->data;
122 10939 : stmt *s = n->next->data;
123 :
124 10939 : if (rel == ref)
125 : return s;
126 : }
127 : return NULL;
128 : }
129 :
130 : static void
131 4913 : refs_update_stmt(list *refs, sql_rel *rel, stmt *s)
132 : {
133 4913 : node *n;
134 :
135 5949 : for (n=refs->h; n; n = n->next->next) {
136 5949 : sql_rel *ref = n->data;
137 :
138 5949 : if (rel == ref) {
139 4913 : n->next->data = s;
140 4913 : break;
141 : }
142 : }
143 : }
144 :
145 :
146 : static void
147 0 : print_stmtlist(allocator *sa, stmt *l)
148 : {
149 0 : node *n;
150 0 : if (l) {
151 0 : for (n = l->op4.lval->h; n; n = n->next) {
152 0 : const char *rnme = table_name(sa, n->data);
153 0 : const char *nme = column_name(sa, n->data);
154 :
155 0 : TRC_INFO(SQL_EXECUTION, "%s.%s\n", rnme ? rnme : "(null!)", nme ? nme : "(null!)");
156 : }
157 : }
158 0 : }
159 :
160 : static stmt *
161 4000 : list_find_column(backend *be, list *l, const char *rname, const char *name)
162 : {
163 4000 : stmt *res = NULL;
164 4000 : node *n;
165 :
166 4000 : if (!l)
167 : return NULL;
168 4000 : if (!l->ht && list_length(l) > HASH_MIN_SIZE) {
169 799 : l->ht = hash_new(l->sa, MAX(list_length(l), l->expected_cnt), (fkeyvalue)&stmt_key);
170 799 : if (l->ht != NULL) {
171 16143 : for (n = l->h; n; n = n->next) {
172 15344 : const char *nme = column_name(be->mvc->sa, n->data);
173 15344 : if (nme) {
174 15344 : int key = hash_key(nme);
175 :
176 15344 : if (hash_add(l->ht, key, n->data) == NULL) {
177 0 : hash_destroy(l->ht);
178 0 : l->ht = NULL;
179 0 : break;
180 : }
181 : }
182 : }
183 : }
184 : }
185 4000 : if (l->ht) {
186 876 : int key = hash_key(name);
187 876 : sql_hash_e *e = l->ht->buckets[key&(l->ht->size-1)];
188 :
189 876 : if (rname) {
190 907 : for (; e; e = e->chain) {
191 849 : stmt *s = e->value;
192 849 : const char *rnme = table_name(be->mvc->sa, s);
193 849 : const char *nme = column_name(be->mvc->sa, s);
194 :
195 849 : if (rnme && strcmp(rnme, rname) == 0 &&
196 840 : strcmp(nme, name) == 0) {
197 : res = s;
198 : break;
199 : }
200 : }
201 : } else {
202 0 : for (; e; e = e->chain) {
203 0 : stmt *s = e->value;
204 0 : const char *rnme = table_name(be->mvc->sa, s);
205 0 : const char *nme = column_name(be->mvc->sa, s);
206 :
207 0 : if (!rnme && nme && strcmp(nme, name) == 0) {
208 : res = s;
209 : break;
210 : }
211 : }
212 : }
213 876 : if (!res)
214 : return NULL;
215 : return res;
216 : }
217 3124 : if (rname) {
218 7014 : for (n = l->h; n; n = n->next) {
219 6976 : const char *rnme = table_name(be->mvc->sa, n->data);
220 6976 : const char *nme = column_name(be->mvc->sa, n->data);
221 :
222 6976 : if (rnme && strcmp(rnme, rname) == 0 &&
223 6899 : strcmp(nme, name) == 0) {
224 3086 : res = n->data;
225 3086 : break;
226 : }
227 : }
228 : } else {
229 0 : for (n = l->h; n; n = n->next) {
230 0 : const char *rnme = table_name(be->mvc->sa, n->data);
231 0 : const char *nme = column_name(be->mvc->sa, n->data);
232 :
233 0 : if (!rnme && nme && strcmp(nme, name) == 0) {
234 0 : res = n->data;
235 0 : break;
236 : }
237 : }
238 : }
239 3124 : if (!res)
240 : return NULL;
241 : return res;
242 : }
243 :
244 : static stmt *
245 4000 : bin_find_column(backend *be, stmt *sub, const char *rname, const char *name)
246 : {
247 4000 : return list_find_column(be, sub->op4.lval, rname, name);
248 : }
249 :
250 : static stmt *
251 1028217 : list_find_column_nid(backend *be, list *l, int label)
252 : {
253 1028217 : (void)be;
254 1028217 : if (!l)
255 : return NULL;
256 11333872 : for (node *n = l->h; n; n = n->next) {
257 11285916 : stmt *s = n->data;
258 :
259 11285916 : if (s->label == label)
260 : return s;
261 : }
262 : return NULL;
263 : }
264 :
265 : static stmt *
266 1001011 : bin_find_column_nid(backend *be, stmt *sub, int label)
267 : {
268 1001011 : list *l = sub->op4.lval;
269 2989492 : return list_find_column_nid(be, l, label);
270 : }
271 :
272 : static list *
273 : bin_find_columns(backend *be, stmt *sub, const char *name)
274 : {
275 : node *n;
276 : list *l = sa_list(be->mvc->sa);
277 :
278 : for (n = sub->op4.lval->h; n; n = n->next) {
279 : const char *nme = column_name(be->mvc->sa, n->data);
280 :
281 : if (strcmp(nme, name) == 0)
282 : append(l, n->data);
283 : }
284 : if (list_length(l))
285 : return l;
286 : return NULL;
287 : }
288 :
289 : static stmt *
290 2206929 : column(backend *be, stmt *val)
291 : {
292 2206929 : if (val->nrcols == 0)
293 14363 : return const_column(be, val);
294 : return val;
295 : }
296 :
297 : static stmt *
298 63828 : create_const_column(backend *be, stmt *val)
299 : {
300 63828 : if (val->nrcols == 0)
301 16 : val = const_column(be, val);
302 63828 : return stmt_append(be, stmt_temp(be, tail_type(val)), val);
303 : }
304 :
305 : static int
306 667949 : statment_score(stmt *c)
307 : {
308 667949 : sql_subtype *t = tail_type(c);
309 667948 : int score = 0;
310 :
311 667948 : if (c->nrcols != 0) /* no need to create an extra intermediate */
312 667637 : score += 200;
313 :
314 667948 : if (!t)
315 : return score;
316 667948 : switch (ATOMstorage(t->type->localtype)) { /* give preference to smaller types */
317 37535 : case TYPE_bte:
318 37535 : score += 150 - 8;
319 37535 : break;
320 49456 : case TYPE_sht:
321 49456 : score += 150 - 16;
322 49456 : break;
323 203434 : case TYPE_int:
324 203434 : score += 150 - 32;
325 203434 : break;
326 38308 : case TYPE_void:
327 : case TYPE_lng:
328 38308 : score += 150 - 64;
329 38308 : break;
330 1423 : case TYPE_uuid:
331 : #ifdef HAVE_HGE
332 : case TYPE_hge:
333 : #endif
334 1423 : score += 150 - 128;
335 1423 : break;
336 3332 : case TYPE_flt:
337 3332 : score += 75 - 24;
338 3332 : break;
339 5952 : case TYPE_dbl:
340 5952 : score += 75 - 53;
341 5952 : break;
342 : default:
343 : break;
344 : }
345 : return score;
346 : }
347 :
348 : static stmt *
349 78283 : bin_find_smallest_column(backend *be, stmt *sub)
350 : {
351 78283 : stmt *res = sub->op4.lval->h->data;
352 78283 : int best_score = statment_score(sub->op4.lval->h->data);
353 :
354 78282 : if (sub->op4.lval->h->next)
355 653238 : for (node *n = sub->op4.lval->h->next ; n ; n = n->next) {
356 589665 : stmt *c = n->data;
357 589665 : int next_score = statment_score(c);
358 :
359 589666 : if (next_score > best_score) {
360 43358 : res = c;
361 43358 : best_score = next_score;
362 : }
363 : }
364 78283 : if (res->nrcols == 0)
365 260 : return const_column(be, res);
366 : return res;
367 : }
368 :
369 : static stmt *
370 205330 : row2cols(backend *be, stmt *sub)
371 : {
372 205330 : if (sub->nrcols == 0 && sub->key) {
373 4919 : node *n;
374 4919 : list *l = sa_list(be->mvc->sa);
375 4919 : if (l == NULL)
376 : return NULL;
377 :
378 16393 : for (n = sub->op4.lval->h; n; n = n->next) {
379 11474 : stmt *sc = n->data;
380 11474 : assert(sc->type == st_alias);
381 11474 : const char *cname = column_name(be->mvc->sa, sc);
382 11474 : const char *tname = table_name(be->mvc->sa, sc);
383 11474 : int label = sc->label;
384 :
385 11474 : sc = column(be, sc);
386 11474 : list_append(l, stmt_alias(be, sc, label, tname, cname));
387 : }
388 4919 : sub = stmt_list(be, l);
389 : }
390 : return sub;
391 : }
392 :
393 : static stmt*
394 44 : distinct_value_list(backend *be, list *vals, stmt **last_null_value, int depth, int push)
395 : {
396 44 : list *l = sa_list(be->mvc->sa);
397 44 : stmt *s;
398 :
399 : /* create bat append values */
400 1843 : for (node *n = vals->h; n; n = n->next) {
401 1799 : sql_exp *e = n->data;
402 1799 : stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, depth, 0, push);
403 :
404 1799 : if (exp_is_null(e))
405 0 : *last_null_value = i;
406 :
407 1799 : if (!i)
408 : return NULL;
409 :
410 1799 : list_append(l, i);
411 : }
412 44 : s = stmt_append_bulk(be, stmt_temp(be, exp_subtype(vals->h->data)), l);
413 : /* Probably faster to filter out the values directly in the underlying list of atoms.
414 : But for now use groupby to filter out duplicate values. */
415 44 : stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
416 44 : stmt* ext = stmt_result(be, groupby, 1);
417 :
418 44 : return stmt_project(be, ext, s);
419 : }
420 :
421 : static stmt *
422 3020 : stmt_selectnonil(backend *be, stmt *col, stmt *s)
423 : {
424 3020 : sql_subtype *t = tail_type(col);
425 3020 : return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, s, 1, 1);
426 : }
427 :
428 : static int
429 13908 : is_tid_chain(stmt *cand)
430 : {
431 17090 : while(cand && cand->type != st_tid && cand->cand) {
432 : cand = cand->cand;
433 : }
434 13908 : if (cand && cand->type == st_tid)
435 11942 : return 1;
436 : return 0;
437 : }
438 :
439 : static stmt *
440 996249 : subrel_project(backend *be, stmt *s, list *refs, sql_rel *rel)
441 : {
442 996249 : if (!s || s->type != st_list || !s->cand)
443 : return s;
444 :
445 139648 : list *l = sa_list(be->mvc->sa);
446 139648 : stmt *cand = s->cand;
447 139648 : if (!l)
448 : return NULL;
449 631857 : for (node *n = s->op4.lval->h; n; n = n->next) {
450 492206 : stmt *c = n->data;
451 :
452 492206 : assert(c->type == st_alias || (c->type == st_join && c->flag == cmp_project) || c->type == st_bat || c->type == st_idxbat || c->type == st_single);
453 492206 : if (c->type != st_alias) {
454 0 : c = stmt_project(be, cand, c);
455 492206 : } else if (c->op1->type == st_mirror && is_tid_chain(cand)) { /* alias with mirror (ie full row ids) */
456 : //c = stmt_alias(be, cand, 0, c->tname, c->cname);
457 11942 : c = stmt_as(be, cand, c);
458 : } else { /* st_alias */
459 480264 : stmt *s = c->op1;
460 480264 : if (s->nrcols == 0)
461 0 : s = stmt_const(be, cand, s);
462 : else
463 480264 : s = stmt_project(be, cand, s);
464 : //c = stmt_alias(be, s, c->flag, c->tname, c->cname);
465 480287 : c = stmt_as(be, s, c);
466 : }
467 492225 : append(l, c);
468 : }
469 139651 : s = stmt_list(be, l);
470 139650 : if (rel && rel_is_ref(rel))
471 4859 : refs_update_stmt(refs, rel, s);
472 : return s;
473 : }
474 :
475 : static stmt *
476 72 : handle_in_tuple_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int reduce, int push)
477 : {
478 72 : mvc *sql = be->mvc;
479 72 : stmt *s = NULL;
480 :
481 72 : list *lvals = ce->f, *lstmts = sa_list(sql->sa);
482 327 : for(node *n = lvals->h; n; n = n->next) {
483 255 : sql_exp *ce = n->data;
484 255 : stmt *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
485 :
486 255 : if (c && reduce && c->nrcols == 0)
487 0 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
488 0 : if(!c)
489 : return NULL;
490 255 : lstmts = append(lstmts, c);
491 : }
492 :
493 72 : sql_subtype *bt = sql_bind_localtype("bit");
494 72 : sql_subfunc *and = sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
495 72 : sql_subfunc *or = sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true);
496 572 : for (node *n = nl->h; n; n = n->next) {
497 500 : sql_exp *e = n->data;
498 500 : list *vals = e->f;
499 500 : stmt *cursel = NULL;
500 :
501 2061 : for (node *m = vals->h, *o = lstmts->h; m && o; m = m->next, o = o->next) {
502 1561 : stmt *c = o->data;
503 3122 : sql_subfunc *cmp = (in)
504 1561 : ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
505 1561 : :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
506 1561 : sql_exp *e = m->data;
507 :
508 1561 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
509 1561 : if(!i)
510 : return NULL;
511 :
512 1561 : i = stmt_binop(be, c, i, NULL, cmp);
513 1561 : if (cursel)
514 1061 : cursel = stmt_binop(be, cursel, i, NULL, in?and:or);
515 : else
516 : cursel = i;
517 : }
518 500 : if (s)
519 428 : s = stmt_binop(be, s, cursel, NULL, in?or:and);
520 : else
521 : s = cursel;
522 : }
523 72 : if (!depth && reduce)
524 144 : s = stmt_uselect(be,
525 72 : s->nrcols == 0?stmt_const(be, bin_find_smallest_column(be, left), s): s,
526 : stmt_bool(be, 1), cmp_equal, sel, 0, 0);
527 : return s;
528 : }
529 :
530 : static stmt *
531 16606 : handle_in_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int reduce, int push)
532 : {
533 16606 : if (ce && is_values(ce))
534 72 : return handle_in_tuple_exps(be, ce, nl, left, right, grp, ext, cnt, sel, in, depth, reduce, push);
535 16534 : mvc *sql = be->mvc;
536 16534 : node *n;
537 16534 : stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
538 :
539 16534 : if(!c)
540 : return NULL;
541 :
542 16534 : if (reduce && c->nrcols == 0)
543 44 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
544 :
545 16534 : if (c->nrcols == 0 || depth || !reduce) {
546 2 : sql_subtype *bt = sql_bind_localtype("bit");
547 4 : sql_subfunc *cmp = (in)
548 2 : ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
549 2 : :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
550 2 : sql_subfunc *a = (in)?sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true)
551 2 : :sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
552 :
553 6 : for (n = nl->h; n; n = n->next) {
554 4 : sql_exp *e = n->data;
555 4 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
556 4 : if(!i)
557 : return NULL;
558 :
559 4 : i = stmt_binop(be, c, i, NULL, cmp);
560 4 : if (s)
561 2 : s = stmt_binop(be, s, i, NULL, a);
562 : else
563 : s = i;
564 : }
565 2 : if (sel && !(depth || !reduce))
566 0 : s = stmt_uselect(be,
567 : stmt_const(be, bin_find_smallest_column(be, left), s),
568 : stmt_bool(be, 1), cmp_equal, sel, 0, 0);
569 16532 : } else if (list_length(nl) < 16) {
570 16488 : comp_type cmp = (in)?cmp_equal:cmp_notequal;
571 :
572 16488 : if (!in)
573 7066 : s = sel;
574 89525 : for (n = nl->h; n; n = n->next) {
575 73037 : sql_exp *e = n->data;
576 73037 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
577 73037 : if(!i)
578 : return NULL;
579 :
580 73037 : if (in) {
581 49087 : i = stmt_uselect(be, c, i, cmp, sel, 0, 0);
582 49087 : if (s)
583 39665 : s = stmt_tunion(be, s, i);
584 : else
585 : s = i;
586 : } else {
587 23950 : s = stmt_uselect(be, c, i, cmp, s, 0, 0);
588 : }
589 : }
590 : } else {
591 : /* TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
592 : For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
593 : make sure that this behavior is replicated by the sql optimizer and not handle_in_exps. */
594 :
595 44 : stmt* last_null_value = NULL; /* CORNER CASE ALERT: See description below. */
596 :
597 : /* The actual in-value-list should not contain duplicates to ensure that final join results are unique. */
598 44 : s = distinct_value_list(be, nl, &last_null_value, depth+1, push);
599 44 : if (!s)
600 0 : return NULL;
601 :
602 44 : if (last_null_value) {
603 : /* The actual in-value-list should not contain null values. */
604 0 : s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
605 : }
606 :
607 44 : if (in) {
608 42 : s = stmt_semijoin(be, c, s, sel, NULL, 0, false);
609 : } else {
610 2 : if (last_null_value) {
611 : /* CORNER CASE ALERT:
612 : In case of a not-in-expression with the associated in-value-list containing a null value,
613 : the entire in-predicate is forced to always return false, i.e. an empty candidate list.
614 : This is similar to postgres behavior.
615 : TODO: However I do not think this behavior is in accordance with SQL standard 2003.
616 :
617 : Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
618 : list* singleton_bat = sa_list(sql->sa);
619 : list_append(singleton_bat, null_value); */
620 0 : s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0, 0);
621 : } else {
622 : /* BACK TO HAPPY FLOW:
623 : Make sure that null values are never returned. */
624 2 : stmt* non_nulls;
625 2 : non_nulls = stmt_selectnonil(be, c, sel);
626 2 : s = stmt_tdiff(be, stmt_project(be, non_nulls, c), s, NULL);
627 2 : s = stmt_project(be, s, non_nulls);
628 : }
629 : }
630 : }
631 : return s;
632 : }
633 :
634 : static stmt *
635 137102 : value_list(backend *be, list *vals, stmt *left, stmt *sel)
636 : {
637 137102 : sql_subtype *type = exp_subtype(vals->h->data);
638 137240 : list *l;
639 :
640 137240 : if (!type)
641 0 : return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
642 : /* create bat append values */
643 137240 : l = sa_list(be->mvc->sa);
644 881695 : for (node *n = vals->h; n; n = n->next) {
645 744860 : sql_exp *e = n->data;
646 744860 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
647 :
648 745840 : if (!i)
649 : return NULL;
650 :
651 745840 : if (list_length(vals) == 1)
652 478 : return i;
653 744876 : list_append(l, i);
654 : }
655 136835 : return stmt_append_bulk(be, stmt_temp(be, type), l);
656 : }
657 :
658 : static stmt *
659 162 : exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
660 : {
661 162 : mvc *sql = be->mvc;
662 162 : node *n;
663 162 : list *nl = sa_list(sql->sa);
664 :
665 162 : if (nl == NULL)
666 : return NULL;
667 433 : for (n = exps->h; n; n = n->next) {
668 271 : sql_exp *e = n->data;
669 271 : stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0, 0);
670 271 : if(!i)
671 : return NULL;
672 :
673 271 : if (n->next && i->type == st_table) /* relational statement */
674 3 : l = i->op1;
675 : else
676 268 : append(nl, i);
677 : }
678 162 : return stmt_list(be, nl);
679 : }
680 :
681 : static stmt *
682 1636 : exp_count_no_nil_arg(sql_exp *e, stmt *ext, sql_exp *ae, stmt *as)
683 : {
684 : /* small optimization, ie use candidates directly on count(*) */
685 1636 : if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
686 : /* skip alias statements */
687 3130 : while (as->type == st_alias)
688 1630 : as = as->op1;
689 : /* use candidate */
690 1500 : if (as && as->type == st_join && as->flag == cmp_project) {
691 1368 : if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
692 1636 : as = as->op1;
693 : }
694 : }
695 1636 : return as;
696 : }
697 :
698 : static stmt *
699 12955 : exp_bin_or(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, bool reduce, int push)
700 : {
701 12955 : sql_subtype *bt = sql_bind_localtype("bit");
702 12955 : list *l = e->l;
703 12955 : node *n;
704 12955 : stmt *sel1 = NULL, *sel2 = NULL, *s = NULL;
705 12955 : int anti = is_anti(e);
706 :
707 12955 : sel1 = sel;
708 12955 : sel2 = sel;
709 27056 : for (n = l->h; n; n = n->next) {
710 14101 : sql_exp *c = n->data;
711 14101 : stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
712 :
713 : /* propagate the anti flag */
714 14101 : if (anti)
715 55 : set_anti(c);
716 14105 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
717 14101 : if (!s)
718 : return s;
719 :
720 14101 : if (!reduce && sin) {
721 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
722 0 : assert(f);
723 0 : s = stmt_binop(be, sin, s, NULL, f);
724 14101 : } else if (!sin && sel1 && sel1->nrcols == 0 && s->nrcols == 0) {
725 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
726 0 : assert(f);
727 0 : s = stmt_binop(be, sel1, s, sin, f);
728 14101 : } else if (sel1 && (sel1->nrcols == 0 || s->nrcols == 0)) {
729 1 : stmt *predicate = bin_find_smallest_column(be, left);
730 :
731 1 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
732 1 : if (s->nrcols == 0)
733 0 : s = stmt_uselect(be, predicate, s, cmp_equal, sel1, anti, is_semantics(c));
734 : else
735 1 : s = stmt_uselect(be, predicate, sel1, cmp_equal, s, anti, is_semantics(c));
736 : }
737 14101 : sel1 = s;
738 : }
739 12955 : l = e->r;
740 28275 : for (n = l->h; n; n = n->next) {
741 15320 : sql_exp *c = n->data;
742 15320 : stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
743 :
744 : /* propagate the anti flag */
745 15320 : if (anti)
746 55 : set_anti(c);
747 15325 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
748 15320 : if (!s)
749 : return s;
750 :
751 15320 : if (!reduce && sin) {
752 2 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
753 1 : assert(f);
754 1 : s = stmt_binop(be, sin, s, NULL, f);
755 15319 : } else if (!sin && sel2 && sel2->nrcols == 0 && s->nrcols == 0) {
756 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
757 0 : assert(f);
758 0 : s = stmt_binop(be, sel2, s, sin, f);
759 15319 : } else if (sel2 && (sel2->nrcols == 0 || s->nrcols == 0)) {
760 6 : stmt *predicate = bin_find_smallest_column(be, left);
761 :
762 6 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
763 6 : if (s->nrcols == 0)
764 5 : s = stmt_uselect(be, predicate, s, cmp_equal, sel2, anti, 0);
765 : else
766 1 : s = stmt_uselect(be, predicate, sel2, cmp_equal, s, anti, 0);
767 : }
768 15320 : sel2 = s;
769 : }
770 12955 : if (sel1->nrcols == 0 && sel2->nrcols == 0) {
771 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
772 0 : assert(f);
773 0 : return stmt_binop(be, sel1, sel2, NULL, f);
774 : }
775 12955 : if (sel1->nrcols == 0) {
776 2 : stmt *predicate = bin_find_smallest_column(be, left);
777 :
778 2 : if (!reduce) {
779 0 : predicate = stmt_const(be, predicate, sel1);
780 : } else {
781 2 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
782 2 : sel1 = stmt_uselect(be, predicate, sel1, cmp_equal, NULL, 0/*anti*/, 0);
783 : }
784 : }
785 12955 : if (sel2->nrcols == 0) {
786 81 : stmt *predicate = bin_find_smallest_column(be, left);
787 :
788 81 : if (!reduce) {
789 0 : predicate = stmt_const(be, predicate, sel2);
790 : } else {
791 81 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
792 81 : sel2 = stmt_uselect(be, predicate, sel2, cmp_equal, NULL, 0/*anti*/, 0);
793 : }
794 : }
795 12955 : if (!reduce) {
796 8 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
797 4 : assert(f);
798 4 : return stmt_binop(be, sel1, sel2, NULL, f);
799 : }
800 12951 : if (anti)
801 55 : return stmt_project(be, stmt_tinter(be, sel1, sel2, false), sel1);
802 12896 : return stmt_tunion(be, sel1, sel2);
803 : }
804 :
805 : static stmt *
806 16231 : exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
807 : {
808 16231 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
809 16231 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
810 16231 : char name[16], *nme = NULL;
811 16231 : sql_subtype *bt = sql_bind_localtype("bit");
812 16231 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
813 16231 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
814 16231 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
815 :
816 16231 : if (single_value) {
817 : /* var_x = nil; */
818 90 : nme = number2name(name, sizeof(name), ++be->mvc->label);
819 90 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
820 : }
821 :
822 16231 : list *exps = fe->l;
823 :
824 : /*
825 : * left - isel: calls down need id's from the range of left
826 : * res - rsel: updates to res need id's in the range from res
827 : */
828 70028 : for (node *en = exps->h; en; en = en->next) {
829 53797 : sql_exp *e = en->data;
830 :
831 53797 : next_cond = next_cond && en->next; /* last else is only a value */
832 :
833 53797 : stmt *nsel = rsel;
834 53797 : if (!single_value) {
835 53473 : if (/*!next_cond &&*/ rsel && isel) {
836 : /* back into left range */
837 7430 : nsel = stmt_project(be, rsel, isel);
838 46043 : } else if (isel && !rsel)
839 53797 : nsel = isel;
840 : }
841 53797 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
842 :
843 53797 : if (!es)
844 : return NULL;
845 53797 : if (!single_value) {
846 : /* create result */
847 53473 : if (!res) {
848 16141 : stmt *l = isel;
849 16141 : if (!l)
850 12440 : l = bin_find_smallest_column(be, left);
851 16141 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
852 16141 : ires = l;
853 16141 : if (res)
854 16141 : res->cand = isel;
855 37332 : } else if (res && !next_cond) { /* use result to update column */
856 34807 : stmt *val = es;
857 34807 : stmt *pos = rsel;
858 :
859 34807 : if (val->nrcols == 0)
860 17639 : val = stmt_const(be, pos, val);
861 17168 : else if (!val->cand && nsel)
862 3544 : val = stmt_project(be, nsel, val);
863 34807 : res = stmt_replace(be, res, pos, val);
864 :
865 34807 : assert(cond);
866 :
867 34807 : if (en->next) {
868 : /* osel - rsel */
869 18666 : if (!osel)
870 16141 : osel = stmt_mirror(be, ires);
871 18666 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
872 18666 : osel = rsel = stmt_project(be, d, osel);
873 : }
874 : }
875 53473 : if (next_cond) {
876 18666 : ncond = cond = es;
877 18666 : if (!ncond->nrcols) {
878 132 : if (osel) {
879 75 : ncond = stmt_const(be, nsel, ncond);
880 75 : ncond->cand = nsel;
881 57 : } else if (isel) {
882 3 : ncond = stmt_const(be, isel, ncond);
883 3 : ncond->cand = isel;
884 : } else
885 54 : ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
886 : }
887 18666 : if (isel && !ncond->cand) {
888 10 : ncond = stmt_project(be, nsel, ncond);
889 10 : ncond->cand = nsel;
890 : }
891 24884 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
892 18666 : if (rsel && ncond->cand)
893 2517 : rsel = stmt_project(be, s, rsel);
894 : else
895 : rsel = s;
896 : }
897 : } else {
898 324 : if (!res) {
899 : /* if_barrier ... */
900 117 : assert(next_cond);
901 117 : if (next_cond) {
902 117 : if (cond) {
903 27 : ncond = stmt_binop(be, cond, es, nsel, and);
904 : } else {
905 : ncond = es;
906 : }
907 : cond = es;
908 : }
909 : } else {
910 : /* var_x = s */
911 207 : (void)stmt_assign(be, NULL, nme, es, 2);
912 : /* endif_barrier */
913 207 : (void)stmt_control_end(be, res);
914 207 : res = NULL;
915 :
916 207 : if (en->next) {
917 117 : cond = stmt_unop(be, cond, nsel, not);
918 :
919 117 : sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
920 117 : cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
921 117 : if (ocond)
922 27 : cond = stmt_binop(be, ocond, cond, nsel, and);
923 117 : ocond = cond;
924 117 : if (!en->next->next)
925 90 : ncond = cond;
926 : }
927 : }
928 324 : if (ncond && (next_cond || (en->next && !en->next->next))) {
929 : /* if_barrier ... */
930 207 : res = stmt_cond(be, ncond, NULL, 0, 0);
931 : }
932 : }
933 53797 : next_cond = !next_cond;
934 : }
935 16231 : if (single_value)
936 90 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
937 : return res;
938 : }
939 :
940 : static stmt *
941 3 : exp2bin_named_placeholders(backend *be, sql_exp *fe)
942 : {
943 3 : int argc = 0;
944 3 : char arg[IDLENGTH];
945 3 : list *args = fe->l;
946 :
947 3 : if (list_empty(args))
948 : return NULL;
949 8 : for (node *n = args->h; n; n = n->next, argc++) {
950 5 : sql_exp *a = n->data;
951 5 : sql_subtype *t = exp_subtype(a);
952 5 : stmt *s = exp_bin(be, a, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, 1);
953 5 : InstrPtr q = newAssignment(be->mb);
954 :
955 5 : if (!q || !t || !s) {
956 0 : sql_error(be->mvc, 10, SQLSTATE(42000) MAL_MALLOC_FAIL);
957 0 : return NULL;
958 : }
959 5 : int type = t->type->localtype, varid = 0;
960 :
961 5 : snprintf(arg, IDLENGTH, "A%d", argc);
962 5 : if ((varid = newVariable(be->mb, arg, strlen(arg), type)) < 0) {
963 0 : sql_error(be->mvc, 10, SQLSTATE(42000) "Internal error while compiling statement: variable id too long");
964 0 : return NULL;
965 : }
966 5 : if (q)
967 5 : getDestVar(q) = varid;
968 5 : q = pushArgument(be->mb, q, s->nr);
969 5 : pushInstruction(be->mb, q);
970 : }
971 : return NULL;
972 : }
973 :
974 : static stmt *
975 2124 : exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
976 : {
977 2124 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
978 2124 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
979 2124 : char name[16], *nme = NULL;
980 2124 : sql_subtype *bt = sql_bind_localtype("bit");
981 2124 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
982 2124 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
983 2124 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
984 2123 : sql_subfunc *cmp;
985 :
986 2123 : if (single_value) {
987 : /* var_x = nil; */
988 85 : nme = number2name(name, sizeof(name), ++be->mvc->label);
989 86 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
990 : }
991 :
992 2124 : list *exps = fe->l;
993 2124 : node *en = exps->h;
994 2124 : sql_exp *e = en->data;
995 :
996 2124 : stmt *nsel = !single_value?isel:NULL;
997 2124 : stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
998 2124 : if (!case_when)
999 : return NULL;
1000 2124 : cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e), exp_subtype(e), F_FUNC, true, true);
1001 2124 : if (!cmp)
1002 : return NULL;
1003 2124 : if (!single_value && !case_when->nrcols) {
1004 34 : stmt *l = isel;
1005 34 : if (!l && left)
1006 29 : l = bin_find_smallest_column(be, left);
1007 5 : else if (!l)
1008 : return NULL;
1009 34 : case_when = stmt_const(be, l, case_when);
1010 34 : if (case_when)
1011 34 : case_when->cand = isel;
1012 : }
1013 2124 : if (!single_value && isel && !case_when->cand) {
1014 308 : case_when = stmt_project(be, isel, case_when);
1015 308 : case_when->cand = isel;
1016 : }
1017 :
1018 : /*
1019 : * left - isel: calls down need id's from the range of left
1020 : * res - rsel: updates to res need id's in the range from res
1021 : */
1022 31056 : for (en = en->next; en; en = en->next) {
1023 28932 : sql_exp *e = en->data;
1024 :
1025 28932 : next_cond = next_cond && en->next; /* last else is only a value */
1026 :
1027 28932 : stmt *nsel = rsel;
1028 28932 : if (!single_value) {
1029 28104 : if (/*!next_cond &&*/ rsel && isel) {
1030 : /* back into left range */
1031 3954 : nsel = stmt_project(be, rsel, isel);
1032 24150 : } else if (isel && !rsel)
1033 28932 : nsel = isel;
1034 : }
1035 28932 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1036 :
1037 28932 : if (!es)
1038 : return NULL;
1039 28932 : if (next_cond) {
1040 13404 : stmt *l = case_when;
1041 13404 : if (!single_value) {
1042 13033 : if (rsel && isel) {
1043 1662 : assert(l->cand == isel);
1044 1662 : l = stmt_project(be, rsel, l);
1045 1662 : l->cand = nsel;
1046 : }
1047 :
1048 13033 : if (es->cand && !l->cand) {
1049 9 : assert(es->cand == rsel);
1050 9 : l = stmt_project(be, es->cand, l);
1051 9 : l->cand = es->cand;
1052 13024 : } else if (nsel && !es->cand) {
1053 11299 : es = stmt_project(be, nsel, es);
1054 11299 : es->cand = nsel;
1055 11299 : if (!l->cand) {
1056 9324 : l = stmt_project(be, nsel, l);
1057 9324 : l->cand = nsel;
1058 : }
1059 : }
1060 13033 : assert(l->cand == es->cand);
1061 : }
1062 13404 : es = stmt_binop(be, l, es, NULL, cmp);
1063 : }
1064 28932 : if (!single_value) {
1065 : /* create result */
1066 28104 : if (!res) {
1067 2038 : stmt *l = isel;
1068 2038 : if (!l)
1069 1723 : l = bin_find_smallest_column(be, left);
1070 2038 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1071 2038 : ires = l;
1072 2038 : if (res)
1073 2038 : res->cand = isel;
1074 26066 : } else if (res && !next_cond) { /* use result to update column */
1075 15071 : stmt *val = es;
1076 15071 : stmt *pos = rsel;
1077 :
1078 15071 : if (val->nrcols == 0)
1079 13399 : val = stmt_const(be, pos, val);
1080 1672 : else if (!val->cand && nsel)
1081 209 : val = stmt_project(be, nsel, val);
1082 15071 : res = stmt_replace(be, res, pos, val);
1083 :
1084 15071 : assert(cond);
1085 :
1086 15071 : if (en->next) {
1087 : /* osel - rsel */
1088 13033 : if (!osel)
1089 2038 : osel = stmt_mirror(be, ires);
1090 13033 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
1091 13033 : osel = rsel = stmt_project(be, d, osel);
1092 : }
1093 : }
1094 28104 : if (next_cond) {
1095 13033 : ncond = cond = es;
1096 13033 : if (!ncond->nrcols) {
1097 0 : if (osel) {
1098 0 : ncond = stmt_const(be, nsel, ncond);
1099 0 : ncond->cand = nsel;
1100 0 : } else if (isel) {
1101 0 : ncond = stmt_const(be, isel, ncond);
1102 0 : ncond->cand = isel;
1103 : } else
1104 0 : ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
1105 : }
1106 13033 : if (isel && !ncond->cand)
1107 0 : ncond = stmt_project(be, nsel, ncond);
1108 24343 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
1109 13033 : if (rsel && ncond->cand)
1110 10995 : rsel = stmt_project(be, s, rsel);
1111 : else
1112 : rsel = s;
1113 : }
1114 : } else {
1115 828 : if (!res) {
1116 : /* if_barrier ... */
1117 371 : assert(next_cond);
1118 371 : if (next_cond) {
1119 371 : if (cond) {
1120 285 : ncond = stmt_binop(be, cond, es, nsel, and);
1121 : } else {
1122 : ncond = es;
1123 : }
1124 : cond = es;
1125 : }
1126 : } else {
1127 : /* var_x = s */
1128 457 : (void)stmt_assign(be, NULL, nme, es, 2);
1129 : /* endif_barrier */
1130 457 : (void)stmt_control_end(be, res);
1131 457 : res = NULL;
1132 :
1133 457 : if (en->next) {
1134 371 : cond = stmt_unop(be, cond, nsel, not);
1135 :
1136 371 : sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
1137 371 : cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
1138 371 : if (ocond)
1139 285 : cond = stmt_binop(be, ocond, cond, nsel, and);
1140 371 : ocond = cond;
1141 371 : if (!en->next->next)
1142 86 : ncond = cond;
1143 : }
1144 : }
1145 828 : if (ncond && (next_cond || (en->next && !en->next->next))) {
1146 : /* if_barrier ... */
1147 457 : res = stmt_cond(be, ncond, NULL, 0, 0);
1148 : }
1149 : }
1150 28932 : next_cond = !next_cond;
1151 : }
1152 2124 : if (single_value)
1153 86 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1154 : return res;
1155 : }
1156 :
1157 : static stmt*
1158 527 : exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
1159 : {
1160 527 : stmt *res = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL;
1161 527 : int single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
1162 527 : char name[16], *nme = NULL;
1163 527 : sql_subtype *bt = sql_bind_localtype("bit");
1164 527 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
1165 527 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
1166 :
1167 527 : if (single_value) {
1168 : /* var_x = nil; */
1169 57 : nme = number2name(name, sizeof(name), ++be->mvc->label);
1170 57 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
1171 : }
1172 :
1173 527 : list *exps = fe->l;
1174 2028 : for (node *en = exps->h; en; en = en->next) {
1175 1501 : sql_exp *e = en->data;
1176 :
1177 1501 : stmt *nsel = rsel;
1178 1501 : if (!single_value) {
1179 1346 : if (/*!next_cond &&*/ rsel && isel) {
1180 : /* back into left range */
1181 48 : nsel = stmt_project(be, rsel, isel);
1182 1298 : } else if (isel && !rsel)
1183 1501 : nsel = isel;
1184 : }
1185 1501 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1186 :
1187 1501 : if (!es)
1188 : return NULL;
1189 : /* create result */
1190 1501 : if (!single_value) {
1191 1346 : if (!res) {
1192 470 : stmt *l = isel;
1193 470 : if (!l)
1194 436 : l = bin_find_smallest_column(be, left);
1195 470 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1196 470 : if (res)
1197 470 : res->cand = isel;
1198 : }
1199 470 : if (res) {
1200 1346 : stmt *val = es;
1201 1346 : stmt *pos = rsel;
1202 :
1203 1346 : if (en->next) {
1204 876 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1205 876 : ncond = stmt_unop(be, es, NULL, a);
1206 876 : if (ncond->nrcols == 0) {
1207 120 : stmt *l = bin_find_smallest_column(be, left);
1208 120 : if (nsel && l)
1209 61 : l = stmt_project(be, nsel, l);
1210 120 : ncond = stmt_const(be, l, ncond);
1211 120 : if (nsel)
1212 61 : ncond->cand = nsel;
1213 756 : } else if (!ncond->cand && nsel)
1214 348 : ncond = stmt_project(be, nsel, ncond);
1215 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0);
1216 876 : if (!val->cand && nsel)
1217 409 : val = stmt_project(be, nsel, val);
1218 876 : val = stmt_project(be, s, val);
1219 876 : if (osel)
1220 406 : rsel = stmt_project(be, s, osel);
1221 : else
1222 : rsel = s;
1223 876 : pos = rsel;
1224 876 : val->cand = pos;
1225 : }
1226 1346 : if (val->nrcols == 0)
1227 163 : val = stmt_const(be, pos, val);
1228 1183 : else if (!val->cand && nsel)
1229 171 : val = stmt_project(be, nsel, val);
1230 :
1231 1346 : res = stmt_replace(be, res, pos, val);
1232 : }
1233 1346 : if (en->next) { /* handled then part */
1234 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0);
1235 876 : if (osel)
1236 406 : rsel = stmt_project(be, s, osel);
1237 : else
1238 : rsel = s;
1239 : osel = rsel;
1240 : }
1241 : } else {
1242 155 : stmt *cond = ocond;
1243 155 : if (en->next) {
1244 98 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1245 98 : ncond = stmt_unop(be, es, nsel, a);
1246 :
1247 98 : if (ocond)
1248 41 : cond = stmt_binop(be, ocond, ncond, nsel, and);
1249 : else
1250 : cond = ncond;
1251 : }
1252 :
1253 : /* if_barrier ... */
1254 155 : stmt *b = stmt_cond(be, cond, NULL, 0, 0);
1255 : /* var_x = s */
1256 155 : (void)stmt_assign(be, NULL, nme, es, 2);
1257 : /* endif_barrier */
1258 155 : (void)stmt_control_end(be, b);
1259 :
1260 155 : cond = stmt_unop(be, ncond, nsel, not);
1261 155 : if (ocond)
1262 98 : ocond = stmt_binop(be, cond, ocond, nsel, and);
1263 : else
1264 : ocond = cond;
1265 : }
1266 : }
1267 527 : if (single_value)
1268 57 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1269 : return res;
1270 : }
1271 :
1272 : // This is the per-column portion of exp2bin_copyfrombinary
1273 : static stmt *
1274 216 : emit_loadcolumn(backend *be, stmt *onclient_stmt, stmt *bswap_stmt, int *count_var, node *file_node, node *type_node)
1275 : {
1276 216 : MalBlkPtr mb = be->mb;
1277 :
1278 216 : sql_exp *file_exp = file_node->data;
1279 216 : stmt *file_stmt = exp_bin(be, file_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1280 216 : sql_subtype *subtype = type_node->data;
1281 216 : int data_type = subtype->type->localtype;
1282 216 : int bat_type = newBatType(data_type);
1283 :
1284 : // The sql.importColumn operator takes a 'method' string to determine how to
1285 : // load the data. This leaves the door open to have multiple loaders for the
1286 : // same backend type, for example nul- and newline terminated strings.
1287 : // For the time being we just use the name of the storage type as the method
1288 : // name.
1289 216 : const char *method = ATOMname(data_type);
1290 :
1291 216 : int width;
1292 216 : switch (subtype->type->eclass) {
1293 37 : case EC_DEC:
1294 : case EC_STRING:
1295 37 : width = subtype->digits;
1296 37 : break;
1297 : default:
1298 : width = 0;
1299 : break;
1300 : }
1301 :
1302 216 : int new_count_var = newTmpVariable(mb, TYPE_oid);
1303 :
1304 216 : InstrPtr p = newStmt(mb, sqlRef, importColumnRef);
1305 216 : if (p != NULL) {
1306 216 : setArgType(mb, p, 0, bat_type);
1307 216 : p = pushReturn(mb, p, new_count_var);
1308 : //
1309 216 : p = pushStr(mb, p, method);
1310 216 : p = pushInt(mb, p, width);
1311 216 : p = pushArgument(mb, p, bswap_stmt->nr);
1312 216 : p = pushArgument(mb, p, file_stmt->nr);
1313 216 : p = pushArgument(mb, p, onclient_stmt->nr);
1314 216 : if (*count_var < 0)
1315 94 : p = pushOid(mb, p, 0);
1316 : else
1317 122 : p = pushArgument(mb, p, *count_var);
1318 216 : pushInstruction(mb, p);
1319 : }
1320 216 : if (p == NULL || mb->errors) {
1321 0 : if (be->mvc->sa->eb.enabled)
1322 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1323 0 : return sql_error(be->mvc, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1324 : }
1325 :
1326 216 : *count_var = new_count_var;
1327 :
1328 216 : stmt *s = stmt_blackbox_result(be, p, 0, subtype);
1329 216 : return s;
1330 : }
1331 :
1332 : // Try to predict which column will be quickest to load first
1333 : static int
1334 216 : node_type_score(node *n)
1335 : {
1336 216 : sql_subtype *st = n->data;
1337 216 : int tpe = st->type->localtype;
1338 216 : int stpe = ATOMstorage(tpe);
1339 216 : int score = stpe + (stpe == TYPE_bit);
1340 216 : return score;
1341 : }
1342 :
1343 : static stmt*
1344 94 : exp2bin_copyfrombinary(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel)
1345 : {
1346 94 : mvc *sql = be->mvc;
1347 94 : assert(left == NULL); (void)left;
1348 94 : assert(right == NULL); (void)right;
1349 94 : assert(isel == NULL); (void)isel;
1350 94 : sql_subfunc *f = fe->f;
1351 :
1352 94 : list *arg_list = fe->l;
1353 94 : list *type_list = f->res;
1354 94 : assert(4 + list_length(type_list) == list_length(arg_list));
1355 :
1356 94 : sql_exp * onclient_exp = arg_list->h->next->next->data;
1357 94 : stmt *onclient_stmt = exp_bin(be, onclient_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1358 94 : sql_exp *bswap_exp = arg_list->h->next->next->next->data;
1359 94 : stmt *bswap_stmt = exp_bin(be, bswap_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1360 :
1361 : // If it's ON SERVER we can optimize by running the imports in parallel
1362 94 : bool onserver = false;
1363 94 : if (onclient_exp->type == e_atom) {
1364 94 : atom *onclient_atom = onclient_exp->l;
1365 94 : int onclient = onclient_atom->data.val.ival;
1366 94 : onserver = (onclient == 0);
1367 : }
1368 :
1369 94 : node *const first_file = arg_list->h->next->next->next->next;
1370 94 : node *const first_type = type_list->h;
1371 94 : node *file, *type;
1372 :
1373 : // The first column we load determines the number of rows.
1374 : // We pass it on to the other columns.
1375 : // The first column to load should therefore be an 'easy' one.
1376 : // We identify the columns by the address of their type node.
1377 94 : node *prototype_file = first_file;
1378 94 : node *prototype_type = first_type;
1379 94 : int score = node_type_score(prototype_type);
1380 216 : for (file = first_file->next, type = first_type->next; file && type; file = file->next, type = type->next) {
1381 122 : int sc = node_type_score(type);
1382 122 : if (sc < score) {
1383 6 : prototype_file = file;
1384 6 : prototype_type = type;
1385 6 : score = sc;
1386 : }
1387 : }
1388 :
1389 : // Emit the columns
1390 94 : int count_var = -1;
1391 94 : list *columns = sa_list(sql->sa);
1392 94 : if (columns == NULL)
1393 : return NULL;
1394 94 : stmt *prototype_stmt = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, prototype_file, prototype_type);
1395 94 : if (!prototype_stmt)
1396 : return NULL;
1397 94 : int orig_count_var = count_var;
1398 310 : for (file = first_file, type = first_type; file && type; file = file->next, type = type->next) {
1399 216 : stmt *s;
1400 216 : if (type == prototype_type) {
1401 : s = prototype_stmt;
1402 : } else {
1403 122 : s = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, file, type);
1404 122 : if (!s)
1405 : return NULL;
1406 : }
1407 216 : list_append(columns, s);
1408 216 : if (onserver) {
1409 : // Not threading the count variable from one importColumn to the next
1410 : // makes it possible to run them in parallel in a dataflow region.
1411 106 : count_var = orig_count_var;
1412 : }
1413 : }
1414 :
1415 94 : return stmt_list(be, columns);
1416 : }
1417 :
1418 : static bool
1419 240 : is_const_func(sql_subfunc *f, list *attr)
1420 : {
1421 240 : if (list_length(attr) != 2)
1422 : return false;
1423 134 : if (strcmp(f->func->base.name, "quantile") == 0 ||
1424 107 : strcmp(f->func->base.name, "quantile_avg") == 0)
1425 30 : return true;
1426 : return false;
1427 : }
1428 :
1429 : static stmt*
1430 12 : exp2bin_file_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
1431 : {
1432 12 : assert(left == NULL); (void)left;
1433 12 : assert(right == NULL); (void)right;
1434 12 : assert(sel == NULL); (void)sel;
1435 12 : sql_subfunc *f = fe->f;
1436 :
1437 12 : list *arg_list = fe->l;
1438 : /*
1439 : list *type_list = f->res;
1440 : assert(1 + list_length(type_list) == list_length(arg_list));
1441 : */
1442 :
1443 12 : sql_exp *eexp = arg_list->h->next->data;
1444 12 : assert(is_atom(eexp->type));
1445 12 : atom *ea = eexp->l;
1446 12 : assert(ea->data.vtype == TYPE_str);
1447 12 : char *ext = ea->data.val.sval;
1448 :
1449 12 : file_loader_t *fl = fl_find(ext);
1450 12 : if (!fl)
1451 0 : fl = fl_find("csv");
1452 0 : if (!fl)
1453 : return NULL;
1454 12 : sql_exp *fexp = arg_list->h->data;
1455 12 : assert(is_atom(fexp->type));
1456 12 : atom *fa = fexp->l;
1457 12 : assert(fa->data.vtype == TYPE_str);
1458 12 : char *filename = fa->data.val.sval;
1459 12 : sql_exp *topn = NULL;
1460 12 : if (list_length(arg_list) == 3)
1461 0 : topn = list_fetch(arg_list, 2);
1462 12 : return (stmt*)fl->load(be, f, filename, topn);
1463 : }
1464 :
1465 : stmt *
1466 4247768 : exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, int reduce, int push)
1467 : {
1468 4247768 : mvc *sql = be->mvc;
1469 4247768 : stmt *s = NULL;
1470 :
1471 4247768 : if (mvc_highwater(sql))
1472 0 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1473 :
1474 4249356 : if (!e) {
1475 0 : assert(0);
1476 : return NULL;
1477 : }
1478 :
1479 4249356 : switch(e->type) {
1480 7058 : case e_psm:
1481 7058 : if (e->flag & PSM_SET) {
1482 597 : stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1483 597 : if(!r)
1484 : return NULL;
1485 597 : if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
1486 6 : r = stmt_fetch(be, r);
1487 597 : return stmt_assign(be, exp_relname(e), exp_name(e), r, GET_PSM_LEVEL(e->flag));
1488 6461 : } else if (e->flag & PSM_VAR) {
1489 176 : if (e->f)
1490 20 : return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
1491 : else
1492 156 : return stmt_var(be, exp_relname(e), exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
1493 6285 : } else if (e->flag & PSM_RETURN) {
1494 507 : sql_exp *l = e->l;
1495 507 : stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel, 0, 0, push);
1496 :
1497 505 : if (!r)
1498 : return NULL;
1499 : /* handle table returning functions */
1500 505 : if (l->type == e_psm && l->flag & PSM_REL) {
1501 240 : stmt *lst = r->op1;
1502 280 : if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
1503 40 : node *n;
1504 40 : list *l = sa_list(sql->sa);
1505 40 : if (l == NULL)
1506 : return NULL;
1507 :
1508 86 : for (n=lst->op4.lval->h; n; n = n->next)
1509 46 : list_append(l, const_column(be, (stmt*)n->data));
1510 40 : r = stmt_list(be, l);
1511 200 : } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */
1512 35 : r = lst->op4.lval->h->data;
1513 35 : if (!r->aggr) /* if the cardinality is atom, no fetch call needed */
1514 4 : r = stmt_fetch(be, r);
1515 : }
1516 240 : if (r->type == st_list)
1517 40 : r = stmt_table(be, r, 1);
1518 : }
1519 505 : return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
1520 5778 : } else if (e->flag & PSM_WHILE) {
1521 : /* while is a if - block true with leave statement
1522 : * needed because the condition needs to be inside this outer block */
1523 17 : stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
1524 17 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1525 17 : stmt *wstmt;
1526 :
1527 17 : if(!cond)
1528 : return NULL;
1529 17 : wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
1530 :
1531 17 : if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
1532 : return NULL;
1533 17 : (void)stmt_control_end(be, wstmt);
1534 17 : return stmt_control_end(be, ifstmt);
1535 5761 : } else if (e->flag & PSM_IF) {
1536 120 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1537 120 : stmt *ifstmt, *res;
1538 :
1539 120 : if(!cond)
1540 : return NULL;
1541 120 : ifstmt = stmt_cond(be, cond, NULL, 0, 0);
1542 120 : if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
1543 : return NULL;
1544 120 : res = stmt_control_end(be, ifstmt);
1545 120 : if (e->f) {
1546 25 : stmt *elsestmt = stmt_cond(be, cond, NULL, 0, 1);
1547 :
1548 25 : if (!exp_list(be, e->f, left, right, grp, ext, cnt, sel))
1549 : return NULL;
1550 25 : res = stmt_control_end(be, elsestmt);
1551 : }
1552 120 : return res;
1553 5641 : } else if (e->flag & PSM_REL) {
1554 5484 : sql_rel *rel = e->l;
1555 5484 : stmt *r = rel_bin(be, rel);
1556 :
1557 5482 : if (!r)
1558 : return NULL;
1559 859 : if (is_modify(rel->op) || is_ddl(rel->op))
1560 : return r;
1561 646 : return stmt_table(be, r, 1);
1562 157 : } else if (e->flag & PSM_EXCEPTION) {
1563 157 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1564 157 : if (!cond)
1565 : return NULL;
1566 157 : if (cond->nrcols)
1567 0 : cond = stmt_fetch(be, cond);
1568 157 : return stmt_exception(be, cond, (const char *) e->r, 0);
1569 : }
1570 : break;
1571 2885586 : case e_atom: {
1572 2885586 : if (e->l) { /* literals */
1573 2744782 : s = stmt_atom(be, e->l);
1574 140804 : } else if (e->r) { /* parameters and declared variables */
1575 1666 : sql_var_name *vname = (sql_var_name*) e->r;
1576 1666 : assert(vname->name);
1577 1894 : s = stmt_var(be, vname->sname ? sa_strdup(sql->sa, vname->sname) : NULL, sa_strdup(sql->sa, vname->name), e->tpe.type?&e->tpe:NULL, 0, e->flag);
1578 139138 : } else if (e->f) { /* values */
1579 137086 : s = value_list(be, e->f, left, sel);
1580 : } else { /* arguments */
1581 2052 : sql_subtype *t = e->tpe.type?&e->tpe:NULL;
1582 2052 : if (!t && 0) {
1583 : sql_arg *a = sql_bind_paramnr(be->mvc, e->flag);
1584 : t = a->type.type?&a->type:NULL;
1585 : }
1586 2052 : s = stmt_varnr(be, e->flag, t);
1587 : }
1588 : } break;
1589 44221 : case e_convert: {
1590 : /* if input is type any NULL or column of nulls, change type */
1591 44221 : list *tps = e->r;
1592 44221 : sql_subtype *from = tps->h->data;
1593 44221 : sql_subtype *to = tps->h->next->data;
1594 44221 : stmt *l;
1595 :
1596 44221 : if (from->type->localtype == 0) {
1597 702 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1598 702 : if (l)
1599 701 : l = stmt_atom(be, atom_general(sql->sa, to, NULL, 0));
1600 : } else {
1601 43519 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1602 : }
1603 44220 : if (!l)
1604 238 : return NULL;
1605 43983 : if (from->type->eclass == EC_SEC && to->type->eclass == EC_SEC) {
1606 : // trivial conversion because EC_SEC is always in milliseconds
1607 : s = l;
1608 44309 : } else if (depth && sel && l->nrcols == 0 && left && left->nrcols && exp_unsafe(e, false, true)) {
1609 389 : stmt *rows = bin_find_smallest_column(be, left);
1610 389 : l = stmt_const(be, rows, l);
1611 389 : s = stmt_convert(be, l, sel, from, to);
1612 43793 : } else if (depth && l->nrcols == 0 && left && left->nrcols && from->type->localtype > to->type->localtype &&
1613 518 : exp_unsafe(e, false, true)) {
1614 256 : stmt *rows = bin_find_smallest_column(be, left);
1615 256 : l = stmt_const(be, rows, l);
1616 256 : s = stmt_convert(be, l, sel, from, to);
1617 : } else {
1618 78335 : s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, from, to);
1619 : }
1620 : } break;
1621 154712 : case e_func: {
1622 154712 : node *en;
1623 154712 : list *l = sa_list(sql->sa), *exps = e->l;
1624 154712 : sql_subfunc *f = e->f;
1625 154712 : const char *fname = f->func->base.name;
1626 154712 : stmt *rows = NULL;
1627 154712 : const char *mod, *fimp;
1628 :
1629 154712 : if (l == NULL)
1630 : return NULL;
1631 :
1632 : /* attempt to instantiate MAL functions now, so we can know if we can push candidate lists */
1633 154712 : if (f->func->lang == FUNC_LANG_MAL && backend_create_mal_func(be->mvc, f) < 0)
1634 : return NULL;
1635 154712 : mod = sql_func_mod(f->func);
1636 154712 : fimp = backend_function_imp(be, f->func);
1637 :
1638 154712 : if (f->func->side_effect && left && left->nrcols > 0 && f->func->type != F_LOADER && exps_card(exps) < CARD_MULTI) {
1639 101 : rows = bin_find_smallest_column(be, left);
1640 : }
1641 154712 : assert(!e->r);
1642 154712 : if (strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
1643 19551 : if (strcmp(fname, "star") == 0) {
1644 465 : if (!left)
1645 1 : return const_column(be, stmt_bool(be, 1));
1646 464 : return left->op4.lval->h->data;
1647 : }
1648 19086 : if (strcmp(fname, "case") == 0)
1649 16231 : return exp2bin_case(be, e, left, right, sel, depth);
1650 2855 : if (strcmp(fname, "casewhen") == 0)
1651 2124 : return exp2bin_casewhen(be, e, left, right, sel, depth);
1652 731 : if (strcmp(fname, "coalesce") == 0)
1653 527 : return exp2bin_coalesce(be, e, left, right, sel, depth);
1654 204 : if (strcmp(fname, "copyfrombinary") == 0)
1655 94 : return exp2bin_copyfrombinary(be, e, left, right, sel);
1656 110 : if (strcmp(fname, "file_loader") == 0)
1657 12 : return exp2bin_file_loader(be, e, left, right, sel);
1658 98 : if (strcmp(fname, "-1") == 0) /* map arguments to A0 .. An */
1659 3 : return exp2bin_named_placeholders(be, e);
1660 : }
1661 135256 : if (!list_empty(exps)) {
1662 134062 : unsigned nrcols = 0;
1663 134062 : int push_cands = can_push_cands(sel, mod, fimp);
1664 :
1665 392912 : for (en = exps->h; en; en = en->next) {
1666 269302 : sql_exp *e = en->data;
1667 491201 : stmt *es = exp_bin(be, e, left, right, grp, ext, cnt, (push_cands)?sel:NULL, depth+1, 0, push);
1668 :
1669 269302 : if (!es)
1670 : return NULL;
1671 : /*if (rows && en == exps->h && f->func->type != F_LOADER)
1672 : es = stmt_const(be, rows, es);*/
1673 258850 : else if (f->func->type == F_ANALYTIC && es->nrcols == 0) {
1674 7846 : if (en == exps->h && left && left->nrcols)
1675 463 : es = stmt_const(be, bin_find_smallest_column(be, left), es); /* ensure the first argument is a column */
1676 7846 : if (!f->func->s && !strcmp(f->func->base.name, "window_bound")
1677 3287 : && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next && left->nrcols)
1678 12 : es = stmt_const(be, bin_find_smallest_column(be, left), es);
1679 : }
1680 258850 : if (es->nrcols > nrcols)
1681 : nrcols = es->nrcols;
1682 258850 : list_append(l, es);
1683 : }
1684 : }
1685 124804 : if (!(s = stmt_Nop(be, stmt_list(be, l), sel, f, rows)))
1686 : return NULL;
1687 : } break;
1688 9883 : case e_aggr: {
1689 9883 : list *attr = e->l;
1690 9883 : list *r = e->r;
1691 9883 : stmt *as = NULL;
1692 9883 : sql_subfunc *a = e->f;
1693 :
1694 9883 : assert(sel == NULL);
1695 : /* cases
1696 : * 0) count(*)
1697 : * 1) general aggregation
1698 : * 2) aggregation with required order (quantile etc)
1699 : * 3) aggregation with optional order by, group_concat, xml_agg
1700 : * */
1701 15256 : if (attr && attr->h) {
1702 5374 : node *en;
1703 5374 : list *l = sa_list(sql->sa);
1704 :
1705 11073 : for (en = attr->h; en; en = en->next) {
1706 5700 : sql_exp *at = en->data;
1707 :
1708 5700 : as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
1709 :
1710 5700 : if (as && as->nrcols <= 0 && left && (!is_const_func(a, attr) || grp))
1711 222 : as = stmt_const(be, bin_find_smallest_column(be, left), as);
1712 5700 : if (en == attr->h && !en->next && exp_aggr_is_count(e))
1713 140 : as = exp_count_no_nil_arg(e, ext, at, as);
1714 : /* insert single value into a column */
1715 5700 : if (as && as->nrcols <= 0 && !left)
1716 64 : as = const_column(be, as);
1717 :
1718 82 : if (!as)
1719 1 : return NULL;
1720 5699 : append(l, as);
1721 : }
1722 5373 : if (need_distinct(e) && (grp || list_length(l) > 1)){
1723 26 : list *nl = sa_list(sql->sa);
1724 26 : stmt *ngrp = grp;
1725 26 : stmt *next = ext;
1726 26 : stmt *ncnt = cnt;
1727 26 : if (nl == NULL)
1728 : return NULL;
1729 54 : for (en = l->h; en; en = en->next) {
1730 28 : stmt *as = en->data;
1731 28 : stmt *g = stmt_group(be, as, ngrp, next, ncnt, 1);
1732 28 : ngrp = stmt_result(be, g, 0);
1733 28 : next = stmt_result(be, g, 1);
1734 28 : ncnt = stmt_result(be, g, 2);
1735 : }
1736 54 : for (en = l->h; en; en = en->next) {
1737 28 : stmt *as = en->data;
1738 28 : append(nl, stmt_project(be, next, as));
1739 : }
1740 26 : if (grp)
1741 25 : grp = stmt_project(be, next, grp);
1742 : l = nl;
1743 5347 : } else if (need_distinct(e)) {
1744 76 : stmt *a = l->h->data;
1745 76 : stmt *u = stmt_unique(be, a);
1746 76 : if (u == NULL)
1747 : return NULL;
1748 76 : l = sa_list(sql->sa);
1749 76 : if (l == NULL)
1750 : return NULL;
1751 76 : append(l, stmt_project(be, u, a));
1752 : }
1753 5373 : if (r) {
1754 22 : list *obe = r->h->data;
1755 22 : if (obe && obe->h) {
1756 22 : stmt *orderby = NULL, *orderby_vals, *orderby_ids, *orderby_grp;
1757 : /* order by */
1758 22 : if (grp) {
1759 22 : orderby = stmt_order(be, grp, true, true);
1760 :
1761 22 : orderby_vals = stmt_result(be, orderby, 0);
1762 22 : orderby_ids = stmt_result(be, orderby, 1);
1763 22 : orderby_grp = stmt_result(be, orderby, 2);
1764 : }
1765 44 : for (node *n = obe->h; n; n = n->next) {
1766 22 : sql_exp *oe = n->data;
1767 22 : stmt *os = exp_bin(be, oe, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
1768 22 : if (orderby)
1769 22 : orderby = stmt_reorder(be, os, is_ascending(oe), nulls_last(oe), orderby_ids, orderby_grp);
1770 : else
1771 0 : orderby = stmt_order(be, os, is_ascending(oe), nulls_last(oe));
1772 22 : orderby_vals = stmt_result(be, orderby, 0);
1773 22 : orderby_ids = stmt_result(be, orderby, 1);
1774 22 : orderby_grp = stmt_result(be, orderby, 2);
1775 : }
1776 : /* depending on type of aggr project input or ordered column */
1777 22 : stmt *h = l->h->data;
1778 22 : l->h->data = h = stmt_project(be, orderby_ids, h);
1779 22 : if (grp)
1780 22 : grp = stmt_project(be, orderby_ids, grp);
1781 5373 : (void)orderby_vals;
1782 : }
1783 : }
1784 5373 : as = stmt_list(be, l);
1785 : } else {
1786 : /* count(*) may need the default group (relation) and
1787 : and/or an attribute to count */
1788 4509 : if (grp) {
1789 : as = grp;
1790 1497 : } else if (left && !list_empty(left->op4.lval)) {
1791 1496 : as = bin_find_smallest_column(be, left);
1792 1496 : as = exp_count_no_nil_arg(e, ext, NULL, as);
1793 : } else {
1794 : /* create dummy single value in a column */
1795 1 : as = stmt_atom_lng(be, 0);
1796 1 : as = const_column(be, as);
1797 : }
1798 : }
1799 9882 : s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e));
1800 9882 : if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
1801 0 : s->flag |= OUTER_ZERO;
1802 : } break;
1803 993537 : case e_column: {
1804 993537 : if (right) /* check relation names */
1805 : //s = bin_find_column(be, right, e->l, e->r);
1806 47058 : s = bin_find_column_nid(be, right, e->nid);
1807 993537 : if (!s && left)
1808 : //s = bin_find_column(be, left, e->l, e->r);
1809 952546 : s = bin_find_column_nid(be, left, e->nid);
1810 993537 : if (s && grp)
1811 289 : s = stmt_project(be, ext, s);
1812 993537 : if (!s && right) {
1813 0 : TRC_CRITICAL(SQL_EXECUTION, "Could not find %s.%s\n", (char*)e->l, (char*)e->r);
1814 0 : print_stmtlist(sql->sa, left);
1815 0 : print_stmtlist(sql->sa, right);
1816 0 : if (!s) {
1817 0 : TRC_ERROR(SQL_EXECUTION, "Query: '%s'\n", be->client->query);
1818 : }
1819 0 : assert(s);
1820 : return NULL;
1821 : }
1822 : } break;
1823 154359 : case e_cmp: {
1824 154359 : stmt *l = NULL, *r = NULL, *r2 = NULL;
1825 154359 : int swapped = 0, is_select = 0, oldvtop, oldstop;
1826 154359 : sql_exp *re = e->r, *re2 = e->f;
1827 :
1828 : /* general predicate, select and join */
1829 154359 : if (e->flag == cmp_filter) {
1830 3572 : list *args;
1831 3572 : list *ops;
1832 3572 : node *n;
1833 3572 : int first = 1;
1834 :
1835 3572 : ops = sa_list(sql->sa);
1836 3572 : if (ops == NULL)
1837 : return NULL;
1838 3572 : args = e->l;
1839 7142 : for (n = args->h; n; n = n->next) {
1840 3572 : oldvtop = be->mb->vtop;
1841 3572 : oldstop = be->mb->stop;
1842 3572 : s = NULL;
1843 3572 : if (!swapped)
1844 3572 : s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
1845 3572 : if (!s && right && (first || swapped)) {
1846 9 : clean_mal_statements(be, oldstop, oldvtop);
1847 9 : s = exp_bin(be, n->data, right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
1848 9 : swapped = 1;
1849 : }
1850 3572 : if (!s)
1851 : return s;
1852 3570 : if (s->nrcols == 0 && first && left)
1853 619 : s = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), s);
1854 3570 : list_append(ops, s);
1855 3570 : first = 0;
1856 : }
1857 3570 : l = stmt_list(be, ops);
1858 3570 : ops = sa_list(sql->sa);
1859 3570 : if (ops == NULL)
1860 : return NULL;
1861 3570 : args = e->r;
1862 14053 : for (n = args->h; n; n = n->next) {
1863 10582 : s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
1864 10483 : if (!s)
1865 : return s;
1866 10483 : list_append(ops, s);
1867 : }
1868 3570 : r = stmt_list(be, ops);
1869 :
1870 3570 : if (!reduce) {
1871 433 : sql_subfunc *f = e->f;
1872 433 : list *ops = sa_list(sql->sa);
1873 866 : for (node *n = l->op4.lval->h ; n ; n = n->next)
1874 433 : append(ops, n->data);
1875 1601 : for (node *n = r->op4.lval->h ; n ; n = n->next)
1876 1168 : append(ops, n->data);
1877 433 : if (!(s = stmt_Nop(be, stmt_list(be, ops), sel, f, NULL)))
1878 : return NULL;
1879 : return s;
1880 : }
1881 :
1882 3137 : if (left && right && (exps_card(e->r) != CARD_ATOM || !exps_are_atoms(e->r))) {
1883 49 : sql_subfunc *f = e->f;
1884 49 : bool first = true;
1885 98 : for (node *n = l->op4.lval->h ; n ; n = n->next) {
1886 49 : stmt *s = n->data;
1887 49 : if (s->nrcols == 0) {
1888 0 : if (first)
1889 0 : n->data = stmt_const(be, bin_find_smallest_column(be, left), n->data);
1890 : else
1891 0 : n->data = column(be, s);
1892 : }
1893 49 : first = false;
1894 : }
1895 49 : first = true;
1896 162 : for (node *n = r->op4.lval->h ; n ; n = n->next) {
1897 113 : stmt *s = n->data;
1898 113 : if (s->nrcols == 0) {
1899 63 : if (first)
1900 3 : n->data = stmt_const(be, bin_find_smallest_column(be, right), s);
1901 : else /* last arg maybe const */
1902 60 : n->data = column(be, s);
1903 : }
1904 113 : first = false;
1905 : }
1906 49 : return stmt_genjoin(be, l, r, f, is_anti(e), swapped);
1907 : }
1908 3088 : assert(!swapped);
1909 3088 : s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
1910 3088 : return s;
1911 : }
1912 150787 : if (e->flag == cmp_in || e->flag == cmp_notin)
1913 16606 : return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), depth, reduce, push);
1914 134181 : if (e->flag == cmp_or && (!right || right->nrcols == 1))
1915 12955 : return exp_bin_or(be, e, left, right, grp, ext, cnt, sel, depth, reduce, push);
1916 121226 : if (e->flag == cmp_or && right) { /* join */
1917 0 : assert(0);
1918 : }
1919 :
1920 : /* mark use of join indices */
1921 121226 : if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
1922 620 : be->join_idx++;
1923 :
1924 121226 : oldvtop = be->mb->vtop;
1925 121226 : oldstop = be->mb->stop;
1926 121226 : if (!l) {
1927 241624 : l = exp_bin(be, e->l, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
1928 121226 : swapped = 0;
1929 : }
1930 121226 : if (!l && right) {
1931 16494 : clean_mal_statements(be, oldstop, oldvtop);
1932 16494 : l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1933 16494 : swapped = 1;
1934 : }
1935 :
1936 121226 : oldvtop = be->mb->vtop;
1937 121226 : oldstop = be->mb->stop;
1938 121226 : if (swapped || !right || !reduce)
1939 81710 : r = exp_bin(be, re, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
1940 : else
1941 40340 : r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1942 121226 : if (!r && !swapped) {
1943 2 : clean_mal_statements(be, oldstop, oldvtop);
1944 2 : r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1945 2 : is_select = 1;
1946 : }
1947 121226 : if (!r && swapped) {
1948 0 : clean_mal_statements(be, oldstop, oldvtop);
1949 0 : r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1950 0 : is_select = 1;
1951 : }
1952 121226 : if (re2 && (swapped || !right || !reduce))
1953 5288 : r2 = exp_bin(be, re2, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
1954 52 : else if (re2)
1955 52 : r2 = exp_bin(be, re2, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1956 :
1957 121226 : if (!l || !r || (re2 && !r2))
1958 : return NULL;
1959 :
1960 121220 : (void)is_select;
1961 121220 : if (reduce && left && right) {
1962 56834 : if (l->nrcols == 0)
1963 0 : l = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), l);
1964 56834 : if (r->nrcols == 0)
1965 4 : r = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r);
1966 56834 : if (r2 && r2->nrcols == 0)
1967 8 : r2 = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r2);
1968 4 : if (r2) {
1969 54 : s = stmt_join2(be, l, r, r2, (comp_type)e->flag, is_anti(e), is_symmetric(e), swapped);
1970 56780 : } else if (swapped) {
1971 16492 : s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag), 0, is_semantics(e), false);
1972 : } else {
1973 40288 : s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag, 0, is_semantics(e), false);
1974 : }
1975 : } else {
1976 64386 : if (r2) { /* handle all cases in stmt_uselect, reducing, non reducing, scalar etc */
1977 5053 : if (l->nrcols == 0 && ((sel && sel->nrcols > 0) || r->nrcols > 0 || r2->nrcols > 0 || reduce))
1978 56 : l = left ? stmt_const(be, bin_find_smallest_column(be, left), l) : column(be, l);
1979 5053 : s = stmt_uselect2(be, l, r, r2, (comp_type)e->flag, sel, is_anti(e), is_symmetric(e), reduce);
1980 : } else {
1981 : /* value compare or select */
1982 59333 : if (!reduce || (l->nrcols == 0 && r->nrcols == 0)) {
1983 775 : sql_subfunc *f = sql_bind_func(sql, "sys", compare_func((comp_type)e->flag, is_anti(e)),
1984 : tail_type(l), tail_type(l), F_FUNC, true, true);
1985 775 : assert(f);
1986 775 : if (is_semantics(e)) {
1987 104 : if (exp_is_null(e->l) && exp_is_null(e->r) && (e->flag == cmp_equal || e->flag == cmp_notequal)) {
1988 4 : s = stmt_bool(be, e->flag == cmp_equal ? !is_anti(e): is_anti(e));
1989 : } else {
1990 100 : list *args = sa_list(sql->sa);
1991 100 : if (args == NULL)
1992 : return NULL;
1993 : /* add nil semantics bit */
1994 100 : list_append(args, l);
1995 100 : list_append(args, r);
1996 100 : list_append(args, stmt_bool(be, 1));
1997 100 : s = stmt_Nop(be, stmt_list(be, args), sel, f, NULL);
1998 : }
1999 : } else {
2000 671 : s = stmt_binop(be, l, r, sel, f);
2001 : }
2002 775 : if (l->cand)
2003 0 : s->cand = l->cand;
2004 775 : if (r->cand)
2005 0 : s->cand = r->cand;
2006 : } else {
2007 : /* this can still be a join (as relational algebra and single value subquery results still means joins */
2008 58558 : s = stmt_uselect(be, l, r, (comp_type)e->flag, sel, is_anti(e), is_semantics(e));
2009 : }
2010 : }
2011 : }
2012 : } break;
2013 : default:
2014 : ;
2015 : }
2016 : return s;
2017 : }
2018 :
2019 : static stmt *
2020 456232 : stmt_col(backend *be, sql_column *c, stmt *del, int part)
2021 : {
2022 456232 : stmt *sc = stmt_bat(be, c, RDONLY, part);
2023 :
2024 456249 : if (isTable(c->t) && c->t->access != TABLE_READONLY &&
2025 444672 : (!isNew(c) || !isNew(c->t) /* alter */) &&
2026 430209 : (c->t->persistence == SQL_PERSIST || c->t->s) /*&& !c->t->commit_action*/) {
2027 430209 : stmt *u = stmt_bat(be, c, RD_UPD_ID, part);
2028 430211 : assert(u);
2029 430211 : sc = stmt_project_delta(be, sc, u);
2030 430375 : if (c->storage_type && c->storage_type[0] == 'D') {
2031 176 : stmt *v = stmt_bat(be, c, RD_EXT, part);
2032 176 : sc = stmt_dict(be, sc, v);
2033 430023 : } else if (c->storage_type && c->storage_type[0] == 'F') {
2034 8 : sc = stmt_for(be, sc, stmt_atom(be, atom_general(be->mvc->sa, &c->type, c->storage_type+4/*skip FOR-*/, be->mvc->timezone)));
2035 : }
2036 430199 : if (del)
2037 25780 : sc = stmt_project(be, del, sc);
2038 26040 : } else if (del) { /* always handle the deletes */
2039 6897 : sc = stmt_project(be, del, sc);
2040 : }
2041 456239 : return sc;
2042 : }
2043 :
2044 : static stmt *
2045 3596 : stmt_idx(backend *be, sql_idx *i, stmt *del, int part)
2046 : {
2047 3596 : stmt *sc = stmt_idxbat(be, i, RDONLY, part);
2048 :
2049 3596 : if (isTable(i->t) && i->t->access != TABLE_READONLY &&
2050 3596 : (!isNew(i) || !isNew(i->t) /* alter */) &&
2051 2871 : (i->t->persistence == SQL_PERSIST || i->t->s) /*&& !i->t->commit_action*/) {
2052 2871 : stmt *u = stmt_idxbat(be, i, RD_UPD_ID, part);
2053 2871 : sc = stmt_project_delta(be, sc, u);
2054 2871 : if (del)
2055 320 : sc = stmt_project(be, del, sc);
2056 725 : } else if (del) { /* always handle the deletes */
2057 613 : sc = stmt_project(be, del, sc);
2058 : }
2059 3596 : return sc;
2060 : }
2061 :
2062 : static int
2063 0 : stmt_set_type_param(mvc *sql, sql_subtype *type, stmt *param)
2064 : {
2065 0 : if (!type || !param || param->type != st_var)
2066 : return -1;
2067 :
2068 0 : if (set_type_param(sql, type, param->flag) == 0) {
2069 0 : param->op4.typeval = *type;
2070 0 : return 0;
2071 : }
2072 : return -1;
2073 : }
2074 :
2075 : /* check_types tries to match the t type with the type of s if they don't
2076 : * match s is converted. Returns NULL on failure.
2077 : */
2078 : static stmt *
2079 5075 : check_types(backend *be, sql_subtype *t, stmt *s, check_type tpe)
2080 : {
2081 5075 : mvc *sql = be->mvc;
2082 5075 : int c, err = 0;
2083 5075 : sql_subtype *fromtype = tail_type(s);
2084 :
2085 5075 : if ((!fromtype || !fromtype->type) && stmt_set_type_param(sql, t, s) == 0)
2086 : return s;
2087 0 : if (!fromtype)
2088 0 : return sql_error(sql, 02, SQLSTATE(42000) "statement has no type information");
2089 :
2090 5075 : if (fromtype && subtype_cmp(t, fromtype) != 0) {
2091 1 : if (EC_INTERVAL(fromtype->type->eclass) && (t->type->eclass == EC_NUM || t->type->eclass == EC_POS) && t->digits < fromtype->digits) {
2092 : err = 1; /* conversion from interval to num depends on the number of digits */
2093 : } else {
2094 1 : c = sql_type_convert(fromtype->type->eclass, t->type->eclass);
2095 1 : if (!c || (c == 2 && tpe == type_set) || (c == 3 && tpe != type_cast)) {
2096 : err = 1;
2097 : } else {
2098 1 : s = stmt_convert(be, s, NULL, fromtype, t);
2099 : }
2100 : }
2101 : }
2102 1 : if (err) {
2103 0 : stmt *res = sql_error(sql, 10, SQLSTATE(42000) "types %s(%u,%u) (%s) and %s(%u,%u) (%s) are not equal",
2104 : fromtype->type->base.name,
2105 : fromtype->digits,
2106 : fromtype->scale,
2107 0 : fromtype->type->impl,
2108 : t->type->base.name,
2109 : t->digits,
2110 : t->scale,
2111 0 : t->type->impl
2112 : );
2113 0 : return res;
2114 : }
2115 : return s;
2116 : }
2117 :
2118 : static stmt *
2119 5896 : sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
2120 : {
2121 5896 : mvc *sql = be->mvc;
2122 5896 : list *sl = sa_list(sql->sa);
2123 5896 : list *tl = sa_list(sql->sa);
2124 5896 : sql_subfunc *f = NULL;
2125 :
2126 5896 : if (sl == NULL || tl == NULL)
2127 : return NULL;
2128 5896 : list_append(sl, a1);
2129 5896 : list_append(tl, tail_type(a1));
2130 5896 : list_append(sl, a2);
2131 5896 : list_append(tl, tail_type(a2));
2132 5896 : list_append(sl, a3);
2133 5896 : list_append(tl, tail_type(a3));
2134 5896 : if (a4) {
2135 0 : list_append(sl, a4);
2136 0 : list_append(tl, tail_type(a4));
2137 : }
2138 :
2139 5896 : if ((f = sql_bind_func_(sql, "sys", fname, tl, F_FUNC, true, true)))
2140 5896 : return stmt_Nop(be, stmt_list(be, sl), NULL, f, NULL);
2141 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such operator '%s'", fname);
2142 : }
2143 :
2144 : static stmt *
2145 10 : parse_value(backend *be, sql_schema *s, char *query, sql_subtype *tpe, char emode)
2146 : {
2147 10 : sql_exp *e = NULL;
2148 :
2149 10 : if (!(e = rel_parse_val(be->mvc, s, query, tpe, emode, NULL)))
2150 : return NULL;
2151 10 : return exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2152 : }
2153 :
2154 : static stmt *
2155 1209 : rel2bin_sql_table(backend *be, sql_table *t, list *aliases)
2156 : {
2157 1209 : mvc *sql = be->mvc;
2158 1209 : list *l = sa_list(sql->sa);
2159 1209 : node *n;
2160 1209 : stmt *dels = stmt_tid(be, t, 0);
2161 :
2162 1209 : if (l == NULL || dels == NULL)
2163 : return NULL;
2164 1209 : if (aliases) {
2165 20474 : for (n = aliases->h; n; n = n->next) {
2166 19265 : sql_exp *e = n->data;
2167 19265 : if (e->type != e_column)
2168 105 : continue;
2169 19160 : assert(e->type == e_column);
2170 19160 : char *name = e->r;
2171 19160 : if (name[0] == '%') {
2172 1203 : if (strcmp(name, TID)==0) {
2173 : /* tid function sql.tid(t) */
2174 1203 : const char *rnme = t->base.name;
2175 :
2176 1203 : stmt *sc = dels?dels:stmt_tid(be, t, 0);
2177 1203 : sc = stmt_alias(be, sc, e->alias.label, rnme, TID);
2178 1203 : list_append(l, sc);
2179 : } else {
2180 0 : node *m = ol_find_name(t->idxs, name+1);
2181 0 : if (!m)
2182 0 : assert(0);
2183 0 : sql_idx *i = m->data;
2184 0 : stmt *sc = stmt_idx(be, i, dels, dels->partition);
2185 0 : const char *rnme = t->base.name;
2186 :
2187 : /* index names are prefixed, to make them independent */
2188 0 : sc = stmt_alias(be, sc, e->alias.label, rnme, sa_strconcat(sql->sa, "%", i->base.name));
2189 0 : list_append(l, sc);
2190 : }
2191 : } else {
2192 17957 : node *m = ol_find_name(t->columns, name);
2193 17957 : if (!m)
2194 0 : assert(0);
2195 17957 : sql_column *c = m->data;
2196 17957 : stmt *sc = stmt_col(be, c, dels, dels->partition);
2197 17957 : sc = stmt_alias(be, sc, e->alias.label, exp_relname(e), exp_name(e));
2198 17957 : list_append(l, sc);
2199 : }
2200 : }
2201 : } else {
2202 0 : assert(0);
2203 : sql_exp *e = NULL;
2204 : for (n = ol_first_node(t->columns); n; n = n->next) {
2205 : sql_column *c = n->data;
2206 : stmt *sc = stmt_col(be, c, dels, dels->partition);
2207 :
2208 : list_append(l, sc);
2209 : }
2210 : /* TID column */
2211 : if (ol_first_node(t->columns)) {
2212 : /* tid function sql.tid(t) */
2213 : const char *rnme = t->base.name;
2214 :
2215 : stmt *sc = dels?dels:stmt_tid(be, t, 0);
2216 : sc = stmt_alias(be, sc, e->alias.label, rnme, TID);
2217 : list_append(l, sc);
2218 : }
2219 : if (t->idxs) {
2220 : for (n = ol_first_node(t->idxs); n; n = n->next) {
2221 : sql_idx *i = n->data;
2222 : stmt *sc = stmt_idx(be, i, dels, dels->partition);
2223 : const char *rnme = t->base.name;
2224 :
2225 : /* index names are prefixed, to make them independent */
2226 : sc = stmt_alias(be, sc, e->alias.label, rnme, sa_strconcat(sql->sa, "%", i->base.name));
2227 : list_append(l, sc);
2228 : }
2229 : }
2230 : }
2231 1209 : return stmt_list(be, l);
2232 : }
2233 :
2234 : static stmt *
2235 132190 : rel2bin_basetable(backend *be, sql_rel *rel)
2236 : {
2237 132190 : mvc *sql = be->mvc;
2238 132190 : sql_table *t = rel->l;
2239 132190 : sql_column *fcol = NULL;
2240 132190 : sql_idx *fi = NULL;
2241 132190 : list *l = sa_list(sql->sa);
2242 132192 : stmt *dels = stmt_tid(be, t, rel->flag == REL_PARTITION), *col = NULL;
2243 132197 : node *en;
2244 :
2245 132197 : if (l == NULL || dels == NULL)
2246 : return NULL;
2247 : /* add aliases */
2248 132197 : assert(rel->exps);
2249 264406 : for (en = rel->exps->h; en && !col; en = en->next) {
2250 132210 : sql_exp *exp = en->data;
2251 132210 : const char *oname = exp->r;
2252 :
2253 132210 : if (is_func(exp->type) || (oname[0] == '%' && strcmp(oname, TID) == 0))
2254 923 : continue;
2255 131287 : if (oname[0] == '%') {
2256 61 : sql_idx *i = find_sql_idx(t, oname+1);
2257 :
2258 : /* do not include empty indices in the plan */
2259 61 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2260 0 : continue;
2261 61 : fi = i;
2262 61 : col = stmt_idx(be, i, NULL/*dels*/, dels->partition);
2263 : } else {
2264 131226 : sql_column *c = find_sql_column(t, oname);
2265 :
2266 131223 : fcol = c;
2267 131223 : col = stmt_col(be, c, NULL/*dels*/, dels->partition);
2268 : }
2269 : }
2270 572453 : for (en = rel->exps->h; en; en = en->next) {
2271 440260 : sql_exp *exp = en->data;
2272 440260 : const char *rname = exp_relname(exp)?exp_relname(exp):exp->l;
2273 440266 : const char *oname = exp->r;
2274 440266 : stmt *s = NULL;
2275 :
2276 440266 : assert(!is_func(exp->type));
2277 440266 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
2278 : /* tid function sql.tid(t) */
2279 : //const char *rnme = t->base.name;
2280 :
2281 14038 : if (col)
2282 13128 : s = stmt_mirror(be, col);
2283 : else {
2284 910 : s = dels?dels:stmt_tid(be, t, 0);
2285 : dels = NULL;
2286 : }
2287 : //s = stmt_alias(be, s, exp->alias.label, rnme, TID);
2288 426228 : } else if (oname[0] == '%') {
2289 2663 : sql_idx *i = find_sql_idx(t, oname+1);
2290 :
2291 : /* do not include empty indices in the plan */
2292 2663 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2293 0 : continue;
2294 2663 : s = (i == fi) ? col : stmt_idx(be, i, NULL/*dels*/, dels->partition);
2295 : //s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
2296 : } else {
2297 423565 : sql_column *c = find_sql_column(t, oname);
2298 :
2299 423575 : s = (c == fcol) ? col : stmt_col(be, c, NULL/*dels*/, dels->partition);
2300 : //s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
2301 : }
2302 440265 : s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
2303 : //s->tname = rname;
2304 : //s->cname = exp_name(exp);
2305 : //s->flag = exp->alias.label;
2306 440261 : list_append(l, s);
2307 : }
2308 132193 : stmt *res = stmt_list(be, l);
2309 132194 : if (res && dels)
2310 131285 : res->cand = dels;
2311 : return res;
2312 : }
2313 :
2314 : static int
2315 21 : alias_cmp(stmt *s, const char *nme)
2316 : {
2317 21 : return strcmp(s->cname, nme);
2318 : }
2319 :
2320 : static list* exps2bin_args(backend *be, list *exps, list *args);
2321 :
2322 : static list *
2323 1947 : exp2bin_args(backend *be, sql_exp *e, list *args)
2324 : {
2325 2018 : mvc *sql = be->mvc;
2326 :
2327 2018 : if (mvc_highwater(sql))
2328 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2329 :
2330 2018 : if (!e || !args)
2331 : return args;
2332 2018 : switch(e->type){
2333 : case e_column:
2334 : case e_psm:
2335 : return args;
2336 79 : case e_cmp:
2337 79 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2338 7 : args = exps2bin_args(be, e->l, args);
2339 7 : args = exps2bin_args(be, e->r, args);
2340 72 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2341 2 : args = exp2bin_args(be, e->l, args);
2342 2 : args = exps2bin_args(be, e->r, args);
2343 : } else {
2344 70 : args = exp2bin_args(be, e->l, args);
2345 70 : args = exp2bin_args(be, e->r, args);
2346 70 : if (e->f)
2347 : args = exp2bin_args(be, e->f, args);
2348 : }
2349 : return args;
2350 54 : case e_convert:
2351 54 : if (e->l)
2352 : return exp2bin_args(be, e->l, args);
2353 : break;
2354 150 : case e_aggr:
2355 : case e_func:
2356 150 : if (e->l)
2357 117 : return exps2bin_args(be, e->l, args);
2358 : break;
2359 337 : case e_atom:
2360 337 : if (e->l) {
2361 : return args;
2362 22 : } else if (e->f) {
2363 0 : return exps2bin_args(be, e->f, args);
2364 22 : } else if (e->r) {
2365 22 : sql_var_name *vname = (sql_var_name*) e->r;
2366 22 : const char *nme = sql_escape_ident(sql->sa, vname->name);
2367 22 : char *buf = NULL;
2368 :
2369 22 : if (vname->sname) { /* Global variable */
2370 3 : const char *sname = sql_escape_ident(sql->sa, vname->sname);
2371 6 : if (!nme || !sname || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(sname) + strlen(nme) + 6)))
2372 0 : return NULL;
2373 3 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(buf, "0\""), sname), "\"\""), nme), "\""); /* escape variable name */
2374 : } else { /* Parameter or local variable */
2375 19 : char levelstr[16];
2376 19 : snprintf(levelstr, sizeof(levelstr), "%u", e->flag);
2377 38 : if (!nme || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(nme) + 3)))
2378 0 : return NULL;
2379 19 : stpcpy(stpcpy(stpcpy(stpcpy(buf, levelstr), "\""), nme), "\""); /* escape variable name */
2380 : }
2381 22 : if (!list_find(args, buf, (fcmp)&alias_cmp)) {
2382 22 : stmt *s = stmt_var(be, vname->sname, vname->name, &e->tpe, 0, e->flag);
2383 :
2384 22 : if (!e->alias.label)
2385 18 : exp_label(be->mvc->sa, e, ++be->mvc->label);
2386 22 : s = stmt_alias(be, s, e->alias.label, NULL, sa_strdup(sql->sa, buf));
2387 22 : list_append(args, s);
2388 : }
2389 : }
2390 : }
2391 : return args;
2392 : }
2393 :
2394 : static list *
2395 417 : exps2bin_args(backend *be, list *exps, list *args)
2396 : {
2397 417 : node *n;
2398 :
2399 417 : if (!exps)
2400 : return args;
2401 2222 : for (n = exps->h; n; n = n->next)
2402 1805 : args = exp2bin_args(be, n->data, args);
2403 : return args;
2404 : }
2405 :
2406 : static list *
2407 197 : rel2bin_args(backend *be, sql_rel *rel, list *args)
2408 : {
2409 479 : if (mvc_highwater(be->mvc))
2410 0 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2411 :
2412 479 : if (!rel || !args)
2413 : return args;
2414 479 : switch(rel->op) {
2415 : case op_basetable:
2416 : case op_table:
2417 : break;
2418 11 : case op_join:
2419 : case op_left:
2420 : case op_right:
2421 : case op_full:
2422 :
2423 : case op_semi:
2424 : case op_anti:
2425 :
2426 : case op_union:
2427 : case op_inter:
2428 : case op_except:
2429 : case op_merge:
2430 11 : args = rel2bin_args(be, rel->l, args);
2431 11 : args = rel2bin_args(be, rel->r, args);
2432 11 : break;
2433 0 : case op_munion:
2434 0 : if (rel->l) {
2435 0 : for (node* n = ((list*)rel->l)->h; n; n = n->next) {
2436 0 : args = rel2bin_args(be, n->data, args);
2437 : }
2438 : }
2439 : break;
2440 49 : case op_groupby:
2441 49 : if (rel->r)
2442 13 : args = exps2bin_args(be, rel->r, args);
2443 : /* fall through */
2444 : case op_project:
2445 : case op_select:
2446 : case op_topn:
2447 : case op_sample:
2448 271 : if (rel->exps)
2449 271 : args = exps2bin_args(be, rel->exps, args);
2450 271 : args = rel2bin_args(be, rel->l, args);
2451 271 : break;
2452 0 : case op_ddl:
2453 0 : args = rel2bin_args(be, rel->l, args);
2454 0 : if (rel->r)
2455 : args = rel2bin_args(be, rel->r, args);
2456 : break;
2457 0 : case op_insert:
2458 : case op_update:
2459 : case op_delete:
2460 : case op_truncate:
2461 0 : args = rel2bin_args(be, rel->r, args);
2462 0 : break;
2463 : }
2464 : return args;
2465 : }
2466 :
2467 : typedef struct trigger_input {
2468 : sql_table *t;
2469 : stmt *tids;
2470 : stmt **updates;
2471 : int type; /* insert 1, update 2, delete 3, truncate 4 */
2472 : const char *on;
2473 : const char *nn;
2474 : } trigger_input;
2475 :
2476 : static stmt *
2477 2406 : rel2bin_table(backend *be, sql_rel *rel, list *refs)
2478 : {
2479 2406 : mvc *sql = be->mvc;
2480 2406 : list *l;
2481 2406 : stmt *sub = NULL, *osub = NULL;
2482 2406 : node *en, *n;
2483 2406 : sql_exp *op = rel->r;
2484 :
2485 2406 : if (rel->flag == TRIGGER_WRAPPER) {
2486 11 : trigger_input *ti = rel->l;
2487 11 : l = sa_list(sql->sa);
2488 11 : if (l == NULL)
2489 : return NULL;
2490 :
2491 20 : assert(list_length(rel->exps) == ((ti->type == 2)?2:1) * ol_length(ti->t->columns));
2492 30 : for (n = ol_first_node(ti->t->columns), en = rel->exps->h; n && en; n = n->next, en = en->next) {
2493 19 : sql_column *c = n->data;
2494 19 : sql_exp *e = en->data;
2495 :
2496 19 : if (ti->type == 2) { /* updates */
2497 4 : stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
2498 4 : append(l, stmt_alias(be, s, e->alias.label, ti->on, c->base.name));
2499 4 : en = en->next;
2500 4 : e = en->data;
2501 : }
2502 19 : if (ti->updates && ti->updates[c->colnr]) {
2503 17 : append(l, stmt_alias(be, ti->updates[c->colnr], e->alias.label, ti->nn, c->base.name));
2504 : } else {
2505 2 : stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
2506 2 : append(l, stmt_alias(be, s, e->alias.label, ti->nn, c->base.name));
2507 2 : assert(ti->type != 1);
2508 : }
2509 : }
2510 11 : sub = stmt_list(be, l);
2511 11 : return sub;
2512 2395 : } else if (op) {
2513 2209 : int i;
2514 2209 : sql_subfunc *f = op->f;
2515 2209 : stmt *psub = NULL;
2516 2209 : list *ops = NULL;
2517 2209 : stmt *ids = NULL;
2518 :
2519 2209 : if (rel->l) { /* first construct the sub relation */
2520 72 : sql_rel *l = rel->l;
2521 72 : if (l->op == op_ddl) {
2522 0 : sql_table *t = rel_ddl_table_get(l);
2523 :
2524 0 : if (t)
2525 0 : sub = rel2bin_sql_table(be, t, NULL);
2526 : } else {
2527 72 : sub = subrel_bin(be, rel->l, refs);
2528 : }
2529 72 : sub = subrel_project(be, sub, refs, rel->l);
2530 72 : if (!sub)
2531 : return NULL;
2532 : }
2533 :
2534 2209 : assert(f);
2535 2209 : if (f->func->res && list_length(f->func->res) + 1 == list_length(rel->exps) && !f->func->varres) {
2536 : /* add inputs in correct order ie loop through args of f and pass column */
2537 23 : list *exps = op->l;
2538 23 : ops = sa_list(be->mvc->sa);
2539 23 : if (exps) {
2540 83 : for (node *en = exps->h; en; en = en->next) {
2541 60 : sql_exp *e = en->data;
2542 :
2543 : /* find column */
2544 60 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2545 60 : if (!s)
2546 : return NULL;
2547 60 : if (en->next)
2548 37 : append(ops, s);
2549 : else /* last added exp is the ids (todo use name base lookup !!) */
2550 : ids = s;
2551 : }
2552 : }
2553 : } else {
2554 2186 : psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0); /* table function */
2555 2186 : if (!psub)
2556 : return NULL;
2557 : }
2558 2209 : l = sa_list(sql->sa);
2559 2209 : if (l == NULL)
2560 : return NULL;
2561 2209 : if (f->func->res) {
2562 2184 : if (f->func->varres) {
2563 11772 : for (i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++) {
2564 10556 : sql_exp *exp = en->data;
2565 10556 : sql_subtype *st = n->data;
2566 10556 : const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
2567 10556 : stmt *s = stmt_rs_column(be, psub, i, st);
2568 :
2569 10556 : s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
2570 10556 : list_append(l, s);
2571 : }
2572 : } else {
2573 968 : node *m = rel->exps->h;
2574 968 : int i = 0;
2575 :
2576 : /* correlated table returning function */
2577 968 : if (list_length(f->func->res) + 1 == list_length(rel->exps)) {
2578 : /* use a simple nested loop solution for this case, ie
2579 : * output a table of (input) row-ids, the output of the table producing function
2580 : */
2581 : /* make sure the input for sql.unionfunc are bats */
2582 23 : if (ids)
2583 23 : ids = column(be, ids);
2584 23 : if (ops)
2585 60 : for (node *en = ops->h; en; en = en->next)
2586 37 : en->data = column(be, (stmt *) en->data);
2587 :
2588 23 : int narg = 3 + list_length(rel->exps);
2589 23 : if (ops)
2590 23 : narg += list_length(ops);
2591 23 : InstrPtr q = newStmtArgs(be->mb, sqlRef, "unionfunc", narg);
2592 23 : if (q == NULL) {
2593 0 : if (be->mvc->sa->eb.enabled)
2594 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors ? be->mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
2595 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
2596 : }
2597 : /* Generate output rowid column and output of function f */
2598 69 : for (i=0; m; m = m->next, i++) {
2599 46 : sql_exp *e = m->data;
2600 46 : int type = exp_subtype(e)->type->localtype;
2601 :
2602 46 : type = newBatType(type);
2603 46 : if (i)
2604 23 : q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
2605 : else
2606 23 : getArg(q, 0) = newTmpVariable(be->mb, type);
2607 : }
2608 23 : if (backend_create_subfunc(be, f, ops) < 0) {
2609 0 : freeInstruction(q);
2610 0 : return NULL;
2611 : }
2612 23 : str mod = sql_func_mod(f->func);
2613 23 : str fcn = backend_function_imp(be, f->func);
2614 23 : q = pushStr(be->mb, q, mod);
2615 23 : q = pushStr(be->mb, q, fcn);
2616 23 : psub = stmt_direct_func(be, q);
2617 23 : if (psub == NULL) {
2618 0 : freeInstruction(q);
2619 0 : return NULL;
2620 : }
2621 :
2622 23 : if (ids) /* push input rowids column */
2623 23 : q = pushArgument(be->mb, q, ids->nr);
2624 :
2625 : /* add inputs in correct order ie loop through args of f and pass column */
2626 23 : if (ops) {
2627 60 : for (node *en = ops->h; en; en = en->next) {
2628 37 : stmt *op = en->data;
2629 :
2630 37 : q = pushArgument(be->mb, q, op->nr);
2631 : }
2632 : }
2633 23 : pushInstruction(be->mb, q);
2634 :
2635 : /* name output of dependent columns, output of function is handled the same as without correlation */
2636 23 : int len = list_length(rel->exps)-list_length(f->func->res);
2637 23 : assert(len== 1);
2638 46 : for (i=0, m=rel->exps->h; m && i<len; m = m->next, i++) {
2639 23 : sql_exp *exp = m->data;
2640 23 : stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp));
2641 :
2642 23 : s = stmt_alias(be, s, exp->alias.label, exp->l, exp->r);
2643 23 : list_append(l, s);
2644 : }
2645 : }
2646 7260 : for (n = f->func->res->h; n && m; n = n->next, m = m->next, i++) {
2647 6292 : sql_arg *a = n->data;
2648 6292 : sql_exp *exp = m->data;
2649 6292 : stmt *s = stmt_rs_column(be, psub, i, &a->type);
2650 6292 : const char *rnme = exp_relname(exp)?exp_relname(exp):exp_find_rel_name(op);
2651 :
2652 6292 : s = stmt_alias(be, s, exp->alias.label, rnme, a->name);
2653 6292 : list_append(l, s);
2654 : }
2655 : }
2656 : }
2657 2209 : assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
2658 2209 : sub = stmt_list(be, l);
2659 2209 : return sub;
2660 186 : } else if (rel->l) { /* handle sub query via function */
2661 186 : int i;
2662 186 : char name[16], *nme;
2663 :
2664 186 : nme = number2name(name, sizeof(name), ++be->remote);
2665 :
2666 186 : l = rel2bin_args(be, rel->l, sa_list(sql->sa));
2667 186 : if (!l)
2668 0 : return NULL;
2669 186 : sub = stmt_list(be, l);
2670 186 : if (!(sub = stmt_func(be, sub, sa_strdup(sql->sa, nme), rel->l, 0)))
2671 : return NULL;
2672 186 : rel->l = sub->op4.rel; /* rel->l may get rewritten */
2673 186 : l = sa_list(sql->sa);
2674 1593 : for (i = 0, n = rel->exps->h; n; n = n->next, i++) {
2675 1407 : sql_exp *c = n->data;
2676 1407 : stmt *s = stmt_rs_column(be, sub, i, exp_subtype(c));
2677 1407 : const char *nme = exp_name(c);
2678 1407 : const char *rnme = exp_relname(c);
2679 :
2680 1407 : s = stmt_alias(be, s, c->alias.label, rnme, nme);
2681 1407 : list_append(l, s);
2682 : }
2683 186 : sub = stmt_list(be, l);
2684 : }
2685 186 : if (!sub) {
2686 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
2687 : return NULL;
2688 : }
2689 186 : l = sa_list(sql->sa);
2690 186 : if (l == NULL)
2691 : return NULL;
2692 1593 : for (en = rel->exps->h; en; en = en->next) {
2693 1407 : sql_exp *exp = en->data;
2694 1407 : const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
2695 : //stmt *s = bin_find_column(be, sub, exp->l, exp->r);
2696 1407 : stmt *s = bin_find_column_nid(be, sub, exp->nid);
2697 :
2698 1407 : if (!s) {
2699 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
2700 : return NULL;
2701 : }
2702 1407 : if (sub && sub->nrcols >= 1 && s->nrcols == 0)
2703 0 : s = stmt_const(be, bin_find_smallest_column(be, sub), s);
2704 1407 : s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
2705 1407 : list_append(l, s);
2706 : }
2707 186 : if (osub && osub->nrcols)
2708 : list_merge(l, osub->op4.lval, NULL);
2709 186 : sub = stmt_list(be, l);
2710 186 : return sub;
2711 : }
2712 :
2713 : static stmt *
2714 90 : rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en)
2715 : {
2716 90 : mvc *sql = be->mvc;
2717 90 : node *n;
2718 90 : sql_subtype *it = sql_bind_localtype("int");
2719 90 : sql_subtype *lng = sql_bind_localtype("lng");
2720 90 : stmt *h = NULL;
2721 90 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
2722 90 : sql_exp *e = en->data;
2723 90 : sql_exp *l = e->l;
2724 90 : stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2725 90 : int swap_exp = 0, swap_rel = 0, semantics = 0;
2726 :
2727 90 : if (!idx) {
2728 49 : swap_exp = 1;
2729 49 : l = e->r;
2730 49 : idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2731 : }
2732 90 : if (!idx && right) {
2733 47 : swap_exp = 0;
2734 47 : swap_rel = 1;
2735 47 : l = e->l;
2736 47 : idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2737 : }
2738 90 : if (!idx && right) {
2739 0 : swap_exp = 1;
2740 0 : swap_rel = 1;
2741 0 : l = e->r;
2742 0 : idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2743 : }
2744 90 : if (!idx)
2745 : return NULL;
2746 : /* should be in key order! */
2747 314 : for (en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next) {
2748 226 : sql_exp *e = en->data;
2749 226 : stmt *s = NULL;
2750 :
2751 226 : if (e->type == e_cmp && e->flag == cmp_equal) {
2752 226 : sql_exp *ee = (swap_exp)?e->l:e->r;
2753 226 : if (swap_rel)
2754 109 : s = exp_bin(be, ee, left, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2755 : else
2756 117 : s = exp_bin(be, ee, right, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2757 : }
2758 :
2759 226 : if (!s)
2760 2 : return NULL;
2761 224 : if (h) {
2762 136 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
2763 :
2764 136 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(
2765 : list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
2766 136 : semantics = 1;
2767 : } else {
2768 88 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
2769 :
2770 88 : h = stmt_unop(be, s, NULL, hf);
2771 : }
2772 : }
2773 88 : if (n != NULL) /* need to use all cols of the index */
2774 : return NULL;
2775 87 : if (h && h->nrcols) {
2776 78 : if (!swap_rel) {
2777 31 : return stmt_join(be, idx, h, 0, cmp_equal, 0, semantics, false);
2778 : } else {
2779 47 : return stmt_join(be, h, idx, 0, cmp_equal, 0, semantics, false);
2780 : }
2781 : } else {
2782 9 : return stmt_uselect(be, idx, h, cmp_equal, NULL, 0, semantics);
2783 : }
2784 : }
2785 :
2786 : static stmt *
2787 4800 : join_hash_key(backend *be, list *l)
2788 : {
2789 4800 : mvc *sql = be->mvc;
2790 4800 : node *m;
2791 4800 : sql_subtype *it, *lng;
2792 4800 : stmt *h = NULL;
2793 4800 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
2794 :
2795 4800 : it = sql_bind_localtype("int");
2796 4800 : lng = sql_bind_localtype("lng");
2797 15220 : for (m = l->h; m; m = m->next) {
2798 10420 : stmt *s = m->data;
2799 :
2800 10420 : if (h) {
2801 5620 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
2802 :
2803 5620 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
2804 : } else {
2805 4800 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
2806 4800 : h = stmt_unop(be, s, NULL, hf);
2807 : }
2808 : }
2809 4800 : return h;
2810 : }
2811 :
2812 : static stmt *
2813 5034 : releqjoin(backend *be, list *l1, list *l2, list *exps, int used_hash, int need_left, int is_semantics)
2814 : {
2815 5034 : node *n1 = l1->h, *n2 = l2->h, *n3 = NULL;
2816 5034 : stmt *l, *r, *res;
2817 5034 : sql_exp *e;
2818 :
2819 5034 : if (exps)
2820 2339 : n3 = exps->h;
2821 5034 : if (list_length(l1) <= 1) {
2822 2309 : l = l1->h->data;
2823 2309 : r = l2->h->data;
2824 2309 : if (!is_semantics && exps) {
2825 0 : e = n3->data;
2826 0 : is_semantics = is_semantics(e);
2827 : }
2828 2309 : r = stmt_join(be, l, r, 0, cmp_equal, need_left, is_semantics, false);
2829 2309 : return r;
2830 : }
2831 2725 : if (used_hash) {
2832 325 : l = n1->data;
2833 325 : r = n2->data;
2834 325 : n1 = n1->next;
2835 325 : n2 = n2->next;
2836 325 : n3 = n3?n3->next:NULL;
2837 325 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
2838 : } else { /* need hash */
2839 2400 : l = join_hash_key(be, l1);
2840 2400 : r = join_hash_key(be, l2);
2841 2400 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
2842 : }
2843 2725 : l = stmt_result(be, res, 0);
2844 2725 : r = stmt_result(be, res, 1);
2845 16400 : for (; n1 && n2; n1 = n1->next, n2 = n2->next, n3 = n3?n3->next:NULL) {
2846 5954 : int semantics = is_semantics;
2847 5954 : stmt *ld = n1->data;
2848 5954 : stmt *rd = n2->data;
2849 5954 : stmt *le = stmt_project(be, l, ld);
2850 5954 : stmt *re = stmt_project(be, r, rd);
2851 5954 : stmt *cmp;
2852 : /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
2853 :
2854 5954 : if (!semantics && exps) {
2855 4996 : e = n3->data;
2856 4996 : semantics = is_semantics(e);
2857 : }
2858 5954 : cmp = stmt_uselect(be, le, re, cmp_equal, NULL, 0, semantics);
2859 5954 : l = stmt_project(be, cmp, l);
2860 5954 : r = stmt_project(be, cmp, r);
2861 : }
2862 2725 : res = stmt_join(be, l, r, 0, cmp_joined, 0, 0, false);
2863 2725 : return res;
2864 : }
2865 :
2866 : static bool
2867 70451 : can_join_exp(sql_rel *rel, sql_exp *e, bool anti)
2868 : {
2869 70451 : bool can_join = 0;
2870 :
2871 70451 : if (e->type == e_cmp) {
2872 70370 : int flag = e->flag;
2873 : /* check if its a select or join expression, ie use only expressions of one relation left and of the other right (than join) */
2874 70370 : if (flag < cmp_filter) { /* theta and range joins */
2875 : /* join or select ? */
2876 70279 : sql_exp *l = e->l, *r = e->r, *f = e->f;
2877 :
2878 70279 : if (f) {
2879 100 : int ll = rel_has_exp(rel->l, l, true) == 0;
2880 100 : int rl = rel_has_exp(rel->r, l, true) == 0;
2881 100 : int lr = rel_has_exp(rel->l, r, true) == 0;
2882 100 : int rr = rel_has_exp(rel->r, r, true) == 0;
2883 100 : int lf = rel_has_exp(rel->l, f, true) == 0;
2884 100 : int rf = rel_has_exp(rel->r, f, true) == 0;
2885 100 : int nrcr1 = 0, nrcr2 = 0, nrcl1 = 0, nrcl2 = 0;
2886 :
2887 100 : if ((ll && !rl &&
2888 82 : ((rr && !lr) || (nrcr1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
2889 70 : ((rf && !lf) || (nrcr2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcr1+nrcr2) <= 1) ||
2890 31 : (rl && !ll &&
2891 16 : ((lr && !rr) || (nrcl1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
2892 15 : ((lf && !rf) || (nrcl2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcl1+nrcl2) <= 1)) {
2893 : can_join = 1;
2894 : }
2895 : } else {
2896 70179 : int ll = 0, lr = 0, rl = 0, rr = 0, cst = 0;
2897 70179 : if (l->card != CARD_ATOM || !exp_is_atom(l)) {
2898 69980 : ll = rel_has_exp(rel->l, l, true) == 0;
2899 69980 : rl = rel_has_exp(rel->r, l, true) == 0;
2900 199 : } else if (anti) {
2901 15 : ll = 1;
2902 15 : cst = 1;
2903 : }
2904 70179 : if (r->card != CARD_ATOM || !exp_is_atom(r)) {
2905 70025 : lr = rel_has_exp(rel->l, r, true) == 0;
2906 70025 : rr = rel_has_exp(rel->r, r, true) == 0;
2907 154 : } else if (anti) {
2908 3 : rr = cst?0:1;
2909 : }
2910 70179 : if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
2911 69850 : can_join = 1;
2912 : }
2913 91 : } else if (flag == cmp_filter) {
2914 61 : list *l = e->l, *r = e->r;
2915 61 : int ll = 0, lr = 0, rl = 0, rr = 0;
2916 :
2917 122 : for (node *n = l->h ; n ; n = n->next) {
2918 61 : sql_exp *ee = n->data;
2919 :
2920 61 : if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
2921 58 : ll |= rel_has_exp(rel->l, ee, true) == 0;
2922 58 : rl |= rel_has_exp(rel->r, ee, true) == 0;
2923 : }
2924 : }
2925 207 : for (node *n = r->h ; n ; n = n->next) {
2926 146 : sql_exp *ee = n->data;
2927 :
2928 146 : if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
2929 63 : lr |= rel_has_exp(rel->l, ee, true) == 0;
2930 63 : rr |= rel_has_exp(rel->r, ee, true) == 0;
2931 : }
2932 : }
2933 61 : if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
2934 69850 : can_join = 1;
2935 : }
2936 : }
2937 70451 : return can_join;
2938 : }
2939 :
2940 : static void
2941 57852 : split_join_exps(sql_rel *rel, list *joinable, list *not_joinable, bool anti)
2942 : {
2943 57852 : if (!list_empty(rel->exps)) {
2944 119672 : for (node *n = rel->exps->h; n; n = n->next) {
2945 61826 : sql_exp *e = n->data;
2946 :
2947 : /* we can handle thetajoins, rangejoins and filter joins (like) */
2948 : /* ToDo how about atom expressions? */
2949 61826 : if (can_join_exp(rel, e, anti)) {
2950 61457 : append(joinable, e);
2951 : } else {
2952 369 : append(not_joinable, e);
2953 : }
2954 : }
2955 : }
2956 57852 : }
2957 :
2958 :
2959 : #define is_equi_exp_(e) ((e)->flag == cmp_equal)
2960 :
2961 : static list *
2962 3091 : get_simple_equi_joins_first(mvc *sql, sql_rel *rel, list *exps, bool *equality_only)
2963 : {
2964 3091 : list *new_exps = sa_list(sql->sa);
2965 3091 : *equality_only = true;
2966 :
2967 3091 : if (!exps)
2968 : return new_exps;
2969 :
2970 6083 : for (node *n = exps->h; n; n = n->next) {
2971 3095 : sql_exp *e = n->data;
2972 :
2973 3095 : if (can_join_exp(rel, e, false) && is_equi_exp_(e) && !is_any(e))
2974 218 : list_append(new_exps, e);
2975 : else
2976 2877 : *equality_only = false;
2977 : }
2978 6083 : for (node *n = exps->h; n; n = n->next) {
2979 3095 : sql_exp *e = n->data;
2980 :
2981 3095 : if (!is_equi_exp_(e) || !can_join_exp(rel, e, false) || is_any(e))
2982 2877 : list_append(new_exps, e);
2983 : }
2984 : return new_exps;
2985 : }
2986 :
2987 : static stmt *
2988 3091 : rel2bin_groupjoin(backend *be, sql_rel *rel, list *refs)
2989 : {
2990 3091 : mvc *sql = be->mvc;
2991 3091 : list *l;
2992 3091 : node *n , *en;
2993 3091 : stmt *left = NULL, *right = NULL, *join = NULL, *jl = NULL, *jr = NULL, *m = NULL, *ls = NULL, *res;
2994 3091 : bool need_project = false, exist = true, mark = false;
2995 :
2996 3091 : if (rel->op == op_left) { /* left outer group join */
2997 3003 : if (list_length(rel->attr) == 1) {
2998 3003 : sql_exp *e = rel->attr->h->data;
2999 3003 : if (exp_is_atom(e))
3000 3003 : mark = true;
3001 3003 : if (exp_is_atom(e) && exp_is_false(e))
3002 3091 : exist = false;
3003 : }
3004 : }
3005 :
3006 3091 : if (rel->l) /* first construct the left sub relation */
3007 3091 : left = subrel_bin(be, rel->l, refs);
3008 3091 : if (rel->r) /* first construct the right sub relation */
3009 3091 : right = subrel_bin(be, rel->r, refs);
3010 3091 : left = subrel_project(be, left, refs, rel->l);
3011 3091 : right = subrel_project(be, right, refs, rel->r);
3012 3091 : if (!left || !right)
3013 : return NULL;
3014 3091 : left = row2cols(be, left);
3015 3091 : right = row2cols(be, right);
3016 :
3017 3091 : bool equality_only = true;
3018 3091 : list *jexps = get_simple_equi_joins_first(sql, rel, rel->exps, &equality_only);
3019 :
3020 3091 : en = jexps?jexps->h:NULL;
3021 3527 : if (list_empty(jexps) || !(is_equi_exp_((sql_exp*)en->data) && can_join_exp(rel, en->data, false))) {
3022 436 : stmt *l = bin_find_smallest_column(be, left);
3023 436 : stmt *r = bin_find_smallest_column(be, right);
3024 436 : if (list_empty(jexps)) {
3025 114 : stmt *limit = stmt_limit(be, r, NULL, NULL, stmt_atom_lng(be, 0), stmt_atom_lng(be, 1), 0, 0, 0, 0, 0);
3026 114 : r = stmt_project(be, limit, r);
3027 : }
3028 436 : join = stmt_join_cand(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, 0, cmp_all, 0, 0, false, rel->op == op_left?false:true);
3029 436 : need_project = true;
3030 436 : jl = stmt_result(be, join, 0);
3031 436 : jr = stmt_result(be, join, 1);
3032 : } else {
3033 2655 : sql_exp *e = en->data;
3034 2655 : en = en->next;
3035 2655 : stmt *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 0, 1, 0), *r = NULL;
3036 2655 : bool swap = false;
3037 :
3038 2655 : if (!l) {
3039 16 : swap = true;
3040 16 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 0, 1, 0);
3041 : }
3042 16 : if (!l)
3043 : return NULL;
3044 2655 : if ((r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 0, 1, 0)) == NULL)
3045 : return NULL;
3046 :
3047 2655 : if (l && l->nrcols == 0)
3048 0 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
3049 2655 : if (r && r->nrcols == 0)
3050 0 : r = stmt_const(be, bin_find_smallest_column(be, right), r);
3051 2655 : if (swap) {
3052 16 : stmt *t = l;
3053 16 : l = r;
3054 16 : r = t;
3055 : }
3056 2655 : if ((!is_semantics(e) && is_anti(e)) || !mark)
3057 88 : ls = l;
3058 2655 : if (en || !mark) {
3059 : /* split out (left)join vs (left)mark-join */
3060 : /* call 3 result version */
3061 168 : if (mark && is_any(e)) {
3062 5 : join = stmt_markjoin(be, l, r, 0);
3063 : } else
3064 163 : join = stmt_join_cand(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_anti(e), (comp_type) cmp_equal/*e->flag*/, 0, is_any(e)|is_semantics(e), false, rel->op == op_left?false:true);
3065 168 : jl = stmt_result(be, join, 0);
3066 168 : jr = stmt_result(be, join, 1);
3067 168 : if (mark && is_any(e))
3068 5 : m = stmt_result(be, join, 2);
3069 : } else {
3070 2487 : join = stmt_markjoin(be, l, r, 1);
3071 2487 : jl = stmt_result(be, join, 0);
3072 2487 : m = stmt_result(be, join, 1);
3073 : }
3074 : }
3075 :
3076 3091 : if (en) {
3077 402 : stmt *sub, *sel = NULL, *osel = NULL;
3078 402 : list *nl;
3079 :
3080 402 : need_project = false;
3081 :
3082 : /* construct relation */
3083 402 : nl = sa_list(sql->sa);
3084 :
3085 : /* first project using equi-joins */
3086 2086 : for (n = left->op4.lval->h; n; n = n->next) {
3087 1684 : stmt *c = n->data;
3088 1684 : assert(c->type == st_alias);
3089 1684 : const char *rnme = table_name(sql->sa, c);
3090 1684 : const char *nme = column_name(sql->sa, c);
3091 1684 : stmt *s = stmt_project(be, jl, column(be, c));
3092 :
3093 1684 : s = stmt_alias(be, s, c->label, rnme, nme);
3094 1684 : list_append(nl, s);
3095 : }
3096 1026 : for (n = right->op4.lval->h; n; n = n->next) {
3097 624 : stmt *c = n->data;
3098 624 : assert(c->type == st_alias);
3099 624 : const char *rnme = table_name(sql->sa, c);
3100 624 : const char *nme = column_name(sql->sa, c);
3101 624 : stmt *s = stmt_project(be, jr, column(be, c));
3102 :
3103 624 : s = stmt_alias(be, s, c->label, rnme, nme);
3104 624 : list_append(nl, s);
3105 : }
3106 402 : left = sub = stmt_list(be, nl);
3107 :
3108 402 : if (!m) {
3109 397 : if (ls) {
3110 0 : stmt *nls = stmt_project(be, jl, ls);
3111 0 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", nls), stmt_bool(be, bit_nil),
3112 : sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL),
3113 : NULL);
3114 : } else {
3115 : /* 0 == empty (no matches possible), nil - no match (but has nil), 1 match */
3116 397 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL);
3117 : }
3118 : }
3119 :
3120 : /* continue with non equi-joins */
3121 842 : for ( ; en; en = en->next) {
3122 440 : sql_exp *e = en->data;
3123 440 : stmt *p = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3124 :
3125 440 : if (!p) {
3126 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3127 : return NULL;
3128 : }
3129 440 : if (p->nrcols == 0)
3130 1 : p = stmt_const(be, bin_find_smallest_column(be, sub), p);
3131 440 : if (sel)
3132 38 : p = stmt_project(be, sel, column(be, p));
3133 38 : stmt *li = jl;
3134 38 : if (sel)
3135 38 : li = stmt_project(be, sel, li);
3136 440 : osel = sel;
3137 440 : if (en->next) {
3138 38 : join = stmt_outerselect(be, li, m, p, is_any(e));
3139 : } else {
3140 402 : join = stmt_markselect(be, li, m, p, is_any(e));
3141 : }
3142 440 : sel = stmt_result(be, join, 0);
3143 440 : m = stmt_result(be, join, 1);
3144 : /* go back to offset in the table */
3145 440 : if (sel && osel)
3146 38 : sel = stmt_project(be, sel, osel);
3147 440 : if (!en->next)
3148 402 : jl = sel;
3149 : }
3150 : }
3151 : /* construct relation */
3152 3091 : l = sa_list(sql->sa);
3153 13831 : for (n = left->op4.lval->h; n; n = n->next) {
3154 10740 : stmt *c = n->data;
3155 10740 : assert(c->type == st_alias);
3156 10740 : const char *rnme = table_name(sql->sa, c);
3157 10740 : const char *nme = column_name(sql->sa, c);
3158 10740 : stmt *s = stmt_project(be, jl, column(be, c));
3159 :
3160 10740 : s = stmt_alias(be, s, c->label, rnme, nme);
3161 10740 : list_append(l, s);
3162 : }
3163 3091 : if (!mark && jr) {
3164 182 : for (n = right->op4.lval->h; n; n = n->next) {
3165 94 : stmt *c = n->data;
3166 94 : assert(c->type == st_alias);
3167 94 : const char *rnme = table_name(sql->sa, c);
3168 94 : const char *nme = column_name(sql->sa, c);
3169 94 : stmt *s = stmt_project(be, jr, column(be, c));
3170 :
3171 94 : s = stmt_alias(be, s, c->label, rnme, nme);
3172 94 : list_append(l, s);
3173 : }
3174 88 : left = stmt_list(be, l);
3175 88 : l = sa_list(sql->sa);
3176 : }
3177 3091 : if (rel->attr) {
3178 3091 : sql_exp *e = rel->attr->h->data;
3179 3091 : const char *rnme = exp_relname(e);
3180 3091 : const char *nme = exp_name(e);
3181 :
3182 3091 : if (mark) {
3183 3003 : if (need_project) {
3184 114 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, !exist), stmt_bool(be, exist), NULL);
3185 : } else {
3186 2889 : assert(m);
3187 2889 : sql_exp *e = rel->attr->h->data;
3188 2889 : if (exp_is_atom(e) && need_no_nil(e))
3189 298 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", m), stmt_bool(be, false), m, NULL);
3190 2889 : if (!exist) {
3191 54 : sql_subtype *bt = sql_bind_localtype("bit");
3192 54 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3193 54 : m = stmt_unop(be, m, NULL, not);
3194 : }
3195 : }
3196 3003 : stmt *s = stmt_alias(be, m, e->alias.label, rnme, nme);
3197 3003 : append(l, s);
3198 : } else {
3199 : /* group / aggrs */
3200 88 : stmt *nls = stmt_project(be, jl, ls);
3201 88 : stmt *groupby = stmt_group(be, nls, NULL, NULL, NULL, true);
3202 88 : stmt *grp = stmt_result(be, groupby, 0);
3203 88 : stmt *ext = stmt_result(be, groupby, 1);
3204 88 : stmt *cnt = stmt_result(be, groupby, 2);
3205 176 : for(node *n = rel->attr->h; n; n = n->next) {
3206 88 : sql_exp *e = n->data;
3207 88 : const char *rnme = exp_relname(e);
3208 88 : const char *nme = exp_name(e);
3209 88 : stmt *s = exp_bin(be, e, left, NULL, grp, ext, cnt, NULL, 0, 0, 0);
3210 88 : s = stmt_alias(be, s, e->alias.label, rnme, nme);
3211 88 : append(l, s);
3212 : }
3213 : }
3214 : }
3215 3091 : res = stmt_list(be, l);
3216 3091 : return res;
3217 : }
3218 :
3219 : static list *
3220 56882 : get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
3221 : {
3222 56882 : list *new_exps = sa_list(sql->sa);
3223 :
3224 117565 : for (node *n = exps->h; n; n = n->next) {
3225 60683 : sql_exp *e = n->data;
3226 :
3227 60683 : assert(e->type == e_cmp && e->flag != cmp_in && e->flag != cmp_notin && e->flag != cmp_or);
3228 60683 : if (is_equi_exp_(e))
3229 56823 : list_append(new_exps, e);
3230 : else
3231 3860 : *equality_only = 0;
3232 : }
3233 117565 : for (node *n = exps->h; n; n = n->next) {
3234 60683 : sql_exp *e = n->data;
3235 :
3236 60683 : if (!is_equi_exp_(e))
3237 3860 : list_append(new_exps, e);
3238 : }
3239 56882 : return new_exps;
3240 : }
3241 :
3242 : static stmt *
3243 67437 : rel2bin_join(backend *be, sql_rel *rel, list *refs)
3244 : {
3245 67437 : mvc *sql = be->mvc;
3246 67437 : list *l, *sexps = NULL, *l2 = NULL;
3247 67437 : node *en = NULL, *n;
3248 67437 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *ld = NULL, *rd = NULL, *res;
3249 67437 : int need_left = (rel->flag & LEFT_JOIN);
3250 :
3251 67437 : if (rel->attr && list_length(rel->attr) > 0)
3252 3091 : return rel2bin_groupjoin(be, rel, refs);
3253 :
3254 64346 : if (rel->l) /* first construct the left sub relation */
3255 64346 : left = subrel_bin(be, rel->l, refs);
3256 64346 : if (rel->r) /* first construct the right sub relation */
3257 64346 : right = subrel_bin(be, rel->r, refs);
3258 64346 : left = subrel_project(be, left, refs, rel->l);
3259 64346 : right = subrel_project(be, right, refs, rel->r);
3260 64346 : if (!left || !right)
3261 : return NULL;
3262 64346 : left = row2cols(be, left);
3263 64346 : right = row2cols(be, right);
3264 : /*
3265 : * split in 2 steps,
3266 : * first cheap join(s) (equality or idx)
3267 : * second selects/filters
3268 : */
3269 64346 : if (!list_empty(rel->exps)) {
3270 54411 : list *jexps = sa_list(sql->sa);
3271 54411 : sexps = sa_list(sql->sa);
3272 :
3273 54411 : split_join_exps(rel, jexps, sexps, false);
3274 54411 : if (list_empty(jexps)) { /* cross product and continue after project */
3275 226 : stmt *l = bin_find_smallest_column(be, left);
3276 226 : stmt *r = bin_find_smallest_column(be, right);
3277 226 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3278 : }
3279 :
3280 226 : if (join) {
3281 226 : en = jexps->h;
3282 : } else {
3283 54185 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
3284 54185 : int used_hash = 0, idx = 0, equality_only = 1;
3285 :
3286 54185 : (void) equality_only;
3287 54185 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
3288 : /* generate a relational join (releqjoin) which does a multi attribute (equi) join */
3289 108341 : for (en = jexps->h; en ; en = en->next) {
3290 56492 : int join_idx = be->join_idx;
3291 56492 : sql_exp *e = en->data;
3292 56492 : stmt *s = NULL;
3293 56492 : prop *p;
3294 :
3295 : /* stop search for equi joins on first non equi */
3296 56492 : if (list_length(lje) && (idx || e->type != e_cmp || e->flag != cmp_equal))
3297 : break;
3298 :
3299 : /* handle possible index lookups, expressions are in index order! */
3300 56414 : if (!join && (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
3301 78 : sql_idx *i = p->value.pval;
3302 78 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
3303 :
3304 78 : join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
3305 78 : if (s) {
3306 78 : list_append(lje, s->op1);
3307 78 : list_append(rje, s->op2);
3308 78 : list_append(exps, NULL);
3309 78 : used_hash = 1;
3310 : } else {
3311 : /* hash lookup cannot be used, clean leftover mal statements */
3312 0 : clean_mal_statements(be, oldstop, oldvtop);
3313 : }
3314 : }
3315 :
3316 56414 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
3317 56414 : if (!s) {
3318 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3319 0 : return NULL;
3320 : }
3321 56414 : if (join_idx != be->join_idx)
3322 620 : idx = 1;
3323 56414 : assert(s->type == st_join || s->type == st_join2 || s->type == st_joinN);
3324 56414 : if (!join)
3325 54107 : join = s;
3326 56414 : if (e->flag != cmp_equal) { /* only collect equi joins */
3327 2258 : en = en->next;
3328 2258 : break;
3329 : }
3330 54156 : list_append(lje, s->op1);
3331 54156 : list_append(rje, s->op2);
3332 54156 : list_append(exps, e);
3333 : }
3334 54185 : if (list_length(lje) > 1) {
3335 1982 : join = releqjoin(be, lje, rje, exps, used_hash, need_left, 0);
3336 52203 : } else if (!join || need_left) {
3337 632 : sql_exp *e = exps->h->data;
3338 632 : join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, need_left, is_semantics(e), false);
3339 : }
3340 : }
3341 : } else {
3342 9935 : stmt *l = bin_find_smallest_column(be, left);
3343 9935 : stmt *r = bin_find_smallest_column(be, right);
3344 9935 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, is_single(rel));
3345 : }
3346 64346 : jl = stmt_result(be, join, 0);
3347 64346 : jr = stmt_result(be, join, 1);
3348 64346 : if (en || (sexps && list_length(sexps))) {
3349 1382 : stmt *sub, *sel = NULL;
3350 1382 : list *nl;
3351 :
3352 : /* construct relation */
3353 1382 : nl = sa_list(sql->sa);
3354 :
3355 : /* first project using equi-joins */
3356 6282 : for (n = left->op4.lval->h; n; n = n->next) {
3357 4900 : stmt *c = n->data;
3358 4900 : assert(c->type == st_alias);
3359 4900 : const char *rnme = table_name(sql->sa, c);
3360 4900 : const char *nme = column_name(sql->sa, c);
3361 4900 : stmt *s = stmt_project(be, jl, column(be, c));
3362 :
3363 4900 : s = stmt_alias(be, s, c->label, rnme, nme);
3364 4900 : list_append(nl, s);
3365 : }
3366 4474 : for (n = right->op4.lval->h; n; n = n->next) {
3367 3092 : stmt *c = n->data;
3368 3092 : assert(c->type == st_alias);
3369 3092 : const char *rnme = table_name(sql->sa, c);
3370 3092 : const char *nme = column_name(sql->sa, c);
3371 3092 : stmt *s = stmt_project(be, jr, column(be, c));
3372 :
3373 3092 : s = stmt_alias(be, s, c->label, rnme, nme);
3374 3092 : list_append(nl, s);
3375 : }
3376 1382 : sub = stmt_list(be, nl);
3377 :
3378 : /* continue with non equi-joins */
3379 3888 : while(sexps) {
3380 2506 : if (!en) {
3381 1382 : en = sexps->h;
3382 1382 : sexps = NULL;
3383 : }
3384 3910 : for ( ; en; en = en->next) {
3385 1404 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
3386 :
3387 1404 : if (!s) {
3388 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3389 : return NULL;
3390 : }
3391 1404 : if (s->nrcols == 0) {
3392 82 : stmt *l = bin_find_smallest_column(be, sub);
3393 82 : s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
3394 : }
3395 1404 : sel = s;
3396 : }
3397 : }
3398 : /* recreate join output */
3399 1382 : jl = stmt_project(be, sel, jl);
3400 1382 : jr = stmt_project(be, sel, jr);
3401 : }
3402 :
3403 : /* construct relation */
3404 64346 : l = sa_list(sql->sa);
3405 :
3406 64346 : if (rel->op == op_left || rel->op == op_full || is_single(rel)) {
3407 : /* we need to add the missing oid's */
3408 8821 : stmt *l = ld = stmt_mirror(be, bin_find_smallest_column(be, left));
3409 8821 : if (rel->op == op_left || rel->op == op_full)
3410 6889 : ld = stmt_tdiff(be, ld, jl, NULL);
3411 8821 : if (is_single(rel) && !list_empty(rel->exps)) {
3412 280 : join = stmt_semijoin(be, l, jl, NULL, NULL, 0, true);
3413 280 : jl = stmt_result(be, join, 0);
3414 280 : jr = stmt_project(be, stmt_result(be, join, 1), jr);
3415 : }
3416 : }
3417 64346 : if (rel->op == op_right || rel->op == op_full) {
3418 : /* we need to add the missing oid's */
3419 166 : rd = stmt_mirror(be, bin_find_smallest_column(be, right));
3420 166 : rd = stmt_tdiff(be, rd, jr, NULL);
3421 : }
3422 :
3423 64346 : if (rel->op == op_left) { /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3424 6818 : l2 = sa_list(sql->sa);
3425 6818 : list_append(l2, left);
3426 6818 : list_append(l2, right);
3427 6818 : list_append(l2, jl);
3428 6818 : list_append(l2, jr);
3429 6818 : list_append(l2, ld);
3430 : }
3431 :
3432 1858699 : for (n = left->op4.lval->h; n; n = n->next) {
3433 1794353 : stmt *c = n->data;
3434 1794353 : const char *rnme = table_name(sql->sa, c);
3435 1794353 : const char *nme = column_name(sql->sa, c);
3436 1794353 : stmt *s = stmt_project(be, jl, column(be, c));
3437 :
3438 : /* as append isn't save, we append to a new copy */
3439 1794353 : if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
3440 42836 : s = create_const_column(be, s);
3441 1794353 : if (rel->op == op_left || rel->op == op_full)
3442 42634 : s = stmt_append(be, s, stmt_project(be, ld, c));
3443 1794353 : if (rel->op == op_right || rel->op == op_full)
3444 324 : 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, 0))));
3445 :
3446 1794353 : s = stmt_alias(be, s, c->label, rnme, nme);
3447 1794353 : list_append(l, s);
3448 : }
3449 245041 : for (n = right->op4.lval->h; n; n = n->next) {
3450 180695 : stmt *c = n->data;
3451 180695 : const char *rnme = table_name(sql->sa, c);
3452 180695 : const char *nme = column_name(sql->sa, c);
3453 180695 : stmt *s = stmt_project(be, jr, column(be, c));
3454 :
3455 : /* as append isn't save, we append to a new copy */
3456 180695 : if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
3457 14970 : s = create_const_column(be, s);
3458 180695 : if (rel->op == op_left || rel->op == op_full)
3459 14710 : 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, 0))));
3460 180695 : if (rel->op == op_right || rel->op == op_full)
3461 372 : s = stmt_append(be, s, stmt_project(be, rd, c));
3462 :
3463 180695 : s = stmt_alias(be, s, c->label, rnme, nme);
3464 180695 : list_append(l, s);
3465 : }
3466 64346 : if (rel->attr) {
3467 0 : sql_exp *e = rel->attr->h->data;
3468 0 : const char *rnme = exp_relname(e);
3469 0 : const char *nme = exp_name(e);
3470 0 : stmt *last = l->t->data;
3471 0 : sql_subtype *tp = tail_type(last);
3472 :
3473 0 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", tp, NULL, F_FUNC, true, true);
3474 :
3475 0 : stmt *s = stmt_unop(be, last, NULL, isnil);
3476 :
3477 0 : sql_subtype *bt = sql_bind_localtype("bit");
3478 0 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3479 :
3480 0 : s = stmt_unop(be, s, NULL, not);
3481 0 : s = stmt_alias(be, s, e->alias.label, rnme, nme);
3482 0 : list_append(l, s);
3483 : }
3484 :
3485 64346 : res = stmt_list(be, l);
3486 64346 : res->extra = l2; /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3487 64346 : return res;
3488 : }
3489 :
3490 : static stmt *
3491 690 : rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
3492 : {
3493 690 : mvc *sql = be->mvc;
3494 690 : list *l, *jexps = NULL, *sexps = NULL;
3495 690 : node *en = NULL, *n;
3496 690 : stmt *left = NULL, *right = NULL, *join = NULL, *sel = NULL, *sub = NULL;
3497 :
3498 690 : if (rel->l) /* first construct the left sub relation */
3499 690 : left = subrel_bin(be, rel->l, refs);
3500 690 : if (rel->r) /* first construct the right sub relation */
3501 690 : right = subrel_bin(be, rel->r, refs);
3502 690 : left = subrel_project(be, left, refs, rel->l);
3503 690 : right = subrel_project(be, right, refs, rel->r);
3504 690 : if (!left || !right)
3505 : return NULL;
3506 690 : left = row2cols(be, left);
3507 690 : right = row2cols(be, right);
3508 :
3509 690 : stmt *li = NULL;
3510 690 : bool swap = false;
3511 :
3512 690 : jexps = sa_list(sql->sa);
3513 690 : sexps = sa_list(sql->sa);
3514 :
3515 690 : split_join_exps(rel, jexps, sexps, true);
3516 690 : if (list_empty(jexps)) {
3517 16 : stmt *l = bin_find_smallest_column(be, left);
3518 16 : stmt *r = bin_find_smallest_column(be, right);
3519 16 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3520 :
3521 16 : jexps = sexps;
3522 16 : sexps = NULL;
3523 16 : en = jexps->h;
3524 : } else {
3525 674 : if (list_length(sexps))
3526 4 : list_merge(jexps, sexps, NULL);
3527 674 : en = jexps->h;
3528 674 : sql_exp *e = en->data;
3529 674 : assert(e->type == e_cmp);
3530 674 : stmt *ls = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0), *rs;
3531 674 : bool constval = false;
3532 674 : if (!ls) {
3533 12 : swap = true;
3534 12 : ls = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3535 : }
3536 12 : if (!ls)
3537 : return NULL;
3538 :
3539 674 : if (!(rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0)))
3540 : return NULL;
3541 :
3542 674 : if (swap) {
3543 12 : stmt *t = ls;
3544 12 : ls = rs;
3545 12 : rs = t;
3546 : }
3547 674 : if (ls->nrcols == 0) {
3548 10 : constval = true;
3549 10 : ls = stmt_const(be, bin_find_smallest_column(be, left), ls);
3550 : }
3551 674 : if (rs->nrcols == 0)
3552 3 : rs = stmt_const(be, bin_find_smallest_column(be, right), rs);
3553 :
3554 674 : if (!li)
3555 674 : li = ls;
3556 :
3557 674 : if (!en->next && (constval || stmt_has_null(ls) /*|| stmt_has_null(rs) (change into check for fk)*/)) {
3558 566 : assert(e->flag == cmp_equal);
3559 566 : join = stmt_tdiff2(be, ls, rs, NULL);
3560 566 : jexps = NULL;
3561 : } else {
3562 108 : join = stmt_join_cand(be, ls, rs, NULL, NULL, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false, true);
3563 : }
3564 674 : en = en->next;
3565 : }
3566 690 : if (en || jexps) {
3567 124 : stmt *jl = stmt_result(be, join, 0);
3568 124 : stmt *jr = stmt_result(be, join, 1);
3569 124 : stmt *nulls = NULL;
3570 :
3571 124 : if (li && stmt_has_null(li)) {
3572 67 : nulls = stmt_selectnil(be, li);
3573 : }
3574 : /* construct relation */
3575 124 : list *nl = sa_list(sql->sa);
3576 : /* first project after equi-joins */
3577 931 : for (n = left->op4.lval->h; n; n = n->next) {
3578 807 : stmt *c = n->data;
3579 807 : assert(c->type == st_alias);
3580 807 : const char *rnme = table_name(sql->sa, c);
3581 807 : const char *nme = column_name(sql->sa, c);
3582 807 : stmt *s = stmt_project(be, jl, column(be, c));
3583 :
3584 807 : s = stmt_alias(be, s, c->label, rnme, nme);
3585 807 : list_append(nl, s);
3586 : }
3587 359 : for (n = right->op4.lval->h; n; n = n->next) {
3588 235 : stmt *c = n->data;
3589 235 : assert(c->type == st_alias);
3590 235 : const char *rnme = table_name(sql->sa, c);
3591 235 : const char *nme = column_name(sql->sa, c);
3592 235 : stmt *s = stmt_project(be, jr, column(be, c));
3593 :
3594 235 : s = stmt_alias(be, s, c->label, rnme, nme);
3595 235 : list_append(nl, s);
3596 : }
3597 124 : sub = stmt_list(be, nl);
3598 :
3599 : /* continue with non equi-joins */
3600 362 : for (; en; en = en->next) {
3601 114 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, NULL /* sel */, 0, 0/* just the project call not the select*/, 0);
3602 :
3603 : /* ifthenelse if (not(predicate)) then false else true (needed for antijoin) */
3604 114 : sql_subtype *bt = sql_bind_localtype("bit");
3605 114 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3606 114 : s = stmt_unop(be, s, NULL, not);
3607 114 : s = sql_Nop_(be, "ifthenelse", s, stmt_bool(be, 0), stmt_bool(be, 1), NULL);
3608 :
3609 114 : if (s->nrcols == 0) {
3610 0 : stmt *l = bin_find_smallest_column(be, sub);
3611 0 : s = stmt_uselect(be, stmt_const(be, l, s), stmt_bool(be, 1), cmp_equal, sel, 0, 0);
3612 : } else {
3613 114 : s = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
3614 : }
3615 :
3616 114 : if (!s) {
3617 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3618 : return NULL;
3619 : }
3620 :
3621 114 : sel = s;
3622 : }
3623 124 : stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
3624 124 : if (nulls) {
3625 67 : stmt *nonilcand = stmt_tdiff(be, c, nulls, NULL);
3626 67 : c = stmt_project(be, nonilcand, c);
3627 : }
3628 124 : if (join && sel) {
3629 : /* recreate join output */
3630 89 : jl = stmt_project(be, sel, jl);
3631 89 : join = stmt_tdiff(be, c, jl, NULL);
3632 : } else {
3633 35 : join = stmt_tdiff2(be, c, jl, NULL);
3634 : }
3635 124 : if (nulls)
3636 67 : join = stmt_project(be, join, c);
3637 :
3638 : } else if (jexps && list_empty(jexps)) {
3639 : stmt *jl = stmt_result(be, join, 0);
3640 : stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
3641 : join = stmt_tdiff2(be, c, jl, NULL);
3642 : }
3643 :
3644 : /* construct relation */
3645 690 : l = sa_list(sql->sa);
3646 :
3647 : /* project all the left columns */
3648 4984 : for (n = left->op4.lval->h; n; n = n->next) {
3649 4294 : stmt *c = n->data;
3650 4294 : assert(c->type == st_alias);
3651 4294 : const char *rnme = table_name(sql->sa, c);
3652 4294 : const char *nme = column_name(sql->sa, c);
3653 4294 : stmt *s = stmt_project(be, join, column(be, c));
3654 :
3655 4294 : s = stmt_alias(be, s, c->label, rnme, nme);
3656 4294 : list_append(l, s);
3657 : }
3658 690 : return stmt_list(be, l);
3659 : }
3660 :
3661 : static stmt *
3662 2784 : rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
3663 : {
3664 2784 : mvc *sql = be->mvc;
3665 2784 : list *l, *sexps = NULL;
3666 2784 : node *en = NULL, *n;
3667 2784 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c, *lcand = NULL;
3668 2784 : int semijoin_only = 0, l_is_base = 0;
3669 :
3670 2784 : assert(rel->op != op_anti);
3671 :
3672 2784 : if (rel->l) { /* first construct the left sub relation */
3673 2784 : sql_rel *l = rel->l;
3674 2784 : l_is_base = is_basetable(l->op);
3675 2784 : left = subrel_bin(be, l, refs);
3676 : }
3677 2784 : if (rel->r) /* first construct the right sub relation */
3678 2784 : right = subrel_bin(be, rel->r, refs);
3679 2784 : if (!left || !right)
3680 : return NULL;
3681 2784 : left = row2cols(be, left);
3682 2784 : right = row2cols(be, right);
3683 : /*
3684 : * split in 2 steps,
3685 : * first cheap join(s) (equality or idx)
3686 : * second selects/filters
3687 : */
3688 2784 : if (!list_empty(rel->exps)) {
3689 2751 : list *jexps = sa_list(sql->sa);
3690 2751 : sexps = sa_list(sql->sa);
3691 :
3692 2751 : split_join_exps(rel, jexps, sexps, false);
3693 2751 : if (list_empty(jexps)) { /* cross product and continue after project */
3694 54 : right = subrel_project(be, right, refs, rel->r);
3695 54 : stmt *l = bin_find_smallest_column(be, left);
3696 54 : stmt *r = bin_find_smallest_column(be, right);
3697 54 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3698 54 : lcand = left->cand;
3699 : }
3700 :
3701 2751 : if (join) {
3702 54 : en = jexps->h;
3703 : } else {
3704 2697 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
3705 2697 : int idx = 0, equality_only = 1;
3706 :
3707 2697 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
3708 2697 : if (!equality_only || list_length(jexps) > 1 || exp_has_func((sql_exp*)jexps->h->data))
3709 827 : left = subrel_project(be, left, refs, rel->l);
3710 2697 : right = subrel_project(be, right, refs, rel->r);
3711 :
3712 5819 : for (en = jexps->h; en; en = en->next) {
3713 3135 : int join_idx = be->join_idx;
3714 3135 : sql_exp *e = en->data;
3715 3135 : stmt *s = NULL;
3716 :
3717 : /* only handle simple joins here */
3718 3135 : if ((exp_has_func(e) && e->flag != cmp_filter) || e->flag == cmp_or || (e->f && is_anti(e))) {
3719 3 : if (!join && !list_length(lje)) {
3720 3 : stmt *l = bin_find_smallest_column(be, left);
3721 3 : stmt *r = bin_find_smallest_column(be, right);
3722 3 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3723 : }
3724 : break;
3725 : }
3726 3132 : if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
3727 428 : (join && e->flag == cmp_filter)))
3728 : break;
3729 :
3730 3122 : if (equality_only) {
3731 2653 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop, swap = 0;
3732 2653 : stmt *r, *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3733 :
3734 2653 : if (l && left && l->nrcols==0 && left->nrcols >0)
3735 1 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
3736 379 : if (!l) {
3737 378 : swap = 1;
3738 378 : clean_mal_statements(be, oldstop, oldvtop);
3739 378 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3740 : }
3741 2653 : r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0);
3742 :
3743 2653 : if (swap) {
3744 378 : stmt *t = l;
3745 378 : l = r;
3746 378 : r = t;
3747 : }
3748 :
3749 2653 : if (!l || !r)
3750 0 : return NULL;
3751 2653 : if (be->no_mitosis && list_length(jexps) == 1 && list_empty(sexps) && rel->op == op_semi && !is_anti(e) && is_equi_exp_(e)) {
3752 0 : join = stmt_semijoin(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_semantics(e), false);
3753 0 : semijoin_only = 1;
3754 0 : en = NULL;
3755 0 : break;
3756 : } else
3757 2653 : s = stmt_join_cand(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false, true);
3758 2653 : lcand = left->cand;
3759 : } else {
3760 469 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
3761 : }
3762 3122 : if (!s) {
3763 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3764 : return NULL;
3765 : }
3766 3122 : if (join_idx != be->join_idx)
3767 0 : idx = 1;
3768 : /* stop on first non equality join */
3769 3122 : if (!join) {
3770 2694 : if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
3771 0 : if (!en->next && (s->type == st_uselect || s->type == st_uselect2))
3772 : join = s;
3773 : else
3774 : break;
3775 : }
3776 : join = s;
3777 428 : } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
3778 : /* handle select expressions */
3779 : break;
3780 : }
3781 3122 : if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
3782 3122 : list_append(lje, s->op1);
3783 3122 : list_append(rje, s->op2);
3784 3122 : list_append(exps, e);
3785 : }
3786 : }
3787 2697 : if (list_length(lje) > 1) {
3788 357 : join = releqjoin(be, lje, rje, exps, 0 /* use hash */, 0, rel->op == op_anti?1:0);
3789 2340 : } else if (!join && list_length(lje) == list_length(rje) && list_length(lje)) {
3790 0 : sql_exp *e = exps->h->data;
3791 0 : join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, 0, is_semantics(e), false);
3792 0 : } else if (!join) {
3793 0 : stmt *l = bin_find_smallest_column(be, left);
3794 0 : stmt *r = bin_find_smallest_column(be, right);
3795 0 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3796 : }
3797 : }
3798 : } else {
3799 33 : right = subrel_project(be, right, refs, rel->r);
3800 33 : stmt *l = bin_find_smallest_column(be, left);
3801 33 : stmt *r = bin_find_smallest_column(be, right);
3802 33 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3803 33 : lcand = left->cand;
3804 : }
3805 2784 : jl = stmt_result(be, join, 0);
3806 2784 : if (en || (sexps && list_length(sexps))) {
3807 88 : stmt *sub, *sel = NULL;
3808 88 : list *nl;
3809 :
3810 88 : jr = stmt_result(be, join, 1);
3811 : /* construct relation */
3812 88 : nl = sa_list(sql->sa);
3813 :
3814 : /* first project after equi-joins */
3815 434 : for (n = left->op4.lval->h; n; n = n->next) {
3816 346 : stmt *c = n->data;
3817 346 : assert(c->type == st_alias);
3818 346 : const char *rnme = table_name(sql->sa, c);
3819 346 : const char *nme = column_name(sql->sa, c);
3820 346 : stmt *s = stmt_project(be, jl, column(be, c));
3821 :
3822 346 : s = stmt_alias(be, s, c->label, rnme, nme);
3823 346 : list_append(nl, s);
3824 : }
3825 247 : for (n = right->op4.lval->h; n; n = n->next) {
3826 159 : stmt *c = n->data;
3827 159 : assert(c->type == st_alias);
3828 159 : const char *rnme = table_name(sql->sa, c);
3829 159 : const char *nme = column_name(sql->sa, c);
3830 159 : stmt *s = stmt_project(be, jr, column(be, c));
3831 :
3832 159 : s = stmt_alias(be, s, c->label, rnme, nme);
3833 159 : list_append(nl, s);
3834 : }
3835 88 : sub = stmt_list(be, nl);
3836 :
3837 : /* continue with non equi-joins */
3838 189 : while(sexps) {
3839 101 : if (!en) {
3840 88 : en = sexps->h;
3841 88 : sexps = NULL;
3842 : }
3843 199 : for ( ; en; en = en->next) {
3844 98 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
3845 :
3846 98 : if (!s) {
3847 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3848 : return NULL;
3849 : }
3850 98 : if (s->nrcols == 0) {
3851 2 : stmt *l = bin_find_smallest_column(be, sub);
3852 2 : s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
3853 : }
3854 98 : sel = s;
3855 : }
3856 : }
3857 : /* recreate join output */
3858 88 : jl = stmt_project(be, sel, jl);
3859 : }
3860 :
3861 : /* construct relation */
3862 2784 : l = sa_list(sql->sa);
3863 :
3864 : /* We did a full join, that's too much.
3865 : Reduce this using difference and intersect */
3866 2784 : if (!semijoin_only) {
3867 2784 : c = stmt_mirror(be, bin_find_smallest_column(be, left));
3868 2784 : if (rel->op == op_anti) {
3869 0 : assert(0);
3870 : join = stmt_tdiff(be, c, jl, lcand);
3871 : } else {
3872 2784 : if (lcand)
3873 1051 : join = stmt_semijoin(be, c, jl, lcand, NULL/*right->cand*/, 0, false);
3874 : else
3875 1733 : join = stmt_tinter(be, c, jl, false);
3876 : }
3877 : }
3878 :
3879 : /* project all the left columns */
3880 20254 : for (n = left->op4.lval->h; n; n = n->next) {
3881 17470 : stmt *c = n->data, *s;
3882 17470 : const char *rnme = table_name(sql->sa, c);
3883 17470 : const char *nme = column_name(sql->sa, c);
3884 :
3885 17470 : if (semijoin_only && l_is_base && nme[0] == '%' && strcmp(nme, TID) == 0)
3886 : s = join;
3887 : else
3888 17470 : s = stmt_project(be, join, column(be, c));
3889 :
3890 17470 : s = stmt_alias(be, s, c->label, rnme, nme);
3891 17470 : list_append(l, s);
3892 : }
3893 2784 : return stmt_list(be, l);
3894 : }
3895 :
3896 : static stmt *
3897 1701 : rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
3898 : {
3899 1701 : mvc *sql = be->mvc;
3900 1701 : node *n;
3901 1701 : stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
3902 1701 : list *rl = sa_list(sql->sa), *tids;
3903 :
3904 : /* single values are unique */
3905 1701 : if (s->key && s->nrcols == 0)
3906 : return s;
3907 :
3908 : /* Use 'all' tid columns */
3909 1692 : if (/* DISABLES CODE */ (0) && (tids = bin_find_columns(be, s, TID)) != NULL) {
3910 : for (n = tids->h; n; n = n->next) {
3911 : stmt *t = n->data;
3912 :
3913 : g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
3914 : grp = stmt_result(be, g, 0);
3915 : ext = stmt_result(be, g, 1);
3916 : cnt = stmt_result(be, g, 2);
3917 : }
3918 : } else {
3919 3754 : for (n = s->op4.lval->h; n; n = n->next) {
3920 2062 : stmt *t = n->data;
3921 :
3922 2062 : g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
3923 2062 : grp = stmt_result(be, g, 0);
3924 2062 : ext = stmt_result(be, g, 1);
3925 2062 : cnt = stmt_result(be, g, 2);
3926 : }
3927 : }
3928 1692 : if (!ext)
3929 : return NULL;
3930 :
3931 3754 : for (n = s->op4.lval->h; n; n = n->next) {
3932 2062 : stmt *t = n->data;
3933 :
3934 2062 : stmt *s = stmt_project(be, ext, t);
3935 2062 : t = stmt_alias(be, s, t->label, table_name(sql->sa, t), column_name(sql->sa, t));
3936 2062 : list_append(rl, t);
3937 : }
3938 :
3939 1692 : if (distinct)
3940 5 : *distinct = ext;
3941 1692 : s = stmt_list(be, rl);
3942 1692 : return s;
3943 : }
3944 :
3945 : static stmt *
3946 11 : rel2bin_single(backend *be, stmt *s)
3947 : {
3948 11 : if (s->key && s->nrcols == 0)
3949 : return s;
3950 :
3951 11 : mvc *sql = be->mvc;
3952 11 : list *rl = sa_list(sql->sa);
3953 :
3954 25 : for (node *n = s->op4.lval->h; n; n = n->next) {
3955 14 : stmt *t = n->data;
3956 14 : assert(t->type == st_alias);
3957 14 : const char *rnme = table_name(sql->sa, t);
3958 14 : const char *nme = column_name(sql->sa, t);
3959 14 : int label = t->label;
3960 14 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", tail_type(t), NULL, F_AGGR, true, true);
3961 :
3962 14 : t = stmt_aggr(be, t, NULL, NULL, zero_or_one, 1, 0, 1);
3963 14 : t = stmt_alias(be, t, label, rnme, nme);
3964 14 : list_append(rl, t);
3965 : }
3966 11 : s = stmt_list(be, rl);
3967 11 : return s;
3968 : }
3969 :
3970 : static stmt *
3971 6603 : rel_rename(backend *be, sql_rel *rel, stmt *sub)
3972 : {
3973 6603 : mvc *sql = be->mvc;
3974 :
3975 6603 : (void) sql;
3976 6603 : if (rel->exps) {
3977 6603 : node *en, *n;
3978 6603 : list *l = sa_list(be->mvc->sa);
3979 :
3980 29286 : for (en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next) {
3981 22683 : sql_exp *exp = en->data;
3982 22683 : stmt *s = n->data;
3983 :
3984 22683 : if (!s) {
3985 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3986 : return NULL;
3987 : }
3988 22683 : s = stmt_rename(be, exp, s);
3989 22683 : list_append(l, s);
3990 : }
3991 6603 : sub = stmt_list(be, l);
3992 : }
3993 : return sub;
3994 : }
3995 :
3996 : static stmt *
3997 3905 : rel2bin_munion(backend *be, sql_rel *rel, list *refs)
3998 : {
3999 3905 : mvc *sql = be->mvc;
4000 3905 : list *l, *rstmts;
4001 3905 : node *n, *m;
4002 3905 : stmt *rel_stmt = NULL, *sub;
4003 3905 : int i, len = 0, nr_unions = list_length((list*)rel->l);
4004 :
4005 : /* convert to stmt and store the munion operands in rstmts list */
4006 3905 : rstmts = sa_list(sql->sa);
4007 13869 : for (n = ((list*)rel->l)->h; n; n = n->next) {
4008 9964 : rel_stmt = subrel_bin(be, n->data, refs);
4009 9964 : rel_stmt = subrel_project(be, rel_stmt, refs, n->data);
4010 9964 : if (!rel_stmt)
4011 : return NULL;
4012 9964 : list_append(rstmts, rel_stmt);
4013 9964 : if (!len || len > list_length(rel_stmt->op4.lval))
4014 3905 : len = list_length(rel_stmt->op4.lval);
4015 : }
4016 :
4017 : /* construct relation */
4018 3905 : l = sa_list(sql->sa);
4019 :
4020 : /* for every op4 lval node */
4021 : //len = list_length(((stmt*)rstmts->h->data)->op4.lval);
4022 21797 : for (i = 0; i < len; i++) {
4023 : /* extract t and c name from the first stmt */
4024 13987 : stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
4025 13987 : if (s == NULL)
4026 : return NULL;
4027 13987 : const char *rnme = table_name(sql->sa, s);
4028 13987 : const char *nme = column_name(sql->sa, s);
4029 13987 : int label = s->label;
4030 : /* create a const column also from the first stmt */
4031 13987 : s = stmt_pack(be, column(be, s), nr_unions);
4032 : /* for every other rstmt */
4033 37054 : for (m = rstmts->h->next; m; m = m->next) {
4034 23067 : stmt *t = list_fetch(((stmt*)m->data)->op4.lval, i);
4035 23067 : if (t == NULL)
4036 : return NULL;
4037 23067 : s = stmt_pack_add(be, s, column(be, t));
4038 23067 : if (s == NULL)
4039 : return NULL;
4040 : }
4041 13987 : s = stmt_alias(be, s, label, rnme, nme);
4042 13987 : if (s == NULL)
4043 : return NULL;
4044 13987 : list_append(l, s);
4045 : }
4046 3905 : sub = stmt_list(be, l);
4047 :
4048 3905 : sub = rel_rename(be, rel, sub);
4049 3905 : if (need_distinct(rel))
4050 1687 : sub = rel2bin_distinct(be, sub, NULL);
4051 3905 : if (is_single(rel))
4052 11 : sub = rel2bin_single(be, sub);
4053 : return sub;
4054 : }
4055 :
4056 : static stmt *
4057 301 : rel2bin_union(backend *be, sql_rel *rel, list *refs)
4058 : {
4059 301 : mvc *sql = be->mvc;
4060 301 : list *l;
4061 301 : node *n, *m;
4062 301 : stmt *left = NULL, *right = NULL, *sub;
4063 :
4064 301 : if (rel->l) /* first construct the left sub relation */
4065 301 : left = subrel_bin(be, rel->l, refs);
4066 301 : if (rel->r) /* first construct the right sub relation */
4067 301 : right = subrel_bin(be, rel->r, refs);
4068 301 : left = subrel_project(be, left, refs, rel->l);
4069 301 : right = subrel_project(be, right, refs, rel->r);
4070 301 : if (!left || !right)
4071 : return NULL;
4072 :
4073 : /* construct relation */
4074 301 : l = sa_list(sql->sa);
4075 6323 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m;
4076 6022 : n = n->next, m = m->next) {
4077 6022 : stmt *c1 = n->data;
4078 6022 : assert(c1->type == st_alias);
4079 6022 : stmt *c2 = m->data;
4080 6022 : const char *rnme = table_name(sql->sa, c1);
4081 6022 : const char *nme = column_name(sql->sa, c1);
4082 6022 : stmt *s;
4083 :
4084 6022 : s = stmt_append(be, create_const_column(be, c1), c2);
4085 6022 : if (s == NULL)
4086 : return NULL;
4087 6022 : s = stmt_alias(be, s, c1->label, rnme, nme);
4088 6022 : if (s == NULL)
4089 : return NULL;
4090 6022 : list_append(l, s);
4091 : }
4092 301 : sub = stmt_list(be, l);
4093 :
4094 301 : sub = rel_rename(be, rel, sub);
4095 301 : if (need_distinct(rel))
4096 0 : sub = rel2bin_distinct(be, sub, NULL);
4097 301 : if (is_single(rel))
4098 0 : sub = rel2bin_single(be, sub);
4099 : return sub;
4100 : }
4101 :
4102 : static stmt *
4103 2022 : rel2bin_except(backend *be, sql_rel *rel, list *refs)
4104 : {
4105 2022 : mvc *sql = be->mvc;
4106 2022 : sql_subtype *lng = sql_bind_localtype("lng");
4107 2022 : list *stmts;
4108 2022 : node *n, *m;
4109 2022 : stmt *left = NULL, *right = NULL, *sub;
4110 2022 : sql_subfunc *min;
4111 :
4112 2022 : stmt *lg = NULL, *rg = NULL;
4113 2022 : stmt *lgrp = NULL, *rgrp = NULL;
4114 2022 : stmt *lext = NULL, *rext = NULL, *next = NULL;
4115 2022 : stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
4116 2022 : stmt *s, *lm, *rm;
4117 2022 : list *lje = sa_list(sql->sa);
4118 2022 : list *rje = sa_list(sql->sa);
4119 :
4120 2022 : if (rel->l) /* first construct the left sub relation */
4121 2022 : left = subrel_bin(be, rel->l, refs);
4122 2022 : if (rel->r) /* first construct the right sub relation */
4123 2022 : right = subrel_bin(be, rel->r, refs);
4124 2022 : if (!left || !right)
4125 : return NULL;
4126 2022 : left = subrel_project(be, left, refs, rel->l);
4127 2022 : right = subrel_project(be, right, refs, rel->r);
4128 2022 : left = row2cols(be, left);
4129 2022 : right = row2cols(be, right);
4130 :
4131 : /*
4132 : * The multi column except is handled using group by's and
4133 : * group size counts on both sides of the intersect. We then
4134 : * return for each group of L with min(L.count,R.count),
4135 : * number of rows.
4136 : */
4137 4233 : for (n = left->op4.lval->h; n; n = n->next) {
4138 2211 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4139 2211 : lgrp = stmt_result(be, lg, 0);
4140 2211 : lext = stmt_result(be, lg, 1);
4141 2211 : lcnt = stmt_result(be, lg, 2);
4142 : }
4143 4233 : for (n = right->op4.lval->h; n; n = n->next) {
4144 2211 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4145 2211 : rgrp = stmt_result(be, rg, 0);
4146 2211 : rext = stmt_result(be, rg, 1);
4147 2211 : rcnt = stmt_result(be, rg, 2);
4148 : }
4149 :
4150 2022 : if (!lg || !rg)
4151 : return NULL;
4152 :
4153 2022 : if (need_distinct(rel)) {
4154 1940 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
4155 1940 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
4156 : }
4157 :
4158 : /* now find the matching groups */
4159 4233 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
4160 2211 : stmt *l = column(be, n->data);
4161 2211 : stmt *r = column(be, m->data);
4162 :
4163 2211 : l = stmt_project(be, lext, l);
4164 2211 : r = stmt_project(be, rext, r);
4165 2211 : list_append(lje, l);
4166 2211 : list_append(rje, r);
4167 : }
4168 2022 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
4169 2022 : lm = stmt_result(be, s, 0);
4170 2022 : rm = stmt_result(be, s, 1);
4171 :
4172 2022 : s = stmt_mirror(be, lext);
4173 2022 : s = stmt_tdiff(be, s, lm, NULL);
4174 :
4175 : /* first we find those missing in R */
4176 2022 : next = stmt_project(be, s, lext);
4177 2022 : ncnt = stmt_project(be, s, lcnt);
4178 2022 : zero = stmt_const(be, s, stmt_atom_lng(be, 0));
4179 :
4180 : /* ext, lcount, rcount */
4181 2022 : lext = stmt_project(be, lm, lext);
4182 2022 : lcnt = stmt_project(be, lm, lcnt);
4183 2022 : rcnt = stmt_project(be, rm, rcnt);
4184 :
4185 : /* append those missing in L */
4186 2022 : lext = stmt_append(be, lext, next);
4187 2022 : lcnt = stmt_append(be, lcnt, ncnt);
4188 2022 : rcnt = stmt_append(be, rcnt, zero);
4189 :
4190 2022 : min = sql_bind_func_result(sql, "sys", "sql_sub", F_FUNC, true, lng, 2, lng, lng);
4191 2022 : s = stmt_binop(be, lcnt, rcnt, NULL, min); /* use count */
4192 :
4193 : /* now we have gid,cnt, blowup to full groupsizes */
4194 2022 : s = stmt_gen_group(be, lext, s);
4195 :
4196 : /* project columns of left hand expression */
4197 2022 : stmts = sa_list(sql->sa);
4198 4233 : for (n = left->op4.lval->h; n; n = n->next) {
4199 2211 : stmt *c1 = column(be, n->data);
4200 2211 : assert(c1->type == st_alias);
4201 2211 : const char *rnme = NULL;
4202 2211 : const char *nme = column_name(sql->sa, c1);
4203 2211 : int label = c1->label;
4204 :
4205 : /* retain name via the stmt_alias */
4206 2211 : c1 = stmt_project(be, s, c1);
4207 :
4208 2211 : rnme = table_name(sql->sa, c1);
4209 2211 : c1 = stmt_alias(be, c1, label, rnme, nme);
4210 2211 : list_append(stmts, c1);
4211 : }
4212 2022 : sub = stmt_list(be, stmts);
4213 2022 : return rel_rename(be, rel, sub);
4214 : }
4215 :
4216 : static stmt *
4217 375 : rel2bin_inter(backend *be, sql_rel *rel, list *refs)
4218 : {
4219 375 : mvc *sql = be->mvc;
4220 375 : sql_subtype *lng = sql_bind_localtype("lng");
4221 375 : list *stmts;
4222 375 : node *n, *m;
4223 375 : stmt *left = NULL, *right = NULL, *sub;
4224 375 : sql_subfunc *min;
4225 :
4226 375 : stmt *lg = NULL, *rg = NULL;
4227 375 : stmt *lgrp = NULL, *rgrp = NULL;
4228 375 : stmt *lext = NULL, *rext = NULL;
4229 375 : stmt *lcnt = NULL, *rcnt = NULL;
4230 375 : stmt *s, *lm, *rm;
4231 375 : list *lje = sa_list(sql->sa);
4232 375 : list *rje = sa_list(sql->sa);
4233 :
4234 375 : if (rel->l) /* first construct the left sub relation */
4235 375 : left = subrel_bin(be, rel->l, refs);
4236 375 : if (rel->r) /* first construct the right sub relation */
4237 375 : right = subrel_bin(be, rel->r, refs);
4238 375 : left = subrel_project(be, left, refs, rel->l);
4239 375 : right = subrel_project(be, right, refs, rel->r);
4240 375 : if (!left || !right)
4241 : return NULL;
4242 375 : left = row2cols(be, left);
4243 :
4244 : /*
4245 : * The multi column intersect is handled using group by's and
4246 : * group size counts on both sides of the intersect. We then
4247 : * return for each group of L with min(L.count,R.count),
4248 : * number of rows.
4249 : */
4250 839 : for (n = left->op4.lval->h; n; n = n->next) {
4251 464 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4252 464 : lgrp = stmt_result(be, lg, 0);
4253 464 : lext = stmt_result(be, lg, 1);
4254 464 : lcnt = stmt_result(be, lg, 2);
4255 : }
4256 839 : for (n = right->op4.lval->h; n; n = n->next) {
4257 464 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4258 464 : rgrp = stmt_result(be, rg, 0);
4259 464 : rext = stmt_result(be, rg, 1);
4260 464 : rcnt = stmt_result(be, rg, 2);
4261 : }
4262 :
4263 375 : if (!lg || !rg)
4264 : return NULL;
4265 :
4266 375 : if (need_distinct(rel)) {
4267 364 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
4268 364 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
4269 : }
4270 :
4271 : /* now find the matching groups */
4272 839 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
4273 464 : stmt *l = column(be, n->data);
4274 464 : stmt *r = column(be, m->data);
4275 :
4276 464 : l = stmt_project(be, lext, l);
4277 464 : r = stmt_project(be, rext, r);
4278 464 : list_append(lje, l);
4279 464 : list_append(rje, r);
4280 : }
4281 375 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /* is_semantics */);
4282 375 : lm = stmt_result(be, s, 0);
4283 375 : rm = stmt_result(be, s, 1);
4284 :
4285 : /* ext, lcount, rcount */
4286 375 : lext = stmt_project(be, lm, lext);
4287 375 : lcnt = stmt_project(be, lm, lcnt);
4288 375 : rcnt = stmt_project(be, rm, rcnt);
4289 :
4290 375 : min = sql_bind_func(sql, "sys", "sql_min", lng, lng, F_FUNC, true, true);
4291 375 : s = stmt_binop(be, lcnt, rcnt, NULL, min);
4292 :
4293 : /* now we have gid,cnt, blowup to full groupsizes */
4294 375 : s = stmt_gen_group(be, lext, s);
4295 :
4296 : /* project columns of left hand expression */
4297 375 : stmts = sa_list(sql->sa);
4298 839 : for (n = left->op4.lval->h; n; n = n->next) {
4299 464 : stmt *c1 = column(be, n->data);
4300 464 : assert(c1->type == st_alias);
4301 464 : const char *rnme = NULL;
4302 464 : const char *nme = column_name(sql->sa, c1);
4303 464 : int label = c1->label;
4304 :
4305 : /* retain name via the stmt_alias */
4306 464 : c1 = stmt_project(be, s, c1);
4307 :
4308 464 : rnme = table_name(sql->sa, c1);
4309 464 : c1 = stmt_alias(be, c1, label, rnme, nme);
4310 464 : list_append(stmts, c1);
4311 : }
4312 375 : sub = stmt_list(be, stmts);
4313 375 : return rel_rename(be, rel, sub);
4314 : }
4315 :
4316 : static int
4317 32025 : find_matching_exp(list *exps, sql_exp *e)
4318 : {
4319 32025 : int i = 0;
4320 89758 : for (node *n = exps->h; n; n = n->next, i++) {
4321 75078 : if (exp_match(n->data, e))
4322 17345 : return i;
4323 : }
4324 : return -1;
4325 : }
4326 :
4327 : static stmt *
4328 8212 : sql_reorder(backend *be, stmt *order, list *exps, stmt *s, list *oexps, list *ostmts)
4329 : {
4330 8212 : list *l = sa_list(be->mvc->sa);
4331 :
4332 40237 : for (node *n = s->op4.lval->h, *m = exps->h; n && m; n = n->next, m = m->next) {
4333 32025 : int pos = 0;
4334 32025 : stmt *sc = n->data;
4335 32025 : sql_exp *pe = m->data;
4336 32025 : const char *cname = column_name(be->mvc->sa, sc);
4337 32025 : const char *tname = table_name(be->mvc->sa, sc);
4338 :
4339 32025 : if (oexps && (pos = find_matching_exp(oexps, pe)) >= 0 && list_fetch(ostmts, pos)) {
4340 17345 : sc = list_fetch(ostmts, pos);
4341 : } else {
4342 14680 : sc = stmt_project(be, order, sc);
4343 : }
4344 32025 : sc = stmt_alias(be, sc, pe->alias.label, tname, cname);
4345 32025 : list_append(l, sc);
4346 : }
4347 8212 : return stmt_list(be, l);
4348 : }
4349 :
4350 : static sql_exp*
4351 17083 : topn_limit(sql_rel *rel)
4352 : {
4353 17083 : if (rel->exps) {
4354 17083 : sql_exp *limit = rel->exps->h->data;
4355 17083 : if (exp_is_null(limit)) /* If the limit is NULL, ignore the value */
4356 : return NULL;
4357 : return limit;
4358 : }
4359 : return NULL;
4360 : }
4361 :
4362 : static sql_exp*
4363 17082 : topn_offset(sql_rel *rel)
4364 : {
4365 17082 : if (rel->exps && list_length(rel->exps) > 1) {
4366 159 : sql_exp *offset = rel->exps->h->next->data;
4367 :
4368 159 : return offset;
4369 : }
4370 : return NULL;
4371 : }
4372 :
4373 : static stmt *
4374 333388 : rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
4375 : {
4376 333388 : mvc *sql = be->mvc;
4377 333388 : list *pl;
4378 333388 : node *en, *n;
4379 333388 : stmt *sub = NULL, *psub = NULL;
4380 333388 : stmt *l = NULL;
4381 :
4382 333388 : if (topn) {
4383 319 : sql_exp *le = topn_limit(topn);
4384 319 : sql_exp *oe = topn_offset(topn);
4385 :
4386 319 : if (!le) { /* Don't push only offset */
4387 : topn = NULL;
4388 : } else {
4389 293 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4390 293 : if(!l)
4391 : return NULL;
4392 293 : if (oe) {
4393 44 : sql_subtype *lng = sql_bind_localtype("lng");
4394 44 : sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
4395 44 : stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4396 44 : if(!o)
4397 : return NULL;
4398 44 : l = stmt_binop(be, l, o, NULL, add);
4399 : }
4400 : }
4401 : }
4402 :
4403 333388 : if (!rel->exps)
4404 0 : return stmt_none(be);
4405 :
4406 333388 : if (rel->l) { /* first construct the sub relation */
4407 203610 : sql_rel *l = rel->l;
4408 203610 : if (l->op == op_ddl) {
4409 1209 : sql_table *t = rel_ddl_table_get(l);
4410 :
4411 1209 : if (t)
4412 1209 : sub = rel2bin_sql_table(be, t, rel->exps);
4413 : } else {
4414 202401 : sub = subrel_bin(be, rel->l, refs);
4415 : }
4416 203487 : sub = subrel_project(be, sub, refs, rel->l);
4417 203484 : if (!sub)
4418 : return NULL;
4419 : }
4420 :
4421 333262 : pl = sa_list(sql->sa);
4422 333376 : if (pl == NULL)
4423 : return NULL;
4424 333376 : if (sub)
4425 203563 : pl->expected_cnt = list_length(sub->op4.lval);
4426 333394 : psub = stmt_list(be, pl);
4427 333328 : if (psub == NULL)
4428 : return NULL;
4429 1405822 : for (en = rel->exps->h; en; en = en->next) {
4430 1072426 : sql_exp *exp = en->data;
4431 1072426 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
4432 1072426 : stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL, 0, 0, 0);
4433 :
4434 1072787 : if (!s) { /* try with own projection as well, but first clean leftover statements */
4435 11186 : clean_mal_statements(be, oldstop, oldvtop);
4436 11186 : s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4437 : }
4438 11186 : if (!s) /* error */
4439 : return NULL;
4440 : /* single value with limit */
4441 1072787 : if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
4442 14 : s = const_column(be, s);
4443 1072773 : else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
4444 25125 : s = stmt_const(be, bin_find_smallest_column(be, sub), s);
4445 :
4446 1072787 : if (!exp_name(exp))
4447 77127 : exp_label(sql->sa, exp, ++sql->label);
4448 1072638 : if (exp_name(exp)) {
4449 1072642 : s = stmt_rename(be, exp, s);
4450 : //column_name(sql->sa, s); /* save column name */
4451 1072603 : s->label = exp->alias.label;
4452 : }
4453 1072603 : list_append(pl, s);
4454 : }
4455 333396 : stmt_set_nrcols(psub);
4456 :
4457 : /* In case of a topn
4458 : if both order by and distinct: then get first order by col
4459 : do topn on it. Project all again! Then rest
4460 : */
4461 333269 : if (topn && rel->r) {
4462 274 : list *oexps = rel->r, *npl = sa_list(sql->sa);
4463 : /* distinct, topn returns at least N (unique groups) */
4464 274 : int distinct = need_distinct(rel);
4465 274 : stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
4466 :
4467 858 : for (n=oexps->h; n; n = n->next) {
4468 584 : sql_exp *orderbycole = n->data;
4469 584 : int last = (n->next == NULL);
4470 :
4471 584 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4472 :
4473 584 : if (!orderbycolstmt)
4474 : return NULL;
4475 :
4476 : /* handle constants */
4477 584 : if (orderbycolstmt->nrcols == 0 && !last) /* no need to sort on constant */
4478 0 : continue;
4479 584 : orderbycolstmt = column(be, orderbycolstmt);
4480 584 : if (!limit) { /* topn based on a single column */
4481 274 : limit = stmt_limit(be, orderbycolstmt, NULL, NULL, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
4482 : } else { /* topn based on 2 columns */
4483 310 : limit = stmt_limit(be, orderbycolstmt, lpiv, lgid, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
4484 : }
4485 584 : if (!limit)
4486 : return NULL;
4487 584 : lpiv = limit;
4488 584 : if (!last) {
4489 310 : lpiv = stmt_result(be, limit, 0);
4490 310 : lgid = stmt_result(be, limit, 1);
4491 310 : if (lpiv == NULL || lgid == NULL)
4492 : return NULL;
4493 : }
4494 : }
4495 :
4496 274 : limit = lpiv;
4497 274 : stmt *s;
4498 1471 : for (n=pl->h ; n; n = n->next) {
4499 1197 : stmt *os = n->data;
4500 1197 : list_append(npl, s=stmt_project(be, limit, column(be, os)));
4501 1197 : s->label = os->label;
4502 : }
4503 274 : psub = stmt_list(be, npl);
4504 :
4505 : /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
4506 274 : pl = sub->op4.lval;
4507 274 : npl = sa_list(sql->sa);
4508 1613 : for (n=pl->h ; n; n = n->next) {
4509 1339 : stmt *os = n->data;
4510 1339 : list_append(npl, s = stmt_project(be, limit, column(be, os)));
4511 1339 : s->label = os->label;
4512 : }
4513 274 : sub = stmt_list(be, npl);
4514 : }
4515 333269 : if (need_distinct(rel)) {
4516 14 : stmt *distinct = NULL;
4517 14 : psub = rel2bin_distinct(be, psub, &distinct);
4518 : /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
4519 14 : if (sub && distinct) {
4520 5 : list *npl = sa_list(sql->sa);
4521 :
4522 5 : pl = sub->op4.lval;
4523 21 : for (n=pl->h ; n; n = n->next)
4524 16 : list_append(npl, stmt_project(be, distinct, column(be, n->data)));
4525 5 : sub = stmt_list(be, npl);
4526 : }
4527 : }
4528 333269 : if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
4529 8286 : list *oexps = rel->r;
4530 8286 : stmt *orderby_ids = NULL, *orderby_grp = NULL;
4531 :
4532 8286 : list *ostmts = sa_list(be->mvc->sa);
4533 27218 : for (en = oexps->h; en; en = en->next) {
4534 18932 : stmt *orderby = NULL;
4535 18932 : sql_exp *orderbycole = en->data;
4536 18932 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4537 :
4538 18932 : if (!orderbycolstmt) {
4539 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4540 : return NULL;
4541 : }
4542 : /* single values don't need sorting */
4543 18932 : if (orderbycolstmt->nrcols == 0) {
4544 68 : append(ostmts, NULL);
4545 68 : continue;
4546 : }
4547 18864 : if (orderby_ids)
4548 10652 : orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
4549 : else
4550 8212 : orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
4551 18864 : stmt *orderby_vals = stmt_result(be, orderby, 0);
4552 18864 : append(ostmts, orderby_vals);
4553 18864 : orderby_ids = stmt_result(be, orderby, 1);
4554 18864 : orderby_grp = stmt_result(be, orderby, 2);
4555 : }
4556 8286 : if (orderby_ids)
4557 8212 : psub = sql_reorder(be, orderby_ids, rel->exps, psub, oexps, ostmts);
4558 : }
4559 : return psub;
4560 : }
4561 :
4562 : static stmt *
4563 0 : rel2bin_predicate(backend *be)
4564 : {
4565 0 : return const_column(be, stmt_bool(be, 1));
4566 : }
4567 :
4568 : static stmt *
4569 59089 : rel2bin_select(backend *be, sql_rel *rel, list *refs)
4570 : {
4571 59089 : mvc *sql = be->mvc;
4572 59089 : node *en;
4573 59089 : stmt *sub = NULL, *sel = NULL;
4574 59089 : stmt *predicate = NULL;
4575 :
4576 59089 : if (rel->l) { /* first construct the sub relation */
4577 59089 : sub = subrel_bin(be, rel->l, refs);
4578 59089 : if (!sub)
4579 : return NULL;
4580 59089 : sel = sub->cand;
4581 59089 : sub = row2cols(be, sub);
4582 : }
4583 59089 : if (!sub && !predicate)
4584 0 : predicate = rel2bin_predicate(be);
4585 59089 : if (list_empty(rel->exps)) {
4586 1480 : if (sub)
4587 : return sub;
4588 0 : if (predicate)
4589 : return predicate;
4590 0 : assert(0);
4591 : }
4592 57609 : en = rel->exps->h;
4593 57609 : if (!sub && predicate) {
4594 0 : list *l = sa_list(sql->sa);
4595 0 : assert(predicate);
4596 0 : append(l, predicate);
4597 0 : sub = stmt_list(be, l);
4598 : }
4599 : /* handle possible index lookups */
4600 : /* expressions are in index order ! */
4601 57609 : if (sub && en) {
4602 57609 : sql_exp *e = en->data;
4603 57609 : prop *p;
4604 :
4605 57609 : if ((p=find_prop(e->p, PROP_HASHCOL)) != NULL && !is_anti(e)) {
4606 12 : sql_idx *i = p->value.pval;
4607 12 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
4608 :
4609 12 : if (!(sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, en))) {
4610 : /* hash lookup cannot be used, clean leftover mal statements */
4611 3 : clean_mal_statements(be, oldstop, oldvtop);
4612 : }
4613 : }
4614 : }
4615 124344 : for (en = rel->exps->h; en; en = en->next) {
4616 66735 : sql_exp *e = en->data;
4617 66735 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
4618 :
4619 66735 : if (!s) {
4620 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4621 : return NULL;
4622 : }
4623 66735 : if (s->nrcols == 0){
4624 1450 : if (!predicate && sub && !list_empty(sub->op4.lval))
4625 1442 : predicate = stmt_const(be, bin_find_smallest_column(be, sub), stmt_bool(be, 1));
4626 8 : else if (!predicate)
4627 0 : predicate = const_column(be, stmt_bool(be, 1));
4628 1450 : if (e->type != e_cmp) {
4629 1361 : sql_subtype *bt = sql_bind_localtype("bit");
4630 :
4631 1361 : s = stmt_convert(be, s, NULL, exp_subtype(e), bt);
4632 : }
4633 1450 : sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0, 0);
4634 65285 : } else if (e->type != e_cmp) {
4635 0 : sel = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
4636 : } else {
4637 : sel = s;
4638 : }
4639 : }
4640 :
4641 57609 : if (sub && sel) {
4642 57609 : sub = stmt_list(be, sub->op4.lval); /* protect against references */
4643 57609 : sub->cand = sel;
4644 : }
4645 : return sub;
4646 : }
4647 :
4648 : static stmt *
4649 12871 : rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
4650 : {
4651 12871 : mvc *sql = be->mvc;
4652 12871 : list *l, *aggrs, *gbexps = sa_list(sql->sa);
4653 12871 : node *n, *en;
4654 12871 : stmt *sub = NULL, *cursub;
4655 12871 : stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
4656 :
4657 12871 : if (rel->l) { /* first construct the sub relation */
4658 12871 : sub = subrel_bin(be, rel->l, refs);
4659 12872 : sub = subrel_project(be, sub, refs, rel->l);
4660 12872 : if (!sub)
4661 : return NULL;
4662 : }
4663 :
4664 12872 : if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
4665 289 : list *newl = sa_list(sql->sa);
4666 289 : node *n;
4667 :
4668 670 : for (n=sub->op4.lval->h; n; n = n->next) {
4669 381 : stmt *s = n->data;
4670 381 : assert(s->type == st_alias);
4671 381 : const char *cname = column_name(sql->sa, s);
4672 381 : const char *tname = table_name(sql->sa, s);
4673 381 : int label = s->label;
4674 :
4675 381 : s = column(be, s);
4676 381 : s = stmt_alias(be, s, label, tname, cname);
4677 381 : append(newl, s);
4678 : }
4679 289 : sub = stmt_list(be, newl);
4680 : }
4681 :
4682 : /* groupby columns */
4683 :
4684 : /* Keep groupby columns, so that they can be looked up in the aggr list */
4685 12872 : if (rel->r) {
4686 9290 : list *exps = rel->r;
4687 :
4688 23319 : for (en = exps->h; en; en = en->next) {
4689 14028 : sql_exp *e = en->data;
4690 14028 : stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4691 :
4692 14029 : if (!gbcol) {
4693 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4694 : return NULL;
4695 : }
4696 14029 : if (!gbcol->nrcols)
4697 12 : gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
4698 14029 : groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
4699 14029 : grp = stmt_result(be, groupby, 0);
4700 14029 : ext = stmt_result(be, groupby, 1);
4701 14029 : cnt = stmt_result(be, groupby, 2);
4702 14029 : gbcol = stmt_alias(be, gbcol, e->alias.label, exp_find_rel_name(e), exp_name(e));
4703 14029 : list_append(gbexps, gbcol);
4704 : }
4705 : }
4706 : /* now aggregate */
4707 12873 : l = sa_list(sql->sa);
4708 12873 : if (l == NULL)
4709 : return NULL;
4710 12873 : aggrs = rel->exps;
4711 12873 : cursub = stmt_list(be, l);
4712 12872 : if (cursub == NULL)
4713 : return NULL;
4714 12872 : if (aggrs && !aggrs->h && ext)
4715 0 : list_append(l, ext);
4716 36253 : for (n = aggrs->h; n; n = n->next) {
4717 23380 : sql_exp *aggrexp = n->data;
4718 23380 : stmt *aggrstmt = NULL;
4719 23380 : int oldvtop, oldstop;
4720 :
4721 : /* first look in the current aggr list (l) and group by column list */
4722 23380 : if (l && !aggrstmt && aggrexp->type == e_column)
4723 : //aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
4724 13616 : aggrstmt = list_find_column_nid(be, l, aggrexp->nid);
4725 23380 : if (gbexps && !aggrstmt && aggrexp->type == e_column) {
4726 : //aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
4727 13590 : aggrstmt = list_find_column_nid(be, gbexps, aggrexp->nid);
4728 13590 : if (aggrstmt && groupby) {
4729 13389 : aggrstmt = stmt_project(be, ext, aggrstmt);
4730 13389 : if (list_length(gbexps) == 1)
4731 5560 : aggrstmt->key = 1;
4732 : }
4733 : }
4734 :
4735 23380 : oldvtop = be->mb->vtop;
4736 23380 : oldstop = be->mb->stop;
4737 23380 : if (!aggrstmt)
4738 9965 : aggrstmt = exp_bin(be, aggrexp, sub, NULL, grp, ext, cnt, NULL, 0, 0, 0);
4739 : /* maybe the aggr uses intermediate results of this group by,
4740 : therefore we pass the group by columns too
4741 : */
4742 9966 : if (!aggrstmt) {
4743 1 : clean_mal_statements(be, oldstop, oldvtop);
4744 1 : aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL, 0, 0, 0);
4745 : }
4746 1 : if (!aggrstmt) {
4747 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4748 : return NULL;
4749 : }
4750 :
4751 23381 : if (!aggrstmt->nrcols && ext && ext->nrcols)
4752 0 : aggrstmt = stmt_const(be, ext, aggrstmt);
4753 :
4754 23381 : aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
4755 23381 : list_append(l, aggrstmt);
4756 : }
4757 12873 : stmt_set_nrcols(cursub);
4758 12873 : return cursub;
4759 : }
4760 :
4761 : static stmt *
4762 16760 : rel2bin_topn(backend *be, sql_rel *rel, list *refs)
4763 : {
4764 16760 : mvc *sql = be->mvc;
4765 16760 : sql_exp *oe = NULL, *le = NULL;
4766 16760 : stmt *sub = NULL, *l = NULL, *o = NULL;
4767 16760 : node *n;
4768 :
4769 16760 : if (rel->l) { /* first construct the sub relation */
4770 16760 : sql_rel *rl = rel->l;
4771 :
4772 16760 : if (rl->op == op_project) {
4773 324 : if (rel_is_ref(rl)) {
4774 5 : sub = refs_find_rel(refs, rl);
4775 5 : if (!sub)
4776 0 : sub = rel2bin_project(be, rl, refs, rel);
4777 : } else
4778 319 : sub = rel2bin_project(be, rl, refs, rel);
4779 : } else {
4780 16436 : sub = subrel_bin(be, rl, refs);
4781 : }
4782 16761 : sub = subrel_project(be, sub, refs, rl);
4783 : }
4784 16765 : if (!sub)
4785 0 : return NULL;
4786 :
4787 16765 : le = topn_limit(rel);
4788 16764 : oe = topn_offset(rel);
4789 :
4790 16765 : n = sub->op4.lval->h;
4791 16765 : if (n) {
4792 16765 : stmt *limit = NULL, *sc = n->data;
4793 : //const char *cname = column_name(sql->sa, sc);
4794 : //const char *tname = table_name(sql->sa, sc);
4795 16765 : list *newl = sa_list(sql->sa);
4796 16764 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
4797 :
4798 16764 : if (le)
4799 16736 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4800 16738 : if (!l) {
4801 28 : clean_mal_statements(be, oldstop, oldvtop);
4802 28 : l = stmt_atom_lng_nil(be);
4803 : }
4804 :
4805 16765 : oldvtop = be->mb->vtop;
4806 16765 : oldstop = be->mb->stop;
4807 16765 : if (oe)
4808 89 : o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4809 89 : if (!o) {
4810 16676 : clean_mal_statements(be, oldstop, oldvtop);
4811 16676 : o = stmt_atom_lng(be, 0);
4812 : }
4813 16762 : if (!l || !o)
4814 : return NULL;
4815 :
4816 16762 : sc = column(be, sc);
4817 16763 : limit = stmt_limit(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/, NULL, NULL, o, l, 0,0,0,0,0);
4818 :
4819 117472 : for ( ; n; n = n->next) {
4820 83943 : stmt *sc = n->data;
4821 83943 : assert(sc->type == st_alias);
4822 83943 : const char *cname = column_name(sql->sa, sc);
4823 83936 : const char *tname = table_name(sql->sa, sc);
4824 83937 : int label = sc->label;
4825 :
4826 83937 : sc = column(be, sc);
4827 83941 : sc = stmt_project(be, limit, sc);
4828 83949 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
4829 : }
4830 16766 : sub = stmt_list(be, newl);
4831 : }
4832 : return sub;
4833 : }
4834 :
4835 : static stmt *
4836 21 : rel2bin_sample(backend *be, sql_rel *rel, list *refs)
4837 : {
4838 21 : mvc *sql = be->mvc;
4839 21 : list *newl;
4840 21 : stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
4841 21 : node *n;
4842 :
4843 21 : if (rel->l) /* first construct the sub relation */
4844 21 : sub = subrel_bin(be, rel->l, refs);
4845 21 : sub = subrel_project(be, sub, refs, rel->l);
4846 21 : if (!sub)
4847 : return NULL;
4848 :
4849 21 : n = sub->op4.lval->h;
4850 21 : newl = sa_list(sql->sa);
4851 :
4852 21 : if (n) {
4853 21 : stmt *sc = n->data;
4854 : //const char *cname = column_name(sql->sa, sc);
4855 : //const char *tname = table_name(sql->sa, sc);
4856 :
4857 21 : if (!(sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0)))
4858 : return NULL;
4859 :
4860 21 : if (rel->exps->cnt == 2) {
4861 12 : seed = exp_bin(be, rel->exps->h->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4862 12 : if (!seed)
4863 : return NULL;
4864 : }
4865 :
4866 21 : sc = column(be, sc);
4867 21 : sample = stmt_sample(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/,sample_size, seed);
4868 :
4869 65 : for ( ; n; n = n->next) {
4870 23 : stmt *sc = n->data;
4871 23 : assert(sc->type == st_alias);
4872 23 : const char *cname = column_name(sql->sa, sc);
4873 23 : const char *tname = table_name(sql->sa, sc);
4874 23 : int label = sc->label;
4875 :
4876 23 : sc = column(be, sc);
4877 23 : sc = stmt_project(be, sample, sc);
4878 23 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
4879 : }
4880 : }
4881 21 : sub = stmt_list(be, newl);
4882 21 : return sub;
4883 : }
4884 :
4885 : static stmt *
4886 4935 : sql_parse(backend *be, sql_schema *s, const char *query, char mode)
4887 : {
4888 4935 : sql_rel *rel = rel_parse(be->mvc, s, query, mode);
4889 4935 : stmt *sq = NULL;
4890 :
4891 4935 : if (rel && (rel = sql_processrelation(be->mvc, rel, 0, 1, 1, 1)))
4892 4932 : sq = rel_bin(be, rel);
4893 4935 : return sq;
4894 : }
4895 :
4896 : static stmt *
4897 12705 : insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
4898 : {
4899 12705 : mvc *sql = be->mvc;
4900 : /* pkey's cannot have NULLs, ukeys however can
4901 : current implementation switches on 'NOT NULL' on primary key columns */
4902 :
4903 12705 : char *msg = NULL;
4904 12705 : stmt *res;
4905 :
4906 12705 : sql_subtype *lng = sql_bind_localtype("lng");
4907 12724 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
4908 12723 : sql_subtype *bt = sql_bind_localtype("bit");
4909 12711 : stmt *dels = stmt_tid(be, k->t, 0);
4910 12725 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
4911 :
4912 12720 : if (list_length(k->columns) > 1) {
4913 820 : node *m;
4914 820 : stmt *s = list_fetch(inserts, 0), *ins = s;
4915 820 : sql_subfunc *sum;
4916 820 : stmt *ssum = NULL;
4917 820 : stmt *col = NULL;
4918 :
4919 820 : s = ins;
4920 : /* 1st stage: find out if original contains same values */
4921 820 : if (/*s->key &&*/ s->nrcols == 0) {
4922 586 : s = NULL;
4923 586 : if (k->idx && hash_index(k->idx->type))
4924 586 : s = stmt_uselect(be, stmt_idx(be, k->idx, dels, dels->partition), idx_inserts, cmp_equal, s, 0, 1 /* is_semantics*/);
4925 2149 : for (m = k->columns->h; m; m = m->next) {
4926 1563 : sql_kc *c = m->data;
4927 1563 : stmt *cs = list_fetch(inserts, c->c->colnr);
4928 :
4929 : /* foreach column add predicate */
4930 1563 : stmt_add_column_predicate(be, c->c);
4931 :
4932 1563 : col = stmt_col(be, c->c, dels, dels->partition);
4933 1563 : if (k->type == unndkey)
4934 8 : s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 1);
4935 1664 : else if ((k->type == ukey) && stmt_has_null(col)) {
4936 109 : stmt *nn = stmt_selectnonil(be, col, s);
4937 109 : s = stmt_uselect(be, col, cs, cmp_equal, nn, 0, 0);
4938 : } else {
4939 1446 : s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 0);
4940 : }
4941 : }
4942 : } else {
4943 234 : list *lje = sa_list(sql->sa);
4944 234 : list *rje = sa_list(sql->sa);
4945 234 : if (k->idx && hash_index(k->idx->type)) {
4946 234 : list_append(lje, stmt_idx(be, k->idx, dels, dels->partition));
4947 234 : list_append(rje, idx_inserts);
4948 : }
4949 749 : for (m = k->columns->h; m; m = m->next) {
4950 515 : sql_kc *c = m->data;
4951 515 : stmt *cs = list_fetch(inserts, c->c->colnr);
4952 :
4953 : /* foreach column add predicate */
4954 515 : stmt_add_column_predicate(be, c->c);
4955 :
4956 515 : col = stmt_col(be, c->c, dels, dels->partition);
4957 515 : list_append(lje, col);
4958 515 : list_append(rje, cs);
4959 : }
4960 234 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, k->type == unndkey? 1: 0);
4961 234 : s = stmt_result(be, s, 0);
4962 : }
4963 820 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
4964 :
4965 : /* 2nd stage: find out if inserted are unique */
4966 820 : if ((!idx_inserts && ins->nrcols) || (idx_inserts && idx_inserts->nrcols)) { /* insert columns not atoms */
4967 234 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
4968 234 : stmt *orderby_ids = NULL, *orderby_grp = NULL;
4969 234 : stmt *sel = NULL;
4970 :
4971 : /* remove any nils as in stmt_order NULL = NULL, instead of NULL != NULL */
4972 234 : if (k->type == ukey) {
4973 153 : for (m = k->columns->h; m; m = m->next) {
4974 105 : sql_kc *c = m->data;
4975 105 : stmt *cs = list_fetch(inserts, c->c->colnr);
4976 105 : if (stmt_has_null(cs))
4977 102 : sel = stmt_selectnonil(be, cs, sel);
4978 : }
4979 : }
4980 : /* implementation uses sort key check */
4981 749 : for (m = k->columns->h; m; m = m->next) {
4982 515 : sql_kc *c = m->data;
4983 515 : stmt *orderby;
4984 515 : stmt *cs = list_fetch(inserts, c->c->colnr);
4985 :
4986 515 : if (sel)
4987 102 : cs = stmt_project(be, sel, cs);
4988 515 : if (orderby_grp)
4989 281 : orderby = stmt_reorder(be, cs, 1, 0, orderby_ids, orderby_grp);
4990 : else
4991 234 : orderby = stmt_order(be, cs, 1, 0);
4992 515 : orderby_ids = stmt_result(be, orderby, 1);
4993 515 : orderby_grp = stmt_result(be, orderby, 2);
4994 : }
4995 :
4996 234 : if (!orderby_grp || !orderby_ids)
4997 : return NULL;
4998 :
4999 234 : sum = sql_bind_func(sql, "sys", "not_unique", tail_type(orderby_grp), NULL, F_AGGR, true, true);
5000 234 : ssum = stmt_aggr(be, orderby_grp, NULL, NULL, sum, 1, 0, 1);
5001 : /* combine results */
5002 234 : s = stmt_binop(be, s, ssum, NULL, or);
5003 : }
5004 :
5005 820 : if (k->type == pkey) {
5006 330 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5007 : } else {
5008 490 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5009 : }
5010 820 : res = stmt_exception(be, s, msg, 00001);
5011 : } else { /* single column key */
5012 11872 : sql_kc *c = k->columns->h->data;
5013 11872 : stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
5014 :
5015 : /* add predicate for this column */
5016 11870 : stmt_add_column_predicate(be, c->c);
5017 :
5018 11905 : s = stmt_col(be, c->c, dels, dels->partition);
5019 11906 : if ((k->type == ukey) && stmt_has_null(s)) {
5020 202 : stmt *nn = stmt_selectnonil(be, s, NULL);
5021 202 : s = stmt_project(be, nn, s);
5022 : }
5023 11906 : if (h->nrcols) {
5024 4768 : s = stmt_join(be, s, h, 0, cmp_equal, 0, k->type == unndkey? 1: 0, false);
5025 : /* s should be empty */
5026 4768 : s = stmt_result(be, s, 0);
5027 4768 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5028 : } else {
5029 7138 : s = stmt_uselect(be, s, h, cmp_equal, NULL, 0, k->type == unndkey? 1: 0);
5030 : /* s should be empty */
5031 7134 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5032 : }
5033 : /* s should be empty */
5034 11906 : s = stmt_binop(be, s, stmt_atom_lng(be, 0), NULL, ne);
5035 :
5036 : /* 2e stage: find out if inserts are unique */
5037 11905 : if (h->nrcols) { /* insert multiple atoms */
5038 4768 : sql_subfunc *sum;
5039 4768 : stmt *count_sum = NULL;
5040 4768 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5041 4768 : stmt *ssum, *ss;
5042 :
5043 4768 : stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
5044 :
5045 : /* inserted values may be null */
5046 4768 : if ((k->type == ukey) && stmt_has_null(ins)) {
5047 1747 : stmt *nn = stmt_selectnonil(be, ins, NULL);
5048 1747 : ins = stmt_project(be, nn, ins);
5049 : }
5050 :
5051 4768 : g = stmt_group(be, ins, NULL, NULL, NULL, 1);
5052 4768 : ss = stmt_result(be, g, 2); /* use count */
5053 : /* (count(ss) <> sum(ss)) */
5054 4768 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5055 4768 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5056 4768 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5057 4768 : count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
5058 :
5059 : /* combine results */
5060 4768 : s = stmt_binop(be, s, count_sum, NULL, or);
5061 : }
5062 11905 : if (k->type == pkey) {
5063 9997 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5064 : } else {
5065 1908 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5066 : }
5067 11905 : res = stmt_exception(be, s, msg, 00001);
5068 : }
5069 : return res;
5070 : }
5071 :
5072 : static stmt *
5073 777 : insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
5074 : {
5075 777 : mvc *sql = be->mvc;
5076 777 : char *msg = NULL;
5077 777 : stmt *cs = list_fetch(inserts, 0), *s = cs;
5078 777 : sql_subtype *lng = sql_bind_localtype("lng");
5079 777 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5080 777 : sql_subtype *bt = sql_bind_localtype("bit");
5081 777 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5082 :
5083 777 : stmt *nonil_rows = NULL;
5084 1589 : for (node *m = k->columns->h; m; m = m->next) {
5085 812 : sql_kc *c = m->data;
5086 :
5087 : /* foreach column add predicate */
5088 812 : stmt_add_column_predicate(be, c->c);
5089 :
5090 : // foreach column aggregate the nonil (literally 'null') values.
5091 : // mind that null values are valid fkeys with undefined value so
5092 : // we won't have an entry for them in the idx_inserts col
5093 812 : s = list_fetch(inserts, c->c->colnr);
5094 812 : nonil_rows = stmt_selectnonil(be, s, nonil_rows);
5095 : }
5096 :
5097 777 : if (!s && pin && list_length(pin->op4.lval))
5098 0 : s = pin->op4.lval->h->data;
5099 :
5100 : // we want to make sure that the data column(s) has the same number
5101 : // of (nonil) rows as the index column. if that is **not** the case
5102 : // then we are obviously dealing with an invalid foreign key
5103 777 : if (s->key && s->nrcols == 0) {
5104 0 : s = stmt_binop(be,
5105 : stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
5106 : stmt_aggr(be, const_column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
5107 : NULL, ne);
5108 : } else {
5109 : /* relThetaJoin.notNull.count <> inserts[notNull(col1) && ... && notNull(colN)].count */
5110 777 : s = stmt_binop(be,
5111 : stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
5112 : stmt_aggr(be, column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
5113 : NULL, ne);
5114 : }
5115 :
5116 : /* s should be empty */
5117 777 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5118 777 : return stmt_exception(be, s, msg, 00001);
5119 : }
5120 :
5121 : static stmt *
5122 13490 : sql_insert_key(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
5123 : {
5124 : /* int insert = 1;
5125 : * while insert and has u/pkey and not deferred then
5126 : * if u/pkey values exist then
5127 : * insert = 0
5128 : * while insert and has fkey and not deferred then
5129 : * find id of corresponding u/pkey
5130 : * if (!found)
5131 : * insert = 0
5132 : * if insert
5133 : * insert values
5134 : * insert fkey/pkey index
5135 : */
5136 13490 : if (k->type == pkey || k->type == ukey || k->type == unndkey) {
5137 12713 : return insert_check_ukey(be, inserts, k, idx_inserts);
5138 : } else { /* foreign keys */
5139 777 : return insert_check_fkey(be, inserts, k, idx_inserts, pin);
5140 : }
5141 : }
5142 :
5143 : static int
5144 4654 : sql_stack_add_inserted(mvc *sql, const char *name, sql_table *t, stmt **updates)
5145 : {
5146 : /* Put single relation of updates and old values on to the stack */
5147 4654 : sql_rel *r = NULL;
5148 4654 : node *n;
5149 4654 : list *exps = sa_list(sql->sa);
5150 4654 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
5151 :
5152 4654 : ti->t = t;
5153 4654 : ti->tids = NULL;
5154 4654 : ti->updates = updates;
5155 4654 : ti->type = 1;
5156 4654 : ti->nn = name;
5157 :
5158 12417 : for (n = ol_first_node(t->columns); n; n = n->next) {
5159 7763 : sql_column *c = n->data;
5160 7763 : sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
5161 7763 : ne->alias.label = -(sql->nid++);
5162 :
5163 7763 : append(exps, ne);
5164 : }
5165 4654 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
5166 4654 : r->l = ti;
5167 :
5168 4654 : return stack_push_rel_view(sql, name, r) ? 1 : 0;
5169 : }
5170 :
5171 : static int
5172 131955 : sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
5173 : {
5174 131955 : mvc *sql = be->mvc;
5175 131955 : node *n;
5176 131955 : int res = 1;
5177 :
5178 131955 : if (!ol_length(t->triggers))
5179 : return res;
5180 :
5181 8006 : for (n = ol_first_node(t->triggers); n; n = n->next) {
5182 6386 : sql_trigger *trigger = n->data;
5183 :
5184 6386 : if (!stack_push_frame(sql, "%OLD-NEW"))
5185 : return 0;
5186 6386 : if (trigger->event == 0 && trigger->time == time) {
5187 4654 : const char *n = trigger->new_name;
5188 :
5189 : /* add name for the 'inserted' to the stack */
5190 4654 : if (!n) n = "new";
5191 :
5192 4654 : if(!sql_stack_add_inserted(sql, n, t, updates)) {
5193 0 : stack_pop_frame(sql);
5194 0 : return 0;
5195 : }
5196 4654 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
5197 4626 : stack_pop_frame(sql);
5198 4626 : return 0;
5199 : }
5200 : }
5201 1760 : stack_pop_frame(sql);
5202 : }
5203 : return res;
5204 : }
5205 :
5206 : static void
5207 83 : sql_insert_check(backend *be, sql_key *key, list *inserts)
5208 : {
5209 83 : mvc *sql = be->mvc;
5210 83 : int pos = 0;
5211 83 : sql_rel *rel = rel_basetable(sql, key->t, key->t->base.name);
5212 83 : sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
5213 83 : rel->exps = rel_base_projection(sql, rel, 0);
5214 :
5215 : /* create new sub stmt with needed inserts */
5216 83 : list *ins = sa_list(sql->sa);
5217 173 : for(node *n = key->columns->h; n; n = n->next) {
5218 90 : sql_kc *kc = n->data;
5219 90 : stmt *in = list_fetch(inserts, kc->c->colnr);
5220 :
5221 90 : sql_exp *e = rel_base_bind_column2(sql, rel, kc->c->t->base.name, kc->c->base.name);
5222 90 : in = stmt_alias(be, in, e->alias.label, kc->c->t->base.name, kc->c->base.name);
5223 90 : append(ins, in);
5224 : }
5225 83 : stmt *sub = stmt_list(be, ins);
5226 83 : stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5227 83 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5228 83 : s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
5229 83 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5230 83 : char *msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: violated constraint '%s.%s' CHECK(%s)", key->t->s->base.name, key->base.name, exp->comment);
5231 83 : (void)stmt_exception(be, s, msg, 00001);
5232 83 : }
5233 :
5234 : static sql_table *
5235 67577 : sql_insert_check_null(backend *be, sql_table *t, list *inserts)
5236 : {
5237 67577 : mvc *sql = be->mvc;
5238 67577 : node *m, *n;
5239 67577 : sql_subfunc *cnt = NULL;
5240 :
5241 356689 : for (n = ol_first_node(t->columns), m = inserts->h; n && m;
5242 289112 : n = n->next, m = m->next) {
5243 289101 : stmt *i = m->data;
5244 289101 : sql_column *c = n->data;
5245 :
5246 289101 : if (!c->null) {
5247 24433 : stmt *s = i;
5248 24433 : char *msg = NULL;
5249 :
5250 24433 : if (!(s->key && s->nrcols == 0)) {
5251 11471 : s = stmt_selectnil(be, column(be, i));
5252 11471 : if (!cnt)
5253 3625 : cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5254 11471 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5255 : } else {
5256 12962 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
5257 :
5258 12940 : s = stmt_unop(be, i, NULL, isnil);
5259 : }
5260 24437 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
5261 24435 : (void)stmt_exception(be, s, msg, 00001);
5262 : }
5263 : }
5264 67588 : return t; /* return something to say it succeeded */
5265 : }
5266 :
5267 : static stmt **
5268 71521 : table_update_stmts(mvc *sql, sql_table *t, int *Len)
5269 : {
5270 71521 : *Len = ol_length(t->columns);
5271 71493 : return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
5272 : }
5273 :
5274 : static stmt *
5275 67558 : rel2bin_insert(backend *be, sql_rel *rel, list *refs)
5276 : {
5277 67558 : mvc *sql = be->mvc;
5278 67558 : list *l;
5279 67558 : stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
5280 67558 : int idx_ins = 0, len = 0;
5281 67558 : node *n, *m, *idx_m = NULL;
5282 67558 : sql_rel *tr = rel->l, *prel = rel->r;
5283 67558 : sql_table *t = NULL;
5284 :
5285 67558 : if ((rel->flag&UPD_COMP)) { /* special case ! */
5286 0 : idx_ins = 1;
5287 0 : prel = rel->l;
5288 0 : rel = rel->r;
5289 0 : tr = rel->l;
5290 : }
5291 :
5292 67558 : if (tr->op == op_basetable) {
5293 67466 : t = tr->l;
5294 : } else {
5295 92 : ddl = subrel_bin(be, tr, refs);
5296 92 : ddl = subrel_project(be, ddl, refs, NULL);
5297 92 : if (!ddl)
5298 : return NULL;
5299 92 : t = rel_ddl_table_get(tr);
5300 : }
5301 :
5302 67557 : if (rel->r) /* first construct the inserts relation */
5303 67557 : inserts = subrel_bin(be, rel->r, refs);
5304 67523 : inserts = subrel_project(be, inserts, refs, rel->r);
5305 :
5306 67476 : if (!inserts)
5307 : return NULL;
5308 :
5309 67476 : if (idx_ins)
5310 0 : pin = refs_find_rel(refs, prel);
5311 :
5312 81053 : for (n = ol_first_node(t->keys); n; n = n->next) {
5313 13478 : sql_key * key = n->data;
5314 13478 : if (key->type == ckey)
5315 83 : sql_insert_check(be, key, inserts->op4.lval);
5316 : }
5317 :
5318 67575 : if (!sql_insert_check_null(be, t, inserts->op4.lval))
5319 : return NULL;
5320 :
5321 67590 : updates = table_update_stmts(sql, t, &len);
5322 356063 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5323 288533 : sql_column *c = n->data;
5324 :
5325 288533 : updates[c->colnr] = m->data;
5326 : }
5327 :
5328 : /* before */
5329 67530 : if (!sql_insert_triggers(be, t, updates, 0))
5330 3084 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
5331 :
5332 64471 : insert = inserts->op4.lval->h->data;
5333 64471 : if (insert->nrcols == 0) {
5334 32893 : cnt = stmt_atom_lng(be, 1);
5335 : } else {
5336 31578 : cnt = stmt_aggr(be, insert, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
5337 : }
5338 64495 : insert = NULL;
5339 :
5340 64495 : l = sa_list(sql->sa);
5341 64500 : if (t->idxs) {
5342 64500 : idx_m = m;
5343 79591 : for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
5344 15088 : stmt *is = m->data;
5345 15088 : sql_idx *i = n->data;
5346 :
5347 15088 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
5348 107 : continue;
5349 14981 : if (hash_index(i->type) && list_length(i->columns) <= 1)
5350 14984 : is = NULL;
5351 14984 : if (i->key) {
5352 13499 : stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
5353 :
5354 13500 : list_append(l, ckeys);
5355 : }
5356 14984 : if (!insert)
5357 15091 : insert = is;
5358 : }
5359 64503 : assert(!n && !m);
5360 : }
5361 :
5362 64503 : if (t->s) /* only not declared tables, need this */
5363 64489 : pos = stmt_claim(be, t, cnt);
5364 :
5365 64470 : if (t->idxs) {
5366 79563 : for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
5367 15091 : stmt *is = m->data;
5368 15091 : sql_idx *i = n->data;
5369 :
5370 15091 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
5371 107 : continue;
5372 14984 : if (hash_index(i->type) && list_length(i->columns) <= 1)
5373 : is = NULL;
5374 2220 : if (is)
5375 2220 : is = stmt_append_idx(be, i, pos, is);
5376 : }
5377 64472 : assert(!n && !m);
5378 : }
5379 :
5380 64472 : int mvc_var = be->mvc_var;
5381 347208 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5382 :
5383 282720 : stmt *ins = m->data;
5384 282720 : sql_column *c = n->data;
5385 :
5386 282720 : insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
5387 282816 : append(l,insert);
5388 : }
5389 64488 : be->mvc_var = mvc_var;
5390 64488 : if (!insert)
5391 : return NULL;
5392 :
5393 64488 : if (rel->returning) {
5394 5 : list* il = sa_list(sql->sa);
5395 5 : sql_rel* inner = rel->l;
5396 5 : assert(inner->op == op_basetable);
5397 15 : for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5398 10 : sql_exp* ce = n->data;
5399 10 : stmt* ins = m->data;
5400 10 : stmt* s = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
5401 10 : append(il, s);
5402 : }
5403 5 : returning = stmt_list(be, il);
5404 5 : sql->type = Q_TABLE;
5405 : }
5406 :
5407 64488 : if (!sql_insert_triggers(be, t, updates, 1))
5408 1542 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
5409 : /* update predicate list */
5410 62901 : if (rel->r && !rel_predicates(be, rel->r))
5411 : return NULL;
5412 :
5413 62854 : if (ddl) {
5414 92 : ret = ddl;
5415 92 : list_prepend(l, ddl);
5416 92 : return stmt_list(be, l);
5417 : } else {
5418 62762 : ret = cnt;
5419 62762 : if (add_to_rowcount_accumulator(be, ret->nr) < 0)
5420 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
5421 62743 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
5422 62732 : stmt_add_dependency_change(be, t, ret);
5423 62804 : return returning?returning:ret;
5424 : }
5425 : }
5426 :
5427 : static int
5428 1371 : is_idx_updated(sql_idx * i, stmt **updates)
5429 : {
5430 1371 : int update = 0;
5431 1371 : node *m;
5432 :
5433 2708 : for (m = i->columns->h; m; m = m->next) {
5434 1543 : sql_kc *ic = m->data;
5435 :
5436 1543 : if (updates[ic->c->colnr]) {
5437 : update = 1;
5438 : break;
5439 : }
5440 : }
5441 1371 : return update;
5442 : }
5443 :
5444 : static int
5445 14 : is_check_updated(sql_key * k, stmt **updates)
5446 : {
5447 14 : int update = 0;
5448 14 : node *m;
5449 :
5450 16 : for (m = k->columns->h; m; m = m->next) {
5451 14 : sql_kc *kc = m->data;
5452 :
5453 14 : if (updates[kc->c->colnr]) {
5454 : update = 1;
5455 : break;
5456 : }
5457 : }
5458 14 : return update;
5459 : }
5460 :
5461 : static int
5462 3874 : first_updated_col(stmt **updates, int cnt)
5463 : {
5464 3874 : int i;
5465 :
5466 36213 : for (i = 0; i < cnt; i++) {
5467 35115 : if (updates[i])
5468 : return i;
5469 : }
5470 : return -1;
5471 : }
5472 :
5473 : static stmt *
5474 205 : update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *u_tids, stmt *idx_updates, int updcol)
5475 : {
5476 205 : mvc *sql = be->mvc;
5477 205 : char *msg = NULL;
5478 205 : stmt *res = NULL;
5479 :
5480 205 : sql_subtype *lng = sql_bind_localtype("lng");
5481 205 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5482 205 : sql_subtype *bt = sql_bind_localtype("bit");
5483 205 : sql_subfunc *ne;
5484 :
5485 205 : ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5486 205 : if (list_length(k->columns) > 1) {
5487 48 : stmt *dels = stmt_tid(be, k->t, 0);
5488 48 : node *m;
5489 48 : stmt *s = NULL;
5490 :
5491 : /* 1st stage: find out if original (without the updated)
5492 : do not contain the same values as the updated values.
5493 : This is done using a relation join and a count (which
5494 : should be zero)
5495 : */
5496 48 : if (!isNew(k)) {
5497 11 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
5498 11 : nu_tids = stmt_project(be, nu_tids, dels);
5499 11 : list *lje = sa_list(sql->sa);
5500 11 : list *rje = sa_list(sql->sa);
5501 :
5502 11 : if (k->idx && hash_index(k->idx->type)) {
5503 11 : list_append(lje, stmt_idx(be, k->idx, nu_tids, nu_tids->partition));
5504 11 : list_append(rje, idx_updates);
5505 : }
5506 33 : for (m = k->columns->h; m; m = m->next) {
5507 22 : sql_kc *c = m->data;
5508 22 : stmt *upd;
5509 :
5510 22 : assert(updates);
5511 22 : if (updates[c->c->colnr]) {
5512 : upd = updates[c->c->colnr];
5513 : } else {
5514 8 : upd = stmt_col(be, c->c, u_tids, u_tids->partition);
5515 : }
5516 22 : list_append(lje, stmt_col(be, c->c, nu_tids, nu_tids->partition));
5517 22 : list_append(rje, upd);
5518 : }
5519 11 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
5520 11 : s = stmt_result(be, s, 0);
5521 11 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
5522 : }
5523 :
5524 : /* 2e stage: find out if the updated are unique */
5525 48 : if (!updates || updates[updcol]->nrcols) { /* update columns not atoms */
5526 48 : sql_subfunc *sum;
5527 48 : stmt *count_sum = NULL, *ssum;
5528 48 : stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
5529 48 : stmt *cand = NULL;
5530 48 : stmt *ss;
5531 48 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5532 :
5533 : /* also take the hopefully unique hash keys, to reduce
5534 : (re)group costs */
5535 48 : if (k->idx && hash_index(k->idx->type)) {
5536 48 : g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
5537 48 : grp = stmt_result(be, g, 0);
5538 48 : ext = stmt_result(be, g, 1);
5539 48 : Cnt = stmt_result(be, g, 2);
5540 :
5541 : /* continue only with groups with a cnt > 1 */
5542 48 : cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0, 0);
5543 : /* project cand on ext and Cnt */
5544 48 : Cnt = stmt_project(be, cand, Cnt);
5545 48 : ext = stmt_project(be, cand, ext);
5546 :
5547 : /* join groups with extend to retrieve all oid's of the original
5548 : * bat that belong to a group with Cnt >1 */
5549 48 : g = stmt_join(be, grp, ext, 0, cmp_equal, 0, 0, false);
5550 48 : cand = stmt_result(be, g, 0);
5551 48 : grp = stmt_project(be, cand, grp);
5552 : }
5553 :
5554 154 : for (m = k->columns->h; m; m = m->next) {
5555 106 : sql_kc *c = m->data;
5556 106 : stmt *upd;
5557 :
5558 106 : if (updates && updates[c->c->colnr]) {
5559 : upd = updates[c->c->colnr];
5560 : } else {
5561 92 : upd = stmt_col(be, c->c, dels, dels->partition);
5562 : }
5563 :
5564 : /* apply cand list first */
5565 106 : if (cand)
5566 106 : upd = stmt_project(be, cand, upd);
5567 :
5568 : /* remove nulls */
5569 106 : if ((k->type == ukey) && stmt_has_null(upd)) {
5570 31 : stmt *nn = stmt_selectnonil(be, upd, NULL);
5571 31 : upd = stmt_project(be, nn, upd);
5572 31 : if (grp)
5573 31 : grp = stmt_project(be, nn, grp);
5574 31 : if (cand)
5575 31 : cand = stmt_project(be, nn, cand);
5576 : }
5577 :
5578 : /* apply group by on groups with Cnt > 1 */
5579 106 : g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
5580 106 : grp = stmt_result(be, g, 0);
5581 106 : ext = stmt_result(be, g, 1);
5582 106 : Cnt = stmt_result(be, g, 2);
5583 : }
5584 48 : ss = Cnt; /* use count */
5585 : /* (count(ss) <> sum(ss)) */
5586 48 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5587 48 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5588 48 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5589 48 : count_sum = stmt_binop(be, stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), check_types(be, lng, ssum, type_equal), NULL, ne);
5590 :
5591 : /* combine results */
5592 48 : if (s)
5593 11 : s = stmt_binop(be, s, count_sum, NULL, or);
5594 : else
5595 : s = count_sum;
5596 : }
5597 :
5598 48 : if (k->type == pkey) {
5599 31 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5600 : } else {
5601 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5602 : }
5603 48 : res = stmt_exception(be, s, msg, 00001);
5604 : } else { /* single column key */
5605 157 : stmt *dels = stmt_tid(be, k->t, 0);
5606 157 : sql_kc *c = k->columns->h->data;
5607 157 : stmt *s = NULL, *h = NULL, *o;
5608 :
5609 : /* s should be empty */
5610 157 : if (!isNew(k)) {
5611 69 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
5612 69 : nu_tids = stmt_project(be, nu_tids, dels);
5613 69 : assert (updates);
5614 :
5615 69 : h = updates[c->c->colnr];
5616 69 : o = stmt_col(be, c->c, nu_tids, nu_tids->partition);
5617 69 : s = stmt_join(be, o, h, 0, cmp_equal, 0, 0, false);
5618 69 : s = stmt_result(be, s, 0);
5619 69 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
5620 : }
5621 :
5622 : /* 2e stage: find out if updated are unique */
5623 69 : if (!h || h->nrcols) { /* update columns not atoms */
5624 157 : sql_subfunc *sum;
5625 157 : stmt *count_sum = NULL;
5626 157 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5627 157 : stmt *ssum, *ss;
5628 157 : stmt *upd;
5629 157 : stmt *g;
5630 :
5631 157 : if (updates) {
5632 70 : upd = updates[c->c->colnr];
5633 : } else {
5634 87 : upd = stmt_col(be, c->c, dels, dels->partition);
5635 : }
5636 :
5637 : /* remove nulls */
5638 157 : if ((k->type == ukey) && stmt_has_null(upd)) {
5639 15 : stmt *nn = stmt_selectnonil(be, upd, NULL);
5640 15 : upd = stmt_project(be, nn, upd);
5641 : }
5642 :
5643 157 : g = stmt_group(be, upd, NULL, NULL, NULL, 1);
5644 157 : ss = stmt_result(be, g, 2); /* use count */
5645 :
5646 : /* (count(ss) <> sum(ss)) */
5647 157 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5648 157 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5649 157 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5650 157 : count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
5651 :
5652 : /* combine results */
5653 157 : if (s)
5654 69 : s = stmt_binop(be, s, count_sum, NULL, or);
5655 : else
5656 : s = count_sum;
5657 : }
5658 :
5659 157 : if (k->type == pkey) {
5660 140 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5661 : } else {
5662 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5663 : }
5664 157 : res = stmt_exception(be, s, msg, 00001);
5665 : }
5666 205 : return res;
5667 : }
5668 :
5669 : /*
5670 : A referential constraint is satisfied if one of the following con-
5671 : ditions is true, depending on the <match option> specified in the
5672 : <referential constraint definition>:
5673 :
5674 : - If no <match type> was specified then, for each row R1 of the
5675 : referencing table, either at least one of the values of the
5676 : referencing columns in R1 shall be a null value, or the value of
5677 : each referencing column in R1 shall be equal to the value of the
5678 : corresponding referenced column in some row of the referenced
5679 : table.
5680 :
5681 : - If MATCH FULL was specified then, for each row R1 of the refer-
5682 : encing table, either the value of every referencing column in R1
5683 : shall be a null value, or the value of every referencing column
5684 : in R1 shall not be null and there shall be some row R2 of the
5685 : referenced table such that the value of each referencing col-
5686 : umn in R1 is equal to the value of the corresponding referenced
5687 : column in R2.
5688 :
5689 : - If MATCH PARTIAL was specified then, for each row R1 of the
5690 : referencing table, there shall be some row R2 of the refer-
5691 : enced table such that the value of each referencing column in
5692 : R1 is either null or is equal to the value of the corresponding
5693 : referenced column in R2.
5694 : */
5695 :
5696 : static stmt *
5697 698 : update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
5698 : {
5699 698 : mvc *sql = be->mvc;
5700 698 : char *msg = NULL;
5701 698 : stmt *s, *cur, *null = NULL, *cntnulls;
5702 698 : sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
5703 698 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5704 698 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5705 698 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5706 698 : node *m;
5707 :
5708 698 : if (!idx_updates)
5709 : return NULL;
5710 : /* releqjoin.count <> updates[updcol].count */
5711 698 : if (pup && list_length(pup->op4.lval)) {
5712 655 : cur = pup->op4.lval->h->data;
5713 43 : } else if (updates) {
5714 43 : cur = updates[updcol];
5715 : } else {
5716 0 : sql_kc *c = k->columns->h->data;
5717 0 : stmt *dels = stmt_tid(be, k->t, 0);
5718 0 : assert(0);
5719 : cur = stmt_col(be, c->c, dels, dels->partition);
5720 : }
5721 698 : 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), NULL, ne);
5722 :
5723 1419 : for (m = k->columns->h; m; m = m->next) {
5724 721 : sql_kc *c = m->data;
5725 :
5726 : /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
5727 : /* Currently only the default MATCH SIMPLE is supported */
5728 721 : if (c->c->null) {
5729 309 : stmt *upd, *nn;
5730 :
5731 309 : if (updates && updates[c->c->colnr]) {
5732 : upd = updates[c->c->colnr];
5733 : } else { /* created idx/key using alter */
5734 277 : upd = stmt_col(be, c->c, tids, tids->partition);
5735 : }
5736 309 : nn = stmt_selectnil(be, upd);
5737 309 : if (null)
5738 11 : null = stmt_tunion(be, null, nn);
5739 : else
5740 : null = nn;
5741 : }
5742 : }
5743 698 : if (null) {
5744 298 : cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
5745 : } else {
5746 400 : cntnulls = stmt_atom_lng(be, 0);
5747 : }
5748 698 : s = stmt_binop(be, s,
5749 : stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls, NULL, ne), NULL, or);
5750 :
5751 : /* s should be empty */
5752 698 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5753 698 : return stmt_exception(be, s, msg, 00001);
5754 : }
5755 :
5756 : static stmt *
5757 10 : join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
5758 : {
5759 10 : mvc *sql = be->mvc;
5760 10 : sql_trans *tr = sql->session->tr;
5761 10 : char *msg = NULL;
5762 10 : int nulls = 0;
5763 10 : node *m, *o;
5764 10 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5765 10 : stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
5766 10 : stmt *null = NULL, *rows;
5767 10 : sql_subtype *lng = sql_bind_localtype("lng");
5768 10 : sql_subtype *bt = sql_bind_localtype("bit");
5769 10 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5770 10 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5771 10 : list *lje = sa_list(sql->sa);
5772 10 : list *rje = sa_list(sql->sa);
5773 :
5774 10 : fdels = stmt_tid(be, k->idx->t, 0);
5775 10 : rows = stmt_idx(be, k->idx, fdels, fdels->partition);
5776 :
5777 10 : rows = stmt_join(be, rows, tids, 0, cmp_equal, 0, 0, false); /* join over the join index */
5778 10 : rows = stmt_result(be, rows, 0);
5779 :
5780 22 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5781 12 : sql_kc *fc = m->data;
5782 12 : sql_kc *c = o->data;
5783 12 : stmt *upd, *col;
5784 :
5785 12 : if (updates[c->c->colnr]) {
5786 : upd = updates[c->c->colnr];
5787 : } else {
5788 2 : upd = stmt_project(be, tids, stmt_col(be, c->c, dels, dels->partition));
5789 : }
5790 12 : if (c->c->null) { /* new nulls (MATCH SIMPLE) */
5791 3 : stmt *nn = stmt_selectnil(be, upd);
5792 3 : if (null)
5793 1 : null = stmt_tunion(be, null, nn);
5794 : else
5795 : null = nn;
5796 : nulls = 1;
5797 : }
5798 12 : col = stmt_col(be, fc->c, rows, rows->partition);
5799 12 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5800 0 : return NULL;
5801 12 : list_append(lje, upd);
5802 12 : list_append(rje, col);
5803 : }
5804 10 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
5805 10 : s = stmt_result(be, s, 0);
5806 :
5807 : /* add missing nulls */
5808 10 : cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5809 10 : if (nulls) {
5810 2 : sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
5811 2 : cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), NULL, add);
5812 : }
5813 :
5814 : /* releqjoin.count <> updates[updcol].count */
5815 10 : s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
5816 :
5817 : /* s should be empty */
5818 10 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5819 10 : return stmt_exception(be, s, msg, 00001);
5820 : }
5821 :
5822 : static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
5823 :
5824 : static stmt*
5825 11 : sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
5826 : {
5827 11 : mvc *sql = be->mvc;
5828 11 : sql_trans *tr = sql->session->tr;
5829 11 : list *l = NULL;
5830 11 : int len = 0;
5831 11 : node *m, *o;
5832 11 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5833 11 : stmt **new_updates;
5834 11 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
5835 :
5836 11 : new_updates = table_update_stmts(sql, t, &len);
5837 24 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5838 13 : sql_kc *fc = m->data;
5839 13 : stmt *upd = NULL;
5840 :
5841 13 : if (action == ACT_SET_DEFAULT) {
5842 4 : if (fc->c->def) {
5843 4 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
5844 4 : if (!sq)
5845 : return NULL;
5846 : upd = sq;
5847 : } else {
5848 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5849 : }
5850 : } else {
5851 9 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5852 : }
5853 :
5854 13 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5855 0 : return NULL;
5856 :
5857 13 : if (upd->nrcols <= 0)
5858 13 : upd = stmt_const(be, ftids, upd);
5859 :
5860 13 : new_updates[fc->c->colnr] = upd;
5861 : }
5862 11 : if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
5863 : return NULL;
5864 11 : return stmt_list(be, l);
5865 : }
5866 :
5867 : static stmt*
5868 32 : sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
5869 : {
5870 32 : mvc *sql = be->mvc;
5871 32 : sql_trans *tr = sql->session->tr;
5872 32 : list *l = NULL;
5873 32 : int len = 0;
5874 32 : node *m, *o;
5875 32 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5876 32 : stmt **new_updates;
5877 32 : stmt *rows;
5878 32 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
5879 32 : stmt *ftids, *upd_ids;
5880 :
5881 32 : ftids = stmt_tid(be, k->idx->t, 0);
5882 32 : rows = stmt_idx(be, k->idx, ftids, ftids->partition);
5883 :
5884 32 : rows = stmt_join(be, rows, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
5885 32 : upd_ids = stmt_result(be, rows, 1);
5886 32 : rows = stmt_result(be, rows, 0);
5887 32 : rows = stmt_project(be, rows, ftids);
5888 :
5889 32 : new_updates = table_update_stmts(sql, t, &len);
5890 64 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5891 32 : sql_kc *fc = m->data;
5892 32 : sql_kc *c = o->data;
5893 32 : stmt *upd = NULL;
5894 :
5895 32 : if (!updates[c->c->colnr]) {
5896 0 : continue;
5897 32 : } else if (action == ACT_CASCADE) {
5898 : upd = updates[c->c->colnr];
5899 16 : } else if (action == ACT_SET_DEFAULT) {
5900 6 : if (fc->c->def) {
5901 6 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
5902 6 : if (!sq)
5903 : return NULL;
5904 : upd = sq;
5905 : } else {
5906 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5907 : }
5908 10 : } else if (action == ACT_SET_NULL) {
5909 10 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5910 : }
5911 :
5912 32 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5913 0 : return NULL;
5914 :
5915 32 : if (upd->nrcols <= 0)
5916 16 : upd = stmt_const(be, upd_ids, upd);
5917 : else
5918 16 : upd = stmt_project(be, upd_ids, upd);
5919 :
5920 32 : new_updates[fc->c->colnr] = upd;
5921 : }
5922 :
5923 32 : if ((l = sql_update(be, t, rows, new_updates)) == NULL)
5924 : return NULL;
5925 32 : return stmt_list(be, l);
5926 : }
5927 :
5928 : static int
5929 81 : cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
5930 : {
5931 : /* now iterate over all keys */
5932 81 : sql_trans *tr = be->mvc->session->tr;
5933 81 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
5934 81 : if (keys) {
5935 131 : for (node *n = keys->h; n; n = n->next->next) {
5936 50 : sqlid fkey_id = *(sqlid*)n->data;
5937 50 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
5938 50 : sql_key *fk = (sql_key*)b;
5939 50 : sql_fkey *rk = (sql_fkey*)b;
5940 :
5941 50 : if (fk->type != fkey || rk->rkey != k->base.id)
5942 0 : continue;
5943 :
5944 : /* All rows of the foreign key table which are
5945 : affected by the primary key update should all
5946 : match one of the updated primary keys again.
5947 : */
5948 50 : switch (((sql_fkey*)fk)->on_update) {
5949 : case ACT_NO_ACTION:
5950 : break;
5951 32 : case ACT_SET_NULL:
5952 : case ACT_SET_DEFAULT:
5953 : case ACT_CASCADE:
5954 32 : if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update)) {
5955 0 : list_destroy(keys);
5956 0 : return -1;
5957 : }
5958 : break;
5959 10 : default: /*RESTRICT*/
5960 10 : if (!join_updated_pkey(be, fk, tids, updates)) {
5961 0 : list_destroy(keys);
5962 0 : return -1;
5963 : }
5964 : }
5965 : }
5966 81 : list_destroy(keys);
5967 : }
5968 : return 0;
5969 : }
5970 :
5971 : static void
5972 903 : sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
5973 : {
5974 903 : stmt *ckeys;
5975 :
5976 903 : if (k->type == pkey || k->type == ukey) {
5977 205 : ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
5978 : } else { /* foreign keys */
5979 698 : ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
5980 : }
5981 903 : list_append(l, ckeys);
5982 903 : }
5983 :
5984 : static stmt *
5985 20 : hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
5986 : {
5987 20 : mvc *sql = be->mvc;
5988 : /* calculate new value */
5989 20 : node *m;
5990 20 : sql_subtype *it, *lng;
5991 20 : int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
5992 20 : stmt *h = NULL, *tids;
5993 :
5994 20 : if (list_length(i->columns) <= 1)
5995 : return NULL;
5996 :
5997 0 : tids = stmt_tid(be, i->t, 0);
5998 0 : it = sql_bind_localtype("int");
5999 0 : lng = sql_bind_localtype("lng");
6000 0 : for (m = i->columns->h; m; m = m->next) {
6001 0 : sql_kc *c = m->data;
6002 0 : stmt *upd;
6003 :
6004 0 : if (updates && updates[c->c->colnr]) {
6005 : upd = updates[c->c->colnr];
6006 0 : } else if (updates && updcol >= 0) {
6007 0 : assert(0);
6008 : upd = stmt_col(be, c->c, rows, rows->partition);
6009 : } else { /* created idx/key using alter */
6010 0 : upd = stmt_col(be, c->c, tids, tids->partition);
6011 : }
6012 :
6013 0 : if (h && i->type == hash_idx) {
6014 0 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, &c->c->type);
6015 :
6016 0 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(
6017 : list_append(sa_list(sql->sa), h),
6018 0 : stmt_atom_int(be, bits)), upd)), NULL,
6019 : xor, NULL);
6020 0 : } else if (h) {
6021 0 : stmt *h2;
6022 0 : sql_subfunc *lsh = sql_bind_func_result(sql, "sys", "left_shift", F_FUNC, true, lng, 2, lng, it);
6023 0 : sql_subfunc *lor = sql_bind_func_result(sql, "sys", "bit_or", F_FUNC, true, lng, 2, lng, lng);
6024 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
6025 :
6026 0 : h = stmt_binop(be, h, stmt_atom_int(be, bits), NULL, lsh);
6027 0 : h2 = stmt_unop(be, upd, NULL, hf);
6028 0 : h = stmt_binop(be, h, h2, NULL, lor);
6029 : } else {
6030 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
6031 0 : h = stmt_unop(be, upd, NULL, hf);
6032 0 : if (i->type == oph_idx)
6033 : break;
6034 : }
6035 : }
6036 : return h;
6037 : }
6038 :
6039 : static stmt *
6040 43 : join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
6041 : {
6042 43 : mvc *sql = be->mvc;
6043 43 : sql_trans *tr = sql->session->tr;
6044 43 : node *m, *o;
6045 43 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)i->key)->rkey);
6046 43 : stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
6047 43 : list *lje = sa_list(sql->sa);
6048 43 : list *rje = sa_list(sql->sa);
6049 :
6050 88 : for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
6051 45 : sql_kc *c = m->data;
6052 45 : sql_kc *rc = o->data;
6053 45 : stmt *upd;
6054 :
6055 45 : if (updates && updates[c->c->colnr]) {
6056 : upd = updates[c->c->colnr];
6057 0 : } else if (updates && updcol >= 0) {
6058 0 : assert(0);
6059 : upd = stmt_col(be, c->c, ftids, ftids->partition);
6060 : } else { /* created idx/key using alter */
6061 0 : upd = stmt_col(be, c->c, ftids, ftids->partition);
6062 : }
6063 :
6064 45 : if (!upd || (upd = check_types(be, &rc->c->type, upd, type_equal)) == NULL)
6065 0 : return NULL;
6066 45 : list_append(lje, upd);
6067 45 : list_append(rje, stmt_col(be, rc->c, ptids, ptids->partition));
6068 : }
6069 43 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 0);
6070 43 : l = stmt_result(be, s, 0);
6071 43 : r = stmt_result(be, s, 1);
6072 43 : r = stmt_project(be, r, ptids);
6073 43 : return stmt_left_project(be, ftids, l, r);
6074 : }
6075 :
6076 : static int
6077 3874 : cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
6078 : {
6079 3874 : mvc *sql = be->mvc;
6080 3874 : node *n;
6081 :
6082 3874 : if (!ol_length(t->idxs))
6083 : return 0;
6084 :
6085 2541 : for (n = ol_first_node(t->idxs); n; n = n->next) {
6086 1308 : sql_idx *i = n->data;
6087 :
6088 : /* check if update is needed,
6089 : * ie at least on of the idx columns is updated
6090 : */
6091 1308 : if (is_idx_updated(i, updates) == 0)
6092 1165 : continue;
6093 :
6094 143 : if (i->key) {
6095 140 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
6096 140 : sql_key *k = i->key;
6097 140 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
6098 140 : if (!sql->cascade_action)
6099 65 : sql->cascade_action = sa_list(sql->sa);
6100 140 : *local_id = i->key->base.id;
6101 140 : list_append(sql->cascade_action, local_id);
6102 140 : if (k->type == pkey || k->type == ukey) {
6103 81 : if (cascade_ukey(be, updates, k, rows))
6104 : return -1;
6105 : }
6106 : }
6107 : }
6108 : }
6109 : return 0;
6110 : }
6111 :
6112 : static list *
6113 43 : update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
6114 : {
6115 43 : mvc *sql = be->mvc;
6116 43 : node *n;
6117 43 : int updcol;
6118 43 : list *idx_updates = sa_list(sql->sa);
6119 :
6120 43 : if (!ol_length(t->idxs))
6121 : return idx_updates;
6122 :
6123 43 : updcol = first_updated_col(updates, ol_length(t->columns));
6124 106 : for (n = ol_first_node(t->idxs); n; n = n->next) {
6125 63 : sql_idx *i = n->data;
6126 63 : stmt *is = NULL;
6127 :
6128 : /* check if update is needed,
6129 : * ie at least on of the idx columns is updated
6130 : */
6131 63 : if (is_idx_updated(i, updates) == 0)
6132 0 : continue;
6133 :
6134 63 : if (hash_index(i->type)) {
6135 20 : is = hash_update(be, i, rows, updates, updcol);
6136 43 : } else if (i->type == join_idx) {
6137 43 : if (updcol < 0)
6138 : return NULL;
6139 43 : if (!(is = join_idx_update(be, i, rows, updates, updcol)))
6140 : return NULL;
6141 : }
6142 63 : if (i->key)
6143 63 : sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
6144 63 : if (is)
6145 43 : list_append(idx_updates, stmt_update_idx(be, i, rows, is));
6146 : }
6147 : return idx_updates;
6148 : }
6149 :
6150 : static int
6151 261 : sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
6152 : {
6153 : /* Put single relation of updates and old values on to the stack */
6154 261 : sql_rel *r = NULL;
6155 261 : node *n;
6156 261 : list *exps = sa_list(sql->sa);
6157 261 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
6158 :
6159 261 : ti->t = t;
6160 261 : ti->tids = tids;
6161 261 : ti->updates = updates;
6162 261 : ti->type = 2;
6163 261 : ti->on = on;
6164 261 : ti->nn = nn;
6165 1459 : for (n = ol_first_node(t->columns); n; n = n->next) {
6166 1198 : sql_column *c = n->data;
6167 :
6168 1198 : if (updates[c->colnr]) {
6169 261 : sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6170 261 : sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6171 261 : oe->alias.label = -(sql->nid++);
6172 261 : ne->alias.label = -(sql->nid++);
6173 :
6174 261 : append(exps, oe);
6175 261 : append(exps, ne);
6176 : } else {
6177 937 : sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6178 937 : sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6179 937 : oe->alias.label = -(sql->nid++);
6180 937 : ne->alias.label = -(sql->nid++);
6181 :
6182 937 : append(exps, oe);
6183 937 : append(exps, ne);
6184 : }
6185 : }
6186 261 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
6187 261 : r->l = ti;
6188 :
6189 : /* put single table into the stack with 2 names, needed for the psm code */
6190 261 : if (!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
6191 0 : return 0;
6192 : return 1;
6193 : }
6194 :
6195 : static int
6196 7748 : sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time)
6197 : {
6198 7748 : mvc *sql = be->mvc;
6199 7748 : node *n;
6200 7748 : int res = 1;
6201 :
6202 7748 : if (!ol_length(t->triggers))
6203 : return res;
6204 :
6205 1016 : for (n = ol_first_node(t->triggers); n; n = n->next) {
6206 542 : sql_trigger *trigger = n->data;
6207 :
6208 542 : if (!stack_push_frame(sql, "%OLD-NEW"))
6209 : return 0;
6210 542 : if (trigger->event == 2 && trigger->time == time) {
6211 : /* add name for the 'inserted' to the stack */
6212 261 : const char *n = trigger->new_name;
6213 261 : const char *o = trigger->old_name;
6214 :
6215 261 : if (!n) n = "new";
6216 261 : if (!o) o = "old";
6217 :
6218 261 : if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
6219 0 : stack_pop_frame(sql);
6220 0 : return 0;
6221 : }
6222 :
6223 261 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
6224 0 : stack_pop_frame(sql);
6225 0 : return 0;
6226 : }
6227 : }
6228 542 : stack_pop_frame(sql);
6229 : }
6230 : return res;
6231 : }
6232 :
6233 : static void
6234 25 : sql_update_check(backend *be, stmt **updates, sql_key *key, stmt *u_tids)
6235 : {
6236 25 : mvc *sql = be->mvc;
6237 25 : int pos = 0;
6238 25 : sql_rel *rel = rel_basetable(sql, key->t, key->t->base.name);
6239 25 : sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
6240 25 : rel->exps = rel_base_projection(sql, rel, 0);
6241 :
6242 : /* create sub stmt with needed updates (or projected col from to be updated table) */
6243 25 : list *ups = sa_list(sql->sa);
6244 55 : for(node *n = key->columns->h; n; n = n->next) {
6245 30 : sql_kc *kc = n->data;
6246 30 : stmt *upd = NULL;
6247 :
6248 30 : if (updates && updates[kc->c->colnr]) {
6249 : upd = updates[kc->c->colnr];
6250 : } else {
6251 17 : upd = stmt_col(be, kc->c, u_tids, u_tids->partition);
6252 : }
6253 30 : sql_exp *e = rel_base_bind_column2(sql, rel, kc->c->t->base.name, kc->c->base.name);
6254 30 : upd = stmt_alias(be, upd, e->alias.label, kc->c->t->base.name, kc->c->base.name);
6255 30 : append(ups, upd);
6256 : }
6257 :
6258 25 : stmt *sub = stmt_list(be, ups);
6259 25 : stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
6260 :
6261 25 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6262 25 : s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
6263 25 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6264 25 : char *msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: violated constraint '%s.%s' CHECK(%s)", key->t->s->base.name, key->base.name, exp->comment);
6265 25 : (void)stmt_exception(be, s, msg, 00001);
6266 25 : }
6267 :
6268 : static void
6269 3874 : sql_update_check_null(backend *be, sql_table *t, stmt **updates)
6270 : {
6271 3874 : mvc *sql = be->mvc;
6272 3874 : node *n;
6273 3874 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6274 :
6275 46036 : for (n = ol_first_node(t->columns); n; n = n->next) {
6276 42162 : sql_column *c = n->data;
6277 :
6278 42162 : if (updates[c->colnr] && !c->null) {
6279 129 : stmt *s = updates[c->colnr];
6280 129 : char *msg = NULL;
6281 :
6282 129 : if (!(s->key && s->nrcols == 0)) {
6283 129 : s = stmt_selectnil(be, updates[c->colnr]);
6284 129 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6285 : } else {
6286 0 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
6287 :
6288 0 : s = stmt_unop(be, updates[c->colnr], NULL, isnil);
6289 : }
6290 129 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
6291 129 : (void)stmt_exception(be, s, msg, 00001);
6292 : }
6293 : }
6294 3874 : }
6295 :
6296 : /* updates: an array of table width, per column holds the values for the to be updated rows */
6297 : static list *
6298 43 : sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
6299 : {
6300 43 : mvc *sql = be->mvc;
6301 43 : list *idx_updates = NULL;
6302 43 : int i, nr_cols = ol_length(t->columns);
6303 43 : list *l = sa_list(sql->sa);
6304 43 : node *n;
6305 43 : stmt *cnt = NULL;
6306 :
6307 43 : sql_update_check_null(be, t, updates);
6308 :
6309 : /* check keys + get idx */
6310 43 : idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
6311 43 : if (!idx_updates) {
6312 0 : assert(0);
6313 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
6314 : }
6315 :
6316 : /* before */
6317 43 : if (!sql_update_triggers(be, t, rows, updates, 0))
6318 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6319 :
6320 : /* apply updates */
6321 131 : for (i = 0, n = ol_first_node(t->columns); i < nr_cols && n; i++, n = n->next) {
6322 88 : sql_column *c = n->data;
6323 :
6324 88 : if (updates[i])
6325 45 : append(l, stmt_update_col(be, c, rows, updates[i]));
6326 : }
6327 43 : if (cascade_updates(be, t, rows, updates))
6328 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
6329 :
6330 : /* after */
6331 43 : if (!sql_update_triggers(be, t, rows, updates, 1))
6332 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6333 :
6334 43 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
6335 43 : cnt = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
6336 43 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
6337 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6338 43 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6339 43 : stmt_add_dependency_change(be, t, cnt);
6340 : /* cascade ?? */
6341 : return l;
6342 : }
6343 :
6344 : /* updates with empty list is alter with create idx or keys */
6345 : static stmt *
6346 3972 : rel2bin_update(backend *be, sql_rel *rel, list *refs)
6347 : {
6348 3972 : mvc *sql = be->mvc;
6349 3972 : stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL, *cnt;
6350 3972 : list *l = sa_list(sql->sa);
6351 3972 : int nr_cols, updcol, idx_ups = 0;
6352 3972 : node *m;
6353 3972 : sql_rel *tr = rel->l, *prel = rel->r;
6354 3972 : sql_table *t = NULL;
6355 :
6356 3972 : if ((rel->flag&UPD_COMP)) { /* special case ! */
6357 1164 : idx_ups = 1;
6358 1164 : prel = rel->l;
6359 1164 : rel = rel->r;
6360 1164 : tr = rel->l;
6361 : }
6362 3972 : if (tr->op == op_basetable) {
6363 2628 : t = tr->l;
6364 : } else {
6365 1344 : ddl = subrel_bin(be, tr, refs);
6366 1344 : ddl = subrel_project(be, ddl, refs, NULL);
6367 1344 : if (!ddl)
6368 : return NULL;
6369 1344 : t = rel_ddl_table_get(tr);
6370 :
6371 : /* no columns to update (probably an new pkey or ckey!) */
6372 1344 : if (!rel->exps) {
6373 141 : stmt *tids = stmt_tid(be, t, 0);
6374 154 : for (m = ol_first_node(t->keys); m; m = m->next) {
6375 13 : sql_key * key = m->data;
6376 13 : if (key->type == ckey && key->base.new)
6377 13 : sql_update_check(be, NULL, key, tids);
6378 : }
6379 : return ddl;
6380 : }
6381 : }
6382 :
6383 3831 : if (rel->r) /* first construct the update relation */
6384 3831 : update = subrel_bin(be, rel->r, refs);
6385 3831 : update = subrel_project(be, update, refs, rel->r);
6386 :
6387 3831 : if (!update)
6388 : return NULL;
6389 :
6390 3831 : if (idx_ups)
6391 1164 : pup = refs_find_rel(refs, prel);
6392 :
6393 3831 : updates = table_update_stmts(sql, t, &nr_cols);
6394 3831 : tids = update->op4.lval->h->data;
6395 :
6396 : /* lookup the updates */
6397 10421 : for (m = rel->exps->h; m; m = m->next) {
6398 6590 : sql_exp *ce = m->data;
6399 6590 : sql_column *c = find_sql_column(t, exp_name(ce));
6400 :
6401 6590 : if (c)
6402 2784 : updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
6403 : }
6404 :
6405 4736 : for (m = ol_first_node(t->keys); m; m = m->next) {
6406 905 : sql_key * key = m->data;
6407 905 : if (key->type == ckey && is_check_updated(key, updates))
6408 12 : sql_update_check(be, updates, key, tids);
6409 : }
6410 3831 : sql_update_check_null(be, t, updates);
6411 :
6412 : /* check keys + get idx */
6413 3831 : updcol = first_updated_col(updates, ol_length(t->columns));
6414 10421 : for (m = rel->exps->h; m; m = m->next) {
6415 6590 : sql_exp *ce = m->data;
6416 6590 : sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
6417 6590 : stmt *update_idx, *is = NULL;
6418 :
6419 6590 : if (i) {
6420 1178 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6421 148 : continue;
6422 :
6423 1030 : update_idx = bin_find_column(be, update, ce->l, ce->r);
6424 1030 : if (update_idx)
6425 : is = update_idx;
6426 1030 : if (hash_index(i->type) && list_length(i->columns) <= 1) {
6427 1030 : is = NULL;
6428 1030 : update_idx = NULL;
6429 : }
6430 1030 : if (i->key)
6431 1603 : sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
6432 1030 : if (is)
6433 780 : list_append(l, stmt_update_idx(be, i, tids, is));
6434 : }
6435 : }
6436 :
6437 : /* before */
6438 3831 : if (!sql_update_triggers(be, t, tids, updates, 0)) {
6439 0 : if (sql->cascade_action)
6440 0 : sql->cascade_action = NULL;
6441 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6442 : }
6443 :
6444 : /* apply the update */
6445 10421 : for (m = rel->exps->h; m; m = m->next) {
6446 6590 : sql_exp *ce = m->data;
6447 6590 : sql_column *c = find_sql_column(t, exp_name(ce));
6448 :
6449 6590 : if (c)
6450 2784 : append(l, stmt_update_col(be, c, tids, updates[c->colnr]));
6451 : }
6452 :
6453 3831 : stmt* returning = NULL;
6454 3831 : if (rel->returning) {
6455 5 : sql_rel* b = rel->l;
6456 5 : int refcnt = b->ref.refcnt; // HACK: forces recalculation of base columns since they are assumed to be updated
6457 5 : b->ref.refcnt = 1;
6458 5 : returning = subrel_bin(be, b, refs);
6459 5 : b->ref.refcnt = refcnt;
6460 5 : returning->cand = tids;
6461 5 : returning = subrel_project(be, returning, refs, b);
6462 5 : sql->type = Q_TABLE;
6463 : }
6464 :
6465 3831 : if (cascade_updates(be, t, tids, updates)) {
6466 0 : if (sql->cascade_action)
6467 0 : sql->cascade_action = NULL;
6468 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
6469 : }
6470 :
6471 : /* after */
6472 3831 : if (!sql_update_triggers(be, t, tids, updates, 1)) {
6473 0 : if (sql->cascade_action)
6474 0 : sql->cascade_action = NULL;
6475 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6476 : }
6477 :
6478 3831 : if (ddl) {
6479 1203 : list_prepend(l, ddl);
6480 1203 : cnt = stmt_list(be, l);
6481 : } else {
6482 2628 : cnt = stmt_aggr(be, tids, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
6483 2628 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
6484 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6485 2628 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6486 2624 : stmt_add_dependency_change(be, t, cnt);
6487 : }
6488 :
6489 3831 : if (sql->cascade_action)
6490 65 : sql->cascade_action = NULL;
6491 3831 : if (rel->r && !rel_predicates(be, rel->r))
6492 : return NULL;
6493 3831 : return returning?returning:cnt;
6494 : }
6495 :
6496 : static int
6497 20 : sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, stmt **deleted_cols, int type)
6498 : {
6499 : /* Put single relation of updates and old values on to the stack */
6500 20 : sql_rel *r = NULL;
6501 20 : node *n;
6502 20 : list *exps = sa_list(sql->sa);
6503 20 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
6504 :
6505 20 : ti->t = t;
6506 20 : ti->tids = tids;
6507 20 : ti->updates = deleted_cols;
6508 20 : ti->type = type;
6509 20 : ti->nn = name;
6510 56 : for (n = ol_first_node(t->columns); n; n = n->next) {
6511 36 : sql_column *c = n->data;
6512 36 : sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6513 36 : ne->alias.label = -(sql->nid++);
6514 :
6515 36 : append(exps, ne);
6516 : }
6517 20 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
6518 20 : r->l = ti;
6519 :
6520 20 : return stack_push_rel_view(sql, name, r) ? 1 : 0;
6521 : }
6522 :
6523 : static int
6524 83977 : sql_delete_triggers(backend *be, sql_table *t, stmt *tids, stmt **deleted_cols, int time, int firing_type, int internal_type)
6525 : {
6526 83977 : mvc *sql = be->mvc;
6527 83977 : node *n;
6528 83977 : int res = 1;
6529 :
6530 83977 : if (!ol_length(t->triggers))
6531 : return res;
6532 :
6533 188 : for (n = ol_first_node(t->triggers); n; n = n->next) {
6534 142 : sql_trigger *trigger = n->data;
6535 :
6536 142 : if (!stack_push_frame(sql, "%OLD-NEW"))
6537 : return 0;
6538 142 : if (trigger->event == firing_type && trigger->time == time) {
6539 : /* add name for the 'deleted' to the stack */
6540 20 : const char *o = trigger->old_name;
6541 :
6542 20 : if (!o) o = "old";
6543 :
6544 20 : if(!sql_stack_add_deleted(sql, o, t, tids, deleted_cols, internal_type)) {
6545 0 : stack_pop_frame(sql);
6546 0 : return 0;
6547 : }
6548 :
6549 20 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
6550 0 : stack_pop_frame(sql);
6551 0 : return 0;
6552 : }
6553 : }
6554 142 : stack_pop_frame(sql);
6555 : }
6556 : return res;
6557 : }
6558 :
6559 : static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
6560 :
6561 : static stmt *
6562 9 : sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
6563 : {
6564 9 : sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
6565 9 : return sql_delete(be, t, ftids);
6566 : }
6567 :
6568 : static void
6569 130 : sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
6570 : {
6571 130 : mvc *sql = be->mvc;
6572 130 : sql_subtype *lng = sql_bind_localtype("lng");
6573 130 : sql_subtype *bt = sql_bind_localtype("bit");
6574 130 : sql_trans *tr = be->mvc->session->tr;
6575 130 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
6576 :
6577 130 : if (keys) {
6578 190 : for (node *n = keys->h; n; n = n->next->next) {
6579 60 : sqlid fkey_id = *(sqlid*)n->data;
6580 60 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
6581 60 : sql_key *fk = (sql_key*)b;
6582 60 : sql_fkey *rk = (sql_fkey*)b;
6583 :
6584 60 : if (fk->type != fkey || rk->rkey != k->base.id)
6585 0 : continue;
6586 60 : char *msg = NULL;
6587 60 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6588 60 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
6589 60 : stmt *s, *tids;
6590 :
6591 60 : tids = stmt_tid(be, fk->idx->t, 0);
6592 60 : s = stmt_idx(be, fk->idx, tids, tids->partition);
6593 60 : s = stmt_join(be, s, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
6594 60 : s = stmt_result(be, s, 0);
6595 60 : tids = stmt_project(be, s, tids);
6596 60 : if(cascade) { /* for truncate statements with the cascade option */
6597 1 : s = sql_delete_cascade_Fkeys(be, fk, tids);
6598 1 : list_prepend(l, s);
6599 : } else {
6600 59 : switch (((sql_fkey*)fk)->on_delete) {
6601 : case ACT_NO_ACTION:
6602 : break;
6603 11 : case ACT_SET_NULL:
6604 : case ACT_SET_DEFAULT:
6605 11 : s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
6606 11 : list_prepend(l, s);
6607 11 : break;
6608 8 : case ACT_CASCADE:
6609 8 : s = sql_delete_cascade_Fkeys(be, fk, tids);
6610 8 : list_prepend(l, s);
6611 8 : break;
6612 38 : default: /*RESTRICT*/
6613 : /* The overlap between deleted primaries and foreign should be empty */
6614 38 : s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
6615 38 : msg = sa_message(sql->sa, SQLSTATE(40002) "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
6616 38 : s = stmt_exception(be, s, msg, 00001);
6617 38 : list_prepend(l, s);
6618 : }
6619 : }
6620 : }
6621 130 : list_destroy(keys);
6622 : }
6623 130 : }
6624 :
6625 : static int
6626 41892 : sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
6627 : {
6628 41892 : mvc *sql = be->mvc;
6629 41892 : int res = 1;
6630 41892 : node *n;
6631 :
6632 41892 : if (!ol_length(t->keys))
6633 : return res;
6634 :
6635 304 : for (n = ol_first_node(t->keys); n; n = n->next) {
6636 173 : sql_key *k = n->data;
6637 :
6638 173 : if (k->type == pkey || k->type == ukey) {
6639 131 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
6640 130 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
6641 130 : if (!sql->cascade_action)
6642 120 : sql->cascade_action = sa_list(sql->sa);
6643 :
6644 130 : *local_id = k->base.id;
6645 130 : list_append(sql->cascade_action, local_id);
6646 130 : sql_delete_ukey(be, rows, k, l, which, cascade);
6647 : }
6648 : }
6649 : }
6650 : return res;
6651 : }
6652 :
6653 : static stmt *
6654 495 : sql_delete(backend *be, sql_table *t, stmt *rows)
6655 : {
6656 495 : mvc *sql = be->mvc;
6657 495 : stmt *v = NULL, *s = NULL;
6658 495 : list *l = sa_list(sql->sa);
6659 495 : stmt **deleted_cols = NULL;
6660 :
6661 495 : if (rows) {
6662 : v = rows;
6663 : } else { /* delete all */
6664 128 : v = stmt_tid(be, t, 0);
6665 : }
6666 :
6667 : /* project all columns */
6668 495 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
6669 38 : int nr = 0;
6670 38 : deleted_cols = table_update_stmts(sql, t, &nr);
6671 38 : int i = 0;
6672 105 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
6673 67 : sql_column *c = n->data;
6674 67 : stmt *s = stmt_col(be, c, v, v->partition);
6675 :
6676 67 : deleted_cols[i] = s;
6677 67 : list_append(l, s);
6678 : }
6679 : }
6680 :
6681 : /* before */
6682 495 : if (!sql_delete_triggers(be, t, v, deleted_cols, 0, 1, 3))
6683 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
6684 :
6685 495 : if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
6686 0 : return sql_error(sql, 10, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
6687 :
6688 495 : if (rows) {
6689 367 : s = stmt_delete(be, t, rows);
6690 367 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
6691 366 : s = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
6692 : } else { /* delete all */
6693 128 : s = stmt_table_clear(be, t, 0); /* first column */
6694 : }
6695 :
6696 : /* after */
6697 495 : if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
6698 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
6699 :
6700 495 : if (add_to_rowcount_accumulator(be, s->nr) < 0)
6701 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6702 495 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6703 493 : stmt_add_dependency_change(be, t, s);
6704 : return s;
6705 : }
6706 :
6707 : static stmt *
6708 486 : rel2bin_delete(backend *be, sql_rel *rel, list *refs)
6709 : {
6710 486 : mvc *sql = be->mvc;
6711 486 : stmt *stdelete = NULL, *tids = NULL, *returning = NULL;
6712 486 : sql_rel *tr = rel->l;
6713 486 : sql_table *t = NULL;
6714 :
6715 486 : if (tr->op == op_basetable)
6716 486 : t = tr->l;
6717 : else
6718 0 : assert(0/*ddl statement*/);
6719 :
6720 486 : if (rel->r) { /* first construct the deletes relation */
6721 358 : stmt *rows = subrel_bin(be, rel->r, refs);
6722 358 : rows = subrel_project(be, rows, refs, rel->r);
6723 358 : if (!rows)
6724 : return NULL;
6725 358 : assert(rows->type == st_list);
6726 358 : tids = rows->op4.lval->h->data; /* TODO this should be the candidate list instead */
6727 : }
6728 :
6729 486 : if (rel->returning) {
6730 4 : returning = subrel_bin(be, rel->l, refs);
6731 4 : returning->cand = tids;
6732 4 : returning = subrel_project(be, returning, refs, rel->l);
6733 4 : sql->type = Q_TABLE;
6734 : }
6735 :
6736 486 : stdelete = sql_delete(be, t, tids);
6737 486 : if (sql->cascade_action)
6738 107 : sql->cascade_action = NULL;
6739 486 : if (!stdelete)
6740 : return NULL;
6741 :
6742 486 : if (rel->r && !rel_predicates(be, rel->r))
6743 : return NULL;
6744 486 : return returning?returning:stdelete;
6745 : }
6746 :
6747 : struct tablelist {
6748 : sql_table *table;
6749 : struct tablelist* next;
6750 : };
6751 :
6752 : static sql_table * /* inspect the other tables recursively for foreign key dependencies */
6753 41662 : check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct tablelist* next_append, sql_table *t, int cascade)
6754 : {
6755 41662 : struct tablelist* new_node;
6756 41662 : sql_trans *tr = sql->session->tr;
6757 41662 : sqlstore *store = sql->session->tr->store;
6758 :
6759 41662 : if (mvc_highwater(sql))
6760 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
6761 :
6762 41698 : if (t->keys) { /* Check for foreign key references */
6763 41716 : for (node *n = ol_first_node(t->keys); n; n = n->next) {
6764 25 : sql_key *k = n->data;
6765 :
6766 25 : if (k->type == ukey || k->type == pkey) {
6767 17 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
6768 :
6769 12 : if (keys) {
6770 21 : for (node *nn = keys->h; nn; nn = nn->next->next) {
6771 6 : sqlid fkey_id = *(sqlid*)nn->data;
6772 6 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
6773 6 : sql_key *fk = (sql_key*)b;
6774 6 : sql_fkey *rk = (sql_fkey*)b;
6775 :
6776 6 : if (fk->type != fkey || rk->rkey != k->base.id)
6777 1 : continue;
6778 5 : k = fk;
6779 : /* make sure it is not a self referencing key */
6780 5 : if (k->t != t && !cascade && isTable(t)) {
6781 4 : node *nnn = ol_first_node(t->columns);
6782 4 : sql_column *c = nnn->data;
6783 4 : size_t n_rows = store->storage_api.count_col(sql->session->tr, c, 10);
6784 4 : if (n_rows > 0) {
6785 2 : list_destroy(keys);
6786 2 : return sql_error(sql, 02, SQLSTATE(23000) "TRUNCATE: FOREIGN KEY %s.%s depends on %s", k->t->base.name, k->base.name, t->base.name);
6787 : }
6788 1 : } else if (k->t != t) {
6789 : int found = 0;
6790 2 : for (struct tablelist *node_check = tlist; node_check; node_check = node_check->next) {
6791 1 : if (node_check->table == k->t)
6792 0 : found = 1;
6793 : }
6794 1 : if (!found) {
6795 2 : if ((new_node = SA_NEW(sql->ta, struct tablelist)) == NULL) {
6796 0 : list_destroy(keys);
6797 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6798 : }
6799 1 : new_node->table = k->t;
6800 1 : new_node->next = NULL;
6801 1 : next_append->next = new_node;
6802 1 : if (!check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade)) {
6803 0 : list_destroy(keys);
6804 0 : return NULL;
6805 : }
6806 : }
6807 : }
6808 : }
6809 15 : list_destroy(keys);
6810 : }
6811 : }
6812 : }
6813 : }
6814 : return t;
6815 : }
6816 :
6817 : static stmt *
6818 41665 : sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
6819 : {
6820 41665 : mvc *sql = be->mvc;
6821 41665 : list *l = sa_list(sql->sa);
6822 41672 : stmt *ret = NULL, *other = NULL;
6823 41672 : struct tablelist *new_list = SA_NEW(sql->ta, struct tablelist);
6824 41694 : stmt **deleted_cols = NULL;
6825 :
6826 41694 : if (!new_list)
6827 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6828 41694 : new_list->table = t;
6829 41694 : new_list->next = NULL;
6830 41694 : if (!check_for_foreign_key_references(sql, new_list, new_list, t, cascade))
6831 2 : goto finalize;
6832 :
6833 83246 : for (struct tablelist *list_node = new_list; list_node; list_node = list_node->next) {
6834 41552 : sql_table *next = list_node->table;
6835 41552 : stmt *v = stmt_tid(be, next, 0);
6836 :
6837 : /* project all columns */
6838 41591 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
6839 18 : int nr = 0;
6840 18 : deleted_cols = table_update_stmts(sql, t, &nr);
6841 18 : int i = 0;
6842 50 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
6843 32 : sql_column *c = n->data;
6844 32 : stmt *s = stmt_col(be, c, v, v->partition);
6845 :
6846 32 : deleted_cols[i] = s;
6847 32 : list_append(l, s);
6848 : }
6849 : }
6850 :
6851 : /* before */
6852 41686 : if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
6853 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
6854 0 : ret = NULL;
6855 0 : goto finalize;
6856 : }
6857 :
6858 41482 : if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
6859 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
6860 0 : ret = NULL;
6861 0 : goto finalize;
6862 : }
6863 :
6864 41425 : other = stmt_table_clear(be, next, restart_sequences);
6865 41516 : list_append(l, other);
6866 41477 : if (next && t && next->base.id == t->base.id)
6867 41477 : ret = other;
6868 :
6869 : /* after */
6870 41477 : if (!sql_delete_triggers(be, next, v, deleted_cols, 1, 3, 4)) {
6871 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
6872 0 : ret = NULL;
6873 0 : goto finalize;
6874 : }
6875 :
6876 41586 : if (add_to_rowcount_accumulator(be, other->nr) < 0) {
6877 0 : (void) sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6878 0 : ret = NULL;
6879 0 : goto finalize;
6880 : }
6881 41401 : if (next->s && isGlobal(next) && !isGlobalTemp(next))
6882 41533 : stmt_add_dependency_change(be, next, other);
6883 : }
6884 :
6885 41694 : finalize:
6886 41696 : sa_reset(sql->ta);
6887 41696 : return ret;
6888 : }
6889 :
6890 : #define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
6891 : #define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
6892 :
6893 : static stmt *
6894 41671 : rel2bin_truncate(backend *be, sql_rel *rel)
6895 : {
6896 41671 : mvc *sql = be->mvc;
6897 41671 : stmt *truncate = NULL;
6898 41671 : sql_rel *tr = rel->l;
6899 41671 : sql_table *t = NULL;
6900 41671 : node *n = NULL;
6901 41671 : int restart_sequences, cascade;
6902 :
6903 41671 : if (tr->op == op_basetable)
6904 41671 : t = tr->l;
6905 : else
6906 0 : assert(0/*ddl statement*/);
6907 :
6908 41671 : n = rel->exps->h;
6909 41671 : restart_sequences = E_ATOM_INT(n->data);
6910 41671 : cascade = E_ATOM_INT(n->next->data);
6911 41671 : truncate = sql_truncate(be, t, restart_sequences, cascade);
6912 41647 : if (sql->cascade_action)
6913 13 : sql->cascade_action = NULL;
6914 41647 : return truncate;
6915 : }
6916 :
6917 234 : static ValPtr take_atom_arg(node **n, int expected_type) {
6918 234 : sql_exp *e = (*n)->data;
6919 234 : atom *a = e->l;
6920 234 : assert(a->tpe.type->localtype == expected_type); (void) expected_type;
6921 234 : assert(!a->isnull);
6922 234 : *n = (*n)->next;
6923 234 : return &a->data;
6924 : }
6925 :
6926 : static stmt *
6927 74 : rel2bin_output(backend *be, sql_rel *rel, list *refs)
6928 : {
6929 74 : mvc *sql = be->mvc;
6930 74 : stmt *sub = NULL, *fns = NULL, *res = NULL;
6931 74 : list *slist = sa_list(sql->sa);
6932 :
6933 74 : if (rel->l) /* first construct the sub relation */
6934 74 : sub = subrel_bin(be, rel->l, refs);
6935 74 : sub = subrel_project(be, sub, refs, rel->l);
6936 74 : if (!sub)
6937 : return NULL;
6938 :
6939 74 : if (!rel->exps)
6940 : return sub;
6941 :
6942 74 : list *arglist = rel->exps;
6943 74 : node *argnode = arglist->h;
6944 74 : atom *a = ((sql_exp*)argnode->data)->l;
6945 74 : int tpe = a->tpe.type->localtype;
6946 :
6947 : // With regular COPY INTO <file>, the first argument is a string.
6948 : // With COPY INTO BINARY, it is an int.
6949 74 : if (tpe == TYPE_str) {
6950 32 : atom *tatom = ((sql_exp*) argnode->data)->l;
6951 32 : const char *tsep = sa_strdup(sql->sa, tatom->isnull ? "" : tatom->data.val.sval);
6952 32 : atom *ratom = ((sql_exp*) argnode->next->data)->l;
6953 32 : const char *rsep = sa_strdup(sql->sa, ratom->isnull ? "" : ratom->data.val.sval);
6954 32 : atom *satom = ((sql_exp*) argnode->next->next->data)->l;
6955 32 : const char *ssep = sa_strdup(sql->sa, satom->isnull ? "" : satom->data.val.sval);
6956 32 : atom *natom = ((sql_exp*) argnode->next->next->next->data)->l;
6957 32 : const char *ns = sa_strdup(sql->sa, natom->isnull ? "" : natom->data.val.sval);
6958 :
6959 32 : const char *fn = NULL;
6960 32 : int onclient = 0;
6961 32 : if (argnode->next->next->next->next) {
6962 23 : fn = E_ATOM_STRING(argnode->next->next->next->next->data);
6963 23 : fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
6964 23 : onclient = E_ATOM_INT(argnode->next->next->next->next->next->data);
6965 : }
6966 32 : stmt *export = stmt_export(be, sub, tsep, rsep, ssep, ns, onclient, fns);
6967 32 : list_append(slist, export);
6968 42 : } else if (tpe == TYPE_int) {
6969 42 : endianness endian = take_atom_arg(&argnode, TYPE_int)->val.ival;
6970 42 : bool do_byteswap = (endian != endian_native && endian != OUR_ENDIANNESS);
6971 42 : int on_client = take_atom_arg(&argnode, TYPE_int)->val.ival;
6972 42 : assert(sub->type == st_list);
6973 42 : list *collist = sub->op4.lval;
6974 192 : for (node *colnode = collist->h; colnode; colnode = colnode->next) {
6975 150 : stmt *colstmt = colnode->data;
6976 150 : assert(argnode != NULL);
6977 150 : const char *filename = take_atom_arg(&argnode, TYPE_str)->val.sval;
6978 150 : stmt *export = stmt_export_bin(be, colstmt, do_byteswap, filename, on_client);
6979 150 : list_append(slist, export);
6980 : }
6981 42 : assert(argnode == NULL);
6982 :
6983 : } else {
6984 0 : assert(0 && "unimplemented export statement type");
6985 : return sub;
6986 : }
6987 :
6988 74 : if (sub->type == st_list && ((stmt*)sub->op4.lval->h->data)->nrcols != 0) {
6989 73 : res = stmt_aggr(be, sub->op4.lval->h->data, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
6990 : } else {
6991 1 : res = stmt_atom_lng(be, 1);
6992 : }
6993 74 : if (add_to_rowcount_accumulator(be, res->nr) < 0)
6994 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6995 : return res;
6996 : }
6997 :
6998 : static list *
6999 54 : merge_stmt_join_projections(backend *be, stmt *left, stmt *right, stmt *jl, stmt *jr, stmt *diff)
7000 : {
7001 54 : mvc *sql = be->mvc;
7002 54 : list *l = sa_list(sql->sa);
7003 :
7004 54 : if (left)
7005 117 : for (node *n = left->op4.lval->h; n; n = n->next) {
7006 89 : stmt *c = n->data;
7007 89 : assert(c->type == st_alias);
7008 89 : const char *rnme = table_name(sql->sa, c);
7009 89 : const char *nme = column_name(sql->sa, c);
7010 89 : stmt *s = stmt_project(be, jl ? jl : diff, column(be, c));
7011 :
7012 89 : s = stmt_alias(be, s, c->label, rnme, nme);
7013 89 : list_append(l, s);
7014 : }
7015 54 : if (right)
7016 154 : for (node *n = right->op4.lval->h; n; n = n->next) {
7017 110 : stmt *c = n->data;
7018 110 : assert(c->type == st_alias);
7019 110 : const char *rnme = table_name(sql->sa, c);
7020 110 : const char *nme = column_name(sql->sa, c);
7021 170 : stmt *s = stmt_project(be, jr ? jr : diff, column(be, c));
7022 :
7023 110 : s = stmt_alias(be, s, c->label, rnme, nme);
7024 110 : list_append(l, s);
7025 : }
7026 54 : return l;
7027 : }
7028 :
7029 : static void
7030 28 : validate_merge_delete_update(backend *be, bool delete, stmt *bt_stmt, sql_rel *bt, stmt *jl, stmt *ld)
7031 : {
7032 28 : mvc *sql = be->mvc;
7033 28 : str msg;
7034 28 : sql_table *t = bt->l;
7035 28 : char *alias = (char *) rel_name(bt);
7036 28 : stmt *cnt1 = stmt_aggr(be, jl, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
7037 28 : stmt *cnt2 = stmt_aggr(be, ld, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
7038 28 : sql_subfunc *add = sql_bind_func(sql, "sys", "sql_add", tail_type(cnt1), tail_type(cnt2), F_FUNC, true, true);
7039 28 : stmt *s1 = stmt_binop(be, cnt1, cnt2, NULL, add);
7040 28 : stmt *cnt3 = stmt_aggr(be, bin_find_smallest_column(be, bt_stmt), NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
7041 28 : sql_subfunc *bf = sql_bind_func(sql, "sys", ">", tail_type(s1), tail_type(cnt3), F_FUNC, true, true);
7042 28 : stmt *s2 = stmt_binop(be, s1, cnt3, NULL, bf);
7043 :
7044 28 : if (alias && strcmp(alias, t->base.name) == 0) /* detect if alias is present */
7045 : alias = NULL;
7046 38 : msg = sa_message(sql->sa, SQLSTATE(40002) "MERGE %s: Multiple rows in the input relation match the same row in the target %s '%s%s%s'",
7047 : delete ? "DELETE" : "UPDATE",
7048 : alias ? "relation" : "table",
7049 22 : alias ? alias : t->s ? t->s->base.name : "", alias ? "" : ".", alias ? "" : t->base.name);
7050 28 : (void)stmt_exception(be, s2, msg, 00001);
7051 28 : }
7052 :
7053 : static stmt *
7054 54 : rel2bin_merge_apply_update(backend *be, sql_rel *join, sql_rel *upd, list *refs, stmt *bt_stmt, stmt *target_stmt, stmt *jl, stmt *jr, stmt *ld, stmt **rd)
7055 : {
7056 54 : if (is_insert(upd->op)) {
7057 26 : if (!*rd) {
7058 26 : *rd = stmt_tdiff(be, stmt_mirror(be, bin_find_smallest_column(be, target_stmt)), jr, NULL);
7059 : }
7060 26 : stmt *s = stmt_list(be, merge_stmt_join_projections(be, NULL, target_stmt, NULL, NULL, *rd));
7061 26 : refs_update_stmt(refs, join, s); /* project the differences on the target side for inserts */
7062 :
7063 26 : return rel2bin_insert(be, upd, refs);
7064 : } else {
7065 48 : stmt *s = stmt_list(be, merge_stmt_join_projections(be, bt_stmt, is_update(upd->op) ? target_stmt : NULL, jl, is_update(upd->op) ? jr : NULL, NULL));
7066 28 : refs_update_stmt(refs, join, s); /* project the matched values on both sides for updates and deletes */
7067 :
7068 28 : assert(is_update(upd->op) || is_delete(upd->op));
7069 : /* the left joined values + left difference must be smaller than the table count */
7070 28 : validate_merge_delete_update(be, is_update(upd->op), bt_stmt, join->l, jl, ld);
7071 :
7072 28 : return is_update(upd->op) ? rel2bin_update(be, upd, refs) : rel2bin_delete(be, upd, refs);
7073 : }
7074 : }
7075 :
7076 : static stmt *
7077 44 : rel2bin_merge(backend *be, sql_rel *rel, list *refs)
7078 : {
7079 44 : mvc *sql = be->mvc;
7080 44 : sql_rel *join;
7081 :
7082 44 : if (is_project(((sql_rel*)rel->l)->op)) {
7083 0 : join = ((sql_rel*)rel->l)->l;
7084 : } else {
7085 : join = rel->l;
7086 : }
7087 :
7088 44 : sql_rel *r = rel->r;
7089 44 : stmt *join_st, *bt_stmt, *target_stmt, *jl, *jr, *ld, *rd = NULL, *ns;
7090 44 : list *slist = sa_list(sql->sa);
7091 :
7092 44 : assert(rel_is_ref(join) && is_left(join->op));
7093 44 : join_st = subrel_bin(be, join, refs);
7094 44 : if (!join_st)
7095 : return NULL;
7096 :
7097 : /* grab generated left join outputs and generate updates accordingly to matched and not matched values */
7098 44 : assert(join_st->type == st_list && list_length(join_st->extra) == 5);
7099 44 : bt_stmt = join_st->extra->h->data;
7100 44 : target_stmt = join_st->extra->h->next->data;
7101 44 : jl = join_st->extra->h->next->next->data;
7102 44 : jr = join_st->extra->h->next->next->next->data;
7103 44 : ld = join_st->extra->h->next->next->next->next->data;
7104 :
7105 44 : if (is_ddl(r->op)) {
7106 44 : assert(r->flag == ddl_list);
7107 44 : if (r->l) {
7108 44 : if ((ns = rel2bin_merge_apply_update(be, join, r->l, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
7109 : return NULL;
7110 44 : list_append(slist, ns);
7111 : }
7112 44 : if (r->r) {
7113 10 : if ((ns = rel2bin_merge_apply_update(be, join, r->r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
7114 : return NULL;
7115 10 : list_append(slist, ns);
7116 : }
7117 : } else {
7118 0 : if (!(ns = rel2bin_merge_apply_update(be, join, r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)))
7119 : return NULL;
7120 0 : list_append(slist, ns);
7121 : }
7122 44 : return stmt_list(be, slist);
7123 : }
7124 :
7125 : static stmt *
7126 518 : rel2bin_list(backend *be, sql_rel *rel, list *refs)
7127 : {
7128 518 : mvc *sql = be->mvc;
7129 518 : stmt *l = NULL, *r = NULL;
7130 518 : list *slist = sa_list(sql->sa);
7131 :
7132 518 : if (rel->l) /* first construct the sub relation */
7133 518 : l = subrel_bin(be, rel->l, refs);
7134 518 : if (rel->r) /* first construct the sub relation */
7135 518 : r = subrel_bin(be, rel->r, refs);
7136 518 : l = subrel_project(be, l, refs, rel->l);
7137 518 : r = subrel_project(be, r, refs, rel->r);
7138 518 : if (!l || !r)
7139 : return NULL;
7140 518 : list_append(slist, l);
7141 518 : list_append(slist, r);
7142 518 : return stmt_list(be, slist);
7143 : }
7144 :
7145 : static stmt *
7146 14591 : rel2bin_psm(backend *be, sql_rel *rel)
7147 : {
7148 14591 : mvc *sql = be->mvc;
7149 14591 : node *n;
7150 14591 : list *l = sa_list(sql->sa);
7151 14590 : stmt *sub = NULL;
7152 :
7153 24970 : for (n = rel->exps->h; n; n = n->next) {
7154 15007 : sql_exp *e = n->data;
7155 15007 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7156 15006 : if (!s)
7157 : return NULL;
7158 :
7159 10380 : if (s && s->type == st_table) /* relational statement */
7160 37 : sub = s->op1;
7161 : else
7162 10343 : append(l, s);
7163 : }
7164 9963 : return stmt_list(be, l);
7165 : }
7166 :
7167 : static stmt *
7168 285 : rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
7169 : {
7170 285 : stmt *l = NULL, *r = NULL;
7171 285 : node *n = NULL;
7172 285 : list *slist = sa_list(be->mvc->sa);
7173 :
7174 285 : if (rel->l) /* first construct the sub relation */
7175 0 : l = subrel_bin(be, rel->l, refs);
7176 285 : if (rel->r) /* first construct the sub relation */
7177 0 : r = subrel_bin(be, rel->r, refs);
7178 285 : l = subrel_project(be, l, refs, rel->l);
7179 285 : r = subrel_project(be, r, refs, rel->r);
7180 285 : if ((rel->l && !l) || (rel->r && !r))
7181 : return NULL;
7182 :
7183 285 : assert(rel->exps);
7184 285 : assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
7185 :
7186 285 : if (rel->exps) {
7187 2909 : for (n = rel->exps->h; n; n = n->next) {
7188 2624 : sql_exp *e = n->data;
7189 2624 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
7190 2624 : if (!s)
7191 : return NULL;
7192 2624 : append(slist, s);
7193 : }
7194 : }
7195 285 : return stmt_catalog(be, rel->flag, stmt_list(be, slist));
7196 : }
7197 :
7198 : static stmt *
7199 157 : rel2bin_exception(backend *be, sql_rel *rel, list *refs)
7200 : {
7201 157 : stmt *l = NULL, *r = NULL;
7202 157 : list *slist = sa_list(be->mvc->sa);
7203 :
7204 157 : if (rel->l) /* first construct the sub relation */
7205 0 : l = subrel_bin(be, rel->l, refs);
7206 157 : if (rel->r) /* first construct the sub relation */
7207 157 : r = subrel_bin(be, rel->r, refs);
7208 157 : l = subrel_project(be, l, refs, rel->l);
7209 157 : r = subrel_project(be, r, refs, rel->r);
7210 157 : if ((rel->l && !l) || (rel->r && !r))
7211 : return NULL;
7212 :
7213 157 : assert(rel->exps);
7214 314 : for (node *n = rel->exps->h; n; n = n->next) {
7215 157 : sql_exp *e = n->data;
7216 157 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
7217 157 : if (!s)
7218 : return NULL;
7219 157 : list_append(slist, s);
7220 : }
7221 157 : return stmt_list(be, slist);
7222 : }
7223 :
7224 : static stmt *
7225 360 : rel2bin_seq(backend *be, sql_rel *rel, list *refs)
7226 : {
7227 360 : mvc *sql = be->mvc;
7228 360 : node *en = rel->exps->h;
7229 360 : stmt *restart, *sname, *seq, *seqname, *sl = NULL;
7230 360 : list *l = sa_list(sql->sa);
7231 :
7232 360 : if (rel->l) { /* first construct the sub relation */
7233 0 : sl = subrel_bin(be, rel->l, refs);
7234 0 : sl = subrel_project(be, sl, refs, rel->l);
7235 0 : if (!sl)
7236 : return NULL;
7237 : }
7238 :
7239 360 : restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7240 360 : sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7241 360 : seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7242 360 : seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7243 360 : if (!restart || !sname || !seqname || !seq)
7244 : return NULL;
7245 :
7246 360 : (void)refs;
7247 360 : append(l, sname);
7248 360 : append(l, seqname);
7249 360 : append(l, seq);
7250 360 : append(l, restart);
7251 360 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7252 : }
7253 :
7254 : static stmt *
7255 3130 : rel2bin_trans(backend *be, sql_rel *rel, list *refs)
7256 : {
7257 3130 : node *en = rel->exps->h;
7258 3130 : stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7259 3130 : stmt *name = NULL;
7260 :
7261 3130 : if (!chain)
7262 : return NULL;
7263 :
7264 3130 : (void)refs;
7265 3130 : if (en->next) {
7266 79 : name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7267 79 : if (!name)
7268 : return NULL;
7269 : }
7270 3130 : return stmt_trans(be, rel->flag, chain, name);
7271 : }
7272 :
7273 : static stmt *
7274 1273 : rel2bin_catalog_schema(backend *be, sql_rel *rel, list *refs)
7275 : {
7276 1273 : mvc *sql = be->mvc;
7277 1273 : node *en = rel->exps->h;
7278 1273 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7279 1273 : stmt *sname = NULL, *name = NULL, *ifexists = NULL;
7280 1273 : list *l = sa_list(sql->sa);
7281 :
7282 1273 : if (!action)
7283 : return NULL;
7284 :
7285 1273 : (void)refs;
7286 1273 : en = en->next;
7287 1273 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7288 1273 : if (!sname)
7289 : return NULL;
7290 1273 : append(l, sname);
7291 1273 : en = en->next;
7292 1273 : if (rel->flag == ddl_create_schema) {
7293 1082 : if (en) {
7294 38 : name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7295 38 : if (!name)
7296 : return NULL;
7297 : } else {
7298 1044 : name = stmt_atom_string_nil(be);
7299 : }
7300 1082 : append(l, name);
7301 : } else {
7302 191 : assert(rel->flag == ddl_drop_schema);
7303 191 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7304 191 : if (!ifexists)
7305 : return NULL;
7306 191 : append(l, ifexists);
7307 : }
7308 1273 : append(l, action);
7309 1273 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7310 : }
7311 :
7312 : static stmt *
7313 37779 : rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
7314 : {
7315 37779 : mvc *sql = be->mvc;
7316 37779 : node *en = rel->exps->h;
7317 37779 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7318 37779 : stmt *table = NULL, *sname, *tname = NULL, *kname = NULL, *ifexists = NULL, *replace = NULL;
7319 37779 : list *l = sa_list(sql->sa);
7320 :
7321 37779 : if (!action)
7322 : return NULL;
7323 :
7324 37779 : (void)refs;
7325 37779 : en = en->next;
7326 37779 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7327 37779 : if (!sname)
7328 : return NULL;
7329 37779 : en = en->next;
7330 37779 : if (en) {
7331 37779 : tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7332 37779 : if (!tname)
7333 : return NULL;
7334 37779 : en = en->next;
7335 : }
7336 37779 : append(l, sname);
7337 37779 : assert(tname);
7338 37779 : append(l, tname);
7339 37779 : if (rel->flag == ddl_drop_constraint) { /* needs extra string parameter for constraint name */
7340 150 : if (en) {
7341 150 : kname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7342 150 : if (!kname)
7343 : return NULL;
7344 150 : en = en->next;
7345 : }
7346 150 : append(l, kname);
7347 : }
7348 37779 : if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
7349 33730 : if (en) {
7350 33730 : table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7351 33730 : if (!table)
7352 : return NULL;
7353 33730 : en = en->next;
7354 : }
7355 33730 : append(l, table);
7356 : } else {
7357 4049 : if (en) {
7358 4049 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7359 4049 : if (!ifexists)
7360 : return NULL;
7361 4049 : en = en->next;
7362 : } else {
7363 0 : ifexists = stmt_atom_int(be, 0);
7364 : }
7365 4049 : append(l, ifexists);
7366 : }
7367 37779 : append(l, action);
7368 37779 : if (rel->flag == ddl_create_view) {
7369 22262 : if (en) {
7370 22262 : replace = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7371 22262 : if (!replace)
7372 : return NULL;
7373 : } else {
7374 0 : replace = stmt_atom_int(be, 0);
7375 : }
7376 22262 : append(l, replace);
7377 15517 : } else if (rel->flag == ddl_create_table && en) {
7378 101 : stmt *name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7379 101 : if (!name)
7380 : return NULL;
7381 101 : en = en->next;
7382 101 : append(l, name);
7383 101 : if (!en)
7384 : return NULL;
7385 101 : stmt *passwd = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7386 101 : if (!passwd)
7387 : return NULL;
7388 101 : append(l, passwd);
7389 : }
7390 37779 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7391 : }
7392 :
7393 : static stmt *
7394 243828 : rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
7395 : {
7396 243828 : mvc *sql = be->mvc;
7397 243828 : node *en;
7398 243828 : list *l = sa_list(sql->sa);
7399 :
7400 243828 : (void)refs;
7401 1473451 : for (en = rel->exps->h; en; en = en->next) {
7402 1229623 : stmt *es = NULL;
7403 :
7404 1229623 : if (en->data) {
7405 1211291 : es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7406 1211291 : if (!es)
7407 : return NULL;
7408 : } else {
7409 18332 : es = stmt_atom_string_nil(be);
7410 : }
7411 1229623 : append(l,es);
7412 : }
7413 243828 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7414 : }
7415 :
7416 : static stmt *
7417 301995 : rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
7418 : {
7419 301995 : mvc *sql = be->mvc;
7420 301995 : stmt *s = NULL;
7421 :
7422 301995 : switch (rel->flag) {
7423 74 : case ddl_output:
7424 74 : s = rel2bin_output(be, rel, refs);
7425 74 : sql->type = Q_TABLE;
7426 74 : break;
7427 518 : case ddl_list:
7428 518 : s = rel2bin_list(be, rel, refs);
7429 518 : break;
7430 14591 : case ddl_psm:
7431 14591 : s = rel2bin_psm(be, rel);
7432 14591 : break;
7433 157 : case ddl_exception:
7434 157 : s = rel2bin_exception(be, rel, refs);
7435 157 : break;
7436 360 : case ddl_create_seq:
7437 : case ddl_alter_seq:
7438 360 : s = rel2bin_seq(be, rel, refs);
7439 360 : sql->type = Q_SCHEMA;
7440 360 : break;
7441 285 : case ddl_alter_table_add_range_partition:
7442 : case ddl_alter_table_add_list_partition:
7443 285 : s = rel2bin_partition_limits(be, rel, refs);
7444 285 : sql->type = Q_SCHEMA;
7445 285 : break;
7446 3130 : case ddl_release:
7447 : case ddl_commit:
7448 : case ddl_rollback:
7449 : case ddl_trans:
7450 3130 : s = rel2bin_trans(be, rel, refs);
7451 3130 : sql->type = Q_TRANS;
7452 3130 : break;
7453 1273 : case ddl_create_schema:
7454 : case ddl_drop_schema:
7455 1273 : s = rel2bin_catalog_schema(be, rel, refs);
7456 1273 : sql->type = Q_SCHEMA;
7457 1273 : break;
7458 37779 : case ddl_create_table:
7459 : case ddl_drop_table:
7460 : case ddl_create_view:
7461 : case ddl_drop_view:
7462 : case ddl_drop_constraint:
7463 : case ddl_alter_table:
7464 37779 : s = rel2bin_catalog_table(be, rel, refs);
7465 37779 : sql->type = Q_SCHEMA;
7466 37779 : break;
7467 243828 : case ddl_drop_seq:
7468 : case ddl_create_type:
7469 : case ddl_drop_type:
7470 : case ddl_drop_index:
7471 : case ddl_create_function:
7472 : case ddl_drop_function:
7473 : case ddl_create_trigger:
7474 : case ddl_drop_trigger:
7475 : case ddl_grant_roles:
7476 : case ddl_revoke_roles:
7477 : case ddl_grant:
7478 : case ddl_revoke:
7479 : case ddl_grant_func:
7480 : case ddl_revoke_func:
7481 : case ddl_create_user:
7482 : case ddl_drop_user:
7483 : case ddl_alter_user:
7484 : case ddl_rename_user:
7485 : case ddl_create_role:
7486 : case ddl_drop_role:
7487 : case ddl_alter_table_add_table:
7488 : case ddl_alter_table_del_table:
7489 : case ddl_alter_table_set_access:
7490 : case ddl_comment_on:
7491 : case ddl_rename_schema:
7492 : case ddl_rename_table:
7493 : case ddl_rename_column:
7494 243828 : s = rel2bin_catalog2(be, rel, refs);
7495 243828 : sql->type = Q_SCHEMA;
7496 243828 : break;
7497 : default:
7498 0 : assert(0);
7499 : }
7500 301993 : return s;
7501 : }
7502 :
7503 : static stmt *
7504 1055409 : subrel_bin(backend *be, sql_rel *rel, list *refs)
7505 : {
7506 1055409 : mvc *sql = be->mvc;
7507 1055409 : stmt *s = NULL;
7508 :
7509 1055409 : if (mvc_highwater(sql))
7510 11 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
7511 :
7512 1055419 : if (!rel)
7513 : return s;
7514 1055419 : if (rel_is_ref(rel)) {
7515 14420 : s = refs_find_rel(refs, rel);
7516 : /* needs a proper fix!! */
7517 14420 : if (s)
7518 : return s;
7519 : }
7520 1049645 : switch (rel->op) {
7521 132188 : case op_basetable:
7522 132188 : s = rel2bin_basetable(be, rel);
7523 132190 : sql->type = Q_TABLE;
7524 132190 : break;
7525 2406 : case op_table:
7526 2406 : s = rel2bin_table(be, rel, refs);
7527 2406 : sql->type = Q_TABLE;
7528 2406 : break;
7529 67437 : case op_join:
7530 : case op_left:
7531 : case op_right:
7532 : case op_full:
7533 67437 : s = rel2bin_join(be, rel, refs);
7534 67437 : sql->type = Q_TABLE;
7535 67437 : break;
7536 2784 : case op_semi:
7537 2784 : s = rel2bin_semijoin(be, rel, refs);
7538 2784 : sql->type = Q_TABLE;
7539 2784 : break;
7540 690 : case op_anti:
7541 690 : s = rel2bin_antijoin(be, rel, refs);
7542 690 : sql->type = Q_TABLE;
7543 690 : break;
7544 301 : case op_union:
7545 301 : s = rel2bin_union(be, rel, refs);
7546 301 : sql->type = Q_TABLE;
7547 301 : break;
7548 3905 : case op_munion:
7549 3905 : s = rel2bin_munion(be, rel, refs);
7550 3905 : sql->type = Q_TABLE;
7551 3905 : break;
7552 2022 : case op_except:
7553 2022 : s = rel2bin_except(be, rel, refs);
7554 2022 : sql->type = Q_TABLE;
7555 2022 : break;
7556 375 : case op_inter:
7557 375 : s = rel2bin_inter(be, rel, refs);
7558 375 : sql->type = Q_TABLE;
7559 375 : break;
7560 333113 : case op_project:
7561 333113 : s = rel2bin_project(be, rel, refs, NULL);
7562 332947 : sql->type = Q_TABLE;
7563 332947 : break;
7564 59089 : case op_select:
7565 59089 : s = rel2bin_select(be, rel, refs);
7566 59089 : sql->type = Q_TABLE;
7567 59089 : break;
7568 12871 : case op_groupby:
7569 12871 : s = rel2bin_groupby(be, rel, refs);
7570 12873 : sql->type = Q_TABLE;
7571 12873 : break;
7572 16761 : case op_topn:
7573 16761 : s = rel2bin_topn(be, rel, refs);
7574 16766 : sql->type = Q_TABLE;
7575 16766 : break;
7576 21 : case op_sample:
7577 21 : s = rel2bin_sample(be, rel, refs);
7578 21 : sql->type = Q_TABLE;
7579 21 : break;
7580 67545 : case op_insert:
7581 67545 : s = rel2bin_insert(be, rel, refs);
7582 67555 : if (!(rel->returning) && sql->type == Q_TABLE)
7583 62923 : sql->type = Q_UPDATE;
7584 : break;
7585 3954 : case op_update:
7586 3954 : s = rel2bin_update(be, rel, refs);
7587 3954 : if (!(rel->returning) && sql->type == Q_TABLE)
7588 3796 : sql->type = Q_UPDATE;
7589 : break;
7590 476 : case op_delete:
7591 476 : s = rel2bin_delete(be, rel, refs);
7592 476 : if (!(rel->returning) && sql->type == Q_TABLE)
7593 341 : sql->type = Q_UPDATE;
7594 : break;
7595 41668 : case op_truncate:
7596 41668 : s = rel2bin_truncate(be, rel);
7597 41639 : if (sql->type == Q_TABLE)
7598 5 : sql->type = Q_UPDATE;
7599 : break;
7600 44 : case op_merge:
7601 44 : s = rel2bin_merge(be, rel, refs);
7602 44 : if (sql->type == Q_TABLE)
7603 44 : sql->type = Q_UPDATE;
7604 : break;
7605 301995 : case op_ddl:
7606 301995 : s = rel2bin_ddl(be, rel, refs);
7607 301995 : break;
7608 : }
7609 1049467 : if (s && rel_is_ref(rel)) {
7610 8646 : list_append(refs, rel);
7611 8646 : list_append(refs, s);
7612 : }
7613 : return s;
7614 : }
7615 :
7616 : stmt *
7617 10416 : rel_bin(backend *be, sql_rel *rel)
7618 : {
7619 10416 : mvc *sql = be->mvc;
7620 10416 : list *refs = sa_list(sql->sa);
7621 10415 : mapi_query_t sqltype = sql->type;
7622 10415 : stmt *s = subrel_bin(be, rel, refs);
7623 :
7624 10414 : s = subrel_project(be, s, refs, rel);
7625 10414 : if (sqltype == Q_SCHEMA)
7626 317 : sql->type = sqltype; /* reset */
7627 :
7628 10414 : if (be->mb->errors) {
7629 0 : if (be->mvc->sa->eb.enabled)
7630 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors, 1000);
7631 : return NULL;
7632 : }
7633 : return s;
7634 : }
7635 :
7636 : stmt *
7637 522488 : output_rel_bin(backend *be, sql_rel *rel, int top)
7638 : {
7639 522488 : mvc *sql = be->mvc;
7640 522488 : list *refs = sa_list(sql->sa);
7641 522470 : mapi_query_t sqltype = sql->type;
7642 522470 : stmt *s = NULL;
7643 :
7644 522470 : be->join_idx = 0;
7645 522470 : be->rowcount = 0;
7646 522470 : be->silent = !top;
7647 :
7648 522470 : s = subrel_bin(be, rel, refs);
7649 522363 : s = subrel_project(be, s, refs, rel);
7650 :
7651 522401 : if (!s)
7652 : return NULL;
7653 522393 : if (sqltype == Q_SCHEMA)
7654 283632 : sql->type = sqltype; /* reset */
7655 :
7656 522393 : if (!be->silent) { /* don't generate outputs when we are silent */
7657 515956 : if (!is_ddl(rel->op) && sql->type == Q_TABLE && stmt_output(be, s) < 0) {
7658 : return NULL;
7659 515956 : } else if (be->rowcount > 0 && sqltype == Q_UPDATE && stmt_affected_rows(be, be->rowcount) < 0) {
7660 : /* only call stmt_affected_rows outside functions and ddl */
7661 : return NULL;
7662 : }
7663 : }
7664 : return s;
7665 : }
|