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