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