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 46160 : clean_mal_statements(backend *be, int oldstop, int oldvtop)
39 : {
40 46160 : MSresetInstructions(be->mb, oldstop);
41 46166 : freeVariables(be->client, be->mb, NULL, oldvtop);
42 46161 : be->mvc->session->status = 0; /* clean possible generated error */
43 46161 : be->mvc->errstr[0] = '\0';
44 46161 : }
45 :
46 : static int
47 149387 : add_to_rowcount_accumulator(backend *be, int nr)
48 : {
49 149387 : if (be->silent)
50 : return 0;
51 :
52 149260 : if (be->rowcount == 0) {
53 148987 : be->rowcount = nr;
54 148987 : 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 12742 : stmt_selectnil(backend *be, stmt *col)
73 : {
74 12742 : sql_subtype *t = tail_type(col);
75 12742 : 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 5675 : sql_unop_(backend *be, const char *fname, stmt *rs)
80 : {
81 5675 : mvc *sql = be->mvc;
82 5675 : sql_subtype *rt = NULL;
83 5675 : sql_subfunc *f = NULL;
84 :
85 5675 : rt = tail_type(rs);
86 5675 : 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 5675 : 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 5675 : 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 15951 : refs_find_rel(list *refs, sql_rel *rel)
117 : {
118 15951 : node *n;
119 :
120 20196 : for (n=refs->h; n; n = n->next->next) {
121 11253 : sql_rel *ref = n->data;
122 11253 : stmt *s = n->next->data;
123 :
124 11253 : if (rel == ref)
125 : return s;
126 : }
127 : return NULL;
128 : }
129 :
130 : static void
131 4894 : refs_update_stmt(list *refs, sql_rel *rel, stmt *s)
132 : {
133 4894 : node *n;
134 :
135 6108 : for (n=refs->h; n; n = n->next->next) {
136 6108 : sql_rel *ref = n->data;
137 :
138 6108 : if (rel == ref) {
139 4894 : n->next->data = s;
140 4894 : 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 4190 : list_find_column(backend *be, list *l, const char *rname, const char *name)
162 : {
163 4190 : stmt *res = NULL;
164 4190 : node *n;
165 :
166 4190 : if (!l)
167 : return NULL;
168 4190 : 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 4190 : 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 3314 : if (rname) {
218 7389 : for (n = l->h; n; n = n->next) {
219 7351 : const char *rnme = table_name(be->mvc->sa, n->data);
220 7351 : const char *nme = column_name(be->mvc->sa, n->data);
221 :
222 7351 : if (rnme && strcmp(rnme, rname) == 0 &&
223 7278 : strcmp(nme, name) == 0) {
224 3276 : res = n->data;
225 3276 : 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 3314 : if (!res)
240 : return NULL;
241 : return res;
242 : }
243 :
244 : static stmt *
245 4190 : bin_find_column(backend *be, stmt *sub, const char *rname, const char *name)
246 : {
247 4190 : return list_find_column(be, sub->op4.lval, rname, name);
248 : }
249 :
250 : static stmt *
251 1161630 : list_find_column_nid(backend *be, list *l, int label)
252 : {
253 1161630 : (void)be;
254 1161630 : if (!l)
255 : return NULL;
256 12146740 : for (node *n = l->h; n; n = n->next) {
257 12096458 : stmt *s = n->data;
258 :
259 12096458 : if (s->label == label)
260 : return s;
261 : }
262 : return NULL;
263 : }
264 :
265 : static stmt *
266 1133160 : bin_find_column_nid(backend *be, stmt *sub, int label)
267 : {
268 1133160 : list *l = sub->op4.lval;
269 3385437 : 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 2313018 : column(backend *be, stmt *val)
291 : {
292 2313018 : if (val->nrcols == 0)
293 18945 : return const_column(be, val);
294 : return val;
295 : }
296 :
297 : static stmt *
298 83644 : create_const_column(backend *be, stmt *val)
299 : {
300 83644 : if (val->nrcols == 0)
301 16 : val = const_column(be, val);
302 83644 : return stmt_append(be, stmt_temp(be, tail_type(val)), val);
303 : }
304 :
305 : static int
306 774327 : statment_score(stmt *c)
307 : {
308 774327 : sql_subtype *t = tail_type(c);
309 774327 : int score = 0;
310 :
311 774327 : if (c->nrcols != 0) /* no need to create an extra intermediate */
312 774016 : score += 200;
313 :
314 774327 : if (!t)
315 : return score;
316 774327 : switch (ATOMstorage(t->type->localtype)) { /* give preference to smaller types */
317 50249 : case TYPE_bte:
318 50249 : score += 150 - 8;
319 50249 : break;
320 57547 : case TYPE_sht:
321 57547 : score += 150 - 16;
322 57547 : break;
323 248579 : case TYPE_int:
324 248579 : score += 150 - 32;
325 248579 : break;
326 44665 : case TYPE_void:
327 : case TYPE_lng:
328 44665 : score += 150 - 64;
329 44665 : break;
330 1371 : case TYPE_uuid:
331 : #ifdef HAVE_HGE
332 : case TYPE_hge:
333 : #endif
334 1371 : score += 150 - 128;
335 1371 : break;
336 3332 : case TYPE_flt:
337 3332 : score += 75 - 24;
338 3332 : break;
339 5924 : case TYPE_dbl:
340 5924 : score += 75 - 53;
341 5924 : break;
342 : default:
343 : break;
344 : }
345 : return score;
346 : }
347 :
348 : static stmt *
349 89840 : bin_find_smallest_column(backend *be, stmt *sub)
350 : {
351 89840 : stmt *res = sub->op4.lval->h->data;
352 89840 : int best_score = statment_score(sub->op4.lval->h->data);
353 :
354 89840 : if (sub->op4.lval->h->next)
355 759220 : for (node *n = sub->op4.lval->h->next ; n ; n = n->next) {
356 684486 : stmt *c = n->data;
357 684486 : int next_score = statment_score(c);
358 :
359 684487 : if (next_score > best_score) {
360 53082 : res = c;
361 53082 : best_score = next_score;
362 : }
363 : }
364 89841 : if (res->nrcols == 0)
365 260 : return const_column(be, res);
366 : return res;
367 : }
368 :
369 : static stmt *
370 231067 : row2cols(backend *be, stmt *sub)
371 : {
372 231067 : if (sub->nrcols == 0 && sub->key) {
373 5370 : node *n;
374 5370 : list *l = sa_list(be->mvc->sa);
375 5370 : if (l == NULL)
376 : return NULL;
377 :
378 21410 : for (n = sub->op4.lval->h; n; n = n->next) {
379 16040 : stmt *sc = n->data;
380 16040 : assert(sc->type == st_alias);
381 16040 : const char *cname = column_name(be->mvc->sa, sc);
382 16040 : const char *tname = table_name(be->mvc->sa, sc);
383 16040 : int label = sc->label;
384 :
385 16040 : sc = column(be, sc);
386 16040 : list_append(l, stmt_alias(be, sc, label, tname, cname));
387 : }
388 5370 : sub = stmt_list(be, l);
389 : }
390 : return sub;
391 : }
392 :
393 : static stmt*
394 44 : distinct_value_list(backend *be, list *vals, stmt **last_null_value, int depth, int push)
395 : {
396 44 : list *l = sa_list(be->mvc->sa);
397 44 : stmt *s;
398 :
399 : /* create bat append values */
400 1843 : for (node *n = vals->h; n; n = n->next) {
401 1799 : sql_exp *e = n->data;
402 1799 : stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, depth, 0, push);
403 :
404 1799 : if (exp_is_null(e))
405 0 : *last_null_value = i;
406 :
407 1799 : if (!i)
408 : return NULL;
409 :
410 1799 : list_append(l, i);
411 : }
412 44 : s = stmt_append_bulk(be, stmt_temp(be, exp_subtype(vals->h->data)), l);
413 : /* Probably faster to filter out the values directly in the underlying list of atoms.
414 : But for now use groupby to filter out duplicate values. */
415 44 : stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
416 44 : stmt* ext = stmt_result(be, groupby, 1);
417 :
418 44 : return stmt_project(be, ext, s);
419 : }
420 :
421 : static stmt *
422 3021 : stmt_selectnonil(backend *be, stmt *col, stmt *s)
423 : {
424 3021 : sql_subtype *t = tail_type(col);
425 3021 : 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 14320 : is_tid_chain(stmt *cand)
430 : {
431 17802 : while(cand && cand->type != st_tid && cand->cand) {
432 : cand = cand->cand;
433 : }
434 14320 : if (cand && cand->type == st_tid)
435 12266 : return 1;
436 : return 0;
437 : }
438 :
439 : static stmt *
440 1118781 : subrel_project(backend *be, stmt *s, list *refs, sql_rel *rel)
441 : {
442 1118781 : if (!s || s->type != st_list || !s->cand)
443 : return s;
444 :
445 155443 : list *l = sa_list(be->mvc->sa);
446 155443 : stmt *cand = s->cand;
447 155443 : if (!l)
448 : return NULL;
449 712391 : for (node *n = s->op4.lval->h; n; n = n->next) {
450 556944 : stmt *c = n->data;
451 :
452 556944 : 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 556944 : if (c->type != st_alias) {
454 0 : c = stmt_project(be, cand, c);
455 556944 : } 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 12266 : c = stmt_as(be, cand, c);
458 : } else { /* st_alias */
459 544678 : stmt *s = c->op1;
460 544678 : if (s->nrcols == 0)
461 0 : s = stmt_const(be, cand, s);
462 : else
463 544678 : s = stmt_project(be, cand, s);
464 : //c = stmt_alias(be, s, c->flag, c->tname, c->cname);
465 544690 : c = stmt_as(be, s, c);
466 : }
467 556958 : append(l, c);
468 : }
469 155447 : s = stmt_list(be, l);
470 155446 : if (rel && rel_is_ref(rel))
471 4840 : refs_update_stmt(refs, rel, s);
472 : return s;
473 : }
474 :
475 : static stmt *
476 72 : handle_in_tuple_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int reduce, int push)
477 : {
478 72 : mvc *sql = be->mvc;
479 72 : stmt *s = NULL;
480 :
481 72 : list *lvals = ce->f, *lstmts = sa_list(sql->sa);
482 327 : for(node *n = lvals->h; n; n = n->next) {
483 255 : sql_exp *ce = n->data;
484 255 : stmt *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
485 :
486 255 : if (c && reduce && c->nrcols == 0)
487 0 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
488 0 : if(!c)
489 : return NULL;
490 255 : lstmts = append(lstmts, c);
491 : }
492 :
493 72 : sql_subtype *bt = sql_bind_localtype("bit");
494 72 : sql_subfunc *and = sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
495 72 : sql_subfunc *or = sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true);
496 572 : for (node *n = nl->h; n; n = n->next) {
497 500 : sql_exp *e = n->data;
498 500 : list *vals = e->f;
499 500 : stmt *cursel = NULL;
500 :
501 2061 : for (node *m = vals->h, *o = lstmts->h; m && o; m = m->next, o = o->next) {
502 1561 : stmt *c = o->data;
503 3122 : sql_subfunc *cmp = (in)
504 1561 : ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
505 1561 : :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
506 1561 : sql_exp *e = m->data;
507 :
508 1561 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
509 1561 : if(!i)
510 : return NULL;
511 :
512 1561 : i = stmt_binop(be, c, i, NULL, cmp);
513 1561 : if (cursel)
514 1061 : cursel = stmt_binop(be, cursel, i, NULL, in?and:or);
515 : else
516 : cursel = i;
517 : }
518 500 : if (s)
519 428 : s = stmt_binop(be, s, cursel, NULL, in?or:and);
520 : else
521 : s = cursel;
522 : }
523 72 : if (!depth && reduce)
524 144 : s = stmt_uselect(be,
525 72 : s->nrcols == 0?stmt_const(be, bin_find_smallest_column(be, left), s): s,
526 : stmt_bool(be, 1), cmp_equal, sel, 0, 0);
527 : return s;
528 : }
529 :
530 : static stmt *
531 17153 : 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 17153 : if (ce && is_values(ce))
534 72 : return handle_in_tuple_exps(be, ce, nl, left, right, grp, ext, cnt, sel, in, depth, reduce, push);
535 17081 : mvc *sql = be->mvc;
536 17081 : node *n;
537 17081 : stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
538 :
539 17081 : if(!c)
540 : return NULL;
541 :
542 17081 : if (reduce && c->nrcols == 0)
543 44 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
544 :
545 17081 : 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 17079 : } else if (list_length(nl) < 16) {
570 17035 : comp_type cmp = (in)?cmp_equal:cmp_notequal;
571 :
572 17035 : if (!in)
573 7090 : s = sel;
574 91826 : for (n = nl->h; n; n = n->next) {
575 74791 : sql_exp *e = n->data;
576 74791 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
577 74791 : if(!i)
578 : return NULL;
579 :
580 74791 : if (in) {
581 50729 : i = stmt_uselect(be, c, i, cmp, sel, 0, 0);
582 50729 : if (s)
583 40784 : s = stmt_tunion(be, s, i);
584 : else
585 : s = i;
586 : } else {
587 24062 : s = stmt_uselect(be, c, i, cmp, s, 0, 0);
588 : }
589 : }
590 : } else {
591 : /* TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
592 : For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
593 : make sure that this behavior is replicated by the sql optimizer and not handle_in_exps. */
594 :
595 44 : stmt* last_null_value = NULL; /* CORNER CASE ALERT: See description below. */
596 :
597 : /* The actual in-value-list should not contain duplicates to ensure that final join results are unique. */
598 44 : s = distinct_value_list(be, nl, &last_null_value, depth+1, push);
599 44 : if (!s)
600 0 : return NULL;
601 :
602 44 : if (last_null_value) {
603 : /* The actual in-value-list should not contain null values. */
604 0 : s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
605 : }
606 :
607 44 : if (in) {
608 42 : s = stmt_semijoin(be, c, s, sel, NULL, 0, false);
609 : } else {
610 2 : if (last_null_value) {
611 : /* CORNER CASE ALERT:
612 : In case of a not-in-expression with the associated in-value-list containing a null value,
613 : the entire in-predicate is forced to always return false, i.e. an empty candidate list.
614 : This is similar to postgres behavior.
615 : TODO: However I do not think this behavior is in accordance with SQL standard 2003.
616 :
617 : Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
618 : list* singleton_bat = sa_list(sql->sa);
619 : list_append(singleton_bat, null_value); */
620 0 : s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0, 0);
621 : } else {
622 : /* BACK TO HAPPY FLOW:
623 : Make sure that null values are never returned. */
624 2 : stmt* non_nulls;
625 2 : non_nulls = stmt_selectnonil(be, c, sel);
626 2 : s = stmt_tdiff(be, stmt_project(be, non_nulls, c), s, NULL);
627 2 : s = stmt_project(be, s, non_nulls);
628 : }
629 : }
630 : }
631 : return s;
632 : }
633 :
634 : static stmt *
635 137576 : value_list(backend *be, list *vals, stmt *left, stmt *sel)
636 : {
637 137576 : sql_subtype *type = exp_subtype(vals->h->data);
638 137699 : list *l;
639 :
640 137699 : 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 137699 : l = sa_list(be->mvc->sa);
644 883101 : for (node *n = vals->h; n; n = n->next) {
645 745806 : sql_exp *e = n->data;
646 745806 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
647 :
648 746963 : if (!i)
649 : return NULL;
650 :
651 746963 : if (list_length(vals) == 1)
652 567 : return i;
653 745893 : list_append(l, i);
654 : }
655 137295 : return stmt_append_bulk(be, stmt_temp(be, type), l);
656 : }
657 :
658 : static stmt *
659 281 : exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
660 : {
661 281 : mvc *sql = be->mvc;
662 281 : node *n;
663 281 : list *nl = sa_list(sql->sa);
664 :
665 281 : if (nl == NULL)
666 : return NULL;
667 671 : for (n = exps->h; n; n = n->next) {
668 390 : sql_exp *e = n->data;
669 390 : stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0, 0);
670 390 : if(!i)
671 : return NULL;
672 :
673 390 : if (n->next && i->type == st_table) /* relational statement */
674 3 : l = i->op1;
675 : else
676 387 : append(nl, i);
677 : }
678 281 : return stmt_list(be, nl);
679 : }
680 :
681 : static stmt *
682 1745 : 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 1745 : if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
686 : /* skip alias statements */
687 3361 : while (as->type == st_alias)
688 1749 : as = as->op1;
689 : /* use candidate */
690 1612 : if (as && as->type == st_join && as->flag == cmp_project) {
691 1367 : if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
692 1745 : as = as->op1;
693 : }
694 : }
695 1745 : return as;
696 : }
697 :
698 : static stmt *
699 13088 : 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 13088 : sql_subtype *bt = sql_bind_localtype("bit");
702 13088 : list *l = e->l;
703 13088 : node *n;
704 13088 : stmt *sel1 = NULL, *sel2 = NULL, *s = NULL;
705 13088 : int anti = is_anti(e);
706 :
707 13088 : sel1 = sel;
708 13088 : sel2 = sel;
709 27322 : for (n = l->h; n; n = n->next) {
710 14234 : sql_exp *c = n->data;
711 14234 : stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
712 :
713 : /* propagate the anti flag */
714 14234 : if (anti)
715 55 : set_anti(c);
716 14235 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
717 14234 : if (!s)
718 : return s;
719 :
720 14234 : 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 14234 : } 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 14234 : } 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 14234 : sel1 = s;
738 : }
739 13088 : l = e->r;
740 28554 : for (n = l->h; n; n = n->next) {
741 15466 : sql_exp *c = n->data;
742 15466 : stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
743 :
744 : /* propagate the anti flag */
745 15466 : if (anti)
746 55 : set_anti(c);
747 15468 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
748 15466 : if (!s)
749 : return s;
750 :
751 15466 : 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 15465 : } 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 15465 : } 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 15466 : sel2 = s;
769 : }
770 13088 : 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 13088 : 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 13088 : 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 13088 : if (!reduce) {
796 2 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
797 1 : assert(f);
798 1 : return stmt_binop(be, sel1, sel2, NULL, f);
799 : }
800 13087 : if (anti)
801 55 : return stmt_project(be, stmt_tinter(be, sel1, sel2, false), sel1);
802 13032 : return stmt_tunion(be, sel1, sel2);
803 : }
804 :
805 : static stmt *
806 17945 : exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
807 : {
808 17945 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
809 17945 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
810 17945 : char name[16], *nme = NULL;
811 17945 : sql_subtype *bt = sql_bind_localtype("bit");
812 17945 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
813 17945 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
814 17945 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
815 :
816 17945 : 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 17945 : 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 76948 : for (node *en = exps->h; en; en = en->next) {
829 59003 : sql_exp *e = en->data;
830 :
831 59003 : next_cond = next_cond && en->next; /* last else is only a value */
832 :
833 59003 : stmt *nsel = rsel;
834 59003 : if (!single_value) {
835 58679 : if (/*!next_cond &&*/ rsel && isel) {
836 : /* back into left range */
837 8430 : nsel = stmt_project(be, rsel, isel);
838 50249 : } else if (isel && !rsel)
839 59003 : nsel = isel;
840 : }
841 59003 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
842 :
843 59003 : if (!es)
844 : return NULL;
845 59003 : if (!single_value) {
846 : /* create result */
847 58679 : if (!res) {
848 17855 : stmt *l = isel;
849 17855 : if (!l)
850 13654 : l = bin_find_smallest_column(be, left);
851 17855 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
852 17855 : ires = l;
853 17855 : if (res)
854 17855 : res->cand = isel;
855 40824 : } else if (res && !next_cond) { /* use result to update column */
856 38267 : stmt *val = es;
857 38267 : stmt *pos = rsel;
858 :
859 38267 : if (val->nrcols == 0)
860 18899 : val = stmt_const(be, pos, val);
861 19368 : else if (!val->cand && nsel)
862 4042 : val = stmt_project(be, nsel, val);
863 38267 : res = stmt_replace(be, res, pos, val);
864 :
865 38267 : assert(cond);
866 :
867 38267 : if (en->next) {
868 : /* osel - rsel */
869 20412 : if (!osel)
870 17855 : osel = stmt_mirror(be, ires);
871 20412 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
872 20412 : osel = rsel = stmt_project(be, d, osel);
873 : }
874 : }
875 58679 : if (next_cond) {
876 20412 : ncond = cond = es;
877 20412 : 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 20412 : if (isel && !ncond->cand) {
888 10 : ncond = stmt_project(be, nsel, ncond);
889 10 : ncond->cand = nsel;
890 : }
891 27162 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
892 20412 : if (rsel && ncond->cand)
893 2549 : 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 59003 : next_cond = !next_cond;
934 : }
935 17945 : 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 2283 : exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
976 : {
977 2283 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
978 2283 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
979 2283 : char name[16], *nme = NULL;
980 2283 : sql_subtype *bt = sql_bind_localtype("bit");
981 2284 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
982 2283 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
983 2283 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
984 2283 : sql_subfunc *cmp;
985 :
986 2283 : if (single_value) {
987 : /* var_x = nil; */
988 86 : nme = number2name(name, sizeof(name), ++be->mvc->label);
989 85 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
990 : }
991 :
992 2283 : list *exps = fe->l;
993 2283 : node *en = exps->h;
994 2283 : sql_exp *e = en->data;
995 :
996 2283 : stmt *nsel = !single_value?isel:NULL;
997 2283 : stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
998 2284 : if (!case_when)
999 : return NULL;
1000 2284 : cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e), exp_subtype(e), F_FUNC, true, true);
1001 2284 : if (!cmp)
1002 : return NULL;
1003 2284 : if (!single_value && !case_when->nrcols) {
1004 34 : stmt *l = isel;
1005 34 : if (!l && left)
1006 29 : l = bin_find_smallest_column(be, left);
1007 5 : else if (!l)
1008 : return NULL;
1009 34 : case_when = stmt_const(be, l, case_when);
1010 34 : if (case_when)
1011 34 : case_when->cand = isel;
1012 : }
1013 2284 : 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 32032 : for (en = en->next; en; en = en->next) {
1023 29748 : sql_exp *e = en->data;
1024 :
1025 29748 : next_cond = next_cond && en->next; /* last else is only a value */
1026 :
1027 29748 : stmt *nsel = rsel;
1028 29748 : if (!single_value) {
1029 28920 : if (/*!next_cond &&*/ rsel && isel) {
1030 : /* back into left range */
1031 3954 : nsel = stmt_project(be, rsel, isel);
1032 24966 : } else if (isel && !rsel)
1033 29748 : nsel = isel;
1034 : }
1035 29748 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1036 :
1037 29748 : if (!es)
1038 : return NULL;
1039 29748 : if (next_cond) {
1040 13732 : stmt *l = case_when;
1041 13732 : if (!single_value) {
1042 13361 : 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 13361 : 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 13352 : } else if (nsel && !es->cand) {
1053 11467 : es = stmt_project(be, nsel, es);
1054 11467 : es->cand = nsel;
1055 11467 : if (!l->cand) {
1056 9492 : l = stmt_project(be, nsel, l);
1057 9492 : l->cand = nsel;
1058 : }
1059 : }
1060 13361 : assert(l->cand == es->cand);
1061 : }
1062 13732 : es = stmt_binop(be, l, es, NULL, cmp);
1063 : }
1064 29748 : if (!single_value) {
1065 : /* create result */
1066 28920 : if (!res) {
1067 2198 : stmt *l = isel;
1068 2198 : if (!l)
1069 1883 : l = bin_find_smallest_column(be, left);
1070 2198 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1071 2198 : ires = l;
1072 2198 : if (res)
1073 2198 : res->cand = isel;
1074 26722 : } else if (res && !next_cond) { /* use result to update column */
1075 15559 : stmt *val = es;
1076 15559 : stmt *pos = rsel;
1077 :
1078 15559 : if (val->nrcols == 0)
1079 13887 : val = stmt_const(be, pos, val);
1080 1672 : else if (!val->cand && nsel)
1081 209 : val = stmt_project(be, nsel, val);
1082 15559 : res = stmt_replace(be, res, pos, val);
1083 :
1084 15559 : assert(cond);
1085 :
1086 15559 : if (en->next) {
1087 : /* osel - rsel */
1088 13361 : if (!osel)
1089 2198 : osel = stmt_mirror(be, ires);
1090 13361 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
1091 13361 : osel = rsel = stmt_project(be, d, osel);
1092 : }
1093 : }
1094 28920 : if (next_cond) {
1095 13361 : ncond = cond = es;
1096 13361 : 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 13361 : if (isel && !ncond->cand)
1107 0 : ncond = stmt_project(be, nsel, ncond);
1108 24839 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
1109 13361 : 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 456 : (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 29748 : next_cond = !next_cond;
1151 : }
1152 2284 : if (single_value)
1153 86 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1154 : return res;
1155 : }
1156 :
1157 : static stmt*
1158 527 : exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
1159 : {
1160 527 : stmt *res = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL;
1161 527 : int single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
1162 527 : char name[16], *nme = NULL;
1163 527 : sql_subtype *bt = sql_bind_localtype("bit");
1164 527 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
1165 527 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
1166 :
1167 527 : if (single_value) {
1168 : /* var_x = nil; */
1169 57 : nme = number2name(name, sizeof(name), ++be->mvc->label);
1170 57 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
1171 : }
1172 :
1173 527 : list *exps = fe->l;
1174 2028 : for (node *en = exps->h; en; en = en->next) {
1175 1501 : sql_exp *e = en->data;
1176 :
1177 1501 : stmt *nsel = rsel;
1178 1501 : if (!single_value) {
1179 1346 : if (/*!next_cond &&*/ rsel && isel) {
1180 : /* back into left range */
1181 48 : nsel = stmt_project(be, rsel, isel);
1182 1298 : } else if (isel && !rsel)
1183 1501 : nsel = isel;
1184 : }
1185 1501 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1186 :
1187 1501 : if (!es)
1188 : return NULL;
1189 : /* create result */
1190 1501 : if (!single_value) {
1191 1346 : if (!res) {
1192 470 : stmt *l = isel;
1193 470 : if (!l)
1194 436 : l = bin_find_smallest_column(be, left);
1195 470 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1196 470 : if (res)
1197 470 : res->cand = isel;
1198 : }
1199 470 : if (res) {
1200 1346 : stmt *val = es;
1201 1346 : stmt *pos = rsel;
1202 :
1203 1346 : if (en->next) {
1204 876 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1205 876 : ncond = stmt_unop(be, es, NULL, a);
1206 876 : if (ncond->nrcols == 0) {
1207 120 : stmt *l = bin_find_smallest_column(be, left);
1208 120 : if (nsel && l)
1209 61 : l = stmt_project(be, nsel, l);
1210 120 : ncond = stmt_const(be, l, ncond);
1211 120 : if (nsel)
1212 61 : ncond->cand = nsel;
1213 756 : } else if (!ncond->cand && nsel)
1214 348 : ncond = stmt_project(be, nsel, ncond);
1215 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0);
1216 876 : if (!val->cand && nsel)
1217 409 : val = stmt_project(be, nsel, val);
1218 876 : val = stmt_project(be, s, val);
1219 876 : if (osel)
1220 406 : rsel = stmt_project(be, s, osel);
1221 : else
1222 : rsel = s;
1223 876 : pos = rsel;
1224 876 : val->cand = pos;
1225 : }
1226 1346 : if (val->nrcols == 0)
1227 163 : val = stmt_const(be, pos, val);
1228 1183 : else if (!val->cand && nsel)
1229 171 : val = stmt_project(be, nsel, val);
1230 :
1231 1346 : res = stmt_replace(be, res, pos, val);
1232 : }
1233 1346 : if (en->next) { /* handled then part */
1234 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0);
1235 876 : if (osel)
1236 406 : rsel = stmt_project(be, s, osel);
1237 : else
1238 : rsel = s;
1239 : osel = rsel;
1240 : }
1241 : } else {
1242 155 : stmt *cond = ocond;
1243 155 : if (en->next) {
1244 98 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1245 98 : ncond = stmt_unop(be, es, nsel, a);
1246 :
1247 98 : if (ocond)
1248 41 : cond = stmt_binop(be, ocond, ncond, nsel, and);
1249 : else
1250 : cond = ncond;
1251 : }
1252 :
1253 : /* if_barrier ... */
1254 155 : stmt *b = stmt_cond(be, cond, NULL, 0, 0);
1255 : /* var_x = s */
1256 155 : (void)stmt_assign(be, NULL, nme, es, 2);
1257 : /* endif_barrier */
1258 155 : (void)stmt_control_end(be, b);
1259 :
1260 155 : cond = stmt_unop(be, ncond, nsel, not);
1261 155 : if (ocond)
1262 98 : ocond = stmt_binop(be, cond, ocond, nsel, and);
1263 : else
1264 : ocond = cond;
1265 : }
1266 : }
1267 527 : if (single_value)
1268 57 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1269 : return res;
1270 : }
1271 :
1272 : // This is the per-column portion of exp2bin_copyfrombinary
1273 : static stmt *
1274 216 : emit_loadcolumn(backend *be, stmt *onclient_stmt, stmt *bswap_stmt, int *count_var, node *file_node, node *type_node)
1275 : {
1276 216 : MalBlkPtr mb = be->mb;
1277 :
1278 216 : sql_exp *file_exp = file_node->data;
1279 216 : stmt *file_stmt = exp_bin(be, file_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1280 216 : sql_subtype *subtype = type_node->data;
1281 216 : int data_type = subtype->type->localtype;
1282 216 : int bat_type = newBatType(data_type);
1283 :
1284 : // The sql.importColumn operator takes a 'method' string to determine how to
1285 : // load the data. This leaves the door open to have multiple loaders for the
1286 : // same backend type, for example nul- and newline terminated strings.
1287 : // For the time being we just use the name of the storage type as the method
1288 : // name.
1289 216 : const char *method = ATOMname(data_type);
1290 :
1291 216 : int width;
1292 216 : switch (subtype->type->eclass) {
1293 37 : case EC_DEC:
1294 : case EC_STRING:
1295 37 : width = subtype->digits;
1296 37 : break;
1297 : default:
1298 : width = 0;
1299 : break;
1300 : }
1301 :
1302 216 : int new_count_var = newTmpVariable(mb, TYPE_oid);
1303 :
1304 216 : InstrPtr p = newStmt(mb, sqlRef, importColumnRef);
1305 216 : if (p != NULL) {
1306 216 : setArgType(mb, p, 0, bat_type);
1307 216 : p = pushReturn(mb, p, new_count_var);
1308 : //
1309 216 : p = pushStr(mb, p, method);
1310 216 : p = pushInt(mb, p, width);
1311 216 : p = pushArgument(mb, p, bswap_stmt->nr);
1312 216 : p = pushArgument(mb, p, file_stmt->nr);
1313 216 : p = pushArgument(mb, p, onclient_stmt->nr);
1314 216 : if (*count_var < 0)
1315 94 : p = pushOid(mb, p, 0);
1316 : else
1317 122 : p = pushArgument(mb, p, *count_var);
1318 216 : pushInstruction(mb, p);
1319 : }
1320 216 : if (p == NULL || mb->errors) {
1321 0 : if (be->mvc->sa->eb.enabled)
1322 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1323 0 : return sql_error(be->mvc, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1324 : }
1325 :
1326 216 : *count_var = new_count_var;
1327 :
1328 216 : stmt *s = stmt_blackbox_result(be, p, 0, subtype);
1329 216 : return s;
1330 : }
1331 :
1332 : // Try to predict which column will be quickest to load first
1333 : static int
1334 216 : node_type_score(node *n)
1335 : {
1336 216 : sql_subtype *st = n->data;
1337 216 : int tpe = st->type->localtype;
1338 216 : int stpe = ATOMstorage(tpe);
1339 216 : int score = stpe + (stpe == TYPE_bit);
1340 216 : return score;
1341 : }
1342 :
1343 : static stmt*
1344 94 : exp2bin_copyfrombinary(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel)
1345 : {
1346 94 : mvc *sql = be->mvc;
1347 94 : assert(left == NULL); (void)left;
1348 94 : assert(right == NULL); (void)right;
1349 94 : assert(isel == NULL); (void)isel;
1350 94 : sql_subfunc *f = fe->f;
1351 :
1352 94 : list *arg_list = fe->l;
1353 94 : list *type_list = f->res;
1354 94 : assert(4 + list_length(type_list) == list_length(arg_list));
1355 :
1356 94 : sql_exp * onclient_exp = arg_list->h->next->next->data;
1357 94 : stmt *onclient_stmt = exp_bin(be, onclient_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1358 94 : sql_exp *bswap_exp = arg_list->h->next->next->next->data;
1359 94 : stmt *bswap_stmt = exp_bin(be, bswap_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1360 :
1361 : // If it's ON SERVER we can optimize by running the imports in parallel
1362 94 : bool onserver = false;
1363 94 : if (onclient_exp->type == e_atom) {
1364 94 : atom *onclient_atom = onclient_exp->l;
1365 94 : int onclient = onclient_atom->data.val.ival;
1366 94 : onserver = (onclient == 0);
1367 : }
1368 :
1369 94 : node *const first_file = arg_list->h->next->next->next->next;
1370 94 : node *const first_type = type_list->h;
1371 94 : node *file, *type;
1372 :
1373 : // The first column we load determines the number of rows.
1374 : // We pass it on to the other columns.
1375 : // The first column to load should therefore be an 'easy' one.
1376 : // We identify the columns by the address of their type node.
1377 94 : node *prototype_file = first_file;
1378 94 : node *prototype_type = first_type;
1379 94 : int score = node_type_score(prototype_type);
1380 216 : for (file = first_file->next, type = first_type->next; file && type; file = file->next, type = type->next) {
1381 122 : int sc = node_type_score(type);
1382 122 : if (sc < score) {
1383 6 : prototype_file = file;
1384 6 : prototype_type = type;
1385 6 : score = sc;
1386 : }
1387 : }
1388 :
1389 : // Emit the columns
1390 94 : int count_var = -1;
1391 94 : list *columns = sa_list(sql->sa);
1392 94 : if (columns == NULL)
1393 : return NULL;
1394 94 : stmt *prototype_stmt = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, prototype_file, prototype_type);
1395 94 : if (!prototype_stmt)
1396 : return NULL;
1397 94 : int orig_count_var = count_var;
1398 310 : for (file = first_file, type = first_type; file && type; file = file->next, type = type->next) {
1399 216 : stmt *s;
1400 216 : if (type == prototype_type) {
1401 : s = prototype_stmt;
1402 : } else {
1403 122 : s = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, file, type);
1404 122 : if (!s)
1405 : return NULL;
1406 : }
1407 216 : list_append(columns, s);
1408 216 : if (onserver) {
1409 : // Not threading the count variable from one importColumn to the next
1410 : // makes it possible to run them in parallel in a dataflow region.
1411 108 : count_var = orig_count_var;
1412 : }
1413 : }
1414 :
1415 94 : return stmt_list(be, columns);
1416 : }
1417 :
1418 : static bool
1419 230 : is_const_func(sql_subfunc *f, list *attr)
1420 : {
1421 230 : 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 4822746 : 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 4822746 : mvc *sql = be->mvc;
1469 4822746 : stmt *s = NULL;
1470 :
1471 4822746 : if (mvc_highwater(sql))
1472 0 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1473 :
1474 4824485 : if (!e) {
1475 0 : assert(0);
1476 : return NULL;
1477 : }
1478 :
1479 4824485 : switch(e->type) {
1480 7471 : case e_psm:
1481 7471 : if (e->flag & PSM_SET) {
1482 587 : stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1483 589 : if(!r)
1484 : return NULL;
1485 589 : if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
1486 6 : r = stmt_fetch(be, r);
1487 589 : return stmt_assign(be, exp_relname(e), exp_name(e), r, GET_PSM_LEVEL(e->flag));
1488 6884 : } else if (e->flag & PSM_VAR) {
1489 169 : if (e->f)
1490 20 : return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
1491 : else
1492 149 : return stmt_var(be, exp_relname(e), exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
1493 6715 : } else if (e->flag & PSM_RETURN) {
1494 647 : sql_exp *l = e->l;
1495 647 : stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel, 0, 0, push);
1496 :
1497 647 : if (!r)
1498 : return NULL;
1499 : /* handle table returning functions */
1500 647 : if (l->type == e_psm && l->flag & PSM_REL) {
1501 236 : stmt *lst = r->op1;
1502 274 : if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
1503 38 : node *n;
1504 38 : list *l = sa_list(sql->sa);
1505 38 : if (l == NULL)
1506 : return NULL;
1507 :
1508 82 : for (n=lst->op4.lval->h; n; n = n->next)
1509 44 : list_append(l, const_column(be, (stmt*)n->data));
1510 38 : r = stmt_list(be, l);
1511 198 : } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */
1512 33 : r = lst->op4.lval->h->data;
1513 33 : if (!r->aggr) /* if the cardinality is atom, no fetch call needed */
1514 4 : r = stmt_fetch(be, r);
1515 : }
1516 236 : if (r->type == st_list)
1517 38 : r = stmt_table(be, r, 1);
1518 : }
1519 647 : return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
1520 6068 : } 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 16 : stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
1524 16 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1525 16 : stmt *wstmt;
1526 :
1527 16 : if(!cond)
1528 : return NULL;
1529 16 : wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
1530 :
1531 16 : if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
1532 : return NULL;
1533 16 : (void)stmt_control_end(be, wstmt);
1534 16 : return stmt_control_end(be, ifstmt);
1535 6052 : } 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 5812 : } else if (e->flag & PSM_REL) {
1554 5655 : sql_rel *rel = e->l;
1555 5655 : stmt *r = rel_bin(be, rel);
1556 :
1557 5656 : if (!r)
1558 : return NULL;
1559 835 : if (is_modify(rel->op) || is_ddl(rel->op))
1560 : return r;
1561 624 : 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 3297770 : case e_atom: {
1572 3297770 : if (e->l) { /* literals */
1573 3156001 : s = stmt_atom(be, e->l);
1574 141769 : } else if (e->r) { /* parameters and declared variables */
1575 2114 : sql_var_name *vname = (sql_var_name*) e->r;
1576 2114 : assert(vname->name);
1577 2542 : 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 139655 : } else if (e->f) { /* values */
1579 137603 : 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 49028 : case e_convert: {
1590 : /* if input is type any NULL or column of nulls, change type */
1591 49028 : list *tps = e->r;
1592 49028 : sql_subtype *from = tps->h->data;
1593 49028 : sql_subtype *to = tps->h->next->data;
1594 49028 : stmt *l;
1595 :
1596 49028 : if (from->type->localtype == 0) {
1597 727 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1598 727 : if (l)
1599 726 : l = stmt_atom(be, atom_general(sql->sa, to, NULL, 0));
1600 : } else {
1601 48301 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1602 : }
1603 49027 : if (!l)
1604 221 : return NULL;
1605 48807 : 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 49156 : } else if (depth && sel && l->nrcols == 0 && left && left->nrcols && exp_unsafe(e, false, true)) {
1609 412 : stmt *rows = bin_find_smallest_column(be, left);
1610 412 : l = stmt_const(be, rows, l);
1611 412 : s = stmt_convert(be, l, sel, from, to);
1612 48596 : } else if (depth && l->nrcols == 0 && left && left->nrcols && from->type->localtype > to->type->localtype &&
1613 520 : 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 87381 : s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, from, to);
1619 : }
1620 : } break;
1621 162769 : case e_func: {
1622 162769 : node *en;
1623 162769 : list *l = sa_list(sql->sa), *exps = e->l;
1624 162768 : sql_subfunc *f = e->f;
1625 162768 : const char *fname = f->func->base.name;
1626 162768 : stmt *rows = NULL;
1627 162768 : const char *mod, *fimp;
1628 :
1629 162768 : 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 162768 : if (f->func->lang == FUNC_LANG_MAL && backend_create_mal_func(be->mvc, f) < 0)
1634 : return NULL;
1635 162767 : mod = sql_func_mod(f->func);
1636 162768 : fimp = backend_function_imp(be, f->func);
1637 :
1638 162769 : 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 162769 : assert(!e->r);
1642 162769 : if (strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
1643 21407 : if (strcmp(fname, "star") == 0) {
1644 449 : if (!left)
1645 1 : return const_column(be, stmt_bool(be, 1));
1646 448 : return left->op4.lval->h->data;
1647 : }
1648 20958 : if (strcmp(fname, "case") == 0)
1649 17945 : return exp2bin_case(be, e, left, right, sel, depth);
1650 3013 : if (strcmp(fname, "casewhen") == 0)
1651 2282 : 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 141457 : if (!list_empty(exps)) {
1662 139529 : unsigned nrcols = 0;
1663 139529 : int push_cands = can_push_cands(sel, mod, fimp);
1664 :
1665 409405 : for (en = exps->h; en; en = en->next) {
1666 280236 : sql_exp *e = en->data;
1667 509944 : stmt *es = exp_bin(be, e, left, right, grp, ext, cnt, (push_cands)?sel:NULL, depth+1, 0, push);
1668 :
1669 280236 : if (!es)
1670 : return NULL;
1671 : /*if (rows && en == exps->h && f->func->type != F_LOADER)
1672 : es = stmt_const(be, rows, es);*/
1673 269876 : else if (f->func->type == F_ANALYTIC && es->nrcols == 0) {
1674 7669 : if (en == exps->h && left && left->nrcols)
1675 442 : es = stmt_const(be, bin_find_smallest_column(be, left), es); /* ensure the first argument is a column */
1676 7669 : if (!f->func->s && !strcmp(f->func->base.name, "window_bound")
1677 3155 : && 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 269876 : if (es->nrcols > nrcols)
1681 : nrcols = es->nrcols;
1682 269876 : list_append(l, es);
1683 : }
1684 : }
1685 131095 : if (!(s = stmt_Nop(be, stmt_list(be, l), sel, f, rows)))
1686 : return NULL;
1687 : } break;
1688 10879 : case e_aggr: {
1689 10879 : list *attr = e->l;
1690 10879 : stmt *as = NULL;
1691 10879 : sql_subfunc *a = e->f;
1692 :
1693 10879 : assert(sel == NULL);
1694 16357 : if (attr && attr->h) {
1695 5478 : node *en;
1696 5478 : list *l = sa_list(sql->sa);
1697 :
1698 11356 : for (en = attr->h; en; en = en->next) {
1699 5878 : sql_exp *at = en->data;
1700 :
1701 5878 : as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
1702 :
1703 5878 : if (as && as->nrcols <= 0 && left && (!is_const_func(a, attr) || grp))
1704 212 : as = stmt_const(be, bin_find_smallest_column(be, left), as);
1705 5878 : if (en == attr->h && !en->next && exp_aggr_is_count(e))
1706 138 : as = exp_count_no_nil_arg(e, ext, at, as);
1707 : /* insert single value into a column */
1708 5878 : if (as && as->nrcols <= 0 && !left)
1709 160 : as = const_column(be, as);
1710 :
1711 178 : if (!as)
1712 0 : return NULL;
1713 5878 : append(l, as);
1714 : }
1715 5478 : if (need_distinct(e) && (grp || list_length(l) > 1)){
1716 25 : list *nl = sa_list(sql->sa);
1717 25 : stmt *ngrp = grp;
1718 25 : stmt *next = ext;
1719 25 : stmt *ncnt = cnt;
1720 25 : if (nl == NULL)
1721 : return NULL;
1722 52 : for (en = l->h; en; en = en->next) {
1723 27 : stmt *as = en->data;
1724 27 : stmt *g = stmt_group(be, as, ngrp, next, ncnt, 1);
1725 27 : ngrp = stmt_result(be, g, 0);
1726 27 : next = stmt_result(be, g, 1);
1727 27 : ncnt = stmt_result(be, g, 2);
1728 : }
1729 52 : for (en = l->h; en; en = en->next) {
1730 27 : stmt *as = en->data;
1731 27 : append(nl, stmt_project(be, next, as));
1732 : }
1733 25 : if (grp)
1734 24 : grp = stmt_project(be, next, grp);
1735 : l = nl;
1736 5453 : } 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 5478 : as = stmt_list(be, l);
1747 : } else {
1748 : /* count(*) may need the default group (relation) and
1749 : and/or an attribute to count */
1750 5401 : if (grp) {
1751 : as = grp;
1752 1608 : } else if (left && !list_empty(left->op4.lval)) {
1753 1607 : as = bin_find_smallest_column(be, left);
1754 1608 : 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 10880 : s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e));
1762 10880 : if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
1763 0 : s->flag |= OUTER_ZERO;
1764 : } break;
1765 1125435 : case e_column: {
1766 1125435 : if (right) /* check relation names */
1767 : //s = bin_find_column(be, right, e->l, e->r);
1768 52354 : s = bin_find_column_nid(be, right, e->nid);
1769 1125435 : if (!s && left)
1770 : //s = bin_find_column(be, left, e->l, e->r);
1771 1079399 : s = bin_find_column_nid(be, left, e->nid);
1772 1125435 : if (s && grp)
1773 285 : s = stmt_project(be, ext, s);
1774 1125435 : 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 171133 : case e_cmp: {
1786 171133 : stmt *l = NULL, *r = NULL, *r2 = NULL;
1787 171133 : int swapped = 0, is_select = 0, oldvtop, oldstop;
1788 171133 : sql_exp *re = e->r, *re2 = e->f;
1789 :
1790 : /* general predicate, select and join */
1791 171133 : if (e->flag == cmp_filter) {
1792 3728 : list *args;
1793 3728 : list *ops;
1794 3728 : node *n;
1795 3728 : int first = 1;
1796 :
1797 3728 : ops = sa_list(sql->sa);
1798 3728 : if (ops == NULL)
1799 : return NULL;
1800 3728 : args = e->l;
1801 7454 : for (n = args->h; n; n = n->next) {
1802 3728 : oldvtop = be->mb->vtop;
1803 3728 : oldstop = be->mb->stop;
1804 3728 : s = NULL;
1805 3728 : if (!swapped)
1806 3728 : s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
1807 3728 : 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 3728 : if (!s)
1813 : return s;
1814 3726 : if (s->nrcols == 0 && first && left)
1815 619 : s = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), s);
1816 3726 : list_append(ops, s);
1817 3726 : first = 0;
1818 : }
1819 3726 : l = stmt_list(be, ops);
1820 3726 : ops = sa_list(sql->sa);
1821 3726 : if (ops == NULL)
1822 : return NULL;
1823 3726 : args = e->r;
1824 14677 : for (n = args->h; n; n = n->next) {
1825 11050 : s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
1826 10951 : if (!s)
1827 : return s;
1828 10951 : list_append(ops, s);
1829 : }
1830 3726 : r = stmt_list(be, ops);
1831 :
1832 3726 : 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 3293 : 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 3244 : assert(!swapped);
1871 3244 : s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
1872 3244 : return s;
1873 : }
1874 167405 : if (e->flag == cmp_in || e->flag == cmp_notin)
1875 17153 : return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), depth, reduce, push);
1876 150252 : if (e->flag == cmp_or && (!right || right->nrcols == 1))
1877 13088 : return exp_bin_or(be, e, left, right, grp, ext, cnt, sel, depth, reduce, push);
1878 137164 : if (e->flag == cmp_or && right) { /* join */
1879 0 : assert(0);
1880 : }
1881 :
1882 : /* mark use of join indices */
1883 137164 : if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
1884 620 : be->join_idx++;
1885 :
1886 137164 : oldvtop = be->mb->vtop;
1887 137164 : oldstop = be->mb->stop;
1888 137164 : if (!l) {
1889 273492 : l = exp_bin(be, e->l, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
1890 137164 : swapped = 0;
1891 : }
1892 137164 : if (!l && right) {
1893 18084 : clean_mal_statements(be, oldstop, oldvtop);
1894 18084 : l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1895 18084 : swapped = 1;
1896 : }
1897 :
1898 137164 : oldvtop = be->mb->vtop;
1899 137164 : oldstop = be->mb->stop;
1900 137164 : if (swapped || !right || !reduce)
1901 92613 : r = exp_bin(be, re, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
1902 : else
1903 45383 : r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
1904 137164 : 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 137164 : 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 137164 : if (re2 && (swapped || !right || !reduce))
1915 5286 : 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 137164 : if (!l || !r || (re2 && !r2))
1920 : return NULL;
1921 :
1922 137158 : (void)is_select;
1923 137158 : if (reduce && left && right) {
1924 63467 : if (l->nrcols == 0)
1925 0 : l = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), l);
1926 63467 : if (r->nrcols == 0)
1927 4 : r = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r);
1928 63467 : 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 63413 : } else if (swapped) {
1933 18082 : s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag), 0, is_semantics(e), false);
1934 : } else {
1935 45331 : s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag, 0, is_semantics(e), false);
1936 : }
1937 : } else {
1938 73691 : if (r2) { /* handle all cases in stmt_uselect, reducing, non reducing, scalar etc */
1939 5052 : 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 5052 : 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 68639 : if (!reduce || (l->nrcols == 0 && r->nrcols == 0)) {
1945 814 : 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 814 : assert(f);
1948 814 : if (is_semantics(e)) {
1949 115 : 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 111 : list *args = sa_list(sql->sa);
1953 111 : if (args == NULL)
1954 : return NULL;
1955 : /* add nil semantics bit */
1956 111 : list_append(args, l);
1957 111 : list_append(args, r);
1958 111 : list_append(args, stmt_bool(be, 1));
1959 111 : s = stmt_Nop(be, stmt_list(be, args), sel, f, NULL);
1960 : }
1961 : } else {
1962 699 : s = stmt_binop(be, l, r, sel, f);
1963 : }
1964 814 : if (l->cand)
1965 0 : s->cand = l->cand;
1966 814 : 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 67825 : 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 503707 : stmt_col(backend *be, sql_column *c, stmt *del, int part)
1983 : {
1984 503707 : stmt *sc = stmt_bat(be, c, RDONLY, part);
1985 :
1986 503704 : if (isTable(c->t) && c->t->access != TABLE_READONLY &&
1987 490487 : (!isNew(c) || !isNew(c->t) /* alter */) &&
1988 476039 : (c->t->persistence == SQL_PERSIST || c->t->s) /*&& !c->t->commit_action*/) {
1989 476039 : stmt *u = stmt_bat(be, c, RD_UPD_ID, part);
1990 476046 : assert(u);
1991 476046 : sc = stmt_project_delta(be, sc, u);
1992 476221 : 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 475869 : } 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 476045 : if (del)
1999 25846 : sc = stmt_project(be, del, sc);
2000 27665 : } else if (del) { /* always handle the deletes */
2001 6896 : sc = stmt_project(be, del, sc);
2002 : }
2003 503710 : return sc;
2004 : }
2005 :
2006 : static stmt *
2007 3596 : stmt_idx(backend *be, sql_idx *i, stmt *del, int part)
2008 : {
2009 3596 : stmt *sc = stmt_idxbat(be, i, RDONLY, part);
2010 :
2011 3596 : if (isTable(i->t) && i->t->access != TABLE_READONLY &&
2012 3596 : (!isNew(i) || !isNew(i->t) /* alter */) &&
2013 2871 : (i->t->persistence == SQL_PERSIST || i->t->s) /*&& !i->t->commit_action*/) {
2014 2871 : stmt *u = stmt_idxbat(be, i, RD_UPD_ID, part);
2015 2871 : sc = stmt_project_delta(be, sc, u);
2016 2871 : if (del)
2017 320 : 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 3596 : 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 5074 : check_types(backend *be, sql_subtype *t, stmt *s, check_type tpe)
2042 : {
2043 5074 : mvc *sql = be->mvc;
2044 5074 : int c, err = 0;
2045 5074 : sql_subtype *fromtype = tail_type(s);
2046 :
2047 5074 : 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 5074 : 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 5880 : sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
2082 : {
2083 5880 : mvc *sql = be->mvc;
2084 5880 : list *sl = sa_list(sql->sa);
2085 5880 : list *tl = sa_list(sql->sa);
2086 5880 : sql_subfunc *f = NULL;
2087 :
2088 5880 : if (sl == NULL || tl == NULL)
2089 : return NULL;
2090 5880 : list_append(sl, a1);
2091 5880 : list_append(tl, tail_type(a1));
2092 5880 : list_append(sl, a2);
2093 5880 : list_append(tl, tail_type(a2));
2094 5880 : list_append(sl, a3);
2095 5880 : list_append(tl, tail_type(a3));
2096 5880 : if (a4) {
2097 0 : list_append(sl, a4);
2098 0 : list_append(tl, tail_type(a4));
2099 : }
2100 :
2101 5880 : if ((f = sql_bind_func_(sql, "sys", fname, tl, F_FUNC, true, true)))
2102 5880 : 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 1209 : rel2bin_sql_table(backend *be, sql_table *t, list *aliases)
2118 : {
2119 1209 : mvc *sql = be->mvc;
2120 1209 : list *l = sa_list(sql->sa);
2121 1209 : node *n;
2122 1209 : stmt *dels = stmt_tid(be, t, 0);
2123 :
2124 1209 : if (l == NULL || dels == NULL)
2125 : return NULL;
2126 1209 : if (aliases) {
2127 20474 : for (n = aliases->h; n; n = n->next) {
2128 19265 : sql_exp *e = n->data;
2129 19265 : if (e->type != e_column)
2130 105 : continue;
2131 19160 : assert(e->type == e_column);
2132 19160 : char *name = e->r;
2133 19160 : if (name[0] == '%') {
2134 1203 : if (strcmp(name, TID)==0) {
2135 : /* tid function sql.tid(t) */
2136 1203 : const char *rnme = t->base.name;
2137 :
2138 1203 : stmt *sc = dels?dels:stmt_tid(be, t, 0);
2139 1203 : sc = stmt_alias(be, sc, e->alias.label, rnme, TID);
2140 1203 : 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 17957 : node *m = ol_find_name(t->columns, name);
2155 17957 : if (!m)
2156 0 : assert(0);
2157 17957 : sql_column *c = m->data;
2158 17957 : stmt *sc = stmt_col(be, c, dels, dels->partition);
2159 17957 : sc = stmt_alias(be, sc, e->alias.label, exp_relname(e), exp_name(e));
2160 17957 : 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 1209 : return stmt_list(be, l);
2194 : }
2195 :
2196 : static stmt *
2197 145101 : rel2bin_basetable(backend *be, sql_rel *rel)
2198 : {
2199 145101 : mvc *sql = be->mvc;
2200 145101 : sql_table *t = rel->l;
2201 145101 : sql_column *fcol = NULL;
2202 145101 : sql_idx *fi = NULL;
2203 145101 : list *l = sa_list(sql->sa);
2204 145103 : stmt *dels = stmt_tid(be, t, rel->flag == REL_PARTITION), *col = NULL;
2205 145108 : node *en;
2206 :
2207 145108 : if (l == NULL || dels == NULL)
2208 : return NULL;
2209 : /* add aliases */
2210 145108 : assert(rel->exps);
2211 290225 : for (en = rel->exps->h; en && !col; en = en->next) {
2212 145120 : sql_exp *exp = en->data;
2213 145120 : const char *oname = exp->r;
2214 :
2215 145120 : if (is_func(exp->type) || (oname[0] == '%' && strcmp(oname, TID) == 0))
2216 854 : continue;
2217 144266 : 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 144205 : sql_column *c = find_sql_column(t, oname);
2227 :
2228 144205 : fcol = c;
2229 144205 : col = stmt_col(be, c, NULL/*dels*/, dels->partition);
2230 : }
2231 : }
2232 633248 : for (en = rel->exps->h; en; en = en->next) {
2233 488145 : sql_exp *exp = en->data;
2234 488145 : const char *rname = exp_relname(exp)?exp_relname(exp):exp->l;
2235 488139 : const char *oname = exp->r;
2236 488139 : stmt *s = NULL;
2237 :
2238 488139 : assert(!is_func(exp->type));
2239 488139 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
2240 : /* tid function sql.tid(t) */
2241 : //const char *rnme = t->base.name;
2242 :
2243 14517 : if (col)
2244 13676 : s = stmt_mirror(be, col);
2245 : else {
2246 841 : s = dels?dels:stmt_tid(be, t, 0);
2247 : dels = NULL;
2248 : }
2249 : //s = stmt_alias(be, s, exp->alias.label, rnme, TID);
2250 473622 : } else if (oname[0] == '%') {
2251 2663 : sql_idx *i = find_sql_idx(t, oname+1);
2252 :
2253 : /* do not include empty indices in the plan */
2254 2663 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2255 0 : continue;
2256 2663 : 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 470959 : sql_column *c = find_sql_column(t, oname);
2260 :
2261 470973 : 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 488152 : 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 488150 : list_append(l, s);
2269 : }
2270 145103 : stmt *res = stmt_list(be, l);
2271 145107 : if (res && dels)
2272 144265 : 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 2018 : mvc *sql = be->mvc;
2288 :
2289 2018 : if (mvc_highwater(sql))
2290 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2291 :
2292 2018 : if (!e || !args)
2293 : return args;
2294 2018 : 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 54 : case e_convert:
2313 54 : 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 3107 : rel2bin_table(backend *be, sql_rel *rel, list *refs)
2440 : {
2441 3107 : mvc *sql = be->mvc;
2442 3107 : list *l;
2443 3107 : stmt *sub = NULL, *osub = NULL;
2444 3107 : node *en, *n;
2445 3107 : sql_exp *op = rel->r;
2446 :
2447 3107 : 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 3096 : } else if (op) {
2475 2910 : int i;
2476 2910 : sql_subfunc *f = op->f;
2477 2910 : stmt *psub = NULL;
2478 2910 : list *ops = NULL;
2479 2910 : stmt *ids = NULL;
2480 :
2481 2910 : if (rel->l) { /* first construct the sub relation */
2482 53 : sql_rel *l = rel->l;
2483 53 : 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 53 : sub = subrel_bin(be, rel->l, refs);
2490 : }
2491 53 : sub = subrel_project(be, sub, refs, rel->l);
2492 53 : if (!sub)
2493 : return NULL;
2494 : }
2495 :
2496 2910 : assert(f);
2497 2910 : 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 14 : list *exps = op->l;
2500 14 : ops = sa_list(be->mvc->sa);
2501 14 : if (exps) {
2502 56 : for (node *en = exps->h; en; en = en->next) {
2503 42 : sql_exp *e = en->data;
2504 :
2505 : /* find column */
2506 42 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2507 42 : if (!s)
2508 : return NULL;
2509 42 : if (en->next)
2510 28 : append(ops, s);
2511 : else /* last added exp is the ids (todo use name base lookup !!) */
2512 : ids = s;
2513 : }
2514 : }
2515 : } else {
2516 2896 : psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0); /* table function */
2517 2896 : if (!psub)
2518 : return NULL;
2519 : }
2520 2910 : l = sa_list(sql->sa);
2521 2910 : if (l == NULL)
2522 : return NULL;
2523 2910 : if (f->func->res) {
2524 2885 : if (f->func->varres) {
2525 11762 : for (i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++) {
2526 10548 : sql_exp *exp = en->data;
2527 10548 : sql_subtype *st = n->data;
2528 10548 : const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
2529 10548 : stmt *s = stmt_rs_column(be, psub, i, st);
2530 :
2531 10548 : s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
2532 10548 : list_append(l, s);
2533 : }
2534 : } else {
2535 1671 : node *m = rel->exps->h;
2536 1671 : int i = 0;
2537 :
2538 : /* correlated table returning function */
2539 1671 : 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 14 : if (ids)
2545 14 : ids = column(be, ids);
2546 14 : if (ops)
2547 42 : for (node *en = ops->h; en; en = en->next)
2548 28 : en->data = column(be, (stmt *) en->data);
2549 :
2550 14 : int narg = 3 + list_length(rel->exps);
2551 14 : if (ops)
2552 14 : narg += list_length(ops);
2553 14 : InstrPtr q = newStmtArgs(be->mb, sqlRef, "unionfunc", narg);
2554 14 : 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 42 : for (i=0; m; m = m->next, i++) {
2561 28 : sql_exp *e = m->data;
2562 28 : int type = exp_subtype(e)->type->localtype;
2563 :
2564 28 : type = newBatType(type);
2565 28 : if (i)
2566 14 : q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
2567 : else
2568 14 : getArg(q, 0) = newTmpVariable(be->mb, type);
2569 : }
2570 14 : if (backend_create_subfunc(be, f, ops) < 0) {
2571 0 : freeInstruction(q);
2572 0 : return NULL;
2573 : }
2574 14 : str mod = sql_func_mod(f->func);
2575 14 : str fcn = backend_function_imp(be, f->func);
2576 14 : q = pushStr(be->mb, q, mod);
2577 14 : q = pushStr(be->mb, q, fcn);
2578 14 : psub = stmt_direct_func(be, q);
2579 14 : if (psub == NULL) {
2580 0 : freeInstruction(q);
2581 0 : return NULL;
2582 : }
2583 :
2584 14 : if (ids) /* push input rowids column */
2585 14 : q = pushArgument(be->mb, q, ids->nr);
2586 :
2587 : /* add inputs in correct order ie loop through args of f and pass column */
2588 14 : if (ops) {
2589 42 : for (node *en = ops->h; en; en = en->next) {
2590 28 : stmt *op = en->data;
2591 :
2592 28 : q = pushArgument(be->mb, q, op->nr);
2593 : }
2594 : }
2595 14 : pushInstruction(be->mb, q);
2596 :
2597 : /* name output of dependent columns, output of function is handled the same as without correlation */
2598 14 : int len = list_length(rel->exps)-list_length(f->func->res);
2599 14 : assert(len== 1);
2600 28 : for (i=0, m=rel->exps->h; m && i<len; m = m->next, i++) {
2601 14 : sql_exp *exp = m->data;
2602 14 : stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp));
2603 :
2604 14 : s = stmt_alias(be, s, exp->alias.label, exp->l, exp->r);
2605 14 : list_append(l, s);
2606 : }
2607 : }
2608 16508 : for (n = f->func->res->h; n && m; n = n->next, m = m->next, i++) {
2609 14837 : sql_arg *a = n->data;
2610 14837 : sql_exp *exp = m->data;
2611 14837 : stmt *s = stmt_rs_column(be, psub, i, &a->type);
2612 14837 : const char *rnme = exp_relname(exp)?exp_relname(exp):exp_find_rel_name(op);
2613 :
2614 14837 : s = stmt_alias(be, s, exp->alias.label, rnme, a->name);
2615 14837 : list_append(l, s);
2616 : }
2617 : }
2618 : }
2619 2910 : assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
2620 2910 : sub = stmt_list(be, l);
2621 2910 : 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 90 : rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en)
2677 : {
2678 90 : mvc *sql = be->mvc;
2679 90 : node *n;
2680 90 : sql_subtype *it = sql_bind_localtype("int");
2681 90 : sql_subtype *lng = sql_bind_localtype("lng");
2682 90 : stmt *h = NULL;
2683 90 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
2684 90 : sql_exp *e = en->data;
2685 90 : sql_exp *l = e->l;
2686 90 : stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2687 90 : int swap_exp = 0, swap_rel = 0, semantics = 0;
2688 :
2689 90 : if (!idx) {
2690 49 : swap_exp = 1;
2691 49 : l = e->r;
2692 49 : idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2693 : }
2694 90 : if (!idx && right) {
2695 47 : swap_exp = 0;
2696 47 : swap_rel = 1;
2697 47 : l = e->l;
2698 47 : idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
2699 : }
2700 90 : 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 90 : if (!idx)
2707 : return NULL;
2708 : /* should be in key order! */
2709 314 : for (en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next) {
2710 226 : sql_exp *e = en->data;
2711 226 : stmt *s = NULL;
2712 :
2713 226 : if (e->type == e_cmp && e->flag == cmp_equal) {
2714 226 : sql_exp *ee = (swap_exp)?e->l:e->r;
2715 226 : if (swap_rel)
2716 109 : 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 226 : if (!s)
2722 2 : return NULL;
2723 224 : if (h) {
2724 136 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
2725 :
2726 136 : 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 136 : semantics = 1;
2729 : } else {
2730 88 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
2731 :
2732 88 : h = stmt_unop(be, s, NULL, hf);
2733 : }
2734 : }
2735 88 : if (n != NULL) /* need to use all cols of the index */
2736 : return NULL;
2737 87 : if (h && h->nrcols) {
2738 78 : if (!swap_rel) {
2739 31 : return stmt_join(be, idx, h, 0, cmp_equal, 0, semantics, false);
2740 : } else {
2741 47 : 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 5544 : join_hash_key(backend *be, list *l)
2750 : {
2751 5544 : mvc *sql = be->mvc;
2752 5544 : node *m;
2753 5544 : sql_subtype *it, *lng;
2754 5544 : stmt *h = NULL;
2755 5544 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
2756 :
2757 5544 : it = sql_bind_localtype("int");
2758 5544 : lng = sql_bind_localtype("lng");
2759 17456 : for (m = l->h; m; m = m->next) {
2760 11912 : stmt *s = m->data;
2761 :
2762 11912 : if (h) {
2763 6368 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
2764 :
2765 6368 : 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 5544 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
2768 5544 : h = stmt_unop(be, s, NULL, hf);
2769 : }
2770 : }
2771 5544 : return h;
2772 : }
2773 :
2774 : static stmt *
2775 5406 : releqjoin(backend *be, list *l1, list *l2, list *exps, int used_hash, int need_left, int is_semantics)
2776 : {
2777 5406 : node *n1 = l1->h, *n2 = l2->h, *n3 = NULL;
2778 5406 : stmt *l, *r, *res;
2779 5406 : sql_exp *e;
2780 :
2781 5406 : if (exps)
2782 2722 : n3 = exps->h;
2783 5406 : 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 3097 : if (used_hash) {
2794 325 : l = n1->data;
2795 325 : r = n2->data;
2796 325 : n1 = n1->next;
2797 325 : n2 = n2->next;
2798 325 : n3 = n3?n3->next:NULL;
2799 325 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
2800 : } else { /* need hash */
2801 2772 : l = join_hash_key(be, l1);
2802 2772 : r = join_hash_key(be, l2);
2803 2772 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
2804 : }
2805 3097 : l = stmt_result(be, res, 0);
2806 3097 : r = stmt_result(be, res, 1);
2807 18674 : for (; n1 && n2; n1 = n1->next, n2 = n2->next, n3 = n3?n3->next:NULL) {
2808 6700 : int semantics = is_semantics;
2809 6700 : stmt *ld = n1->data;
2810 6700 : stmt *rd = n2->data;
2811 6700 : stmt *le = stmt_project(be, l, ld);
2812 6700 : stmt *re = stmt_project(be, r, rd);
2813 6700 : stmt *cmp;
2814 : /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
2815 :
2816 6700 : if (!semantics && exps) {
2817 5780 : e = n3->data;
2818 5780 : semantics = is_semantics(e);
2819 : }
2820 6700 : cmp = stmt_uselect(be, le, re, cmp_equal, NULL, 0, semantics);
2821 6700 : l = stmt_project(be, cmp, l);
2822 6700 : r = stmt_project(be, cmp, r);
2823 : }
2824 3097 : res = stmt_join(be, l, r, 0, cmp_joined, 0, 0, false);
2825 3097 : return res;
2826 : }
2827 :
2828 : static bool
2829 78175 : can_join_exp(sql_rel *rel, sql_exp *e, bool anti)
2830 : {
2831 78175 : bool can_join = 0;
2832 :
2833 78175 : if (e->type == e_cmp) {
2834 78052 : 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 78052 : if (flag < cmp_filter) { /* theta and range joins */
2837 : /* join or select ? */
2838 77975 : sql_exp *l = e->l, *r = e->r, *f = e->f;
2839 :
2840 77975 : 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 77875 : int ll = 0, lr = 0, rl = 0, rr = 0, cst = 0;
2859 77875 : if (l->card != CARD_ATOM || !exp_is_atom(l)) {
2860 77738 : ll = rel_has_exp(rel->l, l, true) == 0;
2861 77738 : rl = rel_has_exp(rel->r, l, true) == 0;
2862 137 : } else if (anti) {
2863 15 : ll = 1;
2864 15 : cst = 1;
2865 : }
2866 77875 : if (r->card != CARD_ATOM || !exp_is_atom(r)) {
2867 77731 : lr = rel_has_exp(rel->l, r, true) == 0;
2868 77731 : rr = rel_has_exp(rel->r, r, true) == 0;
2869 144 : } else if (anti) {
2870 3 : rr = cst?0:1;
2871 : }
2872 77875 : if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
2873 77643 : can_join = 1;
2874 : }
2875 77 : } 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 77643 : can_join = 1;
2897 : }
2898 : }
2899 78175 : return can_join;
2900 : }
2901 :
2902 : static void
2903 65468 : split_join_exps(sql_rel *rel, list *joinable, list *not_joinable, bool anti)
2904 : {
2905 65468 : if (!list_empty(rel->exps)) {
2906 135401 : for (node *n = rel->exps->h; n; n = n->next) {
2907 69938 : sql_exp *e = n->data;
2908 :
2909 : /* we can handle thetajoins, rangejoins and filter joins (like) */
2910 : /* ToDo how about atom expressions? */
2911 69938 : if (can_join_exp(rel, e, anti)) {
2912 69554 : append(joinable, e);
2913 : } else {
2914 384 : append(not_joinable, e);
2915 : }
2916 : }
2917 : }
2918 65468 : }
2919 :
2920 :
2921 : #define is_equi_exp_(e) ((e)->flag == cmp_equal)
2922 :
2923 : static list *
2924 2958 : get_simple_equi_joins_first(mvc *sql, sql_rel *rel, list *exps, bool *equality_only)
2925 : {
2926 2958 : list *new_exps = sa_list(sql->sa);
2927 2958 : *equality_only = true;
2928 :
2929 2958 : if (!exps)
2930 : return new_exps;
2931 :
2932 5832 : for (node *n = exps->h; n; n = n->next) {
2933 2942 : sql_exp *e = n->data;
2934 :
2935 2942 : if (can_join_exp(rel, e, false) && is_equi_exp_(e) && !is_any(e))
2936 162 : list_append(new_exps, e);
2937 : else
2938 2780 : *equality_only = false;
2939 : }
2940 5832 : for (node *n = exps->h; n; n = n->next) {
2941 2942 : sql_exp *e = n->data;
2942 :
2943 2942 : if (!is_equi_exp_(e) || !can_join_exp(rel, e, false) || is_any(e))
2944 2780 : list_append(new_exps, e);
2945 : }
2946 : return new_exps;
2947 : }
2948 :
2949 : static stmt *
2950 2958 : rel2bin_groupjoin(backend *be, sql_rel *rel, list *refs)
2951 : {
2952 2958 : mvc *sql = be->mvc;
2953 2958 : list *l;
2954 2958 : node *n , *en;
2955 2958 : stmt *left = NULL, *right = NULL, *join = NULL, *jl = NULL, *jr = NULL, *m = NULL, *ls = NULL, *res;
2956 2958 : bool need_project = false, exist = true, mark = false;
2957 :
2958 2958 : if (rel->op == op_left) { /* left outer group join */
2959 2870 : if (list_length(rel->attr) == 1) {
2960 2870 : sql_exp *e = rel->attr->h->data;
2961 2870 : if (exp_is_atom(e))
2962 2870 : mark = true;
2963 2870 : if (exp_is_atom(e) && exp_is_false(e))
2964 2958 : exist = false;
2965 : }
2966 : }
2967 :
2968 2958 : if (rel->l) /* first construct the left sub relation */
2969 2958 : left = subrel_bin(be, rel->l, refs);
2970 2958 : if (rel->r) /* first construct the right sub relation */
2971 2958 : right = subrel_bin(be, rel->r, refs);
2972 2958 : left = subrel_project(be, left, refs, rel->l);
2973 2958 : right = subrel_project(be, right, refs, rel->r);
2974 2958 : if (!left || !right)
2975 : return NULL;
2976 2958 : left = row2cols(be, left);
2977 2958 : right = row2cols(be, right);
2978 :
2979 2958 : bool equality_only = true;
2980 2958 : list *jexps = get_simple_equi_joins_first(sql, rel, rel->exps, &equality_only);
2981 :
2982 2958 : en = jexps?jexps->h:NULL;
2983 3335 : if (list_empty(jexps) || !(is_equi_exp_((sql_exp*)en->data) && can_join_exp(rel, en->data, false))) {
2984 377 : stmt *l = bin_find_smallest_column(be, left);
2985 377 : stmt *r = bin_find_smallest_column(be, right);
2986 377 : if (list_empty(jexps)) {
2987 77 : stmt *limit = stmt_limit(be, r, NULL, NULL, stmt_atom_lng(be, 0), stmt_atom_lng(be, 1), 0, 0, 0, 0, 0);
2988 77 : r = stmt_project(be, limit, r);
2989 : }
2990 377 : 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 377 : need_project = true;
2992 377 : jl = stmt_result(be, join, 0);
2993 377 : jr = stmt_result(be, join, 1);
2994 : } else {
2995 2581 : sql_exp *e = en->data;
2996 2581 : en = en->next;
2997 2581 : stmt *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 0, 1, 0), *r = NULL;
2998 2581 : bool swap = false;
2999 :
3000 2581 : if (!l) {
3001 9 : swap = true;
3002 9 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 0, 1, 0);
3003 : }
3004 9 : if (!l)
3005 : return NULL;
3006 2581 : if ((r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 0, 1, 0)) == NULL)
3007 : return NULL;
3008 :
3009 2581 : if (l && l->nrcols == 0)
3010 0 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
3011 2581 : if (r && r->nrcols == 0)
3012 0 : r = stmt_const(be, bin_find_smallest_column(be, right), r);
3013 2581 : if (swap) {
3014 9 : stmt *t = l;
3015 9 : l = r;
3016 9 : r = t;
3017 : }
3018 2581 : if ((!is_semantics(e) && is_anti(e)) || !mark)
3019 88 : ls = l;
3020 2581 : if (en || !mark) {
3021 : /* split out (left)join vs (left)mark-join */
3022 : /* call 3 result version */
3023 130 : if (mark && is_any(e)) {
3024 2 : join = stmt_markjoin(be, l, r, 0);
3025 : } else
3026 128 : 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 130 : jl = stmt_result(be, join, 0);
3028 130 : jr = stmt_result(be, join, 1);
3029 130 : if (mark && is_any(e))
3030 2 : m = stmt_result(be, join, 2);
3031 : } else {
3032 2451 : join = stmt_markjoin(be, l, r, 1);
3033 2451 : jl = stmt_result(be, join, 0);
3034 2451 : m = stmt_result(be, join, 1);
3035 : }
3036 : }
3037 :
3038 2958 : if (en) {
3039 342 : stmt *sub, *sel = NULL, *osel = NULL;
3040 342 : list *nl;
3041 :
3042 342 : need_project = false;
3043 :
3044 : /* construct relation */
3045 342 : nl = sa_list(sql->sa);
3046 :
3047 : /* first project using equi-joins */
3048 1898 : for (n = left->op4.lval->h; n; n = n->next) {
3049 1556 : stmt *c = n->data;
3050 1556 : assert(c->type == st_alias);
3051 1556 : const char *rnme = table_name(sql->sa, c);
3052 1556 : const char *nme = column_name(sql->sa, c);
3053 1556 : stmt *s = stmt_project(be, jl, column(be, c));
3054 :
3055 1556 : s = stmt_alias(be, s, c->label, rnme, nme);
3056 1556 : list_append(nl, s);
3057 : }
3058 852 : for (n = right->op4.lval->h; n; n = n->next) {
3059 510 : stmt *c = n->data;
3060 510 : assert(c->type == st_alias);
3061 510 : const char *rnme = table_name(sql->sa, c);
3062 510 : const char *nme = column_name(sql->sa, c);
3063 510 : stmt *s = stmt_project(be, jr, column(be, c));
3064 :
3065 510 : s = stmt_alias(be, s, c->label, rnme, nme);
3066 510 : list_append(nl, s);
3067 : }
3068 342 : left = sub = stmt_list(be, nl);
3069 :
3070 342 : if (!m) {
3071 340 : 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 340 : 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 703 : for ( ; en; en = en->next) {
3084 361 : sql_exp *e = en->data;
3085 361 : stmt *p = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3086 :
3087 361 : if (!p) {
3088 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3089 : return NULL;
3090 : }
3091 361 : if (p->nrcols == 0)
3092 0 : p = stmt_const(be, bin_find_smallest_column(be, sub), p);
3093 361 : if (sel)
3094 19 : p = stmt_project(be, sel, column(be, p));
3095 19 : stmt *li = jl;
3096 19 : if (sel)
3097 19 : li = stmt_project(be, sel, li);
3098 361 : osel = sel;
3099 361 : if (en->next) {
3100 19 : join = stmt_outerselect(be, li, m, p, is_any(e));
3101 : } else {
3102 342 : join = stmt_markselect(be, li, m, p, is_any(e));
3103 : }
3104 361 : sel = stmt_result(be, join, 0);
3105 361 : m = stmt_result(be, join, 1);
3106 : /* go back to offset in the table */
3107 361 : if (sel && osel)
3108 19 : sel = stmt_project(be, sel, osel);
3109 361 : if (!en->next)
3110 342 : jl = sel;
3111 : }
3112 : }
3113 : /* construct relation */
3114 2958 : l = sa_list(sql->sa);
3115 13239 : for (n = left->op4.lval->h; n; n = n->next) {
3116 10281 : stmt *c = n->data;
3117 10281 : assert(c->type == st_alias);
3118 10281 : const char *rnme = table_name(sql->sa, c);
3119 10281 : const char *nme = column_name(sql->sa, c);
3120 10281 : stmt *s = stmt_project(be, jl, column(be, c));
3121 :
3122 10281 : s = stmt_alias(be, s, c->label, rnme, nme);
3123 10281 : list_append(l, s);
3124 : }
3125 2958 : 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 2958 : if (rel->attr) {
3140 2958 : sql_exp *e = rel->attr->h->data;
3141 2958 : const char *rnme = exp_relname(e);
3142 2958 : const char *nme = exp_name(e);
3143 :
3144 2958 : if (mark) {
3145 2870 : if (need_project) {
3146 77 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, !exist), stmt_bool(be, exist), NULL);
3147 : } else {
3148 2793 : assert(m);
3149 2793 : sql_exp *e = rel->attr->h->data;
3150 2793 : if (exp_is_atom(e) && need_no_nil(e))
3151 286 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", m), stmt_bool(be, false), m, NULL);
3152 2793 : if (!exist) {
3153 44 : sql_subtype *bt = sql_bind_localtype("bit");
3154 44 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3155 44 : m = stmt_unop(be, m, NULL, not);
3156 : }
3157 : }
3158 2870 : stmt *s = stmt_alias(be, m, e->alias.label, rnme, nme);
3159 2870 : 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 2958 : res = stmt_list(be, l);
3178 2958 : return res;
3179 : }
3180 :
3181 : static list *
3182 63682 : get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
3183 : {
3184 63682 : list *new_exps = sa_list(sql->sa);
3185 :
3186 131577 : for (node *n = exps->h; n; n = n->next) {
3187 67895 : sql_exp *e = n->data;
3188 :
3189 67895 : assert(e->type == e_cmp && e->flag != cmp_in && e->flag != cmp_notin && e->flag != cmp_or);
3190 67895 : if (is_equi_exp_(e))
3191 64063 : list_append(new_exps, e);
3192 : else
3193 3832 : *equality_only = 0;
3194 : }
3195 131577 : for (node *n = exps->h; n; n = n->next) {
3196 67895 : sql_exp *e = n->data;
3197 :
3198 67895 : if (!is_equi_exp_(e))
3199 3832 : list_append(new_exps, e);
3200 : }
3201 63682 : return new_exps;
3202 : }
3203 :
3204 : static stmt *
3205 74566 : rel2bin_join(backend *be, sql_rel *rel, list *refs)
3206 : {
3207 74566 : mvc *sql = be->mvc;
3208 74566 : list *l, *sexps = NULL, *l2 = NULL;
3209 74566 : node *en = NULL, *n;
3210 74566 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *ld = NULL, *rd = NULL, *res;
3211 74566 : int need_left = (rel->flag & LEFT_JOIN);
3212 :
3213 74566 : if (rel->attr && list_length(rel->attr) > 0)
3214 2958 : return rel2bin_groupjoin(be, rel, refs);
3215 :
3216 71608 : if (rel->l) /* first construct the left sub relation */
3217 71608 : left = subrel_bin(be, rel->l, refs);
3218 71608 : if (rel->r) /* first construct the right sub relation */
3219 71608 : right = subrel_bin(be, rel->r, refs);
3220 71608 : left = subrel_project(be, left, refs, rel->l);
3221 71608 : right = subrel_project(be, right, refs, rel->r);
3222 71608 : if (!left || !right)
3223 : return NULL;
3224 71608 : left = row2cols(be, left);
3225 71608 : right = row2cols(be, right);
3226 : /*
3227 : * split in 2 steps,
3228 : * first cheap join(s) (equality or idx)
3229 : * second selects/filters
3230 : */
3231 71608 : if (!list_empty(rel->exps)) {
3232 60945 : list *jexps = sa_list(sql->sa);
3233 60945 : sexps = sa_list(sql->sa);
3234 :
3235 60945 : split_join_exps(rel, jexps, sexps, false);
3236 60945 : if (list_empty(jexps)) { /* cross product and continue after project */
3237 255 : stmt *l = bin_find_smallest_column(be, left);
3238 255 : stmt *r = bin_find_smallest_column(be, right);
3239 255 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3240 : }
3241 :
3242 255 : if (join) {
3243 255 : en = jexps->h;
3244 : } else {
3245 60690 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
3246 60690 : int used_hash = 0, idx = 0, equality_only = 1;
3247 :
3248 60690 : (void) equality_only;
3249 60690 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
3250 : /* generate a relational join (releqjoin) which does a multi attribute (equi) join */
3251 121520 : for (en = jexps->h; en ; en = en->next) {
3252 63141 : int join_idx = be->join_idx;
3253 63141 : sql_exp *e = en->data;
3254 63141 : stmt *s = NULL;
3255 63141 : prop *p;
3256 :
3257 : /* stop search for equi joins on first non equi */
3258 63141 : 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 63050 : if (!join && (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
3263 78 : sql_idx *i = p->value.pval;
3264 78 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
3265 :
3266 78 : join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
3267 78 : if (s) {
3268 78 : list_append(lje, s->op1);
3269 78 : list_append(rje, s->op2);
3270 78 : list_append(exps, NULL);
3271 78 : 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 63050 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
3279 63050 : if (!s) {
3280 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3281 0 : return NULL;
3282 : }
3283 63050 : if (join_idx != be->join_idx)
3284 620 : idx = 1;
3285 63050 : assert(s->type == st_join || s->type == st_join2 || s->type == st_joinN);
3286 63050 : if (!join)
3287 60612 : join = s;
3288 63050 : if (e->flag != cmp_equal) { /* only collect equi joins */
3289 2220 : en = en->next;
3290 2220 : break;
3291 : }
3292 60830 : list_append(lje, s->op1);
3293 60830 : list_append(rje, s->op2);
3294 60830 : list_append(exps, e);
3295 : }
3296 60690 : if (list_length(lje) > 1) {
3297 2125 : join = releqjoin(be, lje, rje, exps, used_hash, need_left, 0);
3298 58565 : } 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 10663 : stmt *l = bin_find_smallest_column(be, left);
3305 10663 : stmt *r = bin_find_smallest_column(be, right);
3306 10663 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, is_single(rel));
3307 : }
3308 71608 : jl = stmt_result(be, join, 0);
3309 71608 : jr = stmt_result(be, join, 1);
3310 71608 : if (en || (sexps && list_length(sexps))) {
3311 1420 : stmt *sub, *sel = NULL;
3312 1420 : list *nl;
3313 :
3314 : /* construct relation */
3315 1420 : nl = sa_list(sql->sa);
3316 :
3317 : /* first project using equi-joins */
3318 6804 : for (n = left->op4.lval->h; n; n = n->next) {
3319 5384 : stmt *c = n->data;
3320 5384 : assert(c->type == st_alias);
3321 5384 : const char *rnme = table_name(sql->sa, c);
3322 5384 : const char *nme = column_name(sql->sa, c);
3323 5384 : stmt *s = stmt_project(be, jl, column(be, c));
3324 :
3325 5384 : s = stmt_alias(be, s, c->label, rnme, nme);
3326 5384 : list_append(nl, s);
3327 : }
3328 4591 : for (n = right->op4.lval->h; n; n = n->next) {
3329 3171 : stmt *c = n->data;
3330 3171 : assert(c->type == st_alias);
3331 3171 : const char *rnme = table_name(sql->sa, c);
3332 3171 : const char *nme = column_name(sql->sa, c);
3333 3171 : stmt *s = stmt_project(be, jr, column(be, c));
3334 :
3335 3171 : s = stmt_alias(be, s, c->label, rnme, nme);
3336 3171 : list_append(nl, s);
3337 : }
3338 1420 : sub = stmt_list(be, nl);
3339 :
3340 : /* continue with non equi-joins */
3341 3977 : while(sexps) {
3342 2557 : if (!en) {
3343 1420 : en = sexps->h;
3344 1420 : sexps = NULL;
3345 : }
3346 3999 : for ( ; en; en = en->next) {
3347 1442 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
3348 :
3349 1442 : if (!s) {
3350 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3351 : return NULL;
3352 : }
3353 1442 : 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 1442 : sel = s;
3358 : }
3359 : }
3360 : /* recreate join output */
3361 1420 : jl = stmt_project(be, sel, jl);
3362 1420 : jr = stmt_project(be, sel, jr);
3363 : }
3364 :
3365 : /* construct relation */
3366 71608 : l = sa_list(sql->sa);
3367 :
3368 71608 : if (rel->op == op_left || rel->op == op_full || is_single(rel)) {
3369 : /* we need to add the missing oid's */
3370 10836 : stmt *l = ld = stmt_mirror(be, bin_find_smallest_column(be, left));
3371 10836 : if (rel->op == op_left || rel->op == op_full)
3372 7816 : ld = stmt_tdiff(be, ld, jl, NULL);
3373 10836 : if (is_single(rel) && !list_empty(rel->exps)) {
3374 221 : join = stmt_semijoin(be, l, jl, NULL, NULL, 0, true);
3375 221 : jl = stmt_result(be, join, 0);
3376 221 : jr = stmt_project(be, stmt_result(be, join, 1), jr);
3377 : }
3378 : }
3379 71608 : if (rel->op == op_right || rel->op == op_full) {
3380 : /* we need to add the missing oid's */
3381 161 : rd = stmt_mirror(be, bin_find_smallest_column(be, right));
3382 161 : rd = stmt_tdiff(be, rd, jr, NULL);
3383 : }
3384 :
3385 71608 : if (rel->op == op_left) { /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3386 7750 : l2 = sa_list(sql->sa);
3387 7750 : list_append(l2, left);
3388 7750 : list_append(l2, right);
3389 7750 : list_append(l2, jl);
3390 7750 : list_append(l2, jr);
3391 7750 : list_append(l2, ld);
3392 : }
3393 :
3394 1924193 : for (n = left->op4.lval->h; n; n = n->next) {
3395 1852585 : stmt *c = n->data;
3396 1852585 : const char *rnme = table_name(sql->sa, c);
3397 1852585 : const char *nme = column_name(sql->sa, c);
3398 1852585 : stmt *s = stmt_project(be, jl, column(be, c));
3399 :
3400 : /* as append isn't save, we append to a new copy */
3401 1852585 : if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
3402 59919 : s = create_const_column(be, s);
3403 1852585 : if (rel->op == op_left || rel->op == op_full)
3404 59717 : s = stmt_append(be, s, stmt_project(be, ld, c));
3405 1852585 : if (rel->op == op_right || rel->op == op_full)
3406 309 : 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 1852585 : s = stmt_alias(be, s, c->label, rnme, nme);
3409 1852585 : list_append(l, s);
3410 : }
3411 275171 : for (n = right->op4.lval->h; n; n = n->next) {
3412 203563 : stmt *c = n->data;
3413 203563 : const char *rnme = table_name(sql->sa, c);
3414 203563 : const char *nme = column_name(sql->sa, c);
3415 203563 : stmt *s = stmt_project(be, jr, column(be, c));
3416 :
3417 : /* as append isn't save, we append to a new copy */
3418 203563 : if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
3419 17703 : s = create_const_column(be, s);
3420 203563 : if (rel->op == op_left || rel->op == op_full)
3421 17444 : 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 203563 : if (rel->op == op_right || rel->op == op_full)
3423 357 : s = stmt_append(be, s, stmt_project(be, rd, c));
3424 :
3425 203563 : s = stmt_alias(be, s, c->label, rnme, nme);
3426 203563 : list_append(l, s);
3427 : }
3428 71608 : 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 71608 : res = stmt_list(be, l);
3448 71608 : res->extra = l2; /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3449 71608 : return res;
3450 : }
3451 :
3452 : static stmt *
3453 1482 : rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
3454 : {
3455 1482 : mvc *sql = be->mvc;
3456 1482 : list *l, *jexps = NULL, *sexps = NULL;
3457 1482 : node *en = NULL, *n;
3458 1482 : stmt *left = NULL, *right = NULL, *join = NULL, *sel = NULL, *sub = NULL;
3459 :
3460 1482 : if (rel->l) /* first construct the left sub relation */
3461 1482 : left = subrel_bin(be, rel->l, refs);
3462 1482 : if (rel->r) /* first construct the right sub relation */
3463 1482 : right = subrel_bin(be, rel->r, refs);
3464 1482 : left = subrel_project(be, left, refs, rel->l);
3465 1482 : right = subrel_project(be, right, refs, rel->r);
3466 1482 : if (!left || !right)
3467 : return NULL;
3468 1482 : left = row2cols(be, left);
3469 1482 : right = row2cols(be, right);
3470 :
3471 1482 : stmt *li = NULL;
3472 1482 : bool swap = false;
3473 :
3474 1482 : jexps = sa_list(sql->sa);
3475 1482 : sexps = sa_list(sql->sa);
3476 :
3477 1482 : split_join_exps(rel, jexps, sexps, true);
3478 1482 : if (list_empty(jexps)) {
3479 15 : stmt *l = bin_find_smallest_column(be, left);
3480 15 : stmt *r = bin_find_smallest_column(be, right);
3481 15 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3482 :
3483 15 : jexps = sexps;
3484 15 : sexps = NULL;
3485 15 : en = jexps->h;
3486 : } else {
3487 1467 : if (list_length(sexps))
3488 3 : list_merge(jexps, sexps, NULL);
3489 1467 : en = jexps->h;
3490 1467 : sql_exp *e = en->data;
3491 1467 : assert(e->type == e_cmp);
3492 1467 : stmt *ls = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0), *rs;
3493 1467 : bool constval = false;
3494 1467 : 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 1467 : if (!(rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0)))
3502 : return NULL;
3503 :
3504 1467 : if (swap) {
3505 12 : stmt *t = ls;
3506 12 : ls = rs;
3507 12 : rs = t;
3508 : }
3509 1467 : if (ls->nrcols == 0) {
3510 10 : constval = true;
3511 10 : ls = stmt_const(be, bin_find_smallest_column(be, left), ls);
3512 : }
3513 1467 : if (rs->nrcols == 0)
3514 3 : rs = stmt_const(be, bin_find_smallest_column(be, right), rs);
3515 :
3516 1467 : if (!li)
3517 1467 : li = ls;
3518 :
3519 1467 : if (!en->next && (constval || stmt_has_null(ls) /*|| stmt_has_null(rs) (change into check for fk)*/)) {
3520 1249 : assert(e->flag == cmp_equal);
3521 1249 : join = stmt_tdiff2(be, ls, rs, NULL);
3522 1249 : jexps = NULL;
3523 : } else {
3524 218 : join = stmt_join_cand(be, ls, rs, NULL, NULL, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false, true);
3525 : }
3526 1467 : en = en->next;
3527 : }
3528 1482 : if (en || jexps) {
3529 233 : stmt *jl = stmt_result(be, join, 0);
3530 233 : stmt *jr = stmt_result(be, join, 1);
3531 233 : stmt *nulls = NULL;
3532 :
3533 233 : if (li && stmt_has_null(li)) {
3534 121 : nulls = stmt_selectnil(be, li);
3535 : }
3536 : /* construct relation */
3537 233 : list *nl = sa_list(sql->sa);
3538 : /* first project after equi-joins */
3539 2245 : for (n = left->op4.lval->h; n; n = n->next) {
3540 2012 : stmt *c = n->data;
3541 2012 : assert(c->type == st_alias);
3542 2012 : const char *rnme = table_name(sql->sa, c);
3543 2012 : const char *nme = column_name(sql->sa, c);
3544 2012 : stmt *s = stmt_project(be, jl, column(be, c));
3545 :
3546 2012 : s = stmt_alias(be, s, c->label, rnme, nme);
3547 2012 : list_append(nl, s);
3548 : }
3549 669 : for (n = right->op4.lval->h; n; n = n->next) {
3550 436 : stmt *c = n->data;
3551 436 : assert(c->type == st_alias);
3552 436 : const char *rnme = table_name(sql->sa, c);
3553 436 : const char *nme = column_name(sql->sa, c);
3554 436 : stmt *s = stmt_project(be, jr, column(be, c));
3555 :
3556 436 : s = stmt_alias(be, s, c->label, rnme, nme);
3557 436 : list_append(nl, s);
3558 : }
3559 233 : sub = stmt_list(be, nl);
3560 :
3561 : /* continue with non equi-joins */
3562 671 : for (; en; en = en->next) {
3563 205 : 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 205 : sql_subtype *bt = sql_bind_localtype("bit");
3567 205 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3568 205 : s = stmt_unop(be, s, NULL, not);
3569 205 : s = sql_Nop_(be, "ifthenelse", s, stmt_bool(be, 0), stmt_bool(be, 1), NULL);
3570 :
3571 205 : 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 205 : s = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
3576 : }
3577 :
3578 205 : if (!s) {
3579 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3580 : return NULL;
3581 : }
3582 :
3583 205 : sel = s;
3584 : }
3585 233 : stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
3586 233 : if (nulls) {
3587 121 : stmt *nonilcand = stmt_tdiff(be, c, nulls, NULL);
3588 121 : c = stmt_project(be, nonilcand, c);
3589 : }
3590 233 : if (join && sel) {
3591 : /* recreate join output */
3592 151 : jl = stmt_project(be, sel, jl);
3593 151 : join = stmt_tdiff(be, c, jl, NULL);
3594 : } else {
3595 82 : join = stmt_tdiff2(be, c, jl, NULL);
3596 : }
3597 233 : if (nulls)
3598 121 : 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 1482 : l = sa_list(sql->sa);
3608 :
3609 : /* project all the left columns */
3610 12778 : for (n = left->op4.lval->h; n; n = n->next) {
3611 11296 : stmt *c = n->data;
3612 11296 : assert(c->type == st_alias);
3613 11296 : const char *rnme = table_name(sql->sa, c);
3614 11296 : const char *nme = column_name(sql->sa, c);
3615 11296 : stmt *s = stmt_project(be, join, column(be, c));
3616 :
3617 11296 : s = stmt_alias(be, s, c->label, rnme, nme);
3618 11296 : list_append(l, s);
3619 : }
3620 1482 : return stmt_list(be, l);
3621 : }
3622 :
3623 : static stmt *
3624 3066 : rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
3625 : {
3626 3066 : mvc *sql = be->mvc;
3627 3066 : list *l, *sexps = NULL;
3628 3066 : node *en = NULL, *n;
3629 3066 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c, *lcand = NULL;
3630 3066 : int semijoin_only = 0, l_is_base = 0;
3631 :
3632 3066 : assert(rel->op != op_anti);
3633 :
3634 3066 : if (rel->l) { /* first construct the left sub relation */
3635 3066 : sql_rel *l = rel->l;
3636 3066 : l_is_base = is_basetable(l->op);
3637 3066 : left = subrel_bin(be, l, refs);
3638 : }
3639 3066 : if (rel->r) /* first construct the right sub relation */
3640 3066 : right = subrel_bin(be, rel->r, refs);
3641 3066 : if (!left || !right)
3642 : return NULL;
3643 3066 : left = row2cols(be, left);
3644 3066 : right = row2cols(be, right);
3645 : /*
3646 : * split in 2 steps,
3647 : * first cheap join(s) (equality or idx)
3648 : * second selects/filters
3649 : */
3650 3066 : if (!list_empty(rel->exps)) {
3651 3041 : list *jexps = sa_list(sql->sa);
3652 3041 : sexps = sa_list(sql->sa);
3653 :
3654 3041 : split_join_exps(rel, jexps, sexps, false);
3655 3041 : if (list_empty(jexps)) { /* cross product and continue after project */
3656 49 : right = subrel_project(be, right, refs, rel->r);
3657 49 : stmt *l = bin_find_smallest_column(be, left);
3658 49 : stmt *r = bin_find_smallest_column(be, right);
3659 49 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3660 49 : lcand = left->cand;
3661 : }
3662 :
3663 3041 : if (join) {
3664 49 : en = jexps->h;
3665 : } else {
3666 2992 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
3667 2992 : int idx = 0, equality_only = 1;
3668 :
3669 2992 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
3670 2992 : if (!equality_only || list_length(jexps) > 1 || exp_has_func((sql_exp*)jexps->h->data))
3671 1064 : left = subrel_project(be, left, refs, rel->l);
3672 2992 : right = subrel_project(be, right, refs, rel->r);
3673 :
3674 6679 : for (en = jexps->h; en; en = en->next) {
3675 3698 : int join_idx = be->join_idx;
3676 3698 : sql_exp *e = en->data;
3677 3698 : stmt *s = NULL;
3678 :
3679 : /* only handle simple joins here */
3680 3698 : 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 3695 : if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
3689 698 : (join && e->flag == cmp_filter)))
3690 : break;
3691 :
3692 3687 : if (equality_only) {
3693 3221 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop, swap = 0;
3694 3221 : stmt *r, *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3695 :
3696 3221 : if (l && left && l->nrcols==0 && left->nrcols >0)
3697 1 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
3698 398 : if (!l) {
3699 397 : swap = 1;
3700 397 : clean_mal_statements(be, oldstop, oldvtop);
3701 397 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3702 : }
3703 3221 : r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0);
3704 :
3705 3221 : if (swap) {
3706 397 : stmt *t = l;
3707 397 : l = r;
3708 397 : r = t;
3709 : }
3710 :
3711 3221 : if (!l || !r)
3712 0 : return NULL;
3713 3221 : 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 3221 : 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 3221 : lcand = left->cand;
3721 : } else {
3722 466 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
3723 : }
3724 3687 : if (!s) {
3725 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3726 : return NULL;
3727 : }
3728 3687 : if (join_idx != be->join_idx)
3729 0 : idx = 1;
3730 : /* stop on first non equality join */
3731 3687 : if (!join) {
3732 2989 : 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 698 : } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
3740 : /* handle select expressions */
3741 : break;
3742 : }
3743 3687 : if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
3744 3687 : list_append(lje, s->op1);
3745 3687 : list_append(rje, s->op2);
3746 3687 : list_append(exps, e);
3747 : }
3748 : }
3749 2992 : if (list_length(lje) > 1) {
3750 597 : join = releqjoin(be, lje, rje, exps, 0 /* use hash */, 0, rel->op == op_anti?1:0);
3751 2395 : } 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 25 : right = subrel_project(be, right, refs, rel->r);
3762 25 : stmt *l = bin_find_smallest_column(be, left);
3763 25 : stmt *r = bin_find_smallest_column(be, right);
3764 25 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3765 25 : lcand = left->cand;
3766 : }
3767 3066 : jl = stmt_result(be, join, 0);
3768 3066 : if (en || (sexps && list_length(sexps))) {
3769 77 : stmt *sub, *sel = NULL;
3770 77 : list *nl;
3771 :
3772 77 : jr = stmt_result(be, join, 1);
3773 : /* construct relation */
3774 77 : nl = sa_list(sql->sa);
3775 :
3776 : /* first project after equi-joins */
3777 394 : for (n = left->op4.lval->h; n; n = n->next) {
3778 317 : stmt *c = n->data;
3779 317 : assert(c->type == st_alias);
3780 317 : const char *rnme = table_name(sql->sa, c);
3781 317 : const char *nme = column_name(sql->sa, c);
3782 317 : stmt *s = stmt_project(be, jl, column(be, c));
3783 :
3784 317 : s = stmt_alias(be, s, c->label, rnme, nme);
3785 317 : list_append(nl, s);
3786 : }
3787 209 : for (n = right->op4.lval->h; n; n = n->next) {
3788 132 : stmt *c = n->data;
3789 132 : assert(c->type == st_alias);
3790 132 : const char *rnme = table_name(sql->sa, c);
3791 132 : const char *nme = column_name(sql->sa, c);
3792 132 : stmt *s = stmt_project(be, jr, column(be, c));
3793 :
3794 132 : s = stmt_alias(be, s, c->label, rnme, nme);
3795 132 : list_append(nl, s);
3796 : }
3797 77 : sub = stmt_list(be, nl);
3798 :
3799 : /* continue with non equi-joins */
3800 165 : while(sexps) {
3801 88 : if (!en) {
3802 77 : en = sexps->h;
3803 77 : sexps = NULL;
3804 : }
3805 175 : for ( ; en; en = en->next) {
3806 87 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
3807 :
3808 87 : if (!s) {
3809 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3810 : return NULL;
3811 : }
3812 87 : 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 87 : sel = s;
3817 : }
3818 : }
3819 : /* recreate join output */
3820 77 : jl = stmt_project(be, sel, jl);
3821 : }
3822 :
3823 : /* construct relation */
3824 3066 : l = sa_list(sql->sa);
3825 :
3826 : /* We did a full join, that's too much.
3827 : Reduce this using difference and intersect */
3828 3066 : if (!semijoin_only) {
3829 3066 : c = stmt_mirror(be, bin_find_smallest_column(be, left));
3830 3066 : if (rel->op == op_anti) {
3831 0 : assert(0);
3832 : join = stmt_tdiff(be, c, jl, lcand);
3833 : } else {
3834 3066 : if (lcand)
3835 1081 : join = stmt_semijoin(be, c, jl, lcand, NULL/*right->cand*/, 0, false);
3836 : else
3837 1985 : join = stmt_tinter(be, c, jl, false);
3838 : }
3839 : }
3840 :
3841 : /* project all the left columns */
3842 23912 : for (n = left->op4.lval->h; n; n = n->next) {
3843 20846 : stmt *c = n->data, *s;
3844 20846 : const char *rnme = table_name(sql->sa, c);
3845 20846 : const char *nme = column_name(sql->sa, c);
3846 :
3847 20846 : if (semijoin_only && l_is_base && nme[0] == '%' && strcmp(nme, TID) == 0)
3848 : s = join;
3849 : else
3850 20846 : s = stmt_project(be, join, column(be, c));
3851 :
3852 20846 : s = stmt_alias(be, s, c->label, rnme, nme);
3853 20846 : list_append(l, s);
3854 : }
3855 3066 : return stmt_list(be, l);
3856 : }
3857 :
3858 : static stmt *
3859 1678 : rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
3860 : {
3861 1678 : mvc *sql = be->mvc;
3862 1678 : node *n;
3863 1678 : stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
3864 1678 : list *rl = sa_list(sql->sa), *tids;
3865 :
3866 : /* single values are unique */
3867 1678 : if (s->key && s->nrcols == 0)
3868 : return s;
3869 :
3870 : /* Use 'all' tid columns */
3871 1669 : 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 3666 : for (n = s->op4.lval->h; n; n = n->next) {
3882 1997 : stmt *t = n->data;
3883 :
3884 1997 : g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
3885 1997 : grp = stmt_result(be, g, 0);
3886 1997 : ext = stmt_result(be, g, 1);
3887 1997 : cnt = stmt_result(be, g, 2);
3888 : }
3889 : }
3890 1669 : if (!ext)
3891 : return NULL;
3892 :
3893 3666 : for (n = s->op4.lval->h; n; n = n->next) {
3894 1997 : stmt *t = n->data;
3895 :
3896 1997 : stmt *s = stmt_project(be, ext, t);
3897 1997 : t = stmt_alias(be, s, t->label, table_name(sql->sa, t), column_name(sql->sa, t));
3898 1997 : list_append(rl, t);
3899 : }
3900 :
3901 1669 : if (distinct)
3902 5 : *distinct = ext;
3903 1669 : s = stmt_list(be, rl);
3904 1669 : return s;
3905 : }
3906 :
3907 : static stmt *
3908 10 : rel2bin_single(backend *be, stmt *s)
3909 : {
3910 10 : if (s->key && s->nrcols == 0)
3911 : return s;
3912 :
3913 10 : mvc *sql = be->mvc;
3914 10 : list *rl = sa_list(sql->sa);
3915 :
3916 22 : for (node *n = s->op4.lval->h; n; n = n->next) {
3917 12 : stmt *t = n->data;
3918 12 : assert(t->type == st_alias);
3919 12 : const char *rnme = table_name(sql->sa, t);
3920 12 : const char *nme = column_name(sql->sa, t);
3921 12 : int label = t->label;
3922 12 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", tail_type(t), NULL, F_AGGR, true, true);
3923 :
3924 12 : t = stmt_aggr(be, t, NULL, NULL, zero_or_one, 1, 0, 1);
3925 12 : t = stmt_alias(be, t, label, rnme, nme);
3926 12 : list_append(rl, t);
3927 : }
3928 10 : s = stmt_list(be, rl);
3929 10 : return s;
3930 : }
3931 :
3932 : static stmt *
3933 6877 : rel_rename(backend *be, sql_rel *rel, stmt *sub)
3934 : {
3935 6877 : mvc *sql = be->mvc;
3936 :
3937 6877 : (void) sql;
3938 6877 : if (rel->exps) {
3939 6877 : node *en, *n;
3940 6877 : list *l = sa_list(be->mvc->sa);
3941 :
3942 31512 : for (en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next) {
3943 24635 : sql_exp *exp = en->data;
3944 24635 : stmt *s = n->data;
3945 :
3946 24635 : if (!s) {
3947 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3948 : return NULL;
3949 : }
3950 24635 : s = stmt_rename(be, exp, s);
3951 24635 : list_append(l, s);
3952 : }
3953 6877 : sub = stmt_list(be, l);
3954 : }
3955 : return sub;
3956 : }
3957 :
3958 : static stmt *
3959 4190 : rel2bin_munion(backend *be, sql_rel *rel, list *refs)
3960 : {
3961 4190 : mvc *sql = be->mvc;
3962 4190 : list *l, *rstmts;
3963 4190 : node *n, *m;
3964 4190 : stmt *rel_stmt = NULL, *sub;
3965 4190 : 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 4190 : rstmts = sa_list(sql->sa);
3969 15460 : for (n = ((list*)rel->l)->h; n; n = n->next) {
3970 11270 : rel_stmt = subrel_bin(be, n->data, refs);
3971 11270 : rel_stmt = subrel_project(be, rel_stmt, refs, n->data);
3972 11270 : if (!rel_stmt)
3973 : return NULL;
3974 11270 : list_append(rstmts, rel_stmt);
3975 11270 : if (!len || len > list_length(rel_stmt->op4.lval))
3976 4190 : len = list_length(rel_stmt->op4.lval);
3977 : }
3978 :
3979 : /* construct relation */
3980 4190 : l = sa_list(sql->sa);
3981 :
3982 : /* for every op4 lval node */
3983 : //len = list_length(((stmt*)rstmts->h->data)->op4.lval);
3984 24357 : for (i = 0; i < len; i++) {
3985 : /* extract t and c name from the first stmt */
3986 15977 : stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
3987 15977 : if (s == NULL)
3988 : return NULL;
3989 15977 : const char *rnme = table_name(sql->sa, s);
3990 15977 : const char *nme = column_name(sql->sa, s);
3991 15977 : int label = s->label;
3992 : /* create a const column also from the first stmt */
3993 15977 : s = stmt_pack(be, column(be, s), nr_unions);
3994 : /* for every other rstmt */
3995 45674 : for (m = rstmts->h->next; m; m = m->next) {
3996 29697 : stmt *t = list_fetch(((stmt*)m->data)->op4.lval, i);
3997 29697 : if (t == NULL)
3998 : return NULL;
3999 29697 : s = stmt_pack_add(be, s, column(be, t));
4000 29697 : if (s == NULL)
4001 : return NULL;
4002 : }
4003 15977 : s = stmt_alias(be, s, label, rnme, nme);
4004 15977 : if (s == NULL)
4005 : return NULL;
4006 15977 : list_append(l, s);
4007 : }
4008 4190 : sub = stmt_list(be, l);
4009 :
4010 4190 : sub = rel_rename(be, rel, sub);
4011 4190 : if (need_distinct(rel))
4012 1664 : sub = rel2bin_distinct(be, sub, NULL);
4013 4190 : if (is_single(rel))
4014 10 : sub = rel2bin_single(be, sub);
4015 : return sub;
4016 : }
4017 :
4018 : static stmt *
4019 301 : rel2bin_union(backend *be, sql_rel *rel, list *refs)
4020 : {
4021 301 : mvc *sql = be->mvc;
4022 301 : list *l;
4023 301 : node *n, *m;
4024 301 : stmt *left = NULL, *right = NULL, *sub;
4025 :
4026 301 : if (rel->l) /* first construct the left sub relation */
4027 301 : left = subrel_bin(be, rel->l, refs);
4028 301 : if (rel->r) /* first construct the right sub relation */
4029 301 : right = subrel_bin(be, rel->r, refs);
4030 301 : left = subrel_project(be, left, refs, rel->l);
4031 301 : right = subrel_project(be, right, refs, rel->r);
4032 301 : if (!left || !right)
4033 : return NULL;
4034 :
4035 : /* construct relation */
4036 301 : l = sa_list(sql->sa);
4037 6323 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m;
4038 6022 : n = n->next, m = m->next) {
4039 6022 : stmt *c1 = n->data;
4040 6022 : assert(c1->type == st_alias);
4041 6022 : stmt *c2 = m->data;
4042 6022 : const char *rnme = table_name(sql->sa, c1);
4043 6022 : const char *nme = column_name(sql->sa, c1);
4044 6022 : stmt *s;
4045 :
4046 6022 : s = stmt_append(be, create_const_column(be, c1), c2);
4047 6022 : if (s == NULL)
4048 : return NULL;
4049 6022 : s = stmt_alias(be, s, c1->label, rnme, nme);
4050 6022 : if (s == NULL)
4051 : return NULL;
4052 6022 : list_append(l, s);
4053 : }
4054 301 : sub = stmt_list(be, l);
4055 :
4056 301 : sub = rel_rename(be, rel, sub);
4057 301 : if (need_distinct(rel))
4058 0 : sub = rel2bin_distinct(be, sub, NULL);
4059 301 : if (is_single(rel))
4060 0 : sub = rel2bin_single(be, sub);
4061 : return sub;
4062 : }
4063 :
4064 : static stmt *
4065 2014 : rel2bin_except(backend *be, sql_rel *rel, list *refs)
4066 : {
4067 2014 : mvc *sql = be->mvc;
4068 2014 : sql_subtype *lng = sql_bind_localtype("lng");
4069 2014 : list *stmts;
4070 2014 : node *n, *m;
4071 2014 : stmt *left = NULL, *right = NULL, *sub;
4072 2014 : sql_subfunc *min;
4073 :
4074 2014 : stmt *lg = NULL, *rg = NULL;
4075 2014 : stmt *lgrp = NULL, *rgrp = NULL;
4076 2014 : stmt *lext = NULL, *rext = NULL, *next = NULL;
4077 2014 : stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
4078 2014 : stmt *s, *lm, *rm;
4079 2014 : list *lje = sa_list(sql->sa);
4080 2014 : list *rje = sa_list(sql->sa);
4081 :
4082 2014 : if (rel->l) /* first construct the left sub relation */
4083 2014 : left = subrel_bin(be, rel->l, refs);
4084 2014 : if (rel->r) /* first construct the right sub relation */
4085 2014 : right = subrel_bin(be, rel->r, refs);
4086 2014 : if (!left || !right)
4087 : return NULL;
4088 2014 : left = subrel_project(be, left, refs, rel->l);
4089 2014 : right = subrel_project(be, right, refs, rel->r);
4090 2014 : left = row2cols(be, left);
4091 2014 : 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 4196 : for (n = left->op4.lval->h; n; n = n->next) {
4100 2182 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4101 2182 : lgrp = stmt_result(be, lg, 0);
4102 2182 : lext = stmt_result(be, lg, 1);
4103 2182 : lcnt = stmt_result(be, lg, 2);
4104 : }
4105 4196 : for (n = right->op4.lval->h; n; n = n->next) {
4106 2182 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4107 2182 : rgrp = stmt_result(be, rg, 0);
4108 2182 : rext = stmt_result(be, rg, 1);
4109 2182 : rcnt = stmt_result(be, rg, 2);
4110 : }
4111 :
4112 2014 : if (!lg || !rg)
4113 : return NULL;
4114 :
4115 2014 : if (need_distinct(rel)) {
4116 1935 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
4117 1935 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
4118 : }
4119 :
4120 : /* now find the matching groups */
4121 4196 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
4122 2182 : stmt *l = column(be, n->data);
4123 2182 : stmt *r = column(be, m->data);
4124 :
4125 2182 : l = stmt_project(be, lext, l);
4126 2182 : r = stmt_project(be, rext, r);
4127 2182 : list_append(lje, l);
4128 2182 : list_append(rje, r);
4129 : }
4130 2014 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
4131 2014 : lm = stmt_result(be, s, 0);
4132 2014 : rm = stmt_result(be, s, 1);
4133 :
4134 2014 : s = stmt_mirror(be, lext);
4135 2014 : s = stmt_tdiff(be, s, lm, NULL);
4136 :
4137 : /* first we find those missing in R */
4138 2014 : next = stmt_project(be, s, lext);
4139 2014 : ncnt = stmt_project(be, s, lcnt);
4140 2014 : zero = stmt_const(be, s, stmt_atom_lng(be, 0));
4141 :
4142 : /* ext, lcount, rcount */
4143 2014 : lext = stmt_project(be, lm, lext);
4144 2014 : lcnt = stmt_project(be, lm, lcnt);
4145 2014 : rcnt = stmt_project(be, rm, rcnt);
4146 :
4147 : /* append those missing in L */
4148 2014 : lext = stmt_append(be, lext, next);
4149 2014 : lcnt = stmt_append(be, lcnt, ncnt);
4150 2014 : rcnt = stmt_append(be, rcnt, zero);
4151 :
4152 2014 : min = sql_bind_func_result(sql, "sys", "sql_sub", F_FUNC, true, lng, 2, lng, lng);
4153 2014 : s = stmt_binop(be, lcnt, rcnt, NULL, min); /* use count */
4154 :
4155 : /* now we have gid,cnt, blowup to full groupsizes */
4156 2014 : s = stmt_gen_group(be, lext, s);
4157 :
4158 : /* project columns of left hand expression */
4159 2014 : stmts = sa_list(sql->sa);
4160 4196 : for (n = left->op4.lval->h; n; n = n->next) {
4161 2182 : stmt *c1 = column(be, n->data);
4162 2182 : assert(c1->type == st_alias);
4163 2182 : const char *rnme = NULL;
4164 2182 : const char *nme = column_name(sql->sa, c1);
4165 2182 : int label = c1->label;
4166 :
4167 : /* retain name via the stmt_alias */
4168 2182 : c1 = stmt_project(be, s, c1);
4169 :
4170 2182 : rnme = table_name(sql->sa, c1);
4171 2182 : c1 = stmt_alias(be, c1, label, rnme, nme);
4172 2182 : list_append(stmts, c1);
4173 : }
4174 2014 : sub = stmt_list(be, stmts);
4175 2014 : return rel_rename(be, rel, sub);
4176 : }
4177 :
4178 : static stmt *
4179 372 : rel2bin_inter(backend *be, sql_rel *rel, list *refs)
4180 : {
4181 372 : mvc *sql = be->mvc;
4182 372 : sql_subtype *lng = sql_bind_localtype("lng");
4183 372 : list *stmts;
4184 372 : node *n, *m;
4185 372 : stmt *left = NULL, *right = NULL, *sub;
4186 372 : sql_subfunc *min;
4187 :
4188 372 : stmt *lg = NULL, *rg = NULL;
4189 372 : stmt *lgrp = NULL, *rgrp = NULL;
4190 372 : stmt *lext = NULL, *rext = NULL;
4191 372 : stmt *lcnt = NULL, *rcnt = NULL;
4192 372 : stmt *s, *lm, *rm;
4193 372 : list *lje = sa_list(sql->sa);
4194 372 : list *rje = sa_list(sql->sa);
4195 :
4196 372 : if (rel->l) /* first construct the left sub relation */
4197 372 : left = subrel_bin(be, rel->l, refs);
4198 372 : if (rel->r) /* first construct the right sub relation */
4199 372 : right = subrel_bin(be, rel->r, refs);
4200 372 : left = subrel_project(be, left, refs, rel->l);
4201 372 : right = subrel_project(be, right, refs, rel->r);
4202 372 : if (!left || !right)
4203 : return NULL;
4204 372 : 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 827 : for (n = left->op4.lval->h; n; n = n->next) {
4213 455 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4214 455 : lgrp = stmt_result(be, lg, 0);
4215 455 : lext = stmt_result(be, lg, 1);
4216 455 : lcnt = stmt_result(be, lg, 2);
4217 : }
4218 827 : for (n = right->op4.lval->h; n; n = n->next) {
4219 455 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4220 455 : rgrp = stmt_result(be, rg, 0);
4221 455 : rext = stmt_result(be, rg, 1);
4222 455 : rcnt = stmt_result(be, rg, 2);
4223 : }
4224 :
4225 372 : if (!lg || !rg)
4226 : return NULL;
4227 :
4228 372 : if (need_distinct(rel)) {
4229 361 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
4230 361 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
4231 : }
4232 :
4233 : /* now find the matching groups */
4234 827 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
4235 455 : stmt *l = column(be, n->data);
4236 455 : stmt *r = column(be, m->data);
4237 :
4238 455 : l = stmt_project(be, lext, l);
4239 455 : r = stmt_project(be, rext, r);
4240 455 : list_append(lje, l);
4241 455 : list_append(rje, r);
4242 : }
4243 372 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /* is_semantics */);
4244 372 : lm = stmt_result(be, s, 0);
4245 372 : rm = stmt_result(be, s, 1);
4246 :
4247 : /* ext, lcount, rcount */
4248 372 : lext = stmt_project(be, lm, lext);
4249 372 : lcnt = stmt_project(be, lm, lcnt);
4250 372 : rcnt = stmt_project(be, rm, rcnt);
4251 :
4252 372 : min = sql_bind_func(sql, "sys", "sql_min", lng, lng, F_FUNC, true, true);
4253 372 : s = stmt_binop(be, lcnt, rcnt, NULL, min);
4254 :
4255 : /* now we have gid,cnt, blowup to full groupsizes */
4256 372 : s = stmt_gen_group(be, lext, s);
4257 :
4258 : /* project columns of left hand expression */
4259 372 : stmts = sa_list(sql->sa);
4260 827 : for (n = left->op4.lval->h; n; n = n->next) {
4261 455 : stmt *c1 = column(be, n->data);
4262 455 : assert(c1->type == st_alias);
4263 455 : const char *rnme = NULL;
4264 455 : const char *nme = column_name(sql->sa, c1);
4265 455 : int label = c1->label;
4266 :
4267 : /* retain name via the stmt_alias */
4268 455 : c1 = stmt_project(be, s, c1);
4269 :
4270 455 : rnme = table_name(sql->sa, c1);
4271 455 : c1 = stmt_alias(be, c1, label, rnme, nme);
4272 455 : list_append(stmts, c1);
4273 : }
4274 372 : sub = stmt_list(be, stmts);
4275 372 : return rel_rename(be, rel, sub);
4276 : }
4277 :
4278 : static int
4279 43915 : find_matching_exp(list *exps, sql_exp *e)
4280 : {
4281 43915 : int i = 0;
4282 156177 : for (node *n = exps->h; n; n = n->next, i++) {
4283 133739 : if (exp_match(n->data, e))
4284 21477 : return i;
4285 : }
4286 : return -1;
4287 : }
4288 :
4289 : static stmt *
4290 9925 : sql_reorder(backend *be, stmt *order, list *exps, stmt *s, list *oexps, list *ostmts)
4291 : {
4292 9925 : list *l = sa_list(be->mvc->sa);
4293 :
4294 53840 : for (node *n = s->op4.lval->h, *m = exps->h; n && m; n = n->next, m = m->next) {
4295 43915 : int pos = 0;
4296 43915 : stmt *sc = n->data;
4297 43915 : sql_exp *pe = m->data;
4298 43915 : const char *cname = column_name(be->mvc->sa, sc);
4299 43915 : const char *tname = table_name(be->mvc->sa, sc);
4300 :
4301 43915 : if (oexps && (pos = find_matching_exp(oexps, pe)) >= 0 && list_fetch(ostmts, pos)) {
4302 21477 : sc = list_fetch(ostmts, pos);
4303 : } else {
4304 22438 : sc = stmt_project(be, order, sc);
4305 : }
4306 43915 : sc = stmt_alias(be, sc, pe->alias.label, tname, cname);
4307 43915 : list_append(l, sc);
4308 : }
4309 9925 : return stmt_list(be, l);
4310 : }
4311 :
4312 : static sql_exp*
4313 16995 : topn_limit(sql_rel *rel)
4314 : {
4315 16995 : if (rel->exps) {
4316 16995 : sql_exp *limit = rel->exps->h->data;
4317 16995 : 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 16995 : topn_offset(sql_rel *rel)
4326 : {
4327 16995 : if (rel->exps && list_length(rel->exps) > 1) {
4328 157 : sql_exp *offset = rel->exps->h->next->data;
4329 :
4330 157 : return offset;
4331 : }
4332 : return NULL;
4333 : }
4334 :
4335 : static stmt *
4336 390908 : rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
4337 : {
4338 390908 : mvc *sql = be->mvc;
4339 390908 : list *pl;
4340 390908 : node *en, *n;
4341 390908 : stmt *sub = NULL, *psub = NULL;
4342 390908 : stmt *l = NULL;
4343 :
4344 390908 : if (topn) {
4345 315 : sql_exp *le = topn_limit(topn);
4346 315 : sql_exp *oe = topn_offset(topn);
4347 :
4348 315 : if (!le) { /* Don't push only offset */
4349 : topn = NULL;
4350 : } else {
4351 289 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4352 289 : if(!l)
4353 : return NULL;
4354 289 : if (oe) {
4355 43 : sql_subtype *lng = sql_bind_localtype("lng");
4356 43 : sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
4357 43 : stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4358 43 : if(!o)
4359 : return NULL;
4360 43 : l = stmt_binop(be, l, o, NULL, add);
4361 : }
4362 : }
4363 : }
4364 :
4365 390908 : if (!rel->exps)
4366 0 : return stmt_none(be);
4367 :
4368 390908 : if (rel->l) { /* first construct the sub relation */
4369 218147 : sql_rel *l = rel->l;
4370 218147 : if (l->op == op_ddl) {
4371 1209 : sql_table *t = rel_ddl_table_get(l);
4372 :
4373 1209 : if (t)
4374 1209 : sub = rel2bin_sql_table(be, t, rel->exps);
4375 : } else {
4376 216938 : sub = subrel_bin(be, rel->l, refs);
4377 : }
4378 218044 : sub = subrel_project(be, sub, refs, rel->l);
4379 218012 : if (!sub)
4380 : return NULL;
4381 : }
4382 :
4383 390773 : pl = sa_list(sql->sa);
4384 390869 : if (pl == NULL)
4385 : return NULL;
4386 390869 : if (sub)
4387 218067 : pl->expected_cnt = list_length(sub->op4.lval);
4388 390910 : psub = stmt_list(be, pl);
4389 390746 : if (psub == NULL)
4390 : return NULL;
4391 1950989 : for (en = rel->exps->h; en; en = en->next) {
4392 1560081 : sql_exp *exp = en->data;
4393 1560081 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
4394 1560081 : stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL, 0, 0, 0);
4395 :
4396 1560558 : if (!s) { /* try with own projection as well, but first clean leftover statements */
4397 11049 : clean_mal_statements(be, oldstop, oldvtop);
4398 11049 : s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4399 : }
4400 11049 : if (!s) /* error */
4401 : return NULL;
4402 : /* single value with limit */
4403 1560558 : if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
4404 14 : s = const_column(be, s);
4405 1560544 : else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
4406 30670 : s = stmt_const(be, bin_find_smallest_column(be, sub), s);
4407 :
4408 1560558 : if (!exp_name(exp))
4409 79968 : exp_label(sql->sa, exp, ++sql->label);
4410 1560323 : if (exp_name(exp)) {
4411 1560499 : s = stmt_rename(be, exp, s);
4412 : //column_name(sql->sa, s); /* save column name */
4413 1560464 : s->label = exp->alias.label;
4414 : }
4415 1560464 : list_append(pl, s);
4416 : }
4417 390908 : 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 390826 : if (topn && rel->r) {
4424 270 : list *oexps = rel->r, *npl = sa_list(sql->sa);
4425 : /* distinct, topn returns at least N (unique groups) */
4426 270 : int distinct = need_distinct(rel);
4427 270 : stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
4428 :
4429 850 : for (n=oexps->h; n; n = n->next) {
4430 580 : sql_exp *orderbycole = n->data;
4431 580 : int last = (n->next == NULL);
4432 :
4433 580 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4434 :
4435 580 : if (!orderbycolstmt)
4436 : return NULL;
4437 :
4438 : /* handle constants */
4439 580 : if (orderbycolstmt->nrcols == 0 && !last) /* no need to sort on constant */
4440 0 : continue;
4441 580 : orderbycolstmt = column(be, orderbycolstmt);
4442 580 : if (!limit) { /* topn based on a single column */
4443 270 : 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 580 : if (!limit)
4448 : return NULL;
4449 580 : lpiv = limit;
4450 580 : 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 270 : limit = lpiv;
4459 270 : stmt *s;
4460 1462 : for (n=pl->h ; n; n = n->next) {
4461 1192 : stmt *os = n->data;
4462 1192 : list_append(npl, s=stmt_project(be, limit, column(be, os)));
4463 1192 : s->label = os->label;
4464 : }
4465 270 : 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 270 : pl = sub->op4.lval;
4469 270 : npl = sa_list(sql->sa);
4470 1603 : for (n=pl->h ; n; n = n->next) {
4471 1333 : stmt *os = n->data;
4472 1333 : list_append(npl, s = stmt_project(be, limit, column(be, os)));
4473 1333 : s->label = os->label;
4474 : }
4475 270 : sub = stmt_list(be, npl);
4476 : }
4477 390826 : 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 390826 : if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
4491 9995 : list *oexps = rel->r;
4492 9995 : stmt *orderby_ids = NULL, *orderby_grp = NULL;
4493 :
4494 9995 : list *ostmts = sa_list(be->mvc->sa);
4495 33318 : for (en = oexps->h; en; en = en->next) {
4496 23323 : stmt *orderby = NULL;
4497 23323 : sql_exp *orderbycole = en->data;
4498 23323 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
4499 :
4500 23323 : 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 23323 : if (orderbycolstmt->nrcols == 0) {
4506 61 : append(ostmts, NULL);
4507 61 : continue;
4508 : }
4509 23262 : if (orderby_ids)
4510 13337 : orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
4511 : else
4512 9925 : orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
4513 23262 : stmt *orderby_vals = stmt_result(be, orderby, 0);
4514 23262 : append(ostmts, orderby_vals);
4515 23262 : orderby_ids = stmt_result(be, orderby, 1);
4516 23262 : orderby_grp = stmt_result(be, orderby, 2);
4517 : }
4518 9995 : if (orderby_ids)
4519 9925 : 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 68439 : rel2bin_select(backend *be, sql_rel *rel, list *refs)
4532 : {
4533 68439 : mvc *sql = be->mvc;
4534 68439 : node *en;
4535 68439 : stmt *sub = NULL, *sel = NULL;
4536 68439 : stmt *predicate = NULL;
4537 :
4538 68439 : if (rel->l) { /* first construct the sub relation */
4539 68439 : sub = subrel_bin(be, rel->l, refs);
4540 68439 : if (!sub)
4541 : return NULL;
4542 68439 : sel = sub->cand;
4543 68439 : sub = row2cols(be, sub);
4544 : }
4545 68439 : if (!sub && !predicate)
4546 0 : predicate = rel2bin_predicate(be);
4547 68439 : if (list_empty(rel->exps)) {
4548 1479 : if (sub)
4549 : return sub;
4550 0 : if (predicate)
4551 : return predicate;
4552 0 : assert(0);
4553 : }
4554 66960 : en = rel->exps->h;
4555 66960 : 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 66960 : if (sub && en) {
4564 66960 : sql_exp *e = en->data;
4565 66960 : prop *p;
4566 :
4567 66960 : 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 144256 : for (en = rel->exps->h; en; en = en->next) {
4578 77296 : sql_exp *e = en->data;
4579 77296 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
4580 :
4581 77296 : if (!s) {
4582 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4583 : return NULL;
4584 : }
4585 77296 : if (s->nrcols == 0){
4586 2175 : if (!predicate && sub && !list_empty(sub->op4.lval))
4587 2167 : 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 2175 : if (e->type != e_cmp) {
4591 2056 : sql_subtype *bt = sql_bind_localtype("bit");
4592 :
4593 2056 : s = stmt_convert(be, s, NULL, exp_subtype(e), bt);
4594 : }
4595 2175 : sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0, 0);
4596 75121 : } 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 66960 : if (sub && sel) {
4604 66960 : sub = stmt_list(be, sub->op4.lval); /* protect against references */
4605 66960 : sub->cand = sel;
4606 : }
4607 : return sub;
4608 : }
4609 :
4610 : static stmt *
4611 13225 : rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
4612 : {
4613 13225 : mvc *sql = be->mvc;
4614 13225 : list *l, *aggrs, *gbexps = sa_list(sql->sa);
4615 13226 : node *n, *en;
4616 13226 : stmt *sub = NULL, *cursub;
4617 13226 : stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
4618 :
4619 13226 : if (rel->l) { /* first construct the sub relation */
4620 13226 : sub = subrel_bin(be, rel->l, refs);
4621 13226 : sub = subrel_project(be, sub, refs, rel->l);
4622 13226 : if (!sub)
4623 : return NULL;
4624 : }
4625 :
4626 13226 : if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
4627 340 : list *newl = sa_list(sql->sa);
4628 340 : node *n;
4629 :
4630 771 : for (n=sub->op4.lval->h; n; n = n->next) {
4631 431 : stmt *s = n->data;
4632 431 : assert(s->type == st_alias);
4633 431 : const char *cname = column_name(sql->sa, s);
4634 431 : const char *tname = table_name(sql->sa, s);
4635 431 : int label = s->label;
4636 :
4637 431 : s = column(be, s);
4638 431 : s = stmt_alias(be, s, label, tname, cname);
4639 431 : append(newl, s);
4640 : }
4641 340 : 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 13226 : if (rel->r) {
4648 9700 : list *exps = rel->r;
4649 :
4650 24340 : for (en = exps->h; en; en = en->next) {
4651 14640 : sql_exp *e = en->data;
4652 14640 : stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4653 :
4654 14640 : if (!gbcol) {
4655 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4656 : return NULL;
4657 : }
4658 14640 : if (!gbcol->nrcols)
4659 12 : gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
4660 14640 : groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
4661 14640 : grp = stmt_result(be, groupby, 0);
4662 14640 : ext = stmt_result(be, groupby, 1);
4663 14640 : cnt = stmt_result(be, groupby, 2);
4664 14640 : gbcol = stmt_alias(be, gbcol, e->alias.label, exp_find_rel_name(e), exp_name(e));
4665 14640 : list_append(gbexps, gbcol);
4666 : }
4667 : }
4668 : /* now aggregate */
4669 13226 : l = sa_list(sql->sa);
4670 13226 : if (l == NULL)
4671 : return NULL;
4672 13226 : aggrs = rel->exps;
4673 13226 : cursub = stmt_list(be, l);
4674 13227 : if (cursub == NULL)
4675 : return NULL;
4676 13227 : if (aggrs && !aggrs->h && ext)
4677 0 : list_append(l, ext);
4678 38143 : for (n = aggrs->h; n; n = n->next) {
4679 24916 : sql_exp *aggrexp = n->data;
4680 24916 : stmt *aggrstmt = NULL;
4681 24916 : int oldvtop, oldstop;
4682 :
4683 : /* first look in the current aggr list (l) and group by column list */
4684 24916 : if (l && !aggrstmt && aggrexp->type == e_column)
4685 : //aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
4686 14248 : aggrstmt = list_find_column_nid(be, l, aggrexp->nid);
4687 24916 : if (gbexps && !aggrstmt && aggrexp->type == e_column) {
4688 : //aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
4689 14222 : aggrstmt = list_find_column_nid(be, gbexps, aggrexp->nid);
4690 14222 : if (aggrstmt && groupby) {
4691 14025 : aggrstmt = stmt_project(be, ext, aggrstmt);
4692 14025 : if (list_length(gbexps) == 1)
4693 5817 : aggrstmt->key = 1;
4694 : }
4695 : }
4696 :
4697 24916 : oldvtop = be->mb->vtop;
4698 24916 : oldstop = be->mb->stop;
4699 24916 : if (!aggrstmt)
4700 10865 : 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 10865 : if (!aggrstmt) {
4705 0 : clean_mal_statements(be, oldstop, oldvtop);
4706 0 : aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL, 0, 0, 0);
4707 : }
4708 0 : if (!aggrstmt) {
4709 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4710 : return NULL;
4711 : }
4712 :
4713 24916 : if (!aggrstmt->nrcols && ext && ext->nrcols)
4714 0 : aggrstmt = stmt_const(be, ext, aggrstmt);
4715 :
4716 24916 : aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
4717 24916 : list_append(l, aggrstmt);
4718 : }
4719 13227 : stmt_set_nrcols(cursub);
4720 13227 : return cursub;
4721 : }
4722 :
4723 : static stmt *
4724 16682 : rel2bin_topn(backend *be, sql_rel *rel, list *refs)
4725 : {
4726 16682 : mvc *sql = be->mvc;
4727 16682 : sql_exp *oe = NULL, *le = NULL;
4728 16682 : stmt *sub = NULL, *l = NULL, *o = NULL;
4729 16682 : node *n;
4730 :
4731 16682 : if (rel->l) { /* first construct the sub relation */
4732 16682 : sql_rel *rl = rel->l;
4733 :
4734 16682 : if (rl->op == op_project) {
4735 320 : 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 315 : sub = rel2bin_project(be, rl, refs, rel);
4741 : } else {
4742 16362 : sub = subrel_bin(be, rl, refs);
4743 : }
4744 16677 : sub = subrel_project(be, sub, refs, rl);
4745 : }
4746 16681 : if (!sub)
4747 0 : return NULL;
4748 :
4749 16681 : le = topn_limit(rel);
4750 16680 : oe = topn_offset(rel);
4751 :
4752 16680 : n = sub->op4.lval->h;
4753 16680 : if (n) {
4754 16680 : 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 16680 : list *newl = sa_list(sql->sa);
4758 16680 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
4759 :
4760 16680 : if (le)
4761 16652 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4762 16654 : if (!l) {
4763 28 : clean_mal_statements(be, oldstop, oldvtop);
4764 28 : l = stmt_atom_lng_nil(be);
4765 : }
4766 :
4767 16679 : oldvtop = be->mb->vtop;
4768 16679 : oldstop = be->mb->stop;
4769 16679 : if (oe)
4770 88 : o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4771 88 : if (!o) {
4772 16591 : clean_mal_statements(be, oldstop, oldvtop);
4773 16594 : o = stmt_atom_lng(be, 0);
4774 : }
4775 16677 : if (!l || !o)
4776 : return NULL;
4777 :
4778 16677 : sc = column(be, sc);
4779 16677 : limit = stmt_limit(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/, NULL, NULL, o, l, 0,0,0,0,0);
4780 :
4781 116898 : for ( ; n; n = n->next) {
4782 83538 : stmt *sc = n->data;
4783 83538 : assert(sc->type == st_alias);
4784 83538 : const char *cname = column_name(sql->sa, sc);
4785 83535 : const char *tname = table_name(sql->sa, sc);
4786 83533 : int label = sc->label;
4787 :
4788 83533 : sc = column(be, sc);
4789 83539 : sc = stmt_project(be, limit, sc);
4790 83541 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
4791 : }
4792 16683 : sub = stmt_list(be, newl);
4793 : }
4794 : return sub;
4795 : }
4796 :
4797 : static stmt *
4798 20 : rel2bin_sample(backend *be, sql_rel *rel, list *refs)
4799 : {
4800 20 : mvc *sql = be->mvc;
4801 20 : list *newl;
4802 20 : stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
4803 20 : node *n;
4804 :
4805 20 : if (rel->l) /* first construct the sub relation */
4806 20 : sub = subrel_bin(be, rel->l, refs);
4807 20 : sub = subrel_project(be, sub, refs, rel->l);
4808 20 : if (!sub)
4809 : return NULL;
4810 :
4811 20 : n = sub->op4.lval->h;
4812 20 : newl = sa_list(sql->sa);
4813 :
4814 20 : if (n) {
4815 20 : stmt *sc = n->data;
4816 : //const char *cname = column_name(sql->sa, sc);
4817 : //const char *tname = table_name(sql->sa, sc);
4818 :
4819 20 : if (!(sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0)))
4820 : return NULL;
4821 :
4822 20 : 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 20 : sc = column(be, sc);
4829 20 : sample = stmt_sample(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/,sample_size, seed);
4830 :
4831 62 : for ( ; n; n = n->next) {
4832 22 : stmt *sc = n->data;
4833 22 : assert(sc->type == st_alias);
4834 22 : const char *cname = column_name(sql->sa, sc);
4835 22 : const char *tname = table_name(sql->sa, sc);
4836 22 : int label = sc->label;
4837 :
4838 22 : sc = column(be, sc);
4839 22 : sc = stmt_project(be, sample, sc);
4840 22 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
4841 : }
4842 : }
4843 20 : sub = stmt_list(be, newl);
4844 20 : return sub;
4845 : }
4846 :
4847 : static stmt *
4848 5132 : sql_parse(backend *be, sql_schema *s, const char *query, char mode)
4849 : {
4850 5132 : sql_rel *rel = rel_parse(be->mvc, s, query, mode);
4851 5132 : stmt *sq = NULL;
4852 :
4853 5132 : if (rel && (rel = sql_processrelation(be->mvc, rel, 0, 1, 1, 1)))
4854 5129 : sq = rel_bin(be, rel);
4855 5132 : return sq;
4856 : }
4857 :
4858 : static stmt *
4859 12782 : insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
4860 : {
4861 12782 : 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 12782 : char *msg = NULL;
4866 12782 : stmt *res;
4867 :
4868 12782 : sql_subtype *lng = sql_bind_localtype("lng");
4869 12788 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
4870 12788 : sql_subtype *bt = sql_bind_localtype("bit");
4871 12782 : stmt *dels = stmt_tid(be, k->t, 0);
4872 12791 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
4873 :
4874 12790 : if (list_length(k->columns) > 1) {
4875 820 : node *m;
4876 820 : stmt *s = list_fetch(inserts, 0), *ins = s;
4877 820 : sql_subfunc *sum;
4878 820 : stmt *ssum = NULL;
4879 820 : stmt *col = NULL;
4880 :
4881 820 : s = ins;
4882 : /* 1st stage: find out if original contains same values */
4883 820 : if (/*s->key &&*/ s->nrcols == 0) {
4884 586 : s = NULL;
4885 586 : if (k->idx && hash_index(k->idx->type))
4886 586 : s = stmt_uselect(be, stmt_idx(be, k->idx, dels, dels->partition), idx_inserts, cmp_equal, s, 0, 1 /* is_semantics*/);
4887 2149 : for (m = k->columns->h; m; m = m->next) {
4888 1563 : sql_kc *c = m->data;
4889 1563 : stmt *cs = list_fetch(inserts, c->c->colnr);
4890 :
4891 : /* foreach column add predicate */
4892 1563 : stmt_add_column_predicate(be, c->c);
4893 :
4894 1563 : col = stmt_col(be, c->c, dels, dels->partition);
4895 1563 : if (k->type == unndkey)
4896 8 : s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 1);
4897 1664 : 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 1446 : 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 820 : 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 820 : 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 820 : if (k->type == pkey) {
4968 330 : 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 820 : res = stmt_exception(be, s, msg, 00001);
4973 : } else { /* single column key */
4974 11966 : sql_kc *c = k->columns->h->data;
4975 11966 : stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
4976 :
4977 : /* add predicate for this column */
4978 11942 : stmt_add_column_predicate(be, c->c);
4979 :
4980 11971 : s = stmt_col(be, c->c, dels, dels->partition);
4981 11971 : 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 11971 : if (h->nrcols) {
4986 4767 : s = stmt_join(be, s, h, 0, cmp_equal, 0, k->type == unndkey? 1: 0, false);
4987 : /* s should be empty */
4988 4767 : s = stmt_result(be, s, 0);
4989 4767 : 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 7192 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
4994 : }
4995 : /* s should be empty */
4996 11970 : s = stmt_binop(be, s, stmt_atom_lng(be, 0), NULL, ne);
4997 :
4998 : /* 2e stage: find out if inserts are unique */
4999 11971 : if (h->nrcols) { /* insert multiple atoms */
5000 4767 : sql_subfunc *sum;
5001 4767 : stmt *count_sum = NULL;
5002 4767 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5003 4767 : stmt *ssum, *ss;
5004 :
5005 4767 : stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
5006 :
5007 : /* inserted values may be null */
5008 4767 : if ((k->type == ukey) && stmt_has_null(ins)) {
5009 1748 : stmt *nn = stmt_selectnonil(be, ins, NULL);
5010 1748 : ins = stmt_project(be, nn, ins);
5011 : }
5012 :
5013 4767 : g = stmt_group(be, ins, NULL, NULL, NULL, 1);
5014 4767 : ss = stmt_result(be, g, 2); /* use count */
5015 : /* (count(ss) <> sum(ss)) */
5016 4767 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5017 4767 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5018 4767 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5019 4767 : 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 4767 : s = stmt_binop(be, s, count_sum, NULL, or);
5023 : }
5024 11971 : if (k->type == pkey) {
5025 10062 : 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 1909 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5028 : }
5029 11970 : res = stmt_exception(be, s, msg, 00001);
5030 : }
5031 : return res;
5032 : }
5033 :
5034 : static stmt *
5035 777 : insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
5036 : {
5037 777 : mvc *sql = be->mvc;
5038 777 : char *msg = NULL;
5039 777 : stmt *cs = list_fetch(inserts, 0), *s = cs;
5040 777 : sql_subtype *lng = sql_bind_localtype("lng");
5041 777 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5042 777 : sql_subtype *bt = sql_bind_localtype("bit");
5043 777 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5044 :
5045 777 : stmt *nonil_rows = NULL;
5046 1589 : for (node *m = k->columns->h; m; m = m->next) {
5047 812 : sql_kc *c = m->data;
5048 :
5049 : /* foreach column add predicate */
5050 812 : 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 812 : s = list_fetch(inserts, c->c->colnr);
5056 812 : nonil_rows = stmt_selectnonil(be, s, nonil_rows);
5057 : }
5058 :
5059 777 : 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 777 : 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 777 : 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 777 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5080 777 : return stmt_exception(be, s, msg, 00001);
5081 : }
5082 :
5083 : static stmt *
5084 13559 : 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 13559 : if (k->type == pkey || k->type == ukey || k->type == unndkey) {
5099 12782 : return insert_check_ukey(be, inserts, k, idx_inserts);
5100 : } else { /* foreign keys */
5101 777 : 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 216037 : sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
5135 : {
5136 216037 : mvc *sql = be->mvc;
5137 216037 : node *n;
5138 216037 : int res = 1;
5139 :
5140 216037 : 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 109678 : sql_insert_check_null(backend *be, sql_table *t, list *inserts)
5198 : {
5199 109678 : mvc *sql = be->mvc;
5200 109678 : node *m, *n;
5201 109678 : sql_subfunc *cnt = NULL;
5202 :
5203 780305 : for (n = ol_first_node(t->columns), m = inserts->h; n && m;
5204 670627 : n = n->next, m = m->next) {
5205 670594 : stmt *i = m->data;
5206 670594 : sql_column *c = n->data;
5207 :
5208 670594 : if (!c->null) {
5209 24502 : stmt *s = i;
5210 24502 : char *msg = NULL;
5211 :
5212 24502 : if (!(s->key && s->nrcols == 0)) {
5213 11482 : s = stmt_selectnil(be, column(be, i));
5214 11482 : if (!cnt)
5215 3630 : cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5216 11482 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5217 : } else {
5218 13020 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
5219 :
5220 13010 : s = stmt_unop(be, i, NULL, isnil);
5221 : }
5222 24514 : 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 24514 : (void)stmt_exception(be, s, msg, 00001);
5224 : }
5225 : }
5226 109711 : return t; /* return something to say it succeeded */
5227 : }
5228 :
5229 : static stmt **
5230 113825 : table_update_stmts(mvc *sql, sql_table *t, int *Len)
5231 : {
5232 113825 : *Len = ol_length(t->columns);
5233 113812 : return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
5234 : }
5235 :
5236 : static stmt *
5237 109664 : rel2bin_insert(backend *be, sql_rel *rel, list *refs)
5238 : {
5239 109664 : mvc *sql = be->mvc;
5240 109664 : list *l;
5241 109664 : stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
5242 109664 : int idx_ins = 0, len = 0;
5243 109664 : node *n, *m, *idx_m = NULL;
5244 109664 : sql_rel *tr = rel->l, *prel = rel->r;
5245 109664 : sql_table *t = NULL;
5246 :
5247 109664 : 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 109664 : if (tr->op == op_basetable) {
5255 109572 : 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 109664 : if (rel->r) /* first construct the inserts relation */
5265 109695 : inserts = subrel_bin(be, rel->r, refs);
5266 109604 : inserts = subrel_project(be, inserts, refs, rel->r);
5267 :
5268 109629 : if (!inserts)
5269 : return NULL;
5270 :
5271 109629 : if (idx_ins)
5272 0 : pin = refs_find_rel(refs, prel);
5273 :
5274 123265 : for (n = ol_first_node(t->keys); n; n = n->next) {
5275 13587 : sql_key * key = n->data;
5276 13587 : if (key->type == ckey)
5277 83 : sql_insert_check(be, key, inserts->op4.lval);
5278 : }
5279 :
5280 109678 : if (!sql_insert_check_null(be, t, inserts->op4.lval))
5281 : return NULL;
5282 :
5283 109712 : updates = table_update_stmts(sql, t, &len);
5284 779719 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5285 670081 : sql_column *c = n->data;
5286 :
5287 670081 : updates[c->colnr] = m->data;
5288 : }
5289 :
5290 : /* before */
5291 109638 : 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 106402 : insert = inserts->op4.lval->h->data;
5295 106402 : if (insert->nrcols == 0) {
5296 74922 : cnt = stmt_atom_lng(be, 1);
5297 : } else {
5298 31480 : 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 106486 : insert = NULL;
5301 :
5302 106486 : l = sa_list(sql->sa);
5303 106483 : if (t->idxs) {
5304 106483 : idx_m = m;
5305 121638 : for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
5306 15150 : stmt *is = m->data;
5307 15150 : sql_idx *i = n->data;
5308 :
5309 15150 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
5310 107 : continue;
5311 15043 : if (hash_index(i->type) && list_length(i->columns) <= 1)
5312 15046 : is = NULL;
5313 15046 : if (i->key) {
5314 13563 : stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
5315 :
5316 13568 : list_append(l, ckeys);
5317 : }
5318 15048 : if (!insert)
5319 15155 : insert = is;
5320 : }
5321 106488 : assert(!n && !m);
5322 : }
5323 :
5324 106488 : if (t->s) /* only not declared tables, need this */
5325 106472 : pos = stmt_claim(be, t, cnt);
5326 :
5327 106460 : if (t->idxs) {
5328 121610 : for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
5329 15153 : stmt *is = m->data;
5330 15153 : sql_idx *i = n->data;
5331 :
5332 15153 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
5333 107 : continue;
5334 15046 : if (hash_index(i->type) && list_length(i->columns) <= 1)
5335 : is = NULL;
5336 2220 : if (is)
5337 2220 : is = stmt_append_idx(be, i, pos, is);
5338 : }
5339 106457 : assert(!n && !m);
5340 : }
5341 :
5342 106457 : int mvc_var = be->mvc_var;
5343 770365 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5344 :
5345 663893 : stmt *ins = m->data;
5346 663893 : sql_column *c = n->data;
5347 :
5348 663893 : insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
5349 664023 : append(l,insert);
5350 : }
5351 106472 : be->mvc_var = mvc_var;
5352 106472 : if (!insert)
5353 : return NULL;
5354 :
5355 106472 : if (rel->returning) {
5356 5 : list* il = sa_list(sql->sa);
5357 5 : sql_rel* inner = rel->l;
5358 5 : assert(inner->op == op_basetable);
5359 15 : for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
5360 10 : sql_exp* ce = n->data;
5361 10 : stmt* ins = m->data;
5362 10 : stmt* s = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
5363 10 : append(il, s);
5364 : }
5365 5 : returning = stmt_list(be, il);
5366 5 : sql->type = Q_TABLE;
5367 : }
5368 :
5369 106472 : if (!sql_insert_triggers(be, t, updates, 1))
5370 1608 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
5371 : /* update predicate list */
5372 104819 : if (rel->r && !rel_predicates(be, rel->r))
5373 : return NULL;
5374 :
5375 104763 : if (ddl) {
5376 92 : ret = ddl;
5377 92 : list_prepend(l, ddl);
5378 92 : return stmt_list(be, l);
5379 : } else {
5380 104671 : ret = cnt;
5381 104671 : if (add_to_rowcount_accumulator(be, ret->nr) < 0)
5382 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
5383 104674 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
5384 104616 : stmt_add_dependency_change(be, t, ret);
5385 104769 : return returning?returning:ret;
5386 : }
5387 : }
5388 :
5389 : static int
5390 1371 : is_idx_updated(sql_idx * i, stmt **updates)
5391 : {
5392 1371 : int update = 0;
5393 1371 : node *m;
5394 :
5395 2708 : for (m = i->columns->h; m; m = m->next) {
5396 1543 : sql_kc *ic = m->data;
5397 :
5398 1543 : if (updates[ic->c->colnr]) {
5399 : update = 1;
5400 : break;
5401 : }
5402 : }
5403 1371 : return update;
5404 : }
5405 :
5406 : static int
5407 14 : is_check_updated(sql_key * k, stmt **updates)
5408 : {
5409 14 : int update = 0;
5410 14 : node *m;
5411 :
5412 16 : for (m = k->columns->h; m; m = m->next) {
5413 14 : sql_kc *kc = m->data;
5414 :
5415 14 : if (updates[kc->c->colnr]) {
5416 : update = 1;
5417 : break;
5418 : }
5419 : }
5420 14 : return update;
5421 : }
5422 :
5423 : static int
5424 4069 : first_updated_col(stmt **updates, int cnt)
5425 : {
5426 4069 : int i;
5427 :
5428 37661 : for (i = 0; i < cnt; i++) {
5429 36563 : if (updates[i])
5430 : return i;
5431 : }
5432 : return -1;
5433 : }
5434 :
5435 : static stmt *
5436 205 : update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *u_tids, stmt *idx_updates, int updcol)
5437 : {
5438 205 : mvc *sql = be->mvc;
5439 205 : char *msg = NULL;
5440 205 : stmt *res = NULL;
5441 :
5442 205 : sql_subtype *lng = sql_bind_localtype("lng");
5443 205 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5444 205 : sql_subtype *bt = sql_bind_localtype("bit");
5445 205 : sql_subfunc *ne;
5446 :
5447 205 : ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5448 205 : if (list_length(k->columns) > 1) {
5449 48 : stmt *dels = stmt_tid(be, k->t, 0);
5450 48 : node *m;
5451 48 : stmt *s = NULL;
5452 :
5453 : /* 1st stage: find out if original (without the updated)
5454 : do not contain the same values as the updated values.
5455 : This is done using a relation join and a count (which
5456 : should be zero)
5457 : */
5458 48 : if (!isNew(k)) {
5459 11 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
5460 11 : nu_tids = stmt_project(be, nu_tids, dels);
5461 11 : list *lje = sa_list(sql->sa);
5462 11 : list *rje = sa_list(sql->sa);
5463 :
5464 11 : if (k->idx && hash_index(k->idx->type)) {
5465 11 : list_append(lje, stmt_idx(be, k->idx, nu_tids, nu_tids->partition));
5466 11 : list_append(rje, idx_updates);
5467 : }
5468 33 : for (m = k->columns->h; m; m = m->next) {
5469 22 : sql_kc *c = m->data;
5470 22 : stmt *upd;
5471 :
5472 22 : assert(updates);
5473 22 : if (updates[c->c->colnr]) {
5474 : upd = updates[c->c->colnr];
5475 : } else {
5476 8 : upd = stmt_col(be, c->c, u_tids, u_tids->partition);
5477 : }
5478 22 : list_append(lje, stmt_col(be, c->c, nu_tids, nu_tids->partition));
5479 22 : list_append(rje, upd);
5480 : }
5481 11 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
5482 11 : s = stmt_result(be, s, 0);
5483 11 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
5484 : }
5485 :
5486 : /* 2e stage: find out if the updated are unique */
5487 48 : if (!updates || updates[updcol]->nrcols) { /* update columns not atoms */
5488 48 : sql_subfunc *sum;
5489 48 : stmt *count_sum = NULL, *ssum;
5490 48 : stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
5491 48 : stmt *cand = NULL;
5492 48 : stmt *ss;
5493 48 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5494 :
5495 : /* also take the hopefully unique hash keys, to reduce
5496 : (re)group costs */
5497 48 : if (k->idx && hash_index(k->idx->type)) {
5498 48 : g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
5499 48 : grp = stmt_result(be, g, 0);
5500 48 : ext = stmt_result(be, g, 1);
5501 48 : Cnt = stmt_result(be, g, 2);
5502 :
5503 : /* continue only with groups with a cnt > 1 */
5504 48 : cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0, 0);
5505 : /* project cand on ext and Cnt */
5506 48 : Cnt = stmt_project(be, cand, Cnt);
5507 48 : ext = stmt_project(be, cand, ext);
5508 :
5509 : /* join groups with extend to retrieve all oid's of the original
5510 : * bat that belong to a group with Cnt >1 */
5511 48 : g = stmt_join(be, grp, ext, 0, cmp_equal, 0, 0, false);
5512 48 : cand = stmt_result(be, g, 0);
5513 48 : grp = stmt_project(be, cand, grp);
5514 : }
5515 :
5516 154 : for (m = k->columns->h; m; m = m->next) {
5517 106 : sql_kc *c = m->data;
5518 106 : stmt *upd;
5519 :
5520 106 : if (updates && updates[c->c->colnr]) {
5521 : upd = updates[c->c->colnr];
5522 : } else {
5523 92 : upd = stmt_col(be, c->c, dels, dels->partition);
5524 : }
5525 :
5526 : /* apply cand list first */
5527 106 : if (cand)
5528 106 : upd = stmt_project(be, cand, upd);
5529 :
5530 : /* remove nulls */
5531 106 : if ((k->type == ukey) && stmt_has_null(upd)) {
5532 31 : stmt *nn = stmt_selectnonil(be, upd, NULL);
5533 31 : upd = stmt_project(be, nn, upd);
5534 31 : if (grp)
5535 31 : grp = stmt_project(be, nn, grp);
5536 31 : if (cand)
5537 31 : cand = stmt_project(be, nn, cand);
5538 : }
5539 :
5540 : /* apply group by on groups with Cnt > 1 */
5541 106 : g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
5542 106 : grp = stmt_result(be, g, 0);
5543 106 : ext = stmt_result(be, g, 1);
5544 106 : Cnt = stmt_result(be, g, 2);
5545 : }
5546 48 : ss = Cnt; /* use count */
5547 : /* (count(ss) <> sum(ss)) */
5548 48 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5549 48 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5550 48 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5551 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);
5552 :
5553 : /* combine results */
5554 48 : if (s)
5555 11 : s = stmt_binop(be, s, count_sum, NULL, or);
5556 : else
5557 : s = count_sum;
5558 : }
5559 :
5560 48 : if (k->type == pkey) {
5561 31 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5562 : } else {
5563 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5564 : }
5565 48 : res = stmt_exception(be, s, msg, 00001);
5566 : } else { /* single column key */
5567 157 : stmt *dels = stmt_tid(be, k->t, 0);
5568 157 : sql_kc *c = k->columns->h->data;
5569 157 : stmt *s = NULL, *h = NULL, *o;
5570 :
5571 : /* s should be empty */
5572 157 : if (!isNew(k)) {
5573 69 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
5574 69 : nu_tids = stmt_project(be, nu_tids, dels);
5575 69 : assert (updates);
5576 :
5577 69 : h = updates[c->c->colnr];
5578 69 : o = stmt_col(be, c->c, nu_tids, nu_tids->partition);
5579 69 : s = stmt_join(be, o, h, 0, cmp_equal, 0, 0, false);
5580 69 : s = stmt_result(be, s, 0);
5581 69 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
5582 : }
5583 :
5584 : /* 2e stage: find out if updated are unique */
5585 69 : if (!h || h->nrcols) { /* update columns not atoms */
5586 157 : sql_subfunc *sum;
5587 157 : stmt *count_sum = NULL;
5588 157 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5589 157 : stmt *ssum, *ss;
5590 157 : stmt *upd;
5591 157 : stmt *g;
5592 :
5593 157 : if (updates) {
5594 70 : upd = updates[c->c->colnr];
5595 : } else {
5596 87 : upd = stmt_col(be, c->c, dels, dels->partition);
5597 : }
5598 :
5599 : /* remove nulls */
5600 157 : if ((k->type == ukey) && stmt_has_null(upd)) {
5601 15 : stmt *nn = stmt_selectnonil(be, upd, NULL);
5602 15 : upd = stmt_project(be, nn, upd);
5603 : }
5604 :
5605 157 : g = stmt_group(be, upd, NULL, NULL, NULL, 1);
5606 157 : ss = stmt_result(be, g, 2); /* use count */
5607 :
5608 : /* (count(ss) <> sum(ss)) */
5609 157 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5610 157 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5611 157 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5612 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);
5613 :
5614 : /* combine results */
5615 157 : if (s)
5616 69 : s = stmt_binop(be, s, count_sum, NULL, or);
5617 : else
5618 : s = count_sum;
5619 : }
5620 :
5621 157 : if (k->type == pkey) {
5622 140 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5623 : } else {
5624 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5625 : }
5626 157 : res = stmt_exception(be, s, msg, 00001);
5627 : }
5628 205 : return res;
5629 : }
5630 :
5631 : /*
5632 : A referential constraint is satisfied if one of the following con-
5633 : ditions is true, depending on the <match option> specified in the
5634 : <referential constraint definition>:
5635 :
5636 : - If no <match type> was specified then, for each row R1 of the
5637 : referencing table, either at least one of the values of the
5638 : referencing columns in R1 shall be a null value, or the value of
5639 : each referencing column in R1 shall be equal to the value of the
5640 : corresponding referenced column in some row of the referenced
5641 : table.
5642 :
5643 : - If MATCH FULL was specified then, for each row R1 of the refer-
5644 : encing table, either the value of every referencing column in R1
5645 : shall be a null value, or the value of every referencing column
5646 : in R1 shall not be null and there shall be some row R2 of the
5647 : referenced table such that the value of each referencing col-
5648 : umn in R1 is equal to the value of the corresponding referenced
5649 : column in R2.
5650 :
5651 : - If MATCH PARTIAL was specified then, for each row R1 of the
5652 : referencing table, there shall be some row R2 of the refer-
5653 : enced table such that the value of each referencing column in
5654 : R1 is either null or is equal to the value of the corresponding
5655 : referenced column in R2.
5656 : */
5657 :
5658 : static stmt *
5659 698 : update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
5660 : {
5661 698 : mvc *sql = be->mvc;
5662 698 : char *msg = NULL;
5663 698 : stmt *s, *cur, *null = NULL, *cntnulls;
5664 698 : sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
5665 698 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5666 698 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5667 698 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5668 698 : node *m;
5669 :
5670 698 : if (!idx_updates)
5671 : return NULL;
5672 : /* releqjoin.count <> updates[updcol].count */
5673 698 : if (pup && list_length(pup->op4.lval)) {
5674 655 : cur = pup->op4.lval->h->data;
5675 43 : } else if (updates) {
5676 43 : cur = updates[updcol];
5677 : } else {
5678 0 : sql_kc *c = k->columns->h->data;
5679 0 : stmt *dels = stmt_tid(be, k->t, 0);
5680 0 : assert(0);
5681 : cur = stmt_col(be, c->c, dels, dels->partition);
5682 : }
5683 698 : s = stmt_binop(be, stmt_aggr(be, idx_updates, NULL, NULL, cnt, 1, 0, 1), stmt_aggr(be, cur, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
5684 :
5685 1419 : for (m = k->columns->h; m; m = m->next) {
5686 721 : sql_kc *c = m->data;
5687 :
5688 : /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
5689 : /* Currently only the default MATCH SIMPLE is supported */
5690 721 : if (c->c->null) {
5691 309 : stmt *upd, *nn;
5692 :
5693 309 : if (updates && updates[c->c->colnr]) {
5694 : upd = updates[c->c->colnr];
5695 : } else { /* created idx/key using alter */
5696 277 : upd = stmt_col(be, c->c, tids, tids->partition);
5697 : }
5698 309 : nn = stmt_selectnil(be, upd);
5699 309 : if (null)
5700 11 : null = stmt_tunion(be, null, nn);
5701 : else
5702 : null = nn;
5703 : }
5704 : }
5705 698 : if (null) {
5706 298 : cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
5707 : } else {
5708 400 : cntnulls = stmt_atom_lng(be, 0);
5709 : }
5710 698 : s = stmt_binop(be, s,
5711 : stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls, NULL, ne), NULL, or);
5712 :
5713 : /* s should be empty */
5714 698 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5715 698 : return stmt_exception(be, s, msg, 00001);
5716 : }
5717 :
5718 : static stmt *
5719 10 : join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
5720 : {
5721 10 : mvc *sql = be->mvc;
5722 10 : sql_trans *tr = sql->session->tr;
5723 10 : char *msg = NULL;
5724 10 : int nulls = 0;
5725 10 : node *m, *o;
5726 10 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5727 10 : stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
5728 10 : stmt *null = NULL, *rows;
5729 10 : sql_subtype *lng = sql_bind_localtype("lng");
5730 10 : sql_subtype *bt = sql_bind_localtype("bit");
5731 10 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5732 10 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5733 10 : list *lje = sa_list(sql->sa);
5734 10 : list *rje = sa_list(sql->sa);
5735 :
5736 10 : fdels = stmt_tid(be, k->idx->t, 0);
5737 10 : rows = stmt_idx(be, k->idx, fdels, fdels->partition);
5738 :
5739 10 : rows = stmt_join(be, rows, tids, 0, cmp_equal, 0, 0, false); /* join over the join index */
5740 10 : rows = stmt_result(be, rows, 0);
5741 :
5742 22 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5743 12 : sql_kc *fc = m->data;
5744 12 : sql_kc *c = o->data;
5745 12 : stmt *upd, *col;
5746 :
5747 12 : if (updates[c->c->colnr]) {
5748 : upd = updates[c->c->colnr];
5749 : } else {
5750 2 : upd = stmt_project(be, tids, stmt_col(be, c->c, dels, dels->partition));
5751 : }
5752 12 : if (c->c->null) { /* new nulls (MATCH SIMPLE) */
5753 3 : stmt *nn = stmt_selectnil(be, upd);
5754 3 : if (null)
5755 1 : null = stmt_tunion(be, null, nn);
5756 : else
5757 : null = nn;
5758 : nulls = 1;
5759 : }
5760 12 : col = stmt_col(be, fc->c, rows, rows->partition);
5761 12 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5762 0 : return NULL;
5763 12 : list_append(lje, upd);
5764 12 : list_append(rje, col);
5765 : }
5766 10 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
5767 10 : s = stmt_result(be, s, 0);
5768 :
5769 : /* add missing nulls */
5770 10 : cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5771 10 : if (nulls) {
5772 2 : sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
5773 2 : cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), NULL, add);
5774 : }
5775 :
5776 : /* releqjoin.count <> updates[updcol].count */
5777 10 : s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
5778 :
5779 : /* s should be empty */
5780 10 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5781 10 : return stmt_exception(be, s, msg, 00001);
5782 : }
5783 :
5784 : static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
5785 :
5786 : static stmt*
5787 11 : sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
5788 : {
5789 11 : mvc *sql = be->mvc;
5790 11 : sql_trans *tr = sql->session->tr;
5791 11 : list *l = NULL;
5792 11 : int len = 0;
5793 11 : node *m, *o;
5794 11 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5795 11 : stmt **new_updates;
5796 11 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
5797 :
5798 11 : new_updates = table_update_stmts(sql, t, &len);
5799 24 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5800 13 : sql_kc *fc = m->data;
5801 13 : stmt *upd = NULL;
5802 :
5803 13 : if (action == ACT_SET_DEFAULT) {
5804 4 : if (fc->c->def) {
5805 4 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
5806 4 : if (!sq)
5807 : return NULL;
5808 : upd = sq;
5809 : } else {
5810 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5811 : }
5812 : } else {
5813 9 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5814 : }
5815 :
5816 13 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5817 0 : return NULL;
5818 :
5819 13 : if (upd->nrcols <= 0)
5820 13 : upd = stmt_const(be, ftids, upd);
5821 :
5822 13 : new_updates[fc->c->colnr] = upd;
5823 : }
5824 11 : if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
5825 : return NULL;
5826 11 : return stmt_list(be, l);
5827 : }
5828 :
5829 : static stmt*
5830 32 : sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
5831 : {
5832 32 : mvc *sql = be->mvc;
5833 32 : sql_trans *tr = sql->session->tr;
5834 32 : list *l = NULL;
5835 32 : int len = 0;
5836 32 : node *m, *o;
5837 32 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
5838 32 : stmt **new_updates;
5839 32 : stmt *rows;
5840 32 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
5841 32 : stmt *ftids, *upd_ids;
5842 :
5843 32 : ftids = stmt_tid(be, k->idx->t, 0);
5844 32 : rows = stmt_idx(be, k->idx, ftids, ftids->partition);
5845 :
5846 32 : rows = stmt_join(be, rows, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
5847 32 : upd_ids = stmt_result(be, rows, 1);
5848 32 : rows = stmt_result(be, rows, 0);
5849 32 : rows = stmt_project(be, rows, ftids);
5850 :
5851 32 : new_updates = table_update_stmts(sql, t, &len);
5852 64 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
5853 32 : sql_kc *fc = m->data;
5854 32 : sql_kc *c = o->data;
5855 32 : stmt *upd = NULL;
5856 :
5857 32 : if (!updates[c->c->colnr]) {
5858 0 : continue;
5859 32 : } else if (action == ACT_CASCADE) {
5860 : upd = updates[c->c->colnr];
5861 16 : } else if (action == ACT_SET_DEFAULT) {
5862 6 : if (fc->c->def) {
5863 6 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
5864 6 : if (!sq)
5865 : return NULL;
5866 : upd = sq;
5867 : } else {
5868 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5869 : }
5870 10 : } else if (action == ACT_SET_NULL) {
5871 10 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
5872 : }
5873 :
5874 32 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
5875 0 : return NULL;
5876 :
5877 32 : if (upd->nrcols <= 0)
5878 16 : upd = stmt_const(be, upd_ids, upd);
5879 : else
5880 16 : upd = stmt_project(be, upd_ids, upd);
5881 :
5882 32 : new_updates[fc->c->colnr] = upd;
5883 : }
5884 :
5885 32 : if ((l = sql_update(be, t, rows, new_updates)) == NULL)
5886 : return NULL;
5887 32 : return stmt_list(be, l);
5888 : }
5889 :
5890 : static int
5891 81 : cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
5892 : {
5893 : /* now iterate over all keys */
5894 81 : sql_trans *tr = be->mvc->session->tr;
5895 81 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
5896 81 : if (keys) {
5897 131 : for (node *n = keys->h; n; n = n->next->next) {
5898 50 : sqlid fkey_id = *(sqlid*)n->data;
5899 50 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
5900 50 : sql_key *fk = (sql_key*)b;
5901 50 : sql_fkey *rk = (sql_fkey*)b;
5902 :
5903 50 : if (fk->type != fkey || rk->rkey != k->base.id)
5904 0 : continue;
5905 :
5906 : /* All rows of the foreign key table which are
5907 : affected by the primary key update should all
5908 : match one of the updated primary keys again.
5909 : */
5910 50 : switch (((sql_fkey*)fk)->on_update) {
5911 : case ACT_NO_ACTION:
5912 : break;
5913 32 : case ACT_SET_NULL:
5914 : case ACT_SET_DEFAULT:
5915 : case ACT_CASCADE:
5916 32 : if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update)) {
5917 0 : list_destroy(keys);
5918 0 : return -1;
5919 : }
5920 : break;
5921 10 : default: /*RESTRICT*/
5922 10 : if (!join_updated_pkey(be, fk, tids, updates)) {
5923 0 : list_destroy(keys);
5924 0 : return -1;
5925 : }
5926 : }
5927 : }
5928 81 : list_destroy(keys);
5929 : }
5930 : return 0;
5931 : }
5932 :
5933 : static void
5934 903 : sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
5935 : {
5936 903 : stmt *ckeys;
5937 :
5938 903 : if (k->type == pkey || k->type == ukey) {
5939 205 : ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
5940 : } else { /* foreign keys */
5941 698 : ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
5942 : }
5943 903 : list_append(l, ckeys);
5944 903 : }
5945 :
5946 : static stmt *
5947 20 : hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
5948 : {
5949 20 : mvc *sql = be->mvc;
5950 : /* calculate new value */
5951 20 : node *m;
5952 20 : sql_subtype *it, *lng;
5953 20 : int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
5954 20 : stmt *h = NULL, *tids;
5955 :
5956 20 : if (list_length(i->columns) <= 1)
5957 : return NULL;
5958 :
5959 0 : tids = stmt_tid(be, i->t, 0);
5960 0 : it = sql_bind_localtype("int");
5961 0 : lng = sql_bind_localtype("lng");
5962 0 : for (m = i->columns->h; m; m = m->next) {
5963 0 : sql_kc *c = m->data;
5964 0 : stmt *upd;
5965 :
5966 0 : if (updates && updates[c->c->colnr]) {
5967 : upd = updates[c->c->colnr];
5968 0 : } else if (updates && updcol >= 0) {
5969 0 : assert(0);
5970 : upd = stmt_col(be, c->c, rows, rows->partition);
5971 : } else { /* created idx/key using alter */
5972 0 : upd = stmt_col(be, c->c, tids, tids->partition);
5973 : }
5974 :
5975 0 : if (h && i->type == hash_idx) {
5976 0 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, &c->c->type);
5977 :
5978 0 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(
5979 : list_append(sa_list(sql->sa), h),
5980 0 : stmt_atom_int(be, bits)), upd)), NULL,
5981 : xor, NULL);
5982 0 : } else if (h) {
5983 0 : stmt *h2;
5984 0 : sql_subfunc *lsh = sql_bind_func_result(sql, "sys", "left_shift", F_FUNC, true, lng, 2, lng, it);
5985 0 : sql_subfunc *lor = sql_bind_func_result(sql, "sys", "bit_or", F_FUNC, true, lng, 2, lng, lng);
5986 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
5987 :
5988 0 : h = stmt_binop(be, h, stmt_atom_int(be, bits), NULL, lsh);
5989 0 : h2 = stmt_unop(be, upd, NULL, hf);
5990 0 : h = stmt_binop(be, h, h2, NULL, lor);
5991 : } else {
5992 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
5993 0 : h = stmt_unop(be, upd, NULL, hf);
5994 0 : if (i->type == oph_idx)
5995 : break;
5996 : }
5997 : }
5998 : return h;
5999 : }
6000 :
6001 : static stmt *
6002 43 : join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
6003 : {
6004 43 : mvc *sql = be->mvc;
6005 43 : sql_trans *tr = sql->session->tr;
6006 43 : node *m, *o;
6007 43 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)i->key)->rkey);
6008 43 : stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
6009 43 : list *lje = sa_list(sql->sa);
6010 43 : list *rje = sa_list(sql->sa);
6011 :
6012 88 : for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
6013 45 : sql_kc *c = m->data;
6014 45 : sql_kc *rc = o->data;
6015 45 : stmt *upd;
6016 :
6017 45 : if (updates && updates[c->c->colnr]) {
6018 : upd = updates[c->c->colnr];
6019 0 : } else if (updates && updcol >= 0) {
6020 0 : assert(0);
6021 : upd = stmt_col(be, c->c, ftids, ftids->partition);
6022 : } else { /* created idx/key using alter */
6023 0 : upd = stmt_col(be, c->c, ftids, ftids->partition);
6024 : }
6025 :
6026 45 : if (!upd || (upd = check_types(be, &rc->c->type, upd, type_equal)) == NULL)
6027 0 : return NULL;
6028 45 : list_append(lje, upd);
6029 45 : list_append(rje, stmt_col(be, rc->c, ptids, ptids->partition));
6030 : }
6031 43 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 0);
6032 43 : l = stmt_result(be, s, 0);
6033 43 : r = stmt_result(be, s, 1);
6034 43 : r = stmt_project(be, r, ptids);
6035 43 : return stmt_left_project(be, ftids, l, r);
6036 : }
6037 :
6038 : static int
6039 4069 : cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
6040 : {
6041 4069 : mvc *sql = be->mvc;
6042 4069 : node *n;
6043 :
6044 4069 : if (!ol_length(t->idxs))
6045 : return 0;
6046 :
6047 2541 : for (n = ol_first_node(t->idxs); n; n = n->next) {
6048 1308 : sql_idx *i = n->data;
6049 :
6050 : /* check if update is needed,
6051 : * ie at least on of the idx columns is updated
6052 : */
6053 1308 : if (is_idx_updated(i, updates) == 0)
6054 1165 : continue;
6055 :
6056 143 : if (i->key) {
6057 140 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
6058 140 : sql_key *k = i->key;
6059 140 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
6060 140 : if (!sql->cascade_action)
6061 65 : sql->cascade_action = sa_list(sql->sa);
6062 140 : *local_id = i->key->base.id;
6063 140 : list_append(sql->cascade_action, local_id);
6064 140 : if (k->type == pkey || k->type == ukey) {
6065 81 : if (cascade_ukey(be, updates, k, rows))
6066 : return -1;
6067 : }
6068 : }
6069 : }
6070 : }
6071 : return 0;
6072 : }
6073 :
6074 : static list *
6075 43 : update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
6076 : {
6077 43 : mvc *sql = be->mvc;
6078 43 : node *n;
6079 43 : int updcol;
6080 43 : list *idx_updates = sa_list(sql->sa);
6081 :
6082 43 : if (!ol_length(t->idxs))
6083 : return idx_updates;
6084 :
6085 43 : updcol = first_updated_col(updates, ol_length(t->columns));
6086 106 : for (n = ol_first_node(t->idxs); n; n = n->next) {
6087 63 : sql_idx *i = n->data;
6088 63 : stmt *is = NULL;
6089 :
6090 : /* check if update is needed,
6091 : * ie at least on of the idx columns is updated
6092 : */
6093 63 : if (is_idx_updated(i, updates) == 0)
6094 0 : continue;
6095 :
6096 63 : if (hash_index(i->type)) {
6097 20 : is = hash_update(be, i, rows, updates, updcol);
6098 43 : } else if (i->type == join_idx) {
6099 43 : if (updcol < 0)
6100 : return NULL;
6101 43 : if (!(is = join_idx_update(be, i, rows, updates, updcol)))
6102 : return NULL;
6103 : }
6104 63 : if (i->key)
6105 63 : sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
6106 63 : if (is)
6107 43 : list_append(idx_updates, stmt_update_idx(be, i, rows, is));
6108 : }
6109 : return idx_updates;
6110 : }
6111 :
6112 : static int
6113 260 : sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
6114 : {
6115 : /* Put single relation of updates and old values on to the stack */
6116 260 : sql_rel *r = NULL;
6117 260 : node *n;
6118 260 : list *exps = sa_list(sql->sa);
6119 260 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
6120 :
6121 260 : ti->t = t;
6122 260 : ti->tids = tids;
6123 260 : ti->updates = updates;
6124 260 : ti->type = 2;
6125 260 : ti->on = on;
6126 260 : ti->nn = nn;
6127 1453 : for (n = ol_first_node(t->columns); n; n = n->next) {
6128 1193 : sql_column *c = n->data;
6129 :
6130 1193 : if (updates[c->colnr]) {
6131 260 : sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6132 260 : sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6133 260 : oe->alias.label = -(sql->nid++);
6134 260 : ne->alias.label = -(sql->nid++);
6135 :
6136 260 : append(exps, oe);
6137 260 : append(exps, ne);
6138 : } else {
6139 933 : sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6140 933 : sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6141 933 : oe->alias.label = -(sql->nid++);
6142 933 : ne->alias.label = -(sql->nid++);
6143 :
6144 933 : append(exps, oe);
6145 933 : append(exps, ne);
6146 : }
6147 : }
6148 260 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
6149 260 : r->l = ti;
6150 :
6151 : /* put single table into the stack with 2 names, needed for the psm code */
6152 260 : if (!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
6153 0 : return 0;
6154 : return 1;
6155 : }
6156 :
6157 : static int
6158 8138 : sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time)
6159 : {
6160 8138 : mvc *sql = be->mvc;
6161 8138 : node *n;
6162 8138 : int res = 1;
6163 :
6164 8138 : if (!ol_length(t->triggers))
6165 : return res;
6166 :
6167 1012 : for (n = ol_first_node(t->triggers); n; n = n->next) {
6168 540 : sql_trigger *trigger = n->data;
6169 :
6170 540 : if (!stack_push_frame(sql, "%OLD-NEW"))
6171 : return 0;
6172 540 : if (trigger->event == 2 && trigger->time == time) {
6173 : /* add name for the 'inserted' to the stack */
6174 260 : const char *n = trigger->new_name;
6175 260 : const char *o = trigger->old_name;
6176 :
6177 260 : if (!n) n = "new";
6178 260 : if (!o) o = "old";
6179 :
6180 260 : if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
6181 0 : stack_pop_frame(sql);
6182 0 : return 0;
6183 : }
6184 :
6185 260 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
6186 0 : stack_pop_frame(sql);
6187 0 : return 0;
6188 : }
6189 : }
6190 540 : stack_pop_frame(sql);
6191 : }
6192 : return res;
6193 : }
6194 :
6195 : static void
6196 25 : sql_update_check(backend *be, stmt **updates, sql_key *key, stmt *u_tids)
6197 : {
6198 25 : mvc *sql = be->mvc;
6199 25 : int pos = 0;
6200 25 : sql_rel *rel = rel_basetable(sql, key->t, key->t->base.name);
6201 25 : sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
6202 25 : rel->exps = rel_base_projection(sql, rel, 0);
6203 :
6204 : /* create sub stmt with needed updates (or projected col from to be updated table) */
6205 25 : list *ups = sa_list(sql->sa);
6206 55 : for(node *n = key->columns->h; n; n = n->next) {
6207 30 : sql_kc *kc = n->data;
6208 30 : stmt *upd = NULL;
6209 :
6210 30 : if (updates && updates[kc->c->colnr]) {
6211 : upd = updates[kc->c->colnr];
6212 : } else {
6213 17 : upd = stmt_col(be, kc->c, u_tids, u_tids->partition);
6214 : }
6215 30 : sql_exp *e = rel_base_bind_column2(sql, rel, kc->c->t->base.name, kc->c->base.name);
6216 30 : upd = stmt_alias(be, upd, e->alias.label, kc->c->t->base.name, kc->c->base.name);
6217 30 : append(ups, upd);
6218 : }
6219 :
6220 25 : stmt *sub = stmt_list(be, ups);
6221 25 : stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
6222 :
6223 25 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6224 25 : s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
6225 25 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6226 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);
6227 25 : (void)stmt_exception(be, s, msg, 00001);
6228 25 : }
6229 :
6230 : static void
6231 4069 : sql_update_check_null(backend *be, sql_table *t, stmt **updates)
6232 : {
6233 4069 : mvc *sql = be->mvc;
6234 4069 : node *n;
6235 4069 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6236 :
6237 47776 : for (n = ol_first_node(t->columns); n; n = n->next) {
6238 43707 : sql_column *c = n->data;
6239 :
6240 43707 : if (updates[c->colnr] && !c->null) {
6241 129 : stmt *s = updates[c->colnr];
6242 129 : char *msg = NULL;
6243 :
6244 129 : if (!(s->key && s->nrcols == 0)) {
6245 129 : s = stmt_selectnil(be, updates[c->colnr]);
6246 129 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6247 : } else {
6248 0 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
6249 :
6250 0 : s = stmt_unop(be, updates[c->colnr], NULL, isnil);
6251 : }
6252 129 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
6253 129 : (void)stmt_exception(be, s, msg, 00001);
6254 : }
6255 : }
6256 4069 : }
6257 :
6258 : /* updates: an array of table width, per column holds the values for the to be updated rows */
6259 : static list *
6260 43 : sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
6261 : {
6262 43 : mvc *sql = be->mvc;
6263 43 : list *idx_updates = NULL;
6264 43 : int i, nr_cols = ol_length(t->columns);
6265 43 : list *l = sa_list(sql->sa);
6266 43 : node *n;
6267 43 : stmt *cnt = NULL;
6268 :
6269 43 : sql_update_check_null(be, t, updates);
6270 :
6271 : /* check keys + get idx */
6272 43 : idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
6273 43 : if (!idx_updates) {
6274 0 : assert(0);
6275 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
6276 : }
6277 :
6278 : /* before */
6279 43 : if (!sql_update_triggers(be, t, rows, updates, 0))
6280 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6281 :
6282 : /* apply updates */
6283 131 : for (i = 0, n = ol_first_node(t->columns); i < nr_cols && n; i++, n = n->next) {
6284 88 : sql_column *c = n->data;
6285 :
6286 88 : if (updates[i])
6287 45 : append(l, stmt_update_col(be, c, rows, updates[i]));
6288 : }
6289 43 : if (cascade_updates(be, t, rows, updates))
6290 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
6291 :
6292 : /* after */
6293 43 : if (!sql_update_triggers(be, t, rows, updates, 1))
6294 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6295 :
6296 43 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
6297 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);
6298 43 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
6299 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6300 43 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6301 43 : stmt_add_dependency_change(be, t, cnt);
6302 : /* cascade ?? */
6303 : return l;
6304 : }
6305 :
6306 : /* updates with empty list is alter with create idx or keys */
6307 : static stmt *
6308 4167 : rel2bin_update(backend *be, sql_rel *rel, list *refs)
6309 : {
6310 4167 : mvc *sql = be->mvc;
6311 4167 : stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL, *cnt;
6312 4167 : list *l = sa_list(sql->sa);
6313 4167 : int nr_cols, updcol, idx_ups = 0;
6314 4167 : node *m;
6315 4167 : sql_rel *tr = rel->l, *prel = rel->r;
6316 4167 : sql_table *t = NULL;
6317 :
6318 4167 : if ((rel->flag&UPD_COMP)) { /* special case ! */
6319 1164 : idx_ups = 1;
6320 1164 : prel = rel->l;
6321 1164 : rel = rel->r;
6322 1164 : tr = rel->l;
6323 : }
6324 4167 : if (tr->op == op_basetable) {
6325 2823 : t = tr->l;
6326 : } else {
6327 1344 : ddl = subrel_bin(be, tr, refs);
6328 1344 : ddl = subrel_project(be, ddl, refs, NULL);
6329 1344 : if (!ddl)
6330 : return NULL;
6331 1344 : t = rel_ddl_table_get(tr);
6332 :
6333 : /* no columns to update (probably an new pkey or ckey!) */
6334 1344 : if (!rel->exps) {
6335 141 : stmt *tids = stmt_tid(be, t, 0);
6336 154 : for (m = ol_first_node(t->keys); m; m = m->next) {
6337 13 : sql_key * key = m->data;
6338 13 : if (key->type == ckey && key->base.new)
6339 13 : sql_update_check(be, NULL, key, tids);
6340 : }
6341 : return ddl;
6342 : }
6343 : }
6344 :
6345 4026 : if (rel->r) /* first construct the update relation */
6346 4026 : update = subrel_bin(be, rel->r, refs);
6347 4026 : update = subrel_project(be, update, refs, rel->r);
6348 :
6349 4026 : if (!update)
6350 : return NULL;
6351 :
6352 4026 : if (idx_ups)
6353 1164 : pup = refs_find_rel(refs, prel);
6354 :
6355 4026 : updates = table_update_stmts(sql, t, &nr_cols);
6356 4026 : tids = update->op4.lval->h->data;
6357 :
6358 : /* lookup the updates */
6359 11001 : for (m = rel->exps->h; m; m = m->next) {
6360 6975 : sql_exp *ce = m->data;
6361 6975 : sql_column *c = find_sql_column(t, exp_name(ce));
6362 :
6363 6975 : if (c)
6364 2974 : updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
6365 : }
6366 :
6367 4931 : for (m = ol_first_node(t->keys); m; m = m->next) {
6368 905 : sql_key * key = m->data;
6369 905 : if (key->type == ckey && is_check_updated(key, updates))
6370 12 : sql_update_check(be, updates, key, tids);
6371 : }
6372 4026 : sql_update_check_null(be, t, updates);
6373 :
6374 : /* check keys + get idx */
6375 4026 : updcol = first_updated_col(updates, ol_length(t->columns));
6376 11001 : for (m = rel->exps->h; m; m = m->next) {
6377 6975 : sql_exp *ce = m->data;
6378 6975 : sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
6379 6975 : stmt *update_idx, *is = NULL;
6380 :
6381 6975 : if (i) {
6382 1178 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6383 148 : continue;
6384 :
6385 1030 : update_idx = bin_find_column(be, update, ce->l, ce->r);
6386 1030 : if (update_idx)
6387 : is = update_idx;
6388 1030 : if (hash_index(i->type) && list_length(i->columns) <= 1) {
6389 1030 : is = NULL;
6390 1030 : update_idx = NULL;
6391 : }
6392 1030 : if (i->key)
6393 1603 : sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
6394 1030 : if (is)
6395 780 : list_append(l, stmt_update_idx(be, i, tids, is));
6396 : }
6397 : }
6398 :
6399 : /* before */
6400 4026 : if (!sql_update_triggers(be, t, tids, updates, 0)) {
6401 0 : if (sql->cascade_action)
6402 0 : sql->cascade_action = NULL;
6403 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6404 : }
6405 :
6406 : /* apply the update */
6407 11001 : for (m = rel->exps->h; m; m = m->next) {
6408 6975 : sql_exp *ce = m->data;
6409 6975 : sql_column *c = find_sql_column(t, exp_name(ce));
6410 :
6411 6975 : if (c)
6412 2974 : append(l, stmt_update_col(be, c, tids, updates[c->colnr]));
6413 : }
6414 :
6415 4026 : stmt* returning = NULL;
6416 4026 : if (rel->returning) {
6417 5 : sql_rel* b = rel->l;
6418 5 : int refcnt = b->ref.refcnt; // HACK: forces recalculation of base columns since they are assumed to be updated
6419 5 : b->ref.refcnt = 1;
6420 5 : returning = subrel_bin(be, b, refs);
6421 5 : b->ref.refcnt = refcnt;
6422 5 : returning->cand = tids;
6423 5 : returning = subrel_project(be, returning, refs, b);
6424 5 : sql->type = Q_TABLE;
6425 : }
6426 :
6427 4026 : if (cascade_updates(be, t, tids, updates)) {
6428 0 : if (sql->cascade_action)
6429 0 : sql->cascade_action = NULL;
6430 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
6431 : }
6432 :
6433 : /* after */
6434 4026 : if (!sql_update_triggers(be, t, tids, updates, 1)) {
6435 0 : if (sql->cascade_action)
6436 0 : sql->cascade_action = NULL;
6437 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
6438 : }
6439 :
6440 4026 : if (ddl) {
6441 1203 : list_prepend(l, ddl);
6442 1203 : cnt = stmt_list(be, l);
6443 : } else {
6444 2823 : 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);
6445 2823 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
6446 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6447 2823 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6448 2819 : stmt_add_dependency_change(be, t, cnt);
6449 : }
6450 :
6451 4026 : if (sql->cascade_action)
6452 65 : sql->cascade_action = NULL;
6453 4026 : if (rel->r && !rel_predicates(be, rel->r))
6454 : return NULL;
6455 4026 : return returning?returning:cnt;
6456 : }
6457 :
6458 : static int
6459 20 : sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, stmt **deleted_cols, int type)
6460 : {
6461 : /* Put single relation of updates and old values on to the stack */
6462 20 : sql_rel *r = NULL;
6463 20 : node *n;
6464 20 : list *exps = sa_list(sql->sa);
6465 20 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
6466 :
6467 20 : ti->t = t;
6468 20 : ti->tids = tids;
6469 20 : ti->updates = deleted_cols;
6470 20 : ti->type = type;
6471 20 : ti->nn = name;
6472 56 : for (n = ol_first_node(t->columns); n; n = n->next) {
6473 36 : sql_column *c = n->data;
6474 36 : sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
6475 36 : ne->alias.label = -(sql->nid++);
6476 :
6477 36 : append(exps, ne);
6478 : }
6479 20 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
6480 20 : r->l = ti;
6481 :
6482 20 : return stack_push_rel_view(sql, name, r) ? 1 : 0;
6483 : }
6484 :
6485 : static int
6486 83907 : sql_delete_triggers(backend *be, sql_table *t, stmt *tids, stmt **deleted_cols, int time, int firing_type, int internal_type)
6487 : {
6488 83907 : mvc *sql = be->mvc;
6489 83907 : node *n;
6490 83907 : int res = 1;
6491 :
6492 83907 : if (!ol_length(t->triggers))
6493 : return res;
6494 :
6495 188 : for (n = ol_first_node(t->triggers); n; n = n->next) {
6496 142 : sql_trigger *trigger = n->data;
6497 :
6498 142 : if (!stack_push_frame(sql, "%OLD-NEW"))
6499 : return 0;
6500 142 : if (trigger->event == firing_type && trigger->time == time) {
6501 : /* add name for the 'deleted' to the stack */
6502 20 : const char *o = trigger->old_name;
6503 :
6504 20 : if (!o) o = "old";
6505 :
6506 20 : if(!sql_stack_add_deleted(sql, o, t, tids, deleted_cols, internal_type)) {
6507 0 : stack_pop_frame(sql);
6508 0 : return 0;
6509 : }
6510 :
6511 20 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
6512 0 : stack_pop_frame(sql);
6513 0 : return 0;
6514 : }
6515 : }
6516 142 : stack_pop_frame(sql);
6517 : }
6518 : return res;
6519 : }
6520 :
6521 : static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
6522 :
6523 : static stmt *
6524 9 : sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
6525 : {
6526 9 : sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
6527 9 : return sql_delete(be, t, ftids);
6528 : }
6529 :
6530 : static void
6531 130 : sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
6532 : {
6533 130 : mvc *sql = be->mvc;
6534 130 : sql_subtype *lng = sql_bind_localtype("lng");
6535 130 : sql_subtype *bt = sql_bind_localtype("bit");
6536 130 : sql_trans *tr = be->mvc->session->tr;
6537 130 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
6538 :
6539 130 : if (keys) {
6540 190 : for (node *n = keys->h; n; n = n->next->next) {
6541 60 : sqlid fkey_id = *(sqlid*)n->data;
6542 60 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
6543 60 : sql_key *fk = (sql_key*)b;
6544 60 : sql_fkey *rk = (sql_fkey*)b;
6545 :
6546 60 : if (fk->type != fkey || rk->rkey != k->base.id)
6547 0 : continue;
6548 60 : char *msg = NULL;
6549 60 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6550 60 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
6551 60 : stmt *s, *tids;
6552 :
6553 60 : tids = stmt_tid(be, fk->idx->t, 0);
6554 60 : s = stmt_idx(be, fk->idx, tids, tids->partition);
6555 60 : s = stmt_join(be, s, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
6556 60 : s = stmt_result(be, s, 0);
6557 60 : tids = stmt_project(be, s, tids);
6558 60 : if(cascade) { /* for truncate statements with the cascade option */
6559 1 : s = sql_delete_cascade_Fkeys(be, fk, tids);
6560 1 : list_prepend(l, s);
6561 : } else {
6562 59 : switch (((sql_fkey*)fk)->on_delete) {
6563 : case ACT_NO_ACTION:
6564 : break;
6565 11 : case ACT_SET_NULL:
6566 : case ACT_SET_DEFAULT:
6567 11 : s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
6568 11 : list_prepend(l, s);
6569 11 : break;
6570 8 : case ACT_CASCADE:
6571 8 : s = sql_delete_cascade_Fkeys(be, fk, tids);
6572 8 : list_prepend(l, s);
6573 8 : break;
6574 38 : default: /*RESTRICT*/
6575 : /* The overlap between deleted primaries and foreign should be empty */
6576 38 : s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
6577 38 : msg = sa_message(sql->sa, SQLSTATE(40002) "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
6578 38 : s = stmt_exception(be, s, msg, 00001);
6579 38 : list_prepend(l, s);
6580 : }
6581 : }
6582 : }
6583 130 : list_destroy(keys);
6584 : }
6585 130 : }
6586 :
6587 : static int
6588 41881 : sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
6589 : {
6590 41881 : mvc *sql = be->mvc;
6591 41881 : int res = 1;
6592 41881 : node *n;
6593 :
6594 41881 : if (!ol_length(t->keys))
6595 : return res;
6596 :
6597 304 : for (n = ol_first_node(t->keys); n; n = n->next) {
6598 173 : sql_key *k = n->data;
6599 :
6600 173 : if (k->type == pkey || k->type == ukey) {
6601 131 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
6602 130 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
6603 130 : if (!sql->cascade_action)
6604 120 : sql->cascade_action = sa_list(sql->sa);
6605 :
6606 130 : *local_id = k->base.id;
6607 130 : list_append(sql->cascade_action, local_id);
6608 130 : sql_delete_ukey(be, rows, k, l, which, cascade);
6609 : }
6610 : }
6611 : }
6612 : return res;
6613 : }
6614 :
6615 : static stmt *
6616 491 : sql_delete(backend *be, sql_table *t, stmt *rows)
6617 : {
6618 491 : mvc *sql = be->mvc;
6619 491 : stmt *v = NULL, *s = NULL;
6620 491 : list *l = sa_list(sql->sa);
6621 491 : stmt **deleted_cols = NULL;
6622 :
6623 491 : if (rows) {
6624 : v = rows;
6625 : } else { /* delete all */
6626 128 : v = stmt_tid(be, t, 0);
6627 : }
6628 :
6629 : /* project all columns */
6630 491 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
6631 38 : int nr = 0;
6632 38 : deleted_cols = table_update_stmts(sql, t, &nr);
6633 38 : int i = 0;
6634 105 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
6635 67 : sql_column *c = n->data;
6636 67 : stmt *s = stmt_col(be, c, v, v->partition);
6637 :
6638 67 : deleted_cols[i] = s;
6639 67 : list_append(l, s);
6640 : }
6641 : }
6642 :
6643 : /* before */
6644 491 : if (!sql_delete_triggers(be, t, v, deleted_cols, 0, 1, 3))
6645 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
6646 :
6647 491 : if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
6648 0 : return sql_error(sql, 10, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
6649 :
6650 491 : if (rows) {
6651 363 : s = stmt_delete(be, t, rows);
6652 363 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
6653 362 : 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);
6654 : } else { /* delete all */
6655 128 : s = stmt_table_clear(be, t, 0); /* first column */
6656 : }
6657 :
6658 : /* after */
6659 491 : if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
6660 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
6661 :
6662 491 : if (add_to_rowcount_accumulator(be, s->nr) < 0)
6663 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6664 491 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6665 489 : stmt_add_dependency_change(be, t, s);
6666 : return s;
6667 : }
6668 :
6669 : static stmt *
6670 482 : rel2bin_delete(backend *be, sql_rel *rel, list *refs)
6671 : {
6672 482 : mvc *sql = be->mvc;
6673 482 : stmt *stdelete = NULL, *tids = NULL, *returning = NULL;
6674 482 : sql_rel *tr = rel->l;
6675 482 : sql_table *t = NULL;
6676 :
6677 482 : if (tr->op == op_basetable)
6678 482 : t = tr->l;
6679 : else
6680 0 : assert(0/*ddl statement*/);
6681 :
6682 482 : if (rel->r) { /* first construct the deletes relation */
6683 354 : stmt *rows = subrel_bin(be, rel->r, refs);
6684 354 : rows = subrel_project(be, rows, refs, rel->r);
6685 354 : if (!rows)
6686 : return NULL;
6687 354 : assert(rows->type == st_list);
6688 354 : tids = rows->op4.lval->h->data; /* TODO this should be the candidate list instead */
6689 : }
6690 :
6691 482 : if (rel->returning) {
6692 4 : returning = subrel_bin(be, rel->l, refs);
6693 4 : returning->cand = tids;
6694 4 : returning = subrel_project(be, returning, refs, rel->l);
6695 4 : sql->type = Q_TABLE;
6696 : }
6697 :
6698 482 : stdelete = sql_delete(be, t, tids);
6699 482 : if (sql->cascade_action)
6700 107 : sql->cascade_action = NULL;
6701 482 : if (!stdelete)
6702 : return NULL;
6703 :
6704 482 : if (rel->r && !rel_predicates(be, rel->r))
6705 : return NULL;
6706 482 : return returning?returning:stdelete;
6707 : }
6708 :
6709 : struct tablelist {
6710 : sql_table *table;
6711 : struct tablelist* next;
6712 : };
6713 :
6714 : static sql_table * /* inspect the other tables recursively for foreign key dependencies */
6715 41669 : check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct tablelist* next_append, sql_table *t, int cascade)
6716 : {
6717 41669 : struct tablelist* new_node;
6718 41669 : sql_trans *tr = sql->session->tr;
6719 41669 : sqlstore *store = sql->session->tr->store;
6720 :
6721 41669 : if (mvc_highwater(sql))
6722 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
6723 :
6724 41690 : if (t->keys) { /* Check for foreign key references */
6725 41708 : for (node *n = ol_first_node(t->keys); n; n = n->next) {
6726 61 : sql_key *k = n->data;
6727 :
6728 61 : if (k->type == ukey || k->type == pkey) {
6729 17 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
6730 :
6731 0 : if (keys) {
6732 21 : for (node *nn = keys->h; nn; nn = nn->next->next) {
6733 6 : sqlid fkey_id = *(sqlid*)nn->data;
6734 6 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
6735 6 : sql_key *fk = (sql_key*)b;
6736 6 : sql_fkey *rk = (sql_fkey*)b;
6737 :
6738 6 : if (fk->type != fkey || rk->rkey != k->base.id)
6739 1 : continue;
6740 5 : k = fk;
6741 : /* make sure it is not a self referencing key */
6742 5 : if (k->t != t && !cascade && isTable(t)) {
6743 4 : node *nnn = ol_first_node(t->columns);
6744 4 : sql_column *c = nnn->data;
6745 4 : size_t n_rows = store->storage_api.count_col(sql->session->tr, c, 10);
6746 4 : if (n_rows > 0) {
6747 2 : list_destroy(keys);
6748 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);
6749 : }
6750 1 : } else if (k->t != t) {
6751 : int found = 0;
6752 2 : for (struct tablelist *node_check = tlist; node_check; node_check = node_check->next) {
6753 1 : if (node_check->table == k->t)
6754 0 : found = 1;
6755 : }
6756 1 : if (!found) {
6757 2 : if ((new_node = SA_NEW(sql->ta, struct tablelist)) == NULL) {
6758 0 : list_destroy(keys);
6759 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6760 : }
6761 1 : new_node->table = k->t;
6762 1 : new_node->next = NULL;
6763 1 : next_append->next = new_node;
6764 1 : if (!check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade)) {
6765 0 : list_destroy(keys);
6766 0 : return NULL;
6767 : }
6768 : }
6769 : }
6770 : }
6771 15 : list_destroy(keys);
6772 : }
6773 : }
6774 : }
6775 : }
6776 : return t;
6777 : }
6778 :
6779 : static stmt *
6780 41658 : sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
6781 : {
6782 41658 : mvc *sql = be->mvc;
6783 41658 : list *l = sa_list(sql->sa);
6784 41661 : stmt *ret = NULL, *other = NULL;
6785 41661 : struct tablelist *new_list = SA_NEW(sql->ta, struct tablelist);
6786 41689 : stmt **deleted_cols = NULL;
6787 :
6788 41689 : if (!new_list)
6789 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6790 41689 : new_list->table = t;
6791 41689 : new_list->next = NULL;
6792 41689 : if (!check_for_foreign_key_references(sql, new_list, new_list, t, cascade))
6793 2 : goto finalize;
6794 :
6795 83298 : for (struct tablelist *list_node = new_list; list_node; list_node = list_node->next) {
6796 41602 : sql_table *next = list_node->table;
6797 41602 : stmt *v = stmt_tid(be, next, 0);
6798 :
6799 : /* project all columns */
6800 41620 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
6801 18 : int nr = 0;
6802 18 : deleted_cols = table_update_stmts(sql, t, &nr);
6803 18 : int i = 0;
6804 50 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
6805 32 : sql_column *c = n->data;
6806 32 : stmt *s = stmt_col(be, c, v, v->partition);
6807 :
6808 32 : deleted_cols[i] = s;
6809 32 : list_append(l, s);
6810 : }
6811 : }
6812 :
6813 : /* before */
6814 41629 : if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
6815 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
6816 0 : ret = NULL;
6817 0 : goto finalize;
6818 : }
6819 :
6820 41520 : if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
6821 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
6822 0 : ret = NULL;
6823 0 : goto finalize;
6824 : }
6825 :
6826 41297 : other = stmt_table_clear(be, next, restart_sequences);
6827 41535 : list_append(l, other);
6828 41493 : if (next && t && next->base.id == t->base.id)
6829 41493 : ret = other;
6830 :
6831 : /* after */
6832 41493 : if (!sql_delete_triggers(be, next, v, deleted_cols, 1, 3, 4)) {
6833 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
6834 0 : ret = NULL;
6835 0 : goto finalize;
6836 : }
6837 :
6838 41485 : if (add_to_rowcount_accumulator(be, other->nr) < 0) {
6839 0 : (void) sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6840 0 : ret = NULL;
6841 0 : goto finalize;
6842 : }
6843 41421 : if (next->s && isGlobal(next) && !isGlobalTemp(next))
6844 41469 : stmt_add_dependency_change(be, next, other);
6845 : }
6846 :
6847 41696 : finalize:
6848 41698 : sa_reset(sql->ta);
6849 41698 : return ret;
6850 : }
6851 :
6852 : #define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
6853 : #define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
6854 :
6855 : static stmt *
6856 41673 : rel2bin_truncate(backend *be, sql_rel *rel)
6857 : {
6858 41673 : mvc *sql = be->mvc;
6859 41673 : stmt *truncate = NULL;
6860 41673 : sql_rel *tr = rel->l;
6861 41673 : sql_table *t = NULL;
6862 41673 : node *n = NULL;
6863 41673 : int restart_sequences, cascade;
6864 :
6865 41673 : if (tr->op == op_basetable)
6866 41673 : t = tr->l;
6867 : else
6868 0 : assert(0/*ddl statement*/);
6869 :
6870 41673 : n = rel->exps->h;
6871 41673 : restart_sequences = E_ATOM_INT(n->data);
6872 41673 : cascade = E_ATOM_INT(n->next->data);
6873 41673 : truncate = sql_truncate(be, t, restart_sequences, cascade);
6874 41633 : if (sql->cascade_action)
6875 13 : sql->cascade_action = NULL;
6876 41633 : return truncate;
6877 : }
6878 :
6879 234 : static ValPtr take_atom_arg(node **n, int expected_type) {
6880 234 : sql_exp *e = (*n)->data;
6881 234 : atom *a = e->l;
6882 234 : assert(a->tpe.type->localtype == expected_type); (void) expected_type;
6883 234 : assert(!a->isnull);
6884 234 : *n = (*n)->next;
6885 234 : return &a->data;
6886 : }
6887 :
6888 : static stmt *
6889 74 : rel2bin_output(backend *be, sql_rel *rel, list *refs)
6890 : {
6891 74 : mvc *sql = be->mvc;
6892 74 : stmt *sub = NULL, *fns = NULL, *res = NULL;
6893 74 : list *slist = sa_list(sql->sa);
6894 :
6895 74 : if (rel->l) /* first construct the sub relation */
6896 74 : sub = subrel_bin(be, rel->l, refs);
6897 74 : sub = subrel_project(be, sub, refs, rel->l);
6898 74 : if (!sub)
6899 : return NULL;
6900 :
6901 74 : if (!rel->exps)
6902 : return sub;
6903 :
6904 74 : list *arglist = rel->exps;
6905 74 : node *argnode = arglist->h;
6906 74 : atom *a = ((sql_exp*)argnode->data)->l;
6907 74 : int tpe = a->tpe.type->localtype;
6908 :
6909 : // With regular COPY INTO <file>, the first argument is a string.
6910 : // With COPY INTO BINARY, it is an int.
6911 74 : if (tpe == TYPE_str) {
6912 32 : atom *tatom = ((sql_exp*) argnode->data)->l;
6913 32 : const char *tsep = sa_strdup(sql->sa, tatom->isnull ? "" : tatom->data.val.sval);
6914 32 : atom *ratom = ((sql_exp*) argnode->next->data)->l;
6915 32 : const char *rsep = sa_strdup(sql->sa, ratom->isnull ? "" : ratom->data.val.sval);
6916 32 : atom *satom = ((sql_exp*) argnode->next->next->data)->l;
6917 32 : const char *ssep = sa_strdup(sql->sa, satom->isnull ? "" : satom->data.val.sval);
6918 32 : atom *natom = ((sql_exp*) argnode->next->next->next->data)->l;
6919 32 : const char *ns = sa_strdup(sql->sa, natom->isnull ? "" : natom->data.val.sval);
6920 :
6921 32 : const char *fn = NULL;
6922 32 : int onclient = 0;
6923 32 : if (argnode->next->next->next->next) {
6924 23 : fn = E_ATOM_STRING(argnode->next->next->next->next->data);
6925 23 : fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
6926 23 : onclient = E_ATOM_INT(argnode->next->next->next->next->next->data);
6927 : }
6928 32 : stmt *export = stmt_export(be, sub, tsep, rsep, ssep, ns, onclient, fns);
6929 32 : list_append(slist, export);
6930 42 : } else if (tpe == TYPE_int) {
6931 42 : endianness endian = take_atom_arg(&argnode, TYPE_int)->val.ival;
6932 42 : bool do_byteswap = (endian != endian_native && endian != OUR_ENDIANNESS);
6933 42 : int on_client = take_atom_arg(&argnode, TYPE_int)->val.ival;
6934 42 : assert(sub->type == st_list);
6935 42 : list *collist = sub->op4.lval;
6936 192 : for (node *colnode = collist->h; colnode; colnode = colnode->next) {
6937 150 : stmt *colstmt = colnode->data;
6938 150 : assert(argnode != NULL);
6939 150 : const char *filename = take_atom_arg(&argnode, TYPE_str)->val.sval;
6940 150 : stmt *export = stmt_export_bin(be, colstmt, do_byteswap, filename, on_client);
6941 150 : list_append(slist, export);
6942 : }
6943 42 : assert(argnode == NULL);
6944 :
6945 : } else {
6946 0 : assert(0 && "unimplemented export statement type");
6947 : return sub;
6948 : }
6949 :
6950 74 : if (sub->type == st_list && ((stmt*)sub->op4.lval->h->data)->nrcols != 0) {
6951 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);
6952 : } else {
6953 1 : res = stmt_atom_lng(be, 1);
6954 : }
6955 74 : if (add_to_rowcount_accumulator(be, res->nr) < 0)
6956 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6957 : return res;
6958 : }
6959 :
6960 : static list *
6961 54 : merge_stmt_join_projections(backend *be, stmt *left, stmt *right, stmt *jl, stmt *jr, stmt *diff)
6962 : {
6963 54 : mvc *sql = be->mvc;
6964 54 : list *l = sa_list(sql->sa);
6965 :
6966 54 : if (left)
6967 117 : for (node *n = left->op4.lval->h; n; n = n->next) {
6968 89 : stmt *c = n->data;
6969 89 : assert(c->type == st_alias);
6970 89 : const char *rnme = table_name(sql->sa, c);
6971 89 : const char *nme = column_name(sql->sa, c);
6972 89 : stmt *s = stmt_project(be, jl ? jl : diff, column(be, c));
6973 :
6974 89 : s = stmt_alias(be, s, c->label, rnme, nme);
6975 89 : list_append(l, s);
6976 : }
6977 54 : if (right)
6978 154 : for (node *n = right->op4.lval->h; n; n = n->next) {
6979 110 : stmt *c = n->data;
6980 110 : assert(c->type == st_alias);
6981 110 : const char *rnme = table_name(sql->sa, c);
6982 110 : const char *nme = column_name(sql->sa, c);
6983 170 : stmt *s = stmt_project(be, jr ? jr : diff, column(be, c));
6984 :
6985 110 : s = stmt_alias(be, s, c->label, rnme, nme);
6986 110 : list_append(l, s);
6987 : }
6988 54 : return l;
6989 : }
6990 :
6991 : static void
6992 28 : validate_merge_delete_update(backend *be, bool delete, stmt *bt_stmt, sql_rel *bt, stmt *jl, stmt *ld)
6993 : {
6994 28 : mvc *sql = be->mvc;
6995 28 : str msg;
6996 28 : sql_table *t = bt->l;
6997 28 : char *alias = (char *) rel_name(bt);
6998 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);
6999 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);
7000 28 : sql_subfunc *add = sql_bind_func(sql, "sys", "sql_add", tail_type(cnt1), tail_type(cnt2), F_FUNC, true, true);
7001 28 : stmt *s1 = stmt_binop(be, cnt1, cnt2, NULL, add);
7002 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);
7003 28 : sql_subfunc *bf = sql_bind_func(sql, "sys", ">", tail_type(s1), tail_type(cnt3), F_FUNC, true, true);
7004 28 : stmt *s2 = stmt_binop(be, s1, cnt3, NULL, bf);
7005 :
7006 28 : if (alias && strcmp(alias, t->base.name) == 0) /* detect if alias is present */
7007 : alias = NULL;
7008 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'",
7009 : delete ? "DELETE" : "UPDATE",
7010 : alias ? "relation" : "table",
7011 22 : alias ? alias : t->s ? t->s->base.name : "", alias ? "" : ".", alias ? "" : t->base.name);
7012 28 : (void)stmt_exception(be, s2, msg, 00001);
7013 28 : }
7014 :
7015 : static stmt *
7016 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)
7017 : {
7018 54 : if (is_insert(upd->op)) {
7019 26 : if (!*rd) {
7020 26 : *rd = stmt_tdiff(be, stmt_mirror(be, bin_find_smallest_column(be, target_stmt)), jr, NULL);
7021 : }
7022 26 : stmt *s = stmt_list(be, merge_stmt_join_projections(be, NULL, target_stmt, NULL, NULL, *rd));
7023 26 : refs_update_stmt(refs, join, s); /* project the differences on the target side for inserts */
7024 :
7025 26 : return rel2bin_insert(be, upd, refs);
7026 : } else {
7027 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));
7028 28 : refs_update_stmt(refs, join, s); /* project the matched values on both sides for updates and deletes */
7029 :
7030 28 : assert(is_update(upd->op) || is_delete(upd->op));
7031 : /* the left joined values + left difference must be smaller than the table count */
7032 28 : validate_merge_delete_update(be, is_update(upd->op), bt_stmt, join->l, jl, ld);
7033 :
7034 28 : return is_update(upd->op) ? rel2bin_update(be, upd, refs) : rel2bin_delete(be, upd, refs);
7035 : }
7036 : }
7037 :
7038 : static stmt *
7039 44 : rel2bin_merge(backend *be, sql_rel *rel, list *refs)
7040 : {
7041 44 : mvc *sql = be->mvc;
7042 44 : sql_rel *join;
7043 :
7044 44 : if (is_project(((sql_rel*)rel->l)->op)) {
7045 0 : join = ((sql_rel*)rel->l)->l;
7046 : } else {
7047 : join = rel->l;
7048 : }
7049 :
7050 44 : sql_rel *r = rel->r;
7051 44 : stmt *join_st, *bt_stmt, *target_stmt, *jl, *jr, *ld, *rd = NULL, *ns;
7052 44 : list *slist = sa_list(sql->sa);
7053 :
7054 44 : assert(rel_is_ref(join) && is_left(join->op));
7055 44 : join_st = subrel_bin(be, join, refs);
7056 44 : if (!join_st)
7057 : return NULL;
7058 :
7059 : /* grab generated left join outputs and generate updates accordingly to matched and not matched values */
7060 44 : assert(join_st->type == st_list && list_length(join_st->extra) == 5);
7061 44 : bt_stmt = join_st->extra->h->data;
7062 44 : target_stmt = join_st->extra->h->next->data;
7063 44 : jl = join_st->extra->h->next->next->data;
7064 44 : jr = join_st->extra->h->next->next->next->data;
7065 44 : ld = join_st->extra->h->next->next->next->next->data;
7066 :
7067 44 : if (is_ddl(r->op)) {
7068 44 : assert(r->flag == ddl_list);
7069 44 : if (r->l) {
7070 44 : if ((ns = rel2bin_merge_apply_update(be, join, r->l, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
7071 : return NULL;
7072 44 : list_append(slist, ns);
7073 : }
7074 44 : if (r->r) {
7075 10 : if ((ns = rel2bin_merge_apply_update(be, join, r->r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
7076 : return NULL;
7077 10 : list_append(slist, ns);
7078 : }
7079 : } else {
7080 0 : if (!(ns = rel2bin_merge_apply_update(be, join, r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)))
7081 : return NULL;
7082 0 : list_append(slist, ns);
7083 : }
7084 44 : return stmt_list(be, slist);
7085 : }
7086 :
7087 : static stmt *
7088 518 : rel2bin_list(backend *be, sql_rel *rel, list *refs)
7089 : {
7090 518 : mvc *sql = be->mvc;
7091 518 : stmt *l = NULL, *r = NULL;
7092 518 : list *slist = sa_list(sql->sa);
7093 :
7094 518 : if (rel->l) /* first construct the sub relation */
7095 518 : l = subrel_bin(be, rel->l, refs);
7096 518 : if (rel->r) /* first construct the sub relation */
7097 518 : r = subrel_bin(be, rel->r, refs);
7098 518 : l = subrel_project(be, l, refs, rel->l);
7099 518 : r = subrel_project(be, r, refs, rel->r);
7100 518 : if (!l || !r)
7101 : return NULL;
7102 518 : list_append(slist, l);
7103 518 : list_append(slist, r);
7104 518 : return stmt_list(be, slist);
7105 : }
7106 :
7107 : static stmt *
7108 14767 : rel2bin_psm(backend *be, sql_rel *rel)
7109 : {
7110 14767 : mvc *sql = be->mvc;
7111 14767 : node *n;
7112 14767 : list *l = sa_list(sql->sa);
7113 14767 : stmt *sub = NULL;
7114 :
7115 25227 : for (n = rel->exps->h; n; n = n->next) {
7116 15286 : sql_exp *e = n->data;
7117 15286 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7118 15284 : if (!s)
7119 : return NULL;
7120 :
7121 10460 : if (s && s->type == st_table) /* relational statement */
7122 33 : sub = s->op1;
7123 : else
7124 10427 : append(l, s);
7125 : }
7126 9941 : return stmt_list(be, l);
7127 : }
7128 :
7129 : static stmt *
7130 275 : rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
7131 : {
7132 275 : stmt *l = NULL, *r = NULL;
7133 275 : node *n = NULL;
7134 275 : list *slist = sa_list(be->mvc->sa);
7135 :
7136 275 : if (rel->l) /* first construct the sub relation */
7137 0 : l = subrel_bin(be, rel->l, refs);
7138 275 : if (rel->r) /* first construct the sub relation */
7139 0 : r = subrel_bin(be, rel->r, refs);
7140 275 : l = subrel_project(be, l, refs, rel->l);
7141 275 : r = subrel_project(be, r, refs, rel->r);
7142 275 : if ((rel->l && !l) || (rel->r && !r))
7143 : return NULL;
7144 :
7145 275 : assert(rel->exps);
7146 275 : assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
7147 :
7148 275 : if (rel->exps) {
7149 2809 : for (n = rel->exps->h; n; n = n->next) {
7150 2534 : sql_exp *e = n->data;
7151 2534 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
7152 2534 : if (!s)
7153 : return NULL;
7154 2534 : append(slist, s);
7155 : }
7156 : }
7157 275 : return stmt_catalog(be, rel->flag, stmt_list(be, slist));
7158 : }
7159 :
7160 : static stmt *
7161 157 : rel2bin_exception(backend *be, sql_rel *rel, list *refs)
7162 : {
7163 157 : stmt *l = NULL, *r = NULL;
7164 157 : list *slist = sa_list(be->mvc->sa);
7165 :
7166 157 : if (rel->l) /* first construct the sub relation */
7167 0 : l = subrel_bin(be, rel->l, refs);
7168 157 : if (rel->r) /* first construct the sub relation */
7169 157 : r = subrel_bin(be, rel->r, refs);
7170 157 : l = subrel_project(be, l, refs, rel->l);
7171 157 : r = subrel_project(be, r, refs, rel->r);
7172 157 : if ((rel->l && !l) || (rel->r && !r))
7173 : return NULL;
7174 :
7175 157 : assert(rel->exps);
7176 314 : for (node *n = rel->exps->h; n; n = n->next) {
7177 157 : sql_exp *e = n->data;
7178 157 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
7179 157 : if (!s)
7180 : return NULL;
7181 157 : list_append(slist, s);
7182 : }
7183 157 : return stmt_list(be, slist);
7184 : }
7185 :
7186 : static stmt *
7187 357 : rel2bin_seq(backend *be, sql_rel *rel, list *refs)
7188 : {
7189 357 : mvc *sql = be->mvc;
7190 357 : node *en = rel->exps->h;
7191 357 : stmt *restart, *sname, *seq, *seqname, *sl = NULL;
7192 357 : list *l = sa_list(sql->sa);
7193 :
7194 357 : if (rel->l) { /* first construct the sub relation */
7195 0 : sl = subrel_bin(be, rel->l, refs);
7196 0 : sl = subrel_project(be, sl, refs, rel->l);
7197 0 : if (!sl)
7198 : return NULL;
7199 : }
7200 :
7201 357 : restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7202 357 : sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7203 357 : seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7204 357 : seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7205 357 : if (!restart || !sname || !seqname || !seq)
7206 : return NULL;
7207 :
7208 357 : (void)refs;
7209 357 : append(l, sname);
7210 357 : append(l, seqname);
7211 357 : append(l, seq);
7212 357 : append(l, restart);
7213 357 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7214 : }
7215 :
7216 : static stmt *
7217 3155 : rel2bin_trans(backend *be, sql_rel *rel, list *refs)
7218 : {
7219 3155 : node *en = rel->exps->h;
7220 3155 : stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7221 3155 : stmt *name = NULL;
7222 :
7223 3155 : if (!chain)
7224 : return NULL;
7225 :
7226 3155 : (void)refs;
7227 3155 : if (en->next) {
7228 79 : name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7229 79 : if (!name)
7230 : return NULL;
7231 : }
7232 3155 : return stmt_trans(be, rel->flag, chain, name);
7233 : }
7234 :
7235 : static stmt *
7236 1269 : rel2bin_catalog_schema(backend *be, sql_rel *rel, list *refs)
7237 : {
7238 1269 : mvc *sql = be->mvc;
7239 1269 : node *en = rel->exps->h;
7240 1269 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7241 1269 : stmt *sname = NULL, *name = NULL, *ifexists = NULL;
7242 1269 : list *l = sa_list(sql->sa);
7243 :
7244 1269 : if (!action)
7245 : return NULL;
7246 :
7247 1269 : (void)refs;
7248 1269 : en = en->next;
7249 1269 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7250 1269 : if (!sname)
7251 : return NULL;
7252 1269 : append(l, sname);
7253 1269 : en = en->next;
7254 1269 : if (rel->flag == ddl_create_schema) {
7255 1078 : if (en) {
7256 38 : name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7257 38 : if (!name)
7258 : return NULL;
7259 : } else {
7260 1040 : name = stmt_atom_string_nil(be);
7261 : }
7262 1078 : append(l, name);
7263 : } else {
7264 191 : assert(rel->flag == ddl_drop_schema);
7265 191 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7266 191 : if (!ifexists)
7267 : return NULL;
7268 191 : append(l, ifexists);
7269 : }
7270 1269 : append(l, action);
7271 1269 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7272 : }
7273 :
7274 : static stmt *
7275 37812 : rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
7276 : {
7277 37812 : mvc *sql = be->mvc;
7278 37812 : node *en = rel->exps->h;
7279 37812 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7280 37812 : stmt *table = NULL, *sname, *tname = NULL, *kname = NULL, *ifexists = NULL, *replace = NULL;
7281 37812 : list *l = sa_list(sql->sa);
7282 :
7283 37812 : if (!action)
7284 : return NULL;
7285 :
7286 37812 : (void)refs;
7287 37812 : en = en->next;
7288 37812 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7289 37812 : if (!sname)
7290 : return NULL;
7291 37812 : en = en->next;
7292 37812 : if (en) {
7293 37812 : tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7294 37812 : if (!tname)
7295 : return NULL;
7296 37812 : en = en->next;
7297 : }
7298 37812 : append(l, sname);
7299 37812 : assert(tname);
7300 37812 : append(l, tname);
7301 37812 : if (rel->flag == ddl_drop_constraint) { /* needs extra string parameter for constraint name */
7302 150 : if (en) {
7303 150 : kname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7304 150 : if (!kname)
7305 : return NULL;
7306 150 : en = en->next;
7307 : }
7308 150 : append(l, kname);
7309 : }
7310 37812 : if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
7311 33682 : if (en) {
7312 33682 : table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7313 33682 : if (!table)
7314 : return NULL;
7315 33682 : en = en->next;
7316 : }
7317 33682 : append(l, table);
7318 : } else {
7319 4130 : if (en) {
7320 4130 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7321 4130 : if (!ifexists)
7322 : return NULL;
7323 4130 : en = en->next;
7324 : } else {
7325 0 : ifexists = stmt_atom_int(be, 0);
7326 : }
7327 4130 : append(l, ifexists);
7328 : }
7329 37812 : append(l, action);
7330 37812 : if (rel->flag == ddl_create_view) {
7331 22262 : if (en) {
7332 22262 : replace = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7333 22262 : if (!replace)
7334 : return NULL;
7335 : } else {
7336 0 : replace = stmt_atom_int(be, 0);
7337 : }
7338 22262 : append(l, replace);
7339 15550 : } else if (rel->flag == ddl_create_table && en) {
7340 101 : stmt *name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7341 101 : if (!name)
7342 : return NULL;
7343 101 : en = en->next;
7344 101 : append(l, name);
7345 101 : if (!en)
7346 : return NULL;
7347 101 : stmt *passwd = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7348 101 : if (!passwd)
7349 : return NULL;
7350 101 : append(l, passwd);
7351 : }
7352 37812 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7353 : }
7354 :
7355 : static stmt *
7356 243966 : rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
7357 : {
7358 243966 : mvc *sql = be->mvc;
7359 243966 : node *en;
7360 243966 : list *l = sa_list(sql->sa);
7361 :
7362 243966 : (void)refs;
7363 1474395 : for (en = rel->exps->h; en; en = en->next) {
7364 1230429 : stmt *es = NULL;
7365 :
7366 1230429 : if (en->data) {
7367 1212098 : es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7368 1212098 : if (!es)
7369 : return NULL;
7370 : } else {
7371 18331 : es = stmt_atom_string_nil(be);
7372 : }
7373 1230429 : append(l,es);
7374 : }
7375 243966 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
7376 : }
7377 :
7378 : static stmt *
7379 302349 : rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
7380 : {
7381 302349 : mvc *sql = be->mvc;
7382 302349 : stmt *s = NULL;
7383 :
7384 302349 : switch (rel->flag) {
7385 74 : case ddl_output:
7386 74 : s = rel2bin_output(be, rel, refs);
7387 74 : sql->type = Q_TABLE;
7388 74 : break;
7389 518 : case ddl_list:
7390 518 : s = rel2bin_list(be, rel, refs);
7391 518 : break;
7392 14766 : case ddl_psm:
7393 14766 : s = rel2bin_psm(be, rel);
7394 14766 : break;
7395 157 : case ddl_exception:
7396 157 : s = rel2bin_exception(be, rel, refs);
7397 157 : break;
7398 357 : case ddl_create_seq:
7399 : case ddl_alter_seq:
7400 357 : s = rel2bin_seq(be, rel, refs);
7401 357 : sql->type = Q_SCHEMA;
7402 357 : break;
7403 275 : case ddl_alter_table_add_range_partition:
7404 : case ddl_alter_table_add_list_partition:
7405 275 : s = rel2bin_partition_limits(be, rel, refs);
7406 275 : sql->type = Q_SCHEMA;
7407 275 : break;
7408 3155 : case ddl_release:
7409 : case ddl_commit:
7410 : case ddl_rollback:
7411 : case ddl_trans:
7412 3155 : s = rel2bin_trans(be, rel, refs);
7413 3155 : sql->type = Q_TRANS;
7414 3155 : break;
7415 1269 : case ddl_create_schema:
7416 : case ddl_drop_schema:
7417 1269 : s = rel2bin_catalog_schema(be, rel, refs);
7418 1269 : sql->type = Q_SCHEMA;
7419 1269 : break;
7420 37812 : case ddl_create_table:
7421 : case ddl_drop_table:
7422 : case ddl_create_view:
7423 : case ddl_drop_view:
7424 : case ddl_drop_constraint:
7425 : case ddl_alter_table:
7426 37812 : s = rel2bin_catalog_table(be, rel, refs);
7427 37812 : sql->type = Q_SCHEMA;
7428 37812 : break;
7429 243966 : case ddl_drop_seq:
7430 : case ddl_create_type:
7431 : case ddl_drop_type:
7432 : case ddl_drop_index:
7433 : case ddl_create_function:
7434 : case ddl_drop_function:
7435 : case ddl_create_trigger:
7436 : case ddl_drop_trigger:
7437 : case ddl_grant_roles:
7438 : case ddl_revoke_roles:
7439 : case ddl_grant:
7440 : case ddl_revoke:
7441 : case ddl_grant_func:
7442 : case ddl_revoke_func:
7443 : case ddl_create_user:
7444 : case ddl_drop_user:
7445 : case ddl_alter_user:
7446 : case ddl_rename_user:
7447 : case ddl_create_role:
7448 : case ddl_drop_role:
7449 : case ddl_alter_table_add_table:
7450 : case ddl_alter_table_del_table:
7451 : case ddl_alter_table_set_access:
7452 : case ddl_comment_on:
7453 : case ddl_rename_schema:
7454 : case ddl_rename_table:
7455 : case ddl_rename_column:
7456 243966 : s = rel2bin_catalog2(be, rel, refs);
7457 243966 : sql->type = Q_SCHEMA;
7458 243966 : break;
7459 : default:
7460 0 : assert(0);
7461 : }
7462 302348 : return s;
7463 : }
7464 :
7465 : static stmt *
7466 1187412 : subrel_bin(backend *be, sql_rel *rel, list *refs)
7467 : {
7468 1187412 : mvc *sql = be->mvc;
7469 1187412 : stmt *s = NULL;
7470 :
7471 1187412 : if (mvc_highwater(sql))
7472 24 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
7473 :
7474 1187413 : if (!rel)
7475 : return s;
7476 1187413 : if (rel_is_ref(rel)) {
7477 14782 : s = refs_find_rel(refs, rel);
7478 : /* needs a proper fix!! */
7479 14782 : if (s)
7480 : return s;
7481 : }
7482 1181574 : switch (rel->op) {
7483 145106 : case op_basetable:
7484 145106 : s = rel2bin_basetable(be, rel);
7485 145103 : sql->type = Q_TABLE;
7486 145103 : break;
7487 3107 : case op_table:
7488 3107 : s = rel2bin_table(be, rel, refs);
7489 3107 : sql->type = Q_TABLE;
7490 3107 : break;
7491 74566 : case op_join:
7492 : case op_left:
7493 : case op_right:
7494 : case op_full:
7495 74566 : s = rel2bin_join(be, rel, refs);
7496 74566 : sql->type = Q_TABLE;
7497 74566 : break;
7498 3066 : case op_semi:
7499 3066 : s = rel2bin_semijoin(be, rel, refs);
7500 3066 : sql->type = Q_TABLE;
7501 3066 : break;
7502 1482 : case op_anti:
7503 1482 : s = rel2bin_antijoin(be, rel, refs);
7504 1482 : sql->type = Q_TABLE;
7505 1482 : break;
7506 301 : case op_union:
7507 301 : s = rel2bin_union(be, rel, refs);
7508 301 : sql->type = Q_TABLE;
7509 301 : break;
7510 4190 : case op_munion:
7511 4190 : s = rel2bin_munion(be, rel, refs);
7512 4190 : sql->type = Q_TABLE;
7513 4190 : break;
7514 2014 : case op_except:
7515 2014 : s = rel2bin_except(be, rel, refs);
7516 2014 : sql->type = Q_TABLE;
7517 2014 : break;
7518 372 : case op_inter:
7519 372 : s = rel2bin_inter(be, rel, refs);
7520 372 : sql->type = Q_TABLE;
7521 372 : break;
7522 390664 : case op_project:
7523 390664 : s = rel2bin_project(be, rel, refs, NULL);
7524 390480 : sql->type = Q_TABLE;
7525 390480 : break;
7526 68439 : case op_select:
7527 68439 : s = rel2bin_select(be, rel, refs);
7528 68439 : sql->type = Q_TABLE;
7529 68439 : break;
7530 13225 : case op_groupby:
7531 13225 : s = rel2bin_groupby(be, rel, refs);
7532 13227 : sql->type = Q_TABLE;
7533 13227 : break;
7534 16681 : case op_topn:
7535 16681 : s = rel2bin_topn(be, rel, refs);
7536 16681 : sql->type = Q_TABLE;
7537 16681 : break;
7538 20 : case op_sample:
7539 20 : s = rel2bin_sample(be, rel, refs);
7540 20 : sql->type = Q_TABLE;
7541 20 : break;
7542 109648 : case op_insert:
7543 109648 : s = rel2bin_insert(be, rel, refs);
7544 109662 : if (!(rel->returning) && sql->type == Q_TABLE)
7545 104840 : sql->type = Q_UPDATE;
7546 : break;
7547 4149 : case op_update:
7548 4149 : s = rel2bin_update(be, rel, refs);
7549 4149 : if (!(rel->returning) && sql->type == Q_TABLE)
7550 3991 : sql->type = Q_UPDATE;
7551 : break;
7552 472 : case op_delete:
7553 472 : s = rel2bin_delete(be, rel, refs);
7554 472 : if (!(rel->returning) && sql->type == Q_TABLE)
7555 337 : sql->type = Q_UPDATE;
7556 : break;
7557 41678 : case op_truncate:
7558 41678 : s = rel2bin_truncate(be, rel);
7559 41619 : if (sql->type == Q_TABLE)
7560 5 : sql->type = Q_UPDATE;
7561 : break;
7562 44 : case op_merge:
7563 44 : s = rel2bin_merge(be, rel, refs);
7564 44 : if (sql->type == Q_TABLE)
7565 44 : sql->type = Q_UPDATE;
7566 : break;
7567 302350 : case op_ddl:
7568 302350 : s = rel2bin_ddl(be, rel, refs);
7569 302350 : break;
7570 : }
7571 1181342 : if (s && rel_is_ref(rel)) {
7572 8943 : list_append(refs, rel);
7573 8943 : list_append(refs, s);
7574 : }
7575 : return s;
7576 : }
7577 :
7578 : stmt *
7579 10784 : rel_bin(backend *be, sql_rel *rel)
7580 : {
7581 10784 : mvc *sql = be->mvc;
7582 10784 : list *refs = sa_list(sql->sa);
7583 10784 : mapi_query_t sqltype = sql->type;
7584 10784 : stmt *s = subrel_bin(be, rel, refs);
7585 :
7586 10785 : s = subrel_project(be, s, refs, rel);
7587 10785 : if (sqltype == Q_SCHEMA)
7588 305 : sql->type = sqltype; /* reset */
7589 :
7590 10785 : if (be->mb->errors) {
7591 0 : if (be->mvc->sa->eb.enabled)
7592 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors, 1000);
7593 : return NULL;
7594 : }
7595 : return s;
7596 : }
7597 :
7598 : stmt *
7599 569962 : output_rel_bin(backend *be, sql_rel *rel, int top)
7600 : {
7601 569962 : mvc *sql = be->mvc;
7602 569962 : list *refs = sa_list(sql->sa);
7603 569941 : mapi_query_t sqltype = sql->type;
7604 569941 : stmt *s = NULL;
7605 :
7606 569941 : be->join_idx = 0;
7607 569941 : be->rowcount = 0;
7608 569941 : be->silent = !top;
7609 :
7610 569941 : s = subrel_bin(be, rel, refs);
7611 569799 : s = subrel_project(be, s, refs, rel);
7612 :
7613 569838 : if (!s)
7614 : return NULL;
7615 569830 : if (sqltype == Q_SCHEMA)
7616 283785 : sql->type = sqltype; /* reset */
7617 :
7618 569830 : if (!be->silent) { /* don't generate outputs when we are silent */
7619 563450 : if (!is_ddl(rel->op) && sql->type == Q_TABLE && stmt_output(be, s) < 0) {
7620 : return NULL;
7621 563407 : } else if (be->rowcount > 0 && sqltype == Q_UPDATE && stmt_affected_rows(be, be->rowcount) < 0) {
7622 : /* only call stmt_affected_rows outside functions and ddl */
7623 : return NULL;
7624 : }
7625 : }
7626 : return s;
7627 : }
|