Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 :
15 : #include "rel_bin.h"
16 : #include "rel_rel.h"
17 : #include "rel_basetable.h"
18 : #include "rel_exp.h"
19 : #include "rel_dump.h"
20 : #include "rel_psm.h"
21 : #include "rel_prop.h"
22 : #include "rel_select.h"
23 : #include "rel_updates.h"
24 : #include "rel_predicates.h"
25 : #include "rel_file_loader.h"
26 : #include "rel_proto_loader.h"
27 : #include "rel_tvtree.h"
28 : #include "sql_env.h"
29 : #include "sql_optimizer.h"
30 : #include "sql_gencode.h"
31 : #include "mal_builder.h"
32 :
33 : static stmt * rel_bin(backend *be, sql_rel *rel);
34 : static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
35 :
36 : static stmt *check_types(backend *be, sql_subtype *fromtype, stmt *s, check_type tpe);
37 :
38 : static void
39 46540 : clean_mal_statements(backend *be, int oldstop, int oldvtop)
40 : {
41 46540 : MSresetInstructions(be->mb, oldstop);
42 46552 : freeVariables(be->client, be->mb, NULL, oldvtop);
43 46549 : be->mvc->session->status = 0; /* clean possible generated error */
44 46549 : be->mvc->errstr[0] = '\0';
45 46549 : }
46 :
47 : static int
48 149746 : add_to_rowcount_accumulator(backend *be, int nr)
49 : {
50 149746 : if (be->silent)
51 : return 0;
52 :
53 149619 : if (be->rowcount == 0) {
54 149346 : be->rowcount = nr;
55 149346 : return 0;
56 : }
57 :
58 273 : InstrPtr q = newStmt(be->mb, calcRef, plusRef);
59 273 : if (q == NULL) {
60 0 : if (be->mvc->sa->eb.enabled)
61 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);
62 : return -1;
63 : }
64 273 : q = pushArgument(be->mb, q, be->rowcount);
65 273 : q = pushArgument(be->mb, q, nr);
66 273 : pushInstruction(be->mb, q);
67 :
68 273 : be->rowcount = getDestVar(q);
69 273 : return 0;
70 : }
71 :
72 : static stmt *
73 12852 : stmt_selectnil(backend *be, stmt *col)
74 : {
75 12852 : sql_subtype *t = tail_type(col);
76 12852 : return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, NULL, 0, 1);
77 : }
78 :
79 : static stmt *
80 5869 : sql_unop_(backend *be, const char *fname, stmt *rs)
81 : {
82 5869 : mvc *sql = be->mvc;
83 5869 : sql_subtype *rt = NULL;
84 5869 : sql_subfunc *f = NULL;
85 :
86 5869 : rt = tail_type(rs);
87 5869 : f = sql_bind_func(sql, "sys", fname, rt, NULL, F_FUNC, true, true);
88 : /* try to find the function without a type, and convert
89 : * the value to the type needed by this function!
90 : */
91 5869 : if (!f && (f = sql_find_func(sql, "sys", fname, 1, F_FUNC, true, NULL)) != NULL) {
92 0 : sql_arg *a = f->func->ops->h->data;
93 :
94 0 : sql->session->status = 0;
95 0 : sql->errstr[0] = '\0';
96 0 : rs = check_types(be, &a->type, rs, type_equal);
97 0 : if (!rs)
98 : f = NULL;
99 : }
100 : if (f) {
101 : /*
102 : if (f->func->res.scale == INOUT) {
103 : f->res.digits = rt->digits;
104 : f->res.scale = rt->scale;
105 : }
106 : */
107 5869 : return stmt_unop(be, rs, NULL, f);
108 0 : } else if (rs) {
109 0 : char *type = tail_type(rs)->type->base.name;
110 :
111 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such unary operator '%s(%s)'", fname, type);
112 : }
113 : return NULL;
114 : }
115 :
116 : static stmt *
117 16777 : refs_find_rel(list *refs, sql_rel *rel)
118 : {
119 21075 : for (node *n = refs->h; n; n = n->next->next) {
120 11607 : sql_rel *ref = n->data;
121 11607 : stmt *s = n->next->data;
122 :
123 11607 : if (rel == ref)
124 : return s;
125 : }
126 : return NULL;
127 : }
128 :
129 : static void
130 5226 : refs_update_stmt(list *refs, sql_rel *rel, stmt *s)
131 : {
132 6465 : for (node *n = refs->h; n; n = n->next->next) {
133 6464 : sql_rel *ref = n->data;
134 :
135 6464 : if (rel == ref) {
136 5225 : n->next->data = s;
137 5225 : break;
138 : }
139 : }
140 : }
141 :
142 :
143 : static void
144 0 : print_stmtlist(allocator *sa, stmt *l)
145 : {
146 0 : node *n;
147 0 : if (l) {
148 0 : for (n = l->op4.lval->h; n; n = n->next) {
149 0 : sql_alias *rnme = table_name(sa, n->data);
150 0 : const char *nme = column_name(sa, n->data);
151 :
152 0 : TRC_INFO(SQL_EXECUTION, "%s.%s\n", rnme ? rnme->name : "(null!)", nme ? nme : "(null!)");
153 : }
154 : }
155 0 : }
156 :
157 : static stmt *
158 4432 : list_find_column(backend *be, list *l, sql_alias *rname, const char *name)
159 : {
160 4432 : stmt *res = NULL;
161 4432 : node *n;
162 :
163 4432 : if (!l)
164 : return NULL;
165 4432 : if (!l->ht && list_length(l) > HASH_MIN_SIZE) {
166 800 : l->ht = hash_new(l->sa, MAX(list_length(l), l->expected_cnt), (fkeyvalue)&stmt_key);
167 800 : if (l->ht != NULL) {
168 16150 : for (n = l->h; n; n = n->next) {
169 15350 : const char *nme = column_name(be->mvc->sa, n->data);
170 15350 : if (nme) {
171 15350 : int key = hash_key(nme);
172 :
173 15350 : if (hash_add(l->ht, key, n->data) == NULL) {
174 0 : hash_destroy(l->ht);
175 0 : l->ht = NULL;
176 0 : break;
177 : }
178 : }
179 : }
180 : }
181 : }
182 4432 : if (l->ht) {
183 878 : int key = hash_key(name);
184 878 : sql_hash_e *e = l->ht->buckets[key&(l->ht->size-1)];
185 :
186 878 : if (rname) {
187 909 : for (; e; e = e->chain) {
188 851 : stmt *s = e->value;
189 851 : sql_alias *rnme = table_name(be->mvc->sa, s);
190 851 : const char *nme = column_name(be->mvc->sa, s);
191 :
192 851 : if (rnme && a_match(rnme, rname) &&
193 842 : strcmp(nme, name) == 0) {
194 : res = s;
195 : break;
196 : }
197 : }
198 : } else {
199 0 : for (; e; e = e->chain) {
200 0 : stmt *s = e->value;
201 0 : sql_alias *rnme = table_name(be->mvc->sa, s);
202 0 : const char *nme = column_name(be->mvc->sa, s);
203 :
204 0 : if (!rnme && nme && strcmp(nme, name) == 0) {
205 : res = s;
206 : break;
207 : }
208 : }
209 : }
210 878 : if (!res)
211 : return NULL;
212 : return res;
213 : }
214 3554 : if (rname) {
215 7876 : for (n = l->h; n; n = n->next) {
216 7838 : sql_alias *rnme = table_name(be->mvc->sa, n->data);
217 7838 : const char *nme = column_name(be->mvc->sa, n->data);
218 :
219 7838 : if (rnme && a_match(rnme, rname) &&
220 7761 : strcmp(nme, name) == 0) {
221 3516 : res = n->data;
222 3516 : break;
223 : }
224 : }
225 : } else {
226 0 : for (n = l->h; n; n = n->next) {
227 0 : sql_alias *rnme = table_name(be->mvc->sa, n->data);
228 0 : const char *nme = column_name(be->mvc->sa, n->data);
229 :
230 0 : if (!rnme && nme && strcmp(nme, name) == 0) {
231 0 : res = n->data;
232 0 : break;
233 : }
234 : }
235 : }
236 3554 : if (!res)
237 : return NULL;
238 : return res;
239 : }
240 :
241 : static stmt *
242 4432 : bin_find_column(backend *be, stmt *sub, sql_alias *rname, const char *name)
243 : {
244 4432 : return list_find_column(be, sub->op4.lval, rname, name);
245 : }
246 :
247 : static stmt *
248 1200225 : list_find_column_nid(backend *be, list *l, int label)
249 : {
250 1200225 : (void)be;
251 1200225 : if (!l)
252 : return NULL;
253 12265133 : for (node *n = l->h; n; n = n->next) {
254 12211198 : stmt *s = n->data;
255 :
256 12211198 : if (s->label == label)
257 1146231 : return s;
258 11064967 : if (s->nrcols > 1) {
259 18308406 : while(s->type == st_alias)
260 9834508 : s = s->op1;
261 8473898 : if (s->type == st_list) {
262 123 : s = list_find_column_nid(be, s->op4.lval, label);
263 123 : if (s)
264 59 : return s;
265 : }
266 : }
267 : }
268 : return NULL;
269 : }
270 :
271 : static stmt *
272 1170617 : bin_find_column_nid(backend *be, stmt *sub, int label)
273 : {
274 1170617 : list *l = sub->op4.lval;
275 1170617 : return list_find_column_nid(be, l, label);
276 : }
277 :
278 : static list *
279 : bin_find_columns(backend *be, stmt *sub, const char *name)
280 : {
281 : node *n;
282 : list *l = sa_list(be->mvc->sa);
283 :
284 : for (n = sub->op4.lval->h; n; n = n->next) {
285 : const char *nme = column_name(be->mvc->sa, n->data);
286 :
287 : if (strcmp(nme, name) == 0)
288 : append(l, n->data);
289 : }
290 : if (list_length(l))
291 : return l;
292 : return NULL;
293 : }
294 :
295 : static stmt *
296 2345398 : column(backend *be, stmt *val)
297 : {
298 2345398 : if (val->nrcols == 0)
299 26035 : return const_column(be, val);
300 : return val;
301 : }
302 :
303 : static stmt *
304 85826 : create_const_column(backend *be, stmt *val, stmt *d1)
305 : {
306 85826 : (void)d1;
307 85826 : if (val->nrcols == 0)
308 15 : val = const_column(be, val);
309 85826 : if (val->nested)
310 0 : return stmt_nest(be, val, NULL, &create_const_column);
311 85826 : return stmt_append(be, stmt_temp(be, tail_type(val)), val);
312 : }
313 :
314 : static int
315 800409 : statment_score(stmt *c)
316 : {
317 800409 : sql_subtype *t = tail_type(c);
318 800409 : int score = 0;
319 :
320 800409 : if (c->nrcols != 0) /* no need to create an extra intermediate */
321 800097 : score += 200;
322 :
323 800409 : if (!t || c->nested)
324 : return score;
325 800409 : switch (ATOMstorage(t->type->localtype)) { /* give preference to smaller types */
326 58149 : case TYPE_bte:
327 58149 : score += 150 - 8;
328 58149 : break;
329 60145 : case TYPE_sht:
330 60145 : score += 150 - 16;
331 60145 : break;
332 257614 : case TYPE_int:
333 257614 : score += 150 - 32;
334 257614 : break;
335 45409 : case TYPE_void:
336 : case TYPE_lng:
337 45409 : score += 150 - 64;
338 45409 : break;
339 1434 : case TYPE_uuid:
340 : #ifdef HAVE_HGE
341 : case TYPE_hge:
342 : #endif
343 1434 : score += 150 - 128;
344 1434 : break;
345 3339 : case TYPE_flt:
346 3339 : score += 75 - 24;
347 3339 : break;
348 5954 : case TYPE_dbl:
349 5954 : score += 75 - 53;
350 5954 : break;
351 : default:
352 : break;
353 : }
354 : return score;
355 : }
356 :
357 : static stmt *
358 95809 : bin_find_smallest_column(backend *be, stmt *sub)
359 : {
360 95809 : stmt *res = sub->op4.lval->h->data;
361 95809 : int best_score = statment_score(res);
362 :
363 95809 : if (sub->op4.lval->h->next)
364 783945 : for (node *n = sub->op4.lval->h->next ; n ; n = n->next) {
365 704600 : stmt *c = n->data;
366 704600 : int next_score = statment_score(c);
367 :
368 704600 : if (next_score > best_score) {
369 55943 : res = c;
370 55943 : best_score = next_score;
371 : }
372 : }
373 95809 : if (res->nrcols == 0)
374 260 : return const_column(be, res);
375 : return res;
376 : }
377 :
378 : static stmt *
379 240723 : row2cols(backend *be, stmt *sub)
380 : {
381 240723 : if (sub->nrcols == 0 && sub->key) {
382 8368 : node *n;
383 8368 : list *l = sa_list(be->mvc->sa);
384 8368 : if (l == NULL)
385 : return NULL;
386 :
387 31433 : for (n = sub->op4.lval->h; n; n = n->next) {
388 23065 : stmt *sc = n->data;
389 23065 : assert(sc->type == st_alias);
390 23065 : const char *cname = column_name(be->mvc->sa, sc);
391 23065 : sql_alias *tname = table_name(be->mvc->sa, sc);
392 23065 : int label = sc->label;
393 :
394 23065 : sc = column(be, sc);
395 23065 : list_append(l, stmt_alias(be, sc, label, tname, cname));
396 : }
397 8368 : sub = stmt_list(be, l);
398 : }
399 : return sub;
400 : }
401 :
402 : static stmt*
403 44 : distinct_value_list(backend *be, list *vals, stmt **last_null_value, int depth, int push)
404 : {
405 44 : list *l = sa_list(be->mvc->sa);
406 44 : stmt *s;
407 :
408 : /* create bat append values */
409 1843 : for (node *n = vals->h; n; n = n->next) {
410 1799 : sql_exp *e = n->data;
411 1799 : stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, depth, 0, push);
412 :
413 1799 : if (exp_is_null(e))
414 0 : *last_null_value = i;
415 :
416 1799 : if (!i)
417 : return NULL;
418 :
419 1799 : list_append(l, i);
420 : }
421 44 : s = stmt_append_bulk(be, stmt_temp(be, exp_subtype(vals->h->data)), l);
422 : /* Probably faster to filter out the values directly in the underlying list of atoms.
423 : But for now use groupby to filter out duplicate values. */
424 44 : stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
425 44 : stmt* ext = stmt_result(be, groupby, 1);
426 :
427 44 : return stmt_project(be, ext, s);
428 : }
429 :
430 : static stmt *
431 3062 : stmt_selectnonil(backend *be, stmt *col, stmt *s)
432 : {
433 3062 : sql_subtype *t = tail_type(col);
434 3062 : return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, s, 1, 1);
435 : }
436 :
437 : static int
438 14891 : is_tid_chain(stmt *cand)
439 : {
440 18568 : while(cand && cand->type != st_tid && cand->cand) {
441 : cand = cand->cand;
442 : }
443 14891 : if (cand && cand->type == st_tid)
444 12716 : return 1;
445 : return 0;
446 : }
447 :
448 : static stmt *
449 1177408 : subrel_project(backend *be, stmt *s, list *refs, sql_rel *rel)
450 : {
451 1177408 : if (!s || s->type != st_list || !s->cand)
452 : return s;
453 :
454 162417 : list *l = sa_list(be->mvc->sa);
455 162414 : stmt *cand = s->cand;
456 162414 : if (!l)
457 : return NULL;
458 744618 : for (node *n = s->op4.lval->h; n; n = n->next) {
459 582198 : stmt *c = n->data;
460 :
461 582198 : 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);
462 582198 : if (c->type != st_alias || c->flag) {
463 52 : c = stmt_project(be, cand, c);
464 582146 : } else if (c->op1->type == st_mirror && is_tid_chain(cand)) { /* alias with mirror (ie full row ids) */
465 : //c = stmt_alias(be, cand, 0, c->tname, c->cname);
466 12716 : c = stmt_as(be, cand, c);
467 : } else { /* st_alias */
468 569430 : stmt *s = c->op1;
469 569430 : if (s->nrcols == 0)
470 0 : s = stmt_const(be, cand, s);
471 : else
472 569430 : s = stmt_project(be, cand, s);
473 : //c = stmt_alias(be, s, c->flag, c->tname, c->cname);
474 569432 : c = stmt_as(be, s, c);
475 : }
476 582210 : append(l, c);
477 : }
478 162420 : s = stmt_list(be, l);
479 162420 : if (rel && rel_is_ref(rel))
480 5101 : refs_update_stmt(refs, rel, s);
481 : return s;
482 : }
483 :
484 : static stmt *
485 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)
486 : {
487 72 : mvc *sql = be->mvc;
488 72 : stmt *s = NULL;
489 :
490 72 : list *lvals = ce->f, *lstmts = sa_list(sql->sa);
491 328 : for(node *n = lvals->h; n; n = n->next) {
492 256 : sql_exp *ce = n->data;
493 256 : stmt *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
494 :
495 256 : if (c && reduce && c->nrcols == 0)
496 0 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
497 0 : if(!c)
498 : return NULL;
499 256 : lstmts = append(lstmts, c);
500 : }
501 :
502 72 : sql_subtype *bt = sql_bind_localtype("bit");
503 72 : sql_subfunc *and = sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
504 72 : sql_subfunc *or = sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true);
505 574 : for (node *n = nl->h; n; n = n->next) {
506 502 : sql_exp *e = n->data;
507 502 : list *vals = e->f;
508 502 : stmt *cursel = NULL;
509 :
510 2072 : for (node *m = vals->h, *o = lstmts->h; m && o; m = m->next, o = o->next) {
511 1570 : stmt *c = o->data;
512 3140 : sql_subfunc *cmp = (in)
513 1570 : ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
514 1570 : :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
515 1570 : sql_exp *e = m->data;
516 :
517 1570 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
518 1570 : if(!i)
519 : return NULL;
520 :
521 1570 : i = stmt_binop(be, c, i, NULL, cmp);
522 1570 : if (cursel)
523 1068 : cursel = stmt_binop(be, cursel, i, NULL, in?and:or);
524 : else
525 : cursel = i;
526 : }
527 502 : if (s)
528 430 : s = stmt_binop(be, s, cursel, NULL, in?or:and);
529 : else
530 : s = cursel;
531 : }
532 72 : if (!depth && reduce)
533 144 : s = stmt_uselect(be,
534 72 : s->nrcols == 0?stmt_const(be, bin_find_smallest_column(be, left), s): s,
535 : stmt_bool(be, 1), cmp_equal, sel, 0, 0);
536 : return s;
537 : }
538 :
539 : static stmt *
540 15751 : 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)
541 : {
542 15751 : if (ce && is_values(ce))
543 72 : return handle_in_tuple_exps(be, ce, nl, left, right, grp, ext, cnt, sel, in, depth, reduce, push);
544 15679 : mvc *sql = be->mvc;
545 15679 : node *n;
546 15679 : stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
547 :
548 15679 : if(!c)
549 : return NULL;
550 :
551 15679 : if (reduce && c->nrcols == 0)
552 47 : c = stmt_const(be, bin_find_smallest_column(be, left), c);
553 :
554 15679 : if (c->nrcols == 0 || depth || !reduce) {
555 2 : sql_subtype *bt = sql_bind_localtype("bit");
556 4 : sql_subfunc *cmp = (in)
557 2 : ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
558 2 : :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
559 2 : sql_subfunc *a = (in)?sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true)
560 2 : :sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
561 :
562 6 : for (n = nl->h; n; n = n->next) {
563 4 : sql_exp *e = n->data;
564 4 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
565 4 : if(!i)
566 : return NULL;
567 :
568 4 : i = stmt_binop(be, c, i, NULL, cmp);
569 4 : if (s)
570 2 : s = stmt_binop(be, s, i, NULL, a);
571 : else
572 : s = i;
573 : }
574 2 : if (sel && !(depth || !reduce))
575 0 : s = stmt_uselect(be,
576 : stmt_const(be, bin_find_smallest_column(be, left), s),
577 : stmt_bool(be, 1), cmp_equal, sel, 0, 0);
578 15677 : } else if (list_length(nl) < 16) {
579 15633 : comp_type cmp = (in)?cmp_equal:cmp_notequal;
580 :
581 15633 : if (!in)
582 5464 : s = sel;
583 80056 : for (n = nl->h; n; n = n->next) {
584 64423 : sql_exp *e = n->data;
585 64423 : stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
586 64423 : if(!i)
587 : return NULL;
588 :
589 64423 : if (in) {
590 51539 : i = stmt_uselect(be, c, i, cmp, sel, 0, 0);
591 51539 : if (s)
592 41370 : s = stmt_tunion(be, s, i);
593 : else
594 : s = i;
595 : } else {
596 12884 : s = stmt_uselect(be, c, i, cmp, s, 0, 0);
597 : }
598 : }
599 : } else {
600 : /* TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
601 : For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
602 : make sure that this behavior is replicated by the sql optimizer and not handle_in_exps. */
603 :
604 44 : stmt* last_null_value = NULL; /* CORNER CASE ALERT: See description below. */
605 :
606 : /* The actual in-value-list should not contain duplicates to ensure that final join results are unique. */
607 44 : s = distinct_value_list(be, nl, &last_null_value, depth+1, push);
608 44 : if (!s)
609 0 : return NULL;
610 :
611 44 : if (last_null_value) {
612 : /* The actual in-value-list should not contain null values. */
613 0 : s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
614 : }
615 :
616 44 : if (in) {
617 42 : s = stmt_semijoin(be, c, s, sel, NULL, 0, false);
618 : } else {
619 2 : if (last_null_value) {
620 : /* CORNER CASE ALERT:
621 : In case of a not-in-expression with the associated in-value-list containing a null value,
622 : the entire in-predicate is forced to always return false, i.e. an empty candidate list.
623 : This is similar to postgres behavior.
624 : TODO: However I do not think this behavior is in accordance with SQL standard 2003.
625 :
626 : Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
627 : list* singleton_bat = sa_list(sql->sa);
628 : list_append(singleton_bat, null_value); */
629 0 : s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0, 0);
630 : } else {
631 : /* BACK TO HAPPY FLOW:
632 : Make sure that null values are never returned. */
633 2 : stmt* non_nulls;
634 2 : non_nulls = stmt_selectnonil(be, c, sel);
635 2 : s = stmt_tdiff(be, stmt_project(be, non_nulls, c), s, NULL);
636 2 : s = stmt_project(be, s, non_nulls);
637 : }
638 : }
639 : }
640 : return s;
641 : }
642 :
643 :
644 : static stmt * value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel);
645 :
646 : static stmt *
647 : composite_value_list(backend *be, sql_exp *tuple, stmt *left, stmt *sel)
648 : {
649 : assert(is_row(tuple));
650 : list *fields = exp_get_values(tuple);
651 : list *f = sa_list(be->mvc->sa);
652 : for (node *n = fields->h; n; n = n->next) {
653 : sql_exp *e = n->data;
654 : stmt *i;
655 :
656 : if(is_values(e))
657 : i = value_list(be, e, left, sel);
658 : else
659 : i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
660 : if (!i)
661 : return NULL;
662 : if (i->type == st_list) {
663 : for( node *n = i->op4.lval->h; n; n = n->next)
664 : list_append(f, n->data);
665 : } else
666 : list_append(f, i);
667 : }
668 : return stmt_list(be, f);
669 : }
670 :
671 : static stmt *
672 : set_value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
673 : {
674 : assert(is_values(vals_exp));
675 : list *vals = exp_get_values(vals_exp);
676 : sql_subtype *type = exp_subtype(vals->h->data);
677 : bool single_value = list_length(vals) <= 1;
678 : int multi_result = 0;
679 :
680 : if (!type)
681 : return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
682 :
683 : /* create bat append values */
684 : list *l = sa_list(be->mvc->sa);
685 : for (node *n = vals->h; n; n = n->next) {
686 : sql_exp *e = n->data;
687 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
688 :
689 : if (!i)
690 : return NULL;
691 : if (single_value)
692 : return i;
693 : list_append(l, i);
694 :
695 : if (i->type == st_list && list_length(i->op4.lval) > 1)
696 : multi_result = list_length(i->op4.lval);
697 : }
698 : /* n-tuples */
699 : if (multi_result) {
700 : list *rl = sa_list(be->mvc->sa);
701 : for(int i = 0; i < multi_result; i++) {
702 : node *n = l->h;
703 : stmt *s = n->data;
704 : stmt *input = list_fetch(s->op4.lval, i);
705 : sql_subtype *type = tail_type(input);
706 : list *nl = list_append(sa_list(be->mvc->sa), input);
707 : for (n = n->next; n; n = n->next) {
708 : stmt *s = n->data;
709 : stmt *input = list_fetch(s->op4.lval, i);
710 : nl = list_append(nl, input);
711 : }
712 : append(rl, stmt_append_bulk(be, stmt_temp(be, type), nl));
713 : }
714 : return stmt_list(be, rl);
715 : }
716 : return stmt_append_bulk(be, stmt_temp(be, type), l);
717 : }
718 :
719 : static int
720 : type_create_result(backend *be, sql_subtype *type, list *cols)
721 : {
722 : if (type->type->composite) {
723 : for(node *n = type->type->d.fields->h; n; n = n->next) {
724 : sql_arg *a = n->data;
725 :
726 : if (a->type.type->composite) {
727 : if(type_create_result(be, &a->type, cols) < 0)
728 : return -1;
729 : } else {
730 : append(cols, sa_list(be->mvc->sa));
731 : }
732 : }
733 : } else {
734 : append(cols, sa_list(be->mvc->sa));
735 : }
736 : if (type->multiset) /* multisetid */
737 : append(cols, sa_list(be->mvc->sa));
738 : if (type->multiset == MS_ARRAY) /* multisetnr */
739 : append(cols, sa_list(be->mvc->sa));
740 : if (type->multiset) /* rowid */
741 : append(cols, sa_list(be->mvc->sa));
742 : return 0;
743 : }
744 :
745 : static node *
746 : append_tuple(backend *be, sql_exp *tuple, sql_subtype *type, stmt *left, stmt *sel, node *cols, int rowcnt, int lcnt, bool row)
747 : {
748 : if (row && !is_row(tuple)) { /* multiset data */
749 : node *ncols = cols;
750 : assert(is_values(tuple));
751 : list *tuples = exp_get_values(tuple);
752 : int i = 1;
753 : if (list_empty(tuples)) {
754 : list *vals = cols->data;
755 : append(vals, stmt_atom_int(be, int_nil));
756 : if (type->type->composite) {
757 : node *n = cols;
758 : if (type->multiset)
759 : n = n->next;
760 : for(node *o = type->type->d.fields->h; n && o; n = n->next, o = o->next)
761 : ;
762 : if (type->multiset)
763 : n = n->next;
764 : if (type->multiset == MS_ARRAY)
765 : n = n->next;
766 : return n;
767 : } else
768 : return cols->next;
769 : }
770 : for(node *n = tuples->h; n; n = n->next, i++)
771 : if ((ncols=append_tuple(be, n->data, type, left, sel, cols, rowcnt, i, 0)) == cols)
772 : return cols;
773 : return ncols;
774 : }
775 : assert(tuple->row);
776 : list *attr = exp_get_values(tuple);
777 : node *n, *m = cols, *o;
778 : sql_subtype *ntype = type;
779 : if (is_row(tuple) && list_length(type->type->d.fields) == 1) {
780 : sql_arg *f = type->type->d.fields->h->data;
781 : ntype = &f->type;
782 : }
783 : if (ntype->type->composite) {
784 : for(n = attr->h, o = ntype->type->d.fields->h; n && o; n = n->next, o = o->next) {
785 : sql_arg *f = o->data;
786 : sql_exp *e = n->data;
787 : list *vals = m->data;
788 : if (f->type.type->composite) {
789 : node *nm = append_tuple(be, e, &f->type, left, sel, m, rowcnt, lcnt, ntype->multiset);
790 : if (nm == m)
791 : return m;
792 : m = nm;
793 : } else {
794 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
795 : append(vals, i);
796 : m = m->next;
797 : }
798 : }
799 : } else {
800 : assert(list_length(attr) == 1);
801 : sql_exp *e = attr->h->data;
802 : list *vals = m->data;
803 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
804 : m = m->next;
805 : append(vals, i);
806 : }
807 : if (type->multiset) {
808 : list *vals = m->data;
809 : append(vals, stmt_atom_int(be, rowcnt));
810 : m = m->next;
811 : }
812 : if (type->multiset == MS_ARRAY) {
813 : list *vals = m->data;
814 : append(vals, stmt_atom_int(be, lcnt));
815 : m = m->next;
816 : }
817 : if (type->multiset) {
818 : if (lcnt == 1) {
819 : list *vals = m->data;
820 : append(vals, stmt_atom_int(be, rowcnt));
821 : }
822 : m = m->next;
823 : }
824 : return m;
825 : }
826 :
827 : static stmt *
828 : tuple_result(backend *be, list *cols)
829 : {
830 : list *row = sa_list(be->mvc->sa);
831 :
832 : for (node *n = cols->h; n; n = n->next) {
833 : list *vals = n->data;
834 : sql_subtype *type = tail_type(vals->h->data);
835 : append(row, stmt_append_bulk(be, stmt_temp(be, type), vals));
836 : }
837 : return stmt_list(be, row);
838 : }
839 :
840 : // TODO: >>>>>>>>>>>>>>>>>>>> remove value_list and friends
841 : static stmt *
842 : value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
843 : {
844 : if (!be) return NULL;
845 :
846 : assert(is_values(vals_exp));
847 : list *vals = exp_get_values(vals_exp);
848 : sql_subtype *type = exp_subtype(vals_exp);
849 : list *l;
850 :
851 : if (!type || list_empty(vals))
852 : return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
853 :
854 : if (!is_row(vals_exp) && type->type->composite) {
855 : list *attr = sa_list(be->mvc->sa);
856 : sql_exp *v = vals->h->data;
857 : if (type_create_result(be, type, attr) < 0)
858 : return NULL;
859 : int rowcnt = 0, lcnt = 1;
860 : int irc = is_row(v)?0:1;
861 : int lrc = is_row(v)?1:0;
862 : for (node *n = vals->h; n; n = n->next, rowcnt += irc, lcnt += lrc) {
863 : if (append_tuple(be, n->data, type, left, sel, attr->h, rowcnt, lcnt, 1) == attr->h)
864 : return NULL;
865 : }
866 : return tuple_result(be, attr);
867 : }
868 : if (type->multiset || (!is_row(vals_exp) && type->type->composite))
869 : return set_value_list(be, vals_exp, left, sel);
870 :
871 : if (is_row(vals_exp))
872 : return composite_value_list(be, vals_exp, left, sel);
873 :
874 : type = exp_subtype(vals->h->data);
875 :
876 : /* create bat append values */
877 : l = sa_list(be->mvc->sa);
878 : for (node *n = vals->h; n; n = n->next) {
879 : sql_exp *e = n->data;
880 : stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
881 :
882 : if (!i)
883 : return NULL;
884 :
885 : if (list_length(vals) == 1)
886 : return i;
887 : list_append(l, i);
888 : }
889 : return stmt_append_bulk(be, stmt_temp(be, type), l);
890 : }
891 :
892 : static stmt *
893 139549 : value_tvtree(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
894 : {
895 139549 : if (!be) return NULL;
896 :
897 139549 : assert(is_values(vals_exp));
898 :
899 139549 : sql_subtype *st = exp_subtype(vals_exp);
900 139531 : tv_tree *t = tv_create(be, st);
901 :
902 : /* EXCEPTION: we might get cases were we have a single basic type
903 : * value wrapped in e_atom->f (probably coming from unnest) in this
904 : * case we just generate the stmt and we bail out. hopefully this
905 : * will be cleaned up in the future */
906 139374 : if (t->tvt == TV_BASIC) {
907 139423 : list *vals = exp_get_values(vals_exp);
908 139265 : if (list_length(vals) == 1) {
909 1981 : sql_exp *v = vals->h->data;
910 1981 : if (v->type == e_atom && v->l)
911 1749 : return stmt_atom(be, v->l);
912 232 : return exp_bin(be, v, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
913 : }
914 : }
915 :
916 137215 : if (false == tv_parse_values(be, t, vals_exp, left, sel))
917 : return NULL;
918 :
919 137515 : stmt *ret = tv_generate_stmts(be, t);
920 :
921 137515 : return ret;
922 : }
923 :
924 : static stmt *
925 282 : exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
926 : {
927 282 : mvc *sql = be->mvc;
928 282 : node *n;
929 282 : list *nl = sa_list(sql->sa);
930 :
931 282 : if (nl == NULL)
932 : return NULL;
933 673 : for (n = exps->h; n; n = n->next) {
934 391 : sql_exp *e = n->data;
935 391 : stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0, 0);
936 391 : if(!i)
937 : return NULL;
938 :
939 391 : if (n->next && i->type == st_table) /* relational statement */
940 3 : l = i->op1;
941 : else
942 388 : append(nl, i);
943 : }
944 282 : return stmt_list(be, nl);
945 : }
946 :
947 : static stmt *
948 1645 : exp_count_no_nil_arg(sql_exp *e, stmt *ext, sql_exp *ae, stmt *as)
949 : {
950 : /* small optimization, ie use candidates directly on count(*) */
951 1645 : if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
952 : /* skip alias statements */
953 3160 : while (as->type == st_alias)
954 1649 : as = as->op1;
955 : /* use candidate */
956 1511 : if (as && as->type == st_join && as->flag == cmp_project) {
957 1378 : if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
958 1645 : as = as->op1;
959 : }
960 : }
961 1645 : return as;
962 : }
963 :
964 : static stmt *
965 10025 : exp_bin_or(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, bool reduce, int push)
966 : {
967 10025 : sql_subtype *bt = sql_bind_localtype("bit");
968 10025 : list *l = e->l;
969 10025 : node *n;
970 10025 : stmt *sel1 = NULL, *sel2 = NULL, *s = NULL;
971 10025 : int anti = is_anti(e);
972 :
973 10025 : sel1 = sel;
974 10025 : sel2 = sel;
975 21198 : for (n = l->h; n; n = n->next) {
976 11173 : sql_exp *c = n->data;
977 11173 : stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
978 :
979 : /* propagate the anti flag */
980 11173 : if (anti)
981 55 : set_anti(c);
982 11177 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
983 11173 : if (!s)
984 : return s;
985 :
986 11173 : if (!reduce && sin) {
987 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
988 0 : assert(f);
989 0 : s = stmt_binop(be, sin, s, NULL, f);
990 11173 : } else if (!sin && sel1 && sel1->nrcols == 0 && s->nrcols == 0) {
991 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
992 0 : assert(f);
993 0 : s = stmt_binop(be, sel1, s, sin, f);
994 11173 : } else if (sel1 && (sel1->nrcols == 0 || s->nrcols == 0)) {
995 1 : stmt *predicate = bin_find_smallest_column(be, left);
996 :
997 1 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
998 1 : if (s->nrcols == 0)
999 0 : s = stmt_uselect(be, predicate, s, cmp_equal, sel1, anti, is_semantics(c));
1000 : else
1001 1 : s = stmt_uselect(be, predicate, sel1, cmp_equal, s, anti, is_semantics(c));
1002 : }
1003 11173 : sel1 = s;
1004 : }
1005 10025 : l = e->r;
1006 22431 : for (n = l->h; n; n = n->next) {
1007 12406 : sql_exp *c = n->data;
1008 12406 : stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
1009 :
1010 : /* propagate the anti flag */
1011 12406 : if (anti)
1012 55 : set_anti(c);
1013 12411 : s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
1014 12406 : if (!s)
1015 : return s;
1016 :
1017 12406 : if (!reduce && sin) {
1018 2 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
1019 1 : assert(f);
1020 1 : s = stmt_binop(be, sin, s, NULL, f);
1021 12405 : } else if (!sin && sel2 && sel2->nrcols == 0 && s->nrcols == 0) {
1022 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
1023 0 : assert(f);
1024 0 : s = stmt_binop(be, sel2, s, sin, f);
1025 12405 : } else if (sel2 && (sel2->nrcols == 0 || s->nrcols == 0)) {
1026 6 : stmt *predicate = bin_find_smallest_column(be, left);
1027 :
1028 6 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
1029 6 : if (s->nrcols == 0)
1030 5 : s = stmt_uselect(be, predicate, s, cmp_equal, sel2, anti, 0);
1031 : else
1032 1 : s = stmt_uselect(be, predicate, sel2, cmp_equal, s, anti, 0);
1033 : }
1034 12406 : sel2 = s;
1035 : }
1036 10025 : if (sel1->nrcols == 0 && sel2->nrcols == 0) {
1037 0 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
1038 0 : assert(f);
1039 0 : return stmt_binop(be, sel1, sel2, NULL, f);
1040 : }
1041 10025 : if (sel1->nrcols == 0) {
1042 3 : stmt *predicate = bin_find_smallest_column(be, left);
1043 :
1044 3 : if (!reduce) {
1045 0 : predicate = stmt_const(be, predicate, sel1);
1046 : } else {
1047 3 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
1048 3 : sel1 = stmt_uselect(be, predicate, sel1, cmp_equal, NULL, 0/*anti*/, 0);
1049 : }
1050 : }
1051 10025 : if (sel2->nrcols == 0) {
1052 81 : stmt *predicate = bin_find_smallest_column(be, left);
1053 :
1054 81 : if (!reduce) {
1055 0 : predicate = stmt_const(be, predicate, sel2);
1056 : } else {
1057 81 : predicate = stmt_const(be, predicate, stmt_bool(be, 1));
1058 81 : sel2 = stmt_uselect(be, predicate, sel2, cmp_equal, NULL, 0/*anti*/, 0);
1059 : }
1060 : }
1061 10025 : if (!reduce) {
1062 8 : sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
1063 4 : assert(f);
1064 4 : return stmt_binop(be, sel1, sel2, NULL, f);
1065 : }
1066 10021 : if (anti)
1067 55 : return stmt_project(be, stmt_tinter(be, sel1, sel2, false), sel1);
1068 9966 : return stmt_tunion(be, sel1, sel2);
1069 : }
1070 :
1071 : static stmt *
1072 18276 : exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
1073 : {
1074 18276 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
1075 18276 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
1076 18276 : char name[16], *nme = NULL;
1077 18276 : sql_subtype *bt = sql_bind_localtype("bit");
1078 18276 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
1079 18276 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
1080 18276 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
1081 :
1082 18276 : if (single_value) {
1083 : /* var_x = nil; */
1084 91 : nme = number2name(name, sizeof(name), ++be->mvc->label);
1085 91 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
1086 : }
1087 :
1088 18276 : list *exps = fe->l;
1089 :
1090 : /*
1091 : * left - isel: calls down need id's from the range of left
1092 : * res - rsel: updates to res need id's in the range from res
1093 : */
1094 78274 : for (node *en = exps->h; en; en = en->next) {
1095 59998 : sql_exp *e = en->data;
1096 :
1097 59998 : next_cond = next_cond && en->next; /* last else is only a value */
1098 :
1099 59998 : stmt *nsel = rsel;
1100 59998 : if (!single_value) {
1101 59671 : if (/*!next_cond &&*/ rsel && isel) {
1102 : /* back into left range */
1103 8584 : nsel = stmt_project(be, rsel, isel);
1104 51087 : } else if (isel && !rsel)
1105 59998 : nsel = isel;
1106 : }
1107 59998 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1108 :
1109 59998 : if (!es)
1110 : return NULL;
1111 59998 : if (!single_value) {
1112 : /* create result */
1113 59671 : if (!res) {
1114 18185 : stmt *l = isel;
1115 18185 : if (!l)
1116 13907 : l = bin_find_smallest_column(be, left);
1117 18185 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1118 18185 : ires = l;
1119 18185 : if (res)
1120 18185 : res->cand = isel;
1121 41486 : } else if (res && !next_cond) { /* use result to update column */
1122 38928 : stmt *val = es;
1123 38928 : stmt *pos = rsel;
1124 :
1125 38928 : if (val->nrcols == 0)
1126 19234 : val = stmt_const(be, pos, val);
1127 19694 : else if (!val->cand && nsel)
1128 4112 : val = stmt_project(be, nsel, val);
1129 38928 : res = stmt_replace(be, res, pos, val);
1130 :
1131 38928 : assert(cond);
1132 :
1133 38928 : if (en->next) {
1134 : /* osel - rsel */
1135 20743 : if (!osel)
1136 18185 : osel = stmt_mirror(be, ires);
1137 20743 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
1138 20743 : osel = rsel = stmt_project(be, d, osel);
1139 : }
1140 : }
1141 59671 : if (next_cond) {
1142 20743 : ncond = cond = es;
1143 20743 : if (!ncond->nrcols) {
1144 134 : if (osel) {
1145 76 : ncond = stmt_const(be, nsel, ncond);
1146 76 : ncond->cand = nsel;
1147 58 : } else if (isel) {
1148 3 : ncond = stmt_const(be, isel, ncond);
1149 3 : ncond->cand = isel;
1150 : } else
1151 55 : ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
1152 : }
1153 20743 : if (isel && !ncond->cand) {
1154 10 : ncond = stmt_project(be, nsel, ncond);
1155 10 : ncond->cand = nsel;
1156 : }
1157 27571 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
1158 20743 : if (rsel && ncond->cand)
1159 2550 : rsel = stmt_project(be, s, rsel);
1160 : else
1161 : rsel = s;
1162 : }
1163 : } else {
1164 327 : if (!res) {
1165 : /* if_barrier ... */
1166 118 : assert(next_cond);
1167 118 : if (next_cond) {
1168 118 : if (cond) {
1169 27 : ncond = stmt_binop(be, cond, es, nsel, and);
1170 : } else {
1171 : ncond = es;
1172 : }
1173 : cond = es;
1174 : }
1175 : } else {
1176 : /* var_x = s */
1177 209 : (void)stmt_assign(be, NULL, nme, es, 2);
1178 : /* endif_barrier */
1179 209 : (void)stmt_control_end(be, res);
1180 209 : res = NULL;
1181 :
1182 209 : if (en->next) {
1183 118 : cond = stmt_unop(be, cond, nsel, not);
1184 :
1185 118 : sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
1186 118 : cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
1187 118 : if (ocond)
1188 27 : cond = stmt_binop(be, ocond, cond, nsel, and);
1189 118 : ocond = cond;
1190 118 : if (!en->next->next)
1191 91 : ncond = cond;
1192 : }
1193 : }
1194 327 : if (ncond && (next_cond || (en->next && !en->next->next))) {
1195 : /* if_barrier ... */
1196 209 : res = stmt_cond(be, ncond, NULL, 0, 0);
1197 : }
1198 : }
1199 59998 : next_cond = !next_cond;
1200 : }
1201 18276 : if (single_value)
1202 91 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1203 : return res;
1204 : }
1205 :
1206 : static stmt *
1207 3 : exp2bin_named_placeholders(backend *be, sql_exp *fe)
1208 : {
1209 3 : int argc = 0;
1210 3 : char arg[IDLENGTH];
1211 3 : list *args = fe->l;
1212 :
1213 3 : if (list_empty(args))
1214 : return NULL;
1215 8 : for (node *n = args->h; n; n = n->next, argc++) {
1216 5 : sql_exp *a = n->data;
1217 5 : sql_subtype *t = exp_subtype(a);
1218 5 : stmt *s = exp_bin(be, a, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, 1);
1219 5 : InstrPtr q = newAssignment(be->mb);
1220 :
1221 5 : if (!q || !t || !s) {
1222 0 : sql_error(be->mvc, 10, SQLSTATE(42000) MAL_MALLOC_FAIL);
1223 0 : return NULL;
1224 : }
1225 5 : int type = t->type->localtype, varid = 0;
1226 :
1227 5 : snprintf(arg, IDLENGTH, "A%d", argc);
1228 5 : if ((varid = newVariable(be->mb, arg, strlen(arg), type)) < 0) {
1229 0 : sql_error(be->mvc, 10, SQLSTATE(42000) "Internal error while compiling statement: variable id too long");
1230 0 : return NULL;
1231 : }
1232 5 : if (q)
1233 5 : getDestVar(q) = varid;
1234 5 : q = pushArgument(be->mb, q, s->nr);
1235 5 : pushInstruction(be->mb, q);
1236 : }
1237 : return NULL;
1238 : }
1239 :
1240 : static stmt *
1241 2283 : exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
1242 : {
1243 2283 : stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
1244 2283 : int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
1245 2283 : char name[16], *nme = NULL;
1246 2283 : sql_subtype *bt = sql_bind_localtype("bit");
1247 2283 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
1248 2283 : sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
1249 2283 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
1250 2283 : sql_subfunc *cmp;
1251 :
1252 2283 : if (single_value) {
1253 : /* var_x = nil; */
1254 86 : nme = number2name(name, sizeof(name), ++be->mvc->label);
1255 86 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
1256 : }
1257 :
1258 2283 : list *exps = fe->l;
1259 2283 : node *en = exps->h;
1260 2283 : sql_exp *e = en->data;
1261 :
1262 2283 : stmt *nsel = !single_value?isel:NULL;
1263 2283 : stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1264 2283 : if (!case_when)
1265 : return NULL;
1266 2283 : cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e), exp_subtype(e), F_FUNC, true, true);
1267 2283 : if (!cmp)
1268 : return NULL;
1269 2283 : if (!single_value && !case_when->nrcols) {
1270 32 : stmt *l = isel;
1271 32 : if (!l && left)
1272 27 : l = bin_find_smallest_column(be, left);
1273 5 : else if (!l)
1274 : return NULL;
1275 32 : case_when = stmt_const(be, l, case_when);
1276 32 : if (case_when)
1277 32 : case_when->cand = isel;
1278 : }
1279 2283 : if (!single_value && isel && !case_when->cand) {
1280 308 : case_when = stmt_project(be, isel, case_when);
1281 308 : case_when->cand = isel;
1282 : }
1283 :
1284 : /*
1285 : * left - isel: calls down need id's from the range of left
1286 : * res - rsel: updates to res need id's in the range from res
1287 : */
1288 32030 : for (en = en->next; en; en = en->next) {
1289 29747 : sql_exp *e = en->data;
1290 :
1291 29747 : next_cond = next_cond && en->next; /* last else is only a value */
1292 :
1293 29747 : stmt *nsel = rsel;
1294 29747 : if (!single_value) {
1295 28919 : if (/*!next_cond &&*/ rsel && isel) {
1296 : /* back into left range */
1297 3954 : nsel = stmt_project(be, rsel, isel);
1298 24965 : } else if (isel && !rsel)
1299 29747 : nsel = isel;
1300 : }
1301 29747 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1302 :
1303 29747 : if (!es)
1304 : return NULL;
1305 29747 : if (next_cond) {
1306 13732 : stmt *l = case_when;
1307 13732 : if (!single_value) {
1308 13361 : if (rsel && isel) {
1309 1662 : assert(l->cand == isel);
1310 1662 : l = stmt_project(be, rsel, l);
1311 1662 : l->cand = nsel;
1312 : }
1313 :
1314 13361 : if (es->cand && !l->cand) {
1315 9 : assert(es->cand == rsel);
1316 9 : l = stmt_project(be, es->cand, l);
1317 9 : l->cand = es->cand;
1318 13352 : } else if (nsel && !es->cand) {
1319 11468 : es = stmt_project(be, nsel, es);
1320 11468 : es->cand = nsel;
1321 11468 : if (!l->cand) {
1322 9493 : l = stmt_project(be, nsel, l);
1323 9493 : l->cand = nsel;
1324 : }
1325 : }
1326 13361 : assert(l->cand == es->cand);
1327 : }
1328 13732 : es = stmt_binop(be, l, es, NULL, cmp);
1329 : }
1330 29747 : if (!single_value) {
1331 : /* create result */
1332 28919 : if (!res) {
1333 2197 : stmt *l = isel;
1334 2197 : if (!l)
1335 1882 : l = bin_find_smallest_column(be, left);
1336 2197 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1337 2197 : ires = l;
1338 2197 : if (res)
1339 2197 : res->cand = isel;
1340 26722 : } else if (res && !next_cond) { /* use result to update column */
1341 15558 : stmt *val = es;
1342 15558 : stmt *pos = rsel;
1343 :
1344 15558 : if (val->nrcols == 0)
1345 13888 : val = stmt_const(be, pos, val);
1346 1670 : else if (!val->cand && nsel)
1347 209 : val = stmt_project(be, nsel, val);
1348 15558 : res = stmt_replace(be, res, pos, val);
1349 :
1350 15558 : assert(cond);
1351 :
1352 15558 : if (en->next) {
1353 : /* osel - rsel */
1354 13361 : if (!osel)
1355 2197 : osel = stmt_mirror(be, ires);
1356 13361 : stmt *d = stmt_tdiff(be, osel, rsel, NULL);
1357 13361 : osel = rsel = stmt_project(be, d, osel);
1358 : }
1359 : }
1360 28919 : if (next_cond) {
1361 13361 : ncond = cond = es;
1362 13361 : if (!ncond->nrcols) {
1363 0 : if (osel) {
1364 0 : ncond = stmt_const(be, nsel, ncond);
1365 0 : ncond->cand = nsel;
1366 0 : } else if (isel) {
1367 0 : ncond = stmt_const(be, isel, ncond);
1368 0 : ncond->cand = isel;
1369 : } else
1370 0 : ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
1371 : }
1372 13361 : if (isel && !ncond->cand)
1373 0 : ncond = stmt_project(be, nsel, ncond);
1374 24840 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
1375 13361 : if (rsel && ncond->cand)
1376 11164 : rsel = stmt_project(be, s, rsel);
1377 : else
1378 : rsel = s;
1379 : }
1380 : } else {
1381 828 : if (!res) {
1382 : /* if_barrier ... */
1383 371 : assert(next_cond);
1384 371 : if (next_cond) {
1385 371 : if (cond) {
1386 285 : ncond = stmt_binop(be, cond, es, nsel, and);
1387 : } else {
1388 : ncond = es;
1389 : }
1390 : cond = es;
1391 : }
1392 : } else {
1393 : /* var_x = s */
1394 457 : (void)stmt_assign(be, NULL, nme, es, 2);
1395 : /* endif_barrier */
1396 457 : (void)stmt_control_end(be, res);
1397 457 : res = NULL;
1398 :
1399 457 : if (en->next) {
1400 371 : cond = stmt_unop(be, cond, nsel, not);
1401 :
1402 371 : sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
1403 371 : cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
1404 371 : if (ocond)
1405 285 : cond = stmt_binop(be, ocond, cond, nsel, and);
1406 371 : ocond = cond;
1407 371 : if (!en->next->next)
1408 86 : ncond = cond;
1409 : }
1410 : }
1411 828 : if (ncond && (next_cond || (en->next && !en->next->next))) {
1412 : /* if_barrier ... */
1413 457 : res = stmt_cond(be, ncond, NULL, 0, 0);
1414 : }
1415 : }
1416 29747 : next_cond = !next_cond;
1417 : }
1418 2283 : if (single_value)
1419 86 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1420 : return res;
1421 : }
1422 :
1423 : static stmt*
1424 527 : exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
1425 : {
1426 527 : stmt *res = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL;
1427 527 : int single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
1428 527 : char name[16], *nme = NULL;
1429 527 : sql_subtype *bt = sql_bind_localtype("bit");
1430 527 : sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
1431 527 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
1432 :
1433 527 : if (single_value) {
1434 : /* var_x = nil; */
1435 57 : nme = number2name(name, sizeof(name), ++be->mvc->label);
1436 57 : (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
1437 : }
1438 :
1439 527 : list *exps = fe->l;
1440 2028 : for (node *en = exps->h; en; en = en->next) {
1441 1501 : sql_exp *e = en->data;
1442 :
1443 1501 : stmt *nsel = rsel;
1444 1501 : if (!single_value) {
1445 1346 : if (/*!next_cond &&*/ rsel && isel) {
1446 : /* back into left range */
1447 48 : nsel = stmt_project(be, rsel, isel);
1448 1298 : } else if (isel && !rsel)
1449 1501 : nsel = isel;
1450 : }
1451 1501 : stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
1452 :
1453 1501 : if (!es)
1454 : return NULL;
1455 : /* create result */
1456 1501 : if (!single_value) {
1457 1346 : if (!res) {
1458 470 : stmt *l = isel;
1459 470 : if (!l)
1460 436 : l = bin_find_smallest_column(be, left);
1461 470 : res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
1462 470 : if (res)
1463 470 : res->cand = isel;
1464 : }
1465 470 : if (res) {
1466 1346 : stmt *val = es;
1467 1346 : stmt *pos = rsel;
1468 :
1469 1346 : if (en->next) {
1470 876 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1471 876 : ncond = stmt_unop(be, es, NULL, a);
1472 876 : if (ncond->nrcols == 0) {
1473 120 : stmt *l = bin_find_smallest_column(be, left);
1474 120 : if (nsel && l)
1475 61 : l = stmt_project(be, nsel, l);
1476 120 : ncond = stmt_const(be, l, ncond);
1477 120 : if (nsel)
1478 61 : ncond->cand = nsel;
1479 756 : } else if (!ncond->cand && nsel)
1480 348 : ncond = stmt_project(be, nsel, ncond);
1481 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0);
1482 876 : if (!val->cand && nsel)
1483 409 : val = stmt_project(be, nsel, val);
1484 876 : val = stmt_project(be, s, val);
1485 876 : if (osel)
1486 406 : rsel = stmt_project(be, s, osel);
1487 : else
1488 : rsel = s;
1489 876 : pos = rsel;
1490 876 : val->cand = pos;
1491 : }
1492 1346 : if (val->nrcols == 0)
1493 163 : val = stmt_const(be, pos, val);
1494 1183 : else if (!val->cand && nsel)
1495 171 : val = stmt_project(be, nsel, val);
1496 :
1497 1346 : res = stmt_replace(be, res, pos, val);
1498 : }
1499 1346 : if (en->next) { /* handled then part */
1500 876 : stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0);
1501 876 : if (osel)
1502 406 : rsel = stmt_project(be, s, osel);
1503 : else
1504 : rsel = s;
1505 : osel = rsel;
1506 : }
1507 : } else {
1508 155 : stmt *cond = ocond;
1509 155 : if (en->next) {
1510 98 : sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
1511 98 : ncond = stmt_unop(be, es, nsel, a);
1512 :
1513 98 : if (ocond)
1514 41 : cond = stmt_binop(be, ocond, ncond, nsel, and);
1515 : else
1516 : cond = ncond;
1517 : }
1518 :
1519 : /* if_barrier ... */
1520 155 : stmt *b = stmt_cond(be, cond, NULL, 0, 0);
1521 : /* var_x = s */
1522 155 : (void)stmt_assign(be, NULL, nme, es, 2);
1523 : /* endif_barrier */
1524 155 : (void)stmt_control_end(be, b);
1525 :
1526 155 : cond = stmt_unop(be, ncond, nsel, not);
1527 155 : if (ocond)
1528 98 : ocond = stmt_binop(be, cond, ocond, nsel, and);
1529 : else
1530 : ocond = cond;
1531 : }
1532 : }
1533 527 : if (single_value)
1534 57 : return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
1535 : return res;
1536 : }
1537 :
1538 : // This is the per-column portion of exp2bin_copyfrombinary
1539 : static stmt *
1540 216 : emit_loadcolumn(backend *be, stmt *onclient_stmt, stmt *bswap_stmt, int *count_var, node *file_node, node *type_node)
1541 : {
1542 216 : MalBlkPtr mb = be->mb;
1543 :
1544 216 : sql_exp *file_exp = file_node->data;
1545 216 : stmt *file_stmt = exp_bin(be, file_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1546 216 : sql_subtype *subtype = type_node->data;
1547 216 : int data_type = subtype->type->localtype;
1548 216 : int bat_type = newBatType(data_type);
1549 :
1550 : // The sql.importColumn operator takes a 'method' string to determine how to
1551 : // load the data. This leaves the door open to have multiple loaders for the
1552 : // same backend type, for example nul- and newline terminated strings.
1553 : // For the time being we just use the name of the storage type as the method
1554 : // name.
1555 216 : const char *method = ATOMname(data_type);
1556 :
1557 216 : int width;
1558 216 : switch (subtype->type->eclass) {
1559 37 : case EC_DEC:
1560 : case EC_STRING:
1561 37 : width = subtype->digits;
1562 37 : break;
1563 : default:
1564 : width = 0;
1565 : break;
1566 : }
1567 :
1568 216 : int new_count_var = newTmpVariable(mb, TYPE_oid);
1569 :
1570 216 : InstrPtr p = newStmt(mb, sqlRef, importColumnRef);
1571 216 : if (p != NULL) {
1572 216 : setArgType(mb, p, 0, bat_type);
1573 216 : p = pushReturn(mb, p, new_count_var);
1574 : //
1575 216 : p = pushStr(mb, p, method);
1576 216 : p = pushInt(mb, p, width);
1577 216 : p = pushArgument(mb, p, bswap_stmt->nr);
1578 216 : p = pushArgument(mb, p, file_stmt->nr);
1579 216 : p = pushArgument(mb, p, onclient_stmt->nr);
1580 216 : if (*count_var < 0)
1581 94 : p = pushOid(mb, p, 0);
1582 : else
1583 122 : p = pushArgument(mb, p, *count_var);
1584 216 : pushInstruction(mb, p);
1585 : }
1586 216 : if (p == NULL || mb->errors) {
1587 0 : if (be->mvc->sa->eb.enabled)
1588 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
1589 0 : return sql_error(be->mvc, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1590 : }
1591 :
1592 216 : *count_var = new_count_var;
1593 :
1594 216 : stmt *s = stmt_blackbox_result(be, p, 0, subtype);
1595 216 : return s;
1596 : }
1597 :
1598 : // Try to predict which column will be quickest to load first
1599 : static int
1600 216 : node_type_score(node *n)
1601 : {
1602 216 : sql_subtype *st = n->data;
1603 216 : int tpe = st->type->localtype;
1604 216 : int stpe = ATOMstorage(tpe);
1605 216 : int score = stpe + (stpe == TYPE_bit);
1606 216 : return score;
1607 : }
1608 :
1609 : static stmt*
1610 94 : exp2bin_copyfrombinary(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel)
1611 : {
1612 94 : mvc *sql = be->mvc;
1613 94 : assert(left == NULL); (void)left;
1614 94 : assert(right == NULL); (void)right;
1615 94 : assert(isel == NULL); (void)isel;
1616 94 : sql_subfunc *f = fe->f;
1617 :
1618 94 : list *arg_list = fe->l;
1619 94 : list *type_list = f->res;
1620 94 : assert(4 + list_length(type_list) == list_length(arg_list));
1621 :
1622 94 : sql_exp * onclient_exp = arg_list->h->next->next->data;
1623 94 : stmt *onclient_stmt = exp_bin(be, onclient_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1624 94 : sql_exp *bswap_exp = arg_list->h->next->next->next->data;
1625 94 : stmt *bswap_stmt = exp_bin(be, bswap_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
1626 :
1627 : // If it's ON SERVER we can optimize by running the imports in parallel
1628 94 : bool onserver = false;
1629 94 : if (onclient_exp->type == e_atom) {
1630 94 : atom *onclient_atom = onclient_exp->l;
1631 94 : int onclient = onclient_atom->data.val.ival;
1632 94 : onserver = (onclient == 0);
1633 : }
1634 :
1635 94 : node *const first_file = arg_list->h->next->next->next->next;
1636 94 : node *const first_type = type_list->h;
1637 94 : node *file, *type;
1638 :
1639 : // The first column we load determines the number of rows.
1640 : // We pass it on to the other columns.
1641 : // The first column to load should therefore be an 'easy' one.
1642 : // We identify the columns by the address of their type node.
1643 94 : node *prototype_file = first_file;
1644 94 : node *prototype_type = first_type;
1645 94 : int score = node_type_score(prototype_type);
1646 216 : for (file = first_file->next, type = first_type->next; file && type; file = file->next, type = type->next) {
1647 122 : int sc = node_type_score(type);
1648 122 : if (sc < score) {
1649 6 : prototype_file = file;
1650 6 : prototype_type = type;
1651 6 : score = sc;
1652 : }
1653 : }
1654 :
1655 : // Emit the columns
1656 94 : int count_var = -1;
1657 94 : list *columns = sa_list(sql->sa);
1658 94 : if (columns == NULL)
1659 : return NULL;
1660 94 : stmt *prototype_stmt = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, prototype_file, prototype_type);
1661 94 : if (!prototype_stmt)
1662 : return NULL;
1663 94 : int orig_count_var = count_var;
1664 310 : for (file = first_file, type = first_type; file && type; file = file->next, type = type->next) {
1665 216 : stmt *s;
1666 216 : if (type == prototype_type) {
1667 : s = prototype_stmt;
1668 : } else {
1669 122 : s = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, file, type);
1670 122 : if (!s)
1671 : return NULL;
1672 : }
1673 216 : list_append(columns, s);
1674 216 : if (onserver) {
1675 : // Not threading the count variable from one importColumn to the next
1676 : // makes it possible to run them in parallel in a dataflow region.
1677 106 : count_var = orig_count_var;
1678 : }
1679 : }
1680 :
1681 94 : return stmt_list(be, columns);
1682 : }
1683 :
1684 : static bool
1685 237 : is_const_func(sql_subfunc *f, list *attr)
1686 : {
1687 237 : if (list_length(attr) != 2)
1688 : return false;
1689 134 : if (strcmp(f->func->base.name, "quantile") == 0 ||
1690 107 : strcmp(f->func->base.name, "quantile_avg") == 0)
1691 30 : return true;
1692 : return false;
1693 : }
1694 :
1695 : static stmt*
1696 0 : exp2bin_multiset(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
1697 : {
1698 0 : assert(0);
1699 : return left;
1700 : (void)fe;
1701 : (void)right;
1702 : (void)sel;
1703 : list *l = sa_list(be->mvc->sa);
1704 : for(node *n = left->op4.lval->h; n; n = n->next) {
1705 : stmt *s = n->data, *ns = s;
1706 : while(ns->type == st_alias)
1707 : ns = ns->op1;
1708 : if (ns->type == st_list) {
1709 : for(node *m = ns->op4.lval->h; m; m = m->next)
1710 : append(l, m->data);
1711 : } else {
1712 : append(l, s);
1713 : }
1714 : }
1715 : return stmt_list(be, l);
1716 : }
1717 :
1718 : static stmt*
1719 20 : exp2bin_file_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
1720 : {
1721 20 : assert(left == NULL); (void)left;
1722 20 : assert(right == NULL); (void)right;
1723 20 : assert(sel == NULL); (void)sel;
1724 20 : sql_subfunc *f = fe->f;
1725 :
1726 20 : list *arg_list = fe->l;
1727 : /*
1728 : list *type_list = f->res;
1729 : assert(1 + list_length(type_list) == list_length(arg_list));
1730 : */
1731 :
1732 20 : sql_exp *eexp = arg_list->h->next->data;
1733 20 : assert(is_atom(eexp->type));
1734 20 : atom *ea = eexp->l;
1735 20 : assert(ea->data.vtype == TYPE_str);
1736 20 : char *ext = ea->data.val.sval;
1737 :
1738 20 : file_loader_t *fl = fl_find(ext);
1739 20 : if (!fl)
1740 0 : fl = fl_find("csv");
1741 0 : if (!fl)
1742 : return NULL;
1743 20 : sql_exp *fexp = arg_list->h->data;
1744 20 : assert(is_atom(fexp->type));
1745 20 : atom *fa = fexp->l;
1746 20 : assert(fa->data.vtype == TYPE_str);
1747 20 : char *filename = fa->data.val.sval;
1748 20 : sql_exp *topn = NULL;
1749 20 : if (list_length(arg_list) == 3)
1750 0 : topn = list_fetch(arg_list, 2);
1751 20 : return (stmt*)fl->load(be, f, filename, topn);
1752 : }
1753 :
1754 : static stmt*
1755 53 : exp2bin_proto_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
1756 : {
1757 53 : assert(left == NULL); (void)left;
1758 53 : assert(right == NULL); (void)right;
1759 53 : assert(sel == NULL); (void)sel;
1760 53 : sql_subfunc *f = fe->f;
1761 :
1762 53 : list *arg_list = fe->l;
1763 : /*
1764 : list *type_list = f->res;
1765 : assert(1 + list_length(type_list) == list_length(arg_list));
1766 : */
1767 :
1768 53 : sql_exp *eexp = arg_list->h->next->data;
1769 53 : assert(is_atom(eexp->type));
1770 53 : atom *ea = eexp->l;
1771 53 : assert(ea->data.vtype == TYPE_str);
1772 53 : char *ext = ea->data.val.sval;
1773 :
1774 53 : proto_loader_t *pl = pl_find(ext);
1775 53 : if (!pl)
1776 0 : pl = pl_find("mapi");
1777 0 : if (!pl)
1778 : return NULL;
1779 53 : sql_exp *fexp = arg_list->h->data;
1780 53 : assert(is_atom(fexp->type));
1781 53 : atom *fa = fexp->l;
1782 53 : assert(fa->data.vtype == TYPE_str);
1783 53 : char *filename = fa->data.val.sval;
1784 53 : sql_exp *topn = NULL;
1785 53 : if (list_length(arg_list) == 3)
1786 0 : topn = list_fetch(arg_list, 2);
1787 53 : return (stmt*)pl->load(be, f, filename, topn);
1788 : }
1789 :
1790 : static stmt *
1791 52 : nested_stmts(backend *be, sql_exp *e, node **M)
1792 : {
1793 52 : assert(is_nested(e));
1794 52 : node *m = *M;
1795 52 : list *r = sa_list(be->mvc->sa);
1796 52 : list *exps = e->f;
1797 :
1798 52 : if (!list_empty(exps)) {
1799 229 : for (node *n = exps->h; n && m; n = n->next) {
1800 177 : sql_exp *e = n->data;
1801 201 : if (e->type == e_column && e->f) {
1802 24 : stmt *s = nested_stmts(be, e, &m);
1803 24 : s = stmt_alias(be, s, e->alias.label, exp_relname(e), exp_name(e));
1804 24 : s->subtype = *exp_subtype(e);
1805 24 : s->nested = true;
1806 24 : append(r, s);
1807 : } else {
1808 153 : stmt *s = m->data;
1809 153 : s = stmt_alias(be, s, e->alias.label, exp_relname(e), exp_name(e));
1810 153 : m = m->next;
1811 153 : append(r, s);
1812 : }
1813 : }
1814 : }
1815 52 : *M = m;
1816 52 : stmt *s = stmt_list(be, r);
1817 52 : s->nrcols = 3;
1818 52 : s->nested = true;
1819 52 : s->subtype = *exp_subtype(e);
1820 52 : s->multiset = s->subtype.multiset;
1821 52 : return s;
1822 : }
1823 :
1824 : stmt *
1825 5065879 : 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)
1826 : {
1827 5065879 : mvc *sql = be->mvc;
1828 5065879 : stmt *s = NULL;
1829 :
1830 5065879 : if (mvc_highwater(sql))
1831 0 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1832 :
1833 5067552 : if (!e) {
1834 0 : assert(0);
1835 : return NULL;
1836 : }
1837 :
1838 5067552 : switch(e->type) {
1839 7610 : case e_psm:
1840 7610 : if (e->flag & PSM_SET) {
1841 602 : stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1842 602 : if(!r)
1843 : return NULL;
1844 602 : if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
1845 6 : r = stmt_fetch(be, r);
1846 602 : return stmt_assign(be, exp_relname(e), exp_name(e), r, GET_PSM_LEVEL(e->flag));
1847 7008 : } else if (e->flag & PSM_VAR) {
1848 176 : if (e->f)
1849 20 : return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
1850 : else
1851 156 : return stmt_var(be, exp_relname(e), exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
1852 6832 : } else if (e->flag & PSM_RETURN) {
1853 665 : sql_exp *l = e->l;
1854 665 : stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel, 0, 0, push);
1855 :
1856 664 : if (!r)
1857 : return NULL;
1858 : /* handle table returning functions */
1859 664 : if (l->type == e_psm && l->flag & PSM_REL) {
1860 243 : stmt *lst = r->op1;
1861 283 : if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
1862 40 : node *n;
1863 40 : list *l = sa_list(sql->sa);
1864 40 : if (l == NULL)
1865 : return NULL;
1866 :
1867 86 : for (n=lst->op4.lval->h; n; n = n->next)
1868 46 : list_append(l, const_column(be, (stmt*)n->data));
1869 40 : r = stmt_list(be, l);
1870 203 : } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */
1871 35 : r = lst->op4.lval->h->data;
1872 35 : if (!r->aggr) /* if the cardinality is atom, no fetch call needed */
1873 4 : r = stmt_fetch(be, r);
1874 : }
1875 243 : if (r->type == st_list)
1876 40 : r = stmt_table(be, r, 1);
1877 : }
1878 664 : return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
1879 6167 : } else if (e->flag & PSM_WHILE) {
1880 : /* while is a if - block true with leave statement
1881 : * needed because the condition needs to be inside this outer block */
1882 17 : stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
1883 17 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1884 17 : stmt *wstmt;
1885 :
1886 17 : if(!cond)
1887 : return NULL;
1888 17 : wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
1889 :
1890 17 : if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
1891 : return NULL;
1892 17 : (void)stmt_control_end(be, wstmt);
1893 17 : return stmt_control_end(be, ifstmt);
1894 6150 : } else if (e->flag & PSM_IF) {
1895 240 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1896 240 : stmt *ifstmt, *res;
1897 :
1898 240 : if(!cond)
1899 : return NULL;
1900 240 : ifstmt = stmt_cond(be, cond, NULL, 0, 0);
1901 240 : if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
1902 : return NULL;
1903 240 : res = stmt_control_end(be, ifstmt);
1904 240 : if (e->f) {
1905 25 : stmt *elsestmt = stmt_cond(be, cond, NULL, 0, 1);
1906 :
1907 25 : if (!exp_list(be, e->f, left, right, grp, ext, cnt, sel))
1908 : return NULL;
1909 25 : res = stmt_control_end(be, elsestmt);
1910 : }
1911 240 : return res;
1912 5910 : } else if (e->flag & PSM_REL) {
1913 5753 : sql_rel *rel = e->l;
1914 5753 : stmt *r = rel_bin(be, rel);
1915 :
1916 5752 : if (!r)
1917 : return NULL;
1918 862 : if (is_modify(rel->op) || is_ddl(rel->op))
1919 : return r;
1920 649 : return stmt_table(be, r, 1);
1921 157 : } else if (e->flag & PSM_EXCEPTION) {
1922 157 : stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
1923 157 : if (!cond)
1924 : return NULL;
1925 157 : if (cond->nrcols)
1926 0 : cond = stmt_fetch(be, cond);
1927 157 : return stmt_exception(be, cond, (const char *) e->r, 0);
1928 : }
1929 : break;
1930 3438348 : case e_atom: {
1931 3438348 : if (e->l) { /* literals */
1932 3294563 : s = stmt_atom(be, e->l);
1933 143785 : } else if (e->r) { /* parameters and declared variables */
1934 2134 : sql_var_name *vname = (sql_var_name*) e->r;
1935 2134 : assert(vname->name);
1936 2134 : s = stmt_var(be, vname->sname ? a_create(sql->sa, sa_strdup(sql->sa, vname->sname)) : NULL, sa_strdup(sql->sa, vname->name), e->tpe.type?&e->tpe:NULL, 0, e->flag);
1937 141651 : } else if (e->f) { /* values */
1938 139601 : s = value_tvtree(be, e, left, sel);
1939 : } else { /* arguments */
1940 2050 : sql_subtype *t = e->tpe.type?&e->tpe:NULL;
1941 2050 : if (!t && 0) {
1942 : sql_arg *a = sql_bind_paramnr(be->mvc, e->flag);
1943 : t = a->type.type?&a->type:NULL;
1944 : }
1945 2050 : s = stmt_varnr(be, e->flag, t);
1946 : }
1947 : } break;
1948 50864 : case e_convert: {
1949 : /* if input is type any NULL or column of nulls, change type */
1950 50864 : list *tps = e->r;
1951 50864 : sql_subtype *from = tps->h->data;
1952 50864 : sql_subtype *to = tps->h->next->data;
1953 50864 : stmt *l;
1954 :
1955 50864 : if (from->type->localtype == 0) {
1956 751 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1957 751 : if (l)
1958 750 : l = stmt_atom(be, atom_general(sql->sa, to, NULL, 0));
1959 : } else {
1960 50113 : l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
1961 : }
1962 50863 : if (!l)
1963 237 : return NULL;
1964 50627 : if (from->type->eclass == EC_SEC && to->type->eclass == EC_SEC) {
1965 : // trivial conversion because EC_SEC is always in milliseconds
1966 : s = l;
1967 50983 : } else if (depth && sel && l->nrcols == 0 && left && left->nrcols && exp_unsafe(e, false, true)) {
1968 419 : stmt *rows = bin_find_smallest_column(be, left);
1969 419 : l = stmt_const(be, rows, l);
1970 419 : s = stmt_convert(be, l, sel, from, to);
1971 50409 : } else if (depth && l->nrcols == 0 && left && left->nrcols && from->type->localtype > to->type->localtype &&
1972 522 : exp_unsafe(e, false, true)) {
1973 258 : stmt *rows = bin_find_smallest_column(be, left);
1974 258 : l = stmt_const(be, rows, l);
1975 258 : s = stmt_convert(be, l, sel, from, to);
1976 : } else {
1977 90532 : s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, from, to);
1978 : }
1979 50627 : if (s && s->type == st_list && e->f) {
1980 28 : s = nested_stmts(be, e, &s->op4.lval->h);
1981 : }
1982 : } break;
1983 232040 : case e_func: {
1984 232040 : node *en;
1985 232040 : list *l = sa_list(sql->sa), *exps = e->l;
1986 232049 : sql_subfunc *f = e->f;
1987 232049 : const char *fname = f->func->base.name;
1988 232049 : stmt *rows = NULL;
1989 232049 : const char *mod, *fimp;
1990 :
1991 232049 : if (l == NULL)
1992 : return NULL;
1993 :
1994 : /* attempt to instantiate MAL functions now, so we can know if we can push candidate lists */
1995 232049 : if (f->func->lang == FUNC_LANG_MAL && backend_create_mal_func(be->mvc, f) < 0)
1996 : return NULL;
1997 232029 : mod = sql_func_mod(f->func);
1998 232027 : fimp = backend_function_imp(be, f->func);
1999 :
2000 232038 : if (f->func->side_effect && left && left->nrcols > 0 && f->func->type != F_LOADER && exps_card(exps) < CARD_MULTI) {
2001 105 : rows = bin_find_smallest_column(be, left);
2002 : }
2003 232038 : assert(!e->r);
2004 232038 : if (strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
2005 21817 : if (strcmp(fname, "star") == 0) {
2006 466 : if (!left)
2007 1 : return const_column(be, stmt_bool(be, 1));
2008 465 : return left->op4.lval->h->data;
2009 : }
2010 21351 : if (strcmp(fname, "case") == 0)
2011 18276 : return exp2bin_case(be, e, left, right, sel, depth);
2012 3075 : if (strcmp(fname, "casewhen") == 0)
2013 2283 : return exp2bin_casewhen(be, e, left, right, sel, depth);
2014 792 : if (strcmp(fname, "coalesce") == 0)
2015 527 : return exp2bin_coalesce(be, e, left, right, sel, depth);
2016 265 : if (strcmp(fname, "copyfrombinary") == 0)
2017 94 : return exp2bin_copyfrombinary(be, e, left, right, sel);
2018 171 : if (strcmp(fname, "file_loader") == 0)
2019 20 : return exp2bin_file_loader(be, e, left, right, sel);
2020 151 : if (strcmp(fname, "proto_loader") == 0)
2021 53 : return exp2bin_proto_loader(be, e, left, right, sel);
2022 98 : if (strcmp(fname, "multiset") == 0)
2023 0 : return exp2bin_multiset(be, e, left, right, sel);
2024 98 : if (strcmp(fname, "-1") == 0) /* map arguments to A0 .. An */
2025 3 : return exp2bin_named_placeholders(be, e);
2026 : }
2027 210316 : if (!list_empty(exps)) {
2028 208425 : unsigned nrcols = 0;
2029 208425 : int push_cands = can_push_cands(sel, mod, fimp);
2030 :
2031 582740 : for (en = exps->h; en; en = en->next) {
2032 384905 : sql_exp *e = en->data;
2033 651519 : stmt *es = exp_bin(be, e, left, right, grp, ext, cnt, (push_cands)?sel:NULL, depth+1, 0, push);
2034 :
2035 384913 : if (!es)
2036 : return NULL;
2037 : /*if (rows && en == exps->h && f->func->type != F_LOADER)
2038 : es = stmt_const(be, rows, es);*/
2039 374344 : else if (f->func->type == F_ANALYTIC && es->nrcols == 0) {
2040 7827 : if (en == exps->h && left && left->nrcols)
2041 464 : es = stmt_const(be, bin_find_smallest_column(be, left), es); /* ensure the first argument is a column */
2042 7827 : if (!f->func->s && !strcmp(f->func->base.name, "window_bound")
2043 3277 : && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next && left->nrcols)
2044 2 : es = stmt_const(be, bin_find_smallest_column(be, left), es);
2045 : }
2046 374344 : if (es->nrcols > nrcols)
2047 : nrcols = es->nrcols;
2048 374344 : list_append(l, es);
2049 : }
2050 : }
2051 199723 : if (!(s = stmt_Nop(be, stmt_list(be, l), sel, f, rows)))
2052 : return NULL;
2053 : } break;
2054 11079 : case e_aggr: {
2055 11079 : list *attr = e->l;
2056 11079 : list *r = e->r;
2057 11079 : stmt *as = NULL;
2058 11079 : sql_subfunc *a = e->f;
2059 :
2060 11079 : assert(sel == NULL);
2061 : /* cases
2062 : * 0) count(*)
2063 : * 1) general aggregation
2064 : * 2) aggregation with required order (quantile etc)
2065 : * 3) aggregation with optional order by, group_concat, xml_agg
2066 : * */
2067 16859 : if (attr && attr->h) {
2068 5781 : node *en;
2069 5781 : list *l = sa_list(sql->sa);
2070 :
2071 11983 : for (en = attr->h; en; en = en->next) {
2072 6203 : sql_exp *at = en->data;
2073 :
2074 6203 : as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
2075 :
2076 6203 : if (as && as->nrcols <= 0 && left && (!is_const_func(a, attr) || grp))
2077 219 : as = stmt_const(be, bin_find_smallest_column(be, left), as);
2078 6203 : if (en == attr->h && !en->next && exp_aggr_is_count(e))
2079 138 : as = exp_count_no_nil_arg(e, ext, at, as);
2080 : /* insert single value into a column */
2081 6203 : if (as && as->nrcols <= 0 && !left)
2082 161 : as = const_column(be, as);
2083 :
2084 179 : if (!as)
2085 1 : return NULL;
2086 6202 : append(l, as);
2087 : }
2088 5780 : if (need_distinct(e) && (grp || list_length(l) > 1)){
2089 26 : list *nl = sa_list(sql->sa);
2090 26 : stmt *ngrp = grp;
2091 26 : stmt *next = ext;
2092 26 : stmt *ncnt = cnt;
2093 26 : if (nl == NULL)
2094 : return NULL;
2095 54 : for (en = l->h; en; en = en->next) {
2096 28 : stmt *as = en->data;
2097 28 : stmt *g = stmt_group(be, as, ngrp, next, ncnt, 1);
2098 28 : ngrp = stmt_result(be, g, 0);
2099 28 : next = stmt_result(be, g, 1);
2100 28 : ncnt = stmt_result(be, g, 2);
2101 : }
2102 54 : for (en = l->h; en; en = en->next) {
2103 28 : stmt *as = en->data;
2104 28 : append(nl, stmt_project(be, next, as));
2105 : }
2106 26 : if (grp)
2107 25 : grp = stmt_project(be, next, grp);
2108 : l = nl;
2109 5754 : } else if (need_distinct(e)) {
2110 76 : stmt *a = l->h->data;
2111 76 : stmt *u = stmt_unique(be, a);
2112 76 : if (u == NULL)
2113 : return NULL;
2114 76 : l = sa_list(sql->sa);
2115 76 : if (l == NULL)
2116 : return NULL;
2117 76 : append(l, stmt_project(be, u, a));
2118 : }
2119 5780 : if (r) {
2120 22 : list *obe = r->h->data;
2121 22 : if (obe && obe->h) {
2122 22 : stmt *orderby = NULL, *orderby_vals, *orderby_ids, *orderby_grp;
2123 : /* order by */
2124 22 : if (grp) {
2125 22 : orderby = stmt_order(be, grp, true, true);
2126 :
2127 22 : orderby_vals = stmt_result(be, orderby, 0);
2128 22 : orderby_ids = stmt_result(be, orderby, 1);
2129 22 : orderby_grp = stmt_result(be, orderby, 2);
2130 : }
2131 44 : for (node *n = obe->h; n; n = n->next) {
2132 22 : sql_exp *oe = n->data;
2133 22 : stmt *os = exp_bin(be, oe, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
2134 22 : if (orderby)
2135 22 : orderby = stmt_reorder(be, os, is_ascending(oe), nulls_last(oe), orderby_ids, orderby_grp);
2136 : else
2137 0 : orderby = stmt_order(be, os, is_ascending(oe), nulls_last(oe));
2138 22 : orderby_vals = stmt_result(be, orderby, 0);
2139 22 : orderby_ids = stmt_result(be, orderby, 1);
2140 22 : orderby_grp = stmt_result(be, orderby, 2);
2141 : }
2142 : /* depending on type of aggr project input or ordered column */
2143 22 : stmt *h = l->h->data;
2144 22 : l->h->data = h = stmt_project(be, orderby_ids, h);
2145 22 : if (grp)
2146 22 : grp = stmt_project(be, orderby_ids, grp);
2147 5780 : (void)orderby_vals;
2148 : }
2149 : }
2150 5780 : as = stmt_list(be, l);
2151 : } else {
2152 : /* count(*) may need the default group (relation) and
2153 : and/or an attribute to count */
2154 5298 : if (grp) {
2155 : as = grp;
2156 1508 : } else if (left && !list_empty(left->op4.lval)) {
2157 1507 : as = bin_find_smallest_column(be, left);
2158 1507 : as = exp_count_no_nil_arg(e, ext, NULL, as);
2159 : } else {
2160 : /* create dummy single value in a column */
2161 1 : as = stmt_atom_lng(be, 0);
2162 1 : as = const_column(be, as);
2163 : }
2164 : }
2165 11078 : s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e));
2166 : //if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
2167 : //s->flag |= OUTER_ZERO;
2168 11078 : } break;
2169 1159927 : case e_column: {
2170 1159927 : if (right) /* check relation names */
2171 : //s = bin_find_column(be, right, e->l, e->r);
2172 56312 : s = bin_find_column_nid(be, right, e->nid);
2173 1159927 : if (!s && left)
2174 : //s = bin_find_column(be, left, e->l, e->r);
2175 1112898 : s = bin_find_column_nid(be, left, e->nid);
2176 1159897 : if (s && grp)
2177 290 : s = stmt_project(be, ext, s);
2178 1159897 : if (!s && right) {
2179 0 : TRC_CRITICAL(SQL_EXECUTION, "Could not find %s.%s\n", (char*)e->l, (char*)e->r);
2180 0 : print_stmtlist(sql->sa, left);
2181 0 : print_stmtlist(sql->sa, right);
2182 0 : if (!s) {
2183 0 : TRC_ERROR(SQL_EXECUTION, "Query: '%s'\n", be->client->query);
2184 : }
2185 0 : assert(s);
2186 : return NULL;
2187 : }
2188 : } break;
2189 167684 : case e_cmp: {
2190 167684 : stmt *l = NULL, *r = NULL, *r2 = NULL;
2191 167684 : int swapped = 0, is_select = 0, oldvtop, oldstop;
2192 167684 : sql_exp *re = e->r, *re2 = e->f;
2193 :
2194 : /* general predicate, select and join */
2195 167684 : if (e->flag == cmp_filter) {
2196 4607 : list *args;
2197 4607 : list *ops;
2198 4607 : node *n;
2199 4607 : int first = 1;
2200 :
2201 4607 : ops = sa_list(sql->sa);
2202 4607 : if (ops == NULL)
2203 : return NULL;
2204 4607 : args = e->l;
2205 9212 : for (n = args->h; n; n = n->next) {
2206 4607 : oldvtop = be->mb->vtop;
2207 4607 : oldstop = be->mb->stop;
2208 4607 : s = NULL;
2209 4607 : if (!swapped)
2210 4607 : s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
2211 4607 : if (!s && right && (first || swapped)) {
2212 4 : clean_mal_statements(be, oldstop, oldvtop);
2213 4 : s = exp_bin(be, n->data, right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
2214 4 : swapped = 1;
2215 : }
2216 4607 : if (!s)
2217 : return s;
2218 4605 : if (s->nrcols == 0 && first && left)
2219 619 : s = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), s);
2220 4605 : list_append(ops, s);
2221 4605 : first = 0;
2222 : }
2223 4605 : l = stmt_list(be, ops);
2224 4605 : ops = sa_list(sql->sa);
2225 4605 : if (ops == NULL)
2226 : return NULL;
2227 4605 : args = e->r;
2228 17956 : for (n = args->h; n; n = n->next) {
2229 13461 : s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
2230 13351 : if (!s)
2231 : return s;
2232 13351 : list_append(ops, s);
2233 : }
2234 4605 : r = stmt_list(be, ops);
2235 :
2236 4605 : if (!reduce) {
2237 440 : sql_subfunc *f = e->f;
2238 440 : list *ops = sa_list(sql->sa);
2239 880 : for (node *n = l->op4.lval->h ; n ; n = n->next)
2240 440 : append(ops, n->data);
2241 1629 : for (node *n = r->op4.lval->h ; n ; n = n->next)
2242 1189 : append(ops, n->data);
2243 440 : if (!(s = stmt_Nop(be, stmt_list(be, ops), sel, f, NULL)))
2244 : return NULL;
2245 : return s;
2246 : }
2247 :
2248 4165 : if (left && right && (exps_card(e->r) != CARD_ATOM || !exps_are_atoms(e->r))) {
2249 48 : sql_subfunc *f = e->f;
2250 48 : bool first = true;
2251 96 : for (node *n = l->op4.lval->h ; n ; n = n->next) {
2252 48 : stmt *s = n->data;
2253 48 : if (s->nrcols == 0) {
2254 0 : if (first)
2255 0 : n->data = stmt_const(be, bin_find_smallest_column(be, left), n->data);
2256 : else
2257 0 : n->data = column(be, s);
2258 : }
2259 48 : first = false;
2260 : }
2261 48 : first = true;
2262 158 : for (node *n = r->op4.lval->h ; n ; n = n->next) {
2263 110 : stmt *s = n->data;
2264 110 : if (s->nrcols == 0) {
2265 61 : if (first)
2266 3 : n->data = stmt_const(be, bin_find_smallest_column(be, right), s);
2267 : else /* last arg maybe const */
2268 58 : n->data = column(be, s);
2269 : }
2270 110 : first = false;
2271 : }
2272 48 : return stmt_genjoin(be, l, r, f, is_anti(e), swapped);
2273 : }
2274 4117 : assert(!swapped);
2275 4117 : s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
2276 4117 : return s;
2277 : }
2278 163077 : if (e->flag == cmp_in || e->flag == cmp_notin)
2279 15751 : return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), depth, reduce, push);
2280 147326 : if (e->flag == cmp_or && (!right || right->nrcols == 1))
2281 10025 : return exp_bin_or(be, e, left, right, grp, ext, cnt, sel, depth, reduce, push);
2282 137301 : if (e->flag == cmp_or && right) { /* join */
2283 0 : assert(0);
2284 : }
2285 :
2286 : /* mark use of join indices */
2287 137301 : if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
2288 623 : be->join_idx++;
2289 :
2290 137301 : oldvtop = be->mb->vtop;
2291 137301 : oldstop = be->mb->stop;
2292 137301 : if (!l) {
2293 273661 : l = exp_bin(be, e->l, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
2294 137301 : swapped = 0;
2295 : }
2296 137301 : if (!l && right) {
2297 17932 : clean_mal_statements(be, oldstop, oldvtop);
2298 17932 : l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
2299 17932 : swapped = 1;
2300 : }
2301 :
2302 137301 : oldvtop = be->mb->vtop;
2303 137301 : oldstop = be->mb->stop;
2304 137301 : if (swapped || !right || !reduce)
2305 91374 : r = exp_bin(be, re, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
2306 : else
2307 46864 : r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
2308 137301 : if (!r && !swapped) {
2309 2 : clean_mal_statements(be, oldstop, oldvtop);
2310 2 : r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel, depth+1, 0, push);
2311 2 : is_select = 1;
2312 : }
2313 137301 : if (!r && swapped) {
2314 0 : clean_mal_statements(be, oldstop, oldvtop);
2315 0 : r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
2316 0 : is_select = 1;
2317 : }
2318 137301 : if (re2 && (swapped || !right || !reduce))
2319 5309 : r2 = exp_bin(be, re2, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
2320 52 : else if (re2)
2321 52 : r2 = exp_bin(be, re2, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
2322 :
2323 137301 : if (!l || !r || (re2 && !r2))
2324 : return NULL;
2325 :
2326 137297 : (void)is_select;
2327 137297 : if (reduce && left && right) {
2328 64796 : if (l->nrcols == 0)
2329 0 : l = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), l);
2330 64796 : if (r->nrcols == 0)
2331 4 : r = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r);
2332 64796 : if (r2 && r2->nrcols == 0)
2333 8 : r2 = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r2);
2334 4 : if (r2) {
2335 54 : s = stmt_join2(be, l, r, r2, (comp_type)e->flag, is_anti(e), is_symmetric(e), swapped);
2336 64742 : } else if (swapped) {
2337 17930 : s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag), 0, is_semantics(e), false);
2338 : } else {
2339 46812 : s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag, 0, is_semantics(e), false);
2340 : }
2341 : } else {
2342 72501 : if (r2) { /* handle all cases in stmt_uselect, reducing, non reducing, scalar etc */
2343 5059 : if (l->nrcols == 0 && ((sel && sel->nrcols > 0) || r->nrcols > 0 || r2->nrcols > 0 || reduce))
2344 54 : l = left ? stmt_const(be, bin_find_smallest_column(be, left), l) : column(be, l);
2345 5059 : s = stmt_uselect2(be, l, r, r2, (comp_type)e->flag, sel, is_anti(e), is_symmetric(e), reduce);
2346 : } else {
2347 : /* value compare or select */
2348 67442 : if (!reduce || (l->nrcols == 0 && r->nrcols == 0)) {
2349 913 : sql_subfunc *f = sql_bind_func(sql, "sys", compare_func((comp_type)e->flag, is_anti(e)),
2350 : tail_type(l), tail_type(l), F_FUNC, true, true);
2351 913 : assert(f);
2352 913 : if (is_semantics(e)) {
2353 137 : if (exp_is_null(e->l) && exp_is_null(e->r) && (e->flag == cmp_equal || e->flag == cmp_notequal)) {
2354 4 : s = stmt_bool(be, e->flag == cmp_equal ? !is_anti(e): is_anti(e));
2355 : } else {
2356 133 : list *args = sa_list(sql->sa);
2357 133 : if (args == NULL)
2358 : return NULL;
2359 : /* add nil semantics bit */
2360 133 : list_append(args, l);
2361 133 : list_append(args, r);
2362 133 : list_append(args, stmt_bool(be, 1));
2363 133 : s = stmt_Nop(be, stmt_list(be, args), sel, f, NULL);
2364 : }
2365 : } else {
2366 776 : s = stmt_binop(be, l, r, sel, f);
2367 : }
2368 913 : if (l->cand)
2369 0 : s->cand = l->cand;
2370 913 : if (r->cand)
2371 0 : s->cand = r->cand;
2372 : } else {
2373 : /* this can still be a join (as relational algebra and single value subquery results still means joins */
2374 66529 : s = stmt_uselect(be, l, r, (comp_type)e->flag, sel, is_anti(e), is_semantics(e));
2375 : }
2376 : }
2377 : }
2378 : } break;
2379 : default:
2380 : ;
2381 : }
2382 : return s;
2383 : }
2384 :
2385 : static stmt *
2386 520096 : stmt_col(backend *be, sql_column *c, stmt *del, int part)
2387 : {
2388 520096 : stmt *sc = stmt_bat(be, c, del?del->tname:NULL, RDONLY, part);
2389 :
2390 520127 : if (isTable(c->t) && c->t->access != TABLE_READONLY &&
2391 506301 : (!isNew(c) || !isNew(c->t) /* alter */) &&
2392 491741 : (c->t->persistence == SQL_PERSIST || c->t->s) /*&& !c->t->commit_action*/) {
2393 491741 : stmt *u = stmt_bat(be, c, del?del->tname:NULL, RD_UPD_ID, part);
2394 491734 : assert(u);
2395 491734 : sc = stmt_project_delta(be, sc, u);
2396 491912 : if (c->storage_type && c->storage_type[0] == 'D') {
2397 176 : stmt *v = stmt_bat(be, c, del?del->tname:NULL, RD_EXT, part);
2398 176 : sc = stmt_dict(be, sc, v);
2399 491560 : } else if (c->storage_type && c->storage_type[0] == 'F') {
2400 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)));
2401 : }
2402 491736 : if (del)
2403 26082 : sc = stmt_project(be, del, sc);
2404 28386 : } else if (del) { /* always handle the deletes */
2405 6991 : sc = stmt_project(be, del, sc);
2406 : }
2407 520120 : return sc;
2408 : }
2409 :
2410 : static stmt *
2411 3601 : stmt_idx(backend *be, sql_idx *i, stmt *del, int part)
2412 : {
2413 3601 : stmt *sc = stmt_idxbat(be, i, del?del->tname:NULL, RDONLY, part);
2414 :
2415 3601 : if (isTable(i->t) && i->t->access != TABLE_READONLY &&
2416 3601 : (!isNew(i) || !isNew(i->t) /* alter */) &&
2417 2871 : (i->t->persistence == SQL_PERSIST || i->t->s) /*&& !i->t->commit_action*/) {
2418 2871 : stmt *u = stmt_idxbat(be, i, del?del->tname:NULL, RD_UPD_ID, part);
2419 2871 : sc = stmt_project_delta(be, sc, u);
2420 2871 : if (del)
2421 320 : sc = stmt_project(be, del, sc);
2422 730 : } else if (del) { /* always handle the deletes */
2423 618 : sc = stmt_project(be, del, sc);
2424 : }
2425 3601 : return sc;
2426 : }
2427 :
2428 : static int
2429 0 : stmt_set_type_param(mvc *sql, sql_subtype *type, stmt *param)
2430 : {
2431 0 : if (!type || !param || param->type != st_var)
2432 : return -1;
2433 :
2434 0 : if (set_type_param(sql, type, param->flag) == 0) {
2435 0 : param->subtype = *type;
2436 0 : return 0;
2437 : }
2438 : return -1;
2439 : }
2440 :
2441 : /* check_types tries to match the t type with the type of s if they don't
2442 : * match s is converted. Returns NULL on failure.
2443 : */
2444 : static stmt *
2445 5162 : check_types(backend *be, sql_subtype *t, stmt *s, check_type tpe)
2446 : {
2447 : /* TODO add checking of composite types */
2448 5162 : mvc *sql = be->mvc;
2449 5162 : int c, err = 0;
2450 5162 : sql_subtype *fromtype = tail_type(s);
2451 :
2452 5162 : if ((!fromtype || !fromtype->type) && stmt_set_type_param(sql, t, s) == 0)
2453 : return s;
2454 0 : if (!fromtype)
2455 0 : return sql_error(sql, 02, SQLSTATE(42000) "statement has no type information");
2456 :
2457 5162 : if (fromtype && subtype_cmp(t, fromtype) != 0) {
2458 1 : if (EC_INTERVAL(fromtype->type->eclass) && (t->type->eclass == EC_NUM || t->type->eclass == EC_POS) && t->digits < fromtype->digits) {
2459 : err = 1; /* conversion from interval to num depends on the number of digits */
2460 : } else {
2461 1 : c = sql_type_convert(fromtype->type->eclass, t->type->eclass);
2462 1 : if (!c || (c == 2 && tpe == type_set) || (c == 3 && tpe != type_cast)) {
2463 : err = 1;
2464 : } else {
2465 1 : s = stmt_convert(be, s, NULL, fromtype, t);
2466 : }
2467 : }
2468 : }
2469 1 : if (err) {
2470 0 : assert(!fromtype->type->composite && !t->type->composite);
2471 0 : stmt *res = sql_error(sql, 10, SQLSTATE(42000) "types %s(%u,%u) (%s) and %s(%u,%u) (%s) are not equal",
2472 : fromtype->type->base.name,
2473 : fromtype->digits,
2474 : fromtype->scale,
2475 : fromtype->type->d.impl,
2476 : t->type->base.name,
2477 : t->digits,
2478 : t->scale,
2479 : t->type->d.impl
2480 : );
2481 0 : return res;
2482 : }
2483 : return s;
2484 : }
2485 :
2486 : static stmt *
2487 6079 : sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
2488 : {
2489 6079 : mvc *sql = be->mvc;
2490 6079 : list *sl = sa_list(sql->sa);
2491 6079 : list *tl = sa_list(sql->sa);
2492 6079 : sql_subfunc *f = NULL;
2493 :
2494 6079 : if (sl == NULL || tl == NULL)
2495 : return NULL;
2496 6079 : list_append(sl, a1);
2497 6079 : list_append(tl, tail_type(a1));
2498 6079 : list_append(sl, a2);
2499 6079 : list_append(tl, tail_type(a2));
2500 6079 : list_append(sl, a3);
2501 6079 : list_append(tl, tail_type(a3));
2502 6079 : if (a4) {
2503 0 : list_append(sl, a4);
2504 0 : list_append(tl, tail_type(a4));
2505 : }
2506 :
2507 6079 : if ((f = sql_bind_func_(sql, "sys", fname, tl, F_FUNC, true, true, false)))
2508 6079 : return stmt_Nop(be, stmt_list(be, sl), NULL, f, NULL);
2509 0 : return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such operator '%s'", fname);
2510 : }
2511 :
2512 : static stmt *
2513 10 : parse_value(backend *be, sql_schema *s, char *query, sql_subtype *tpe, char emode)
2514 : {
2515 10 : sql_exp *e = NULL;
2516 :
2517 10 : if (!(e = rel_parse_val(be->mvc, s, query, tpe, emode, NULL)))
2518 : return NULL;
2519 10 : return exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
2520 : }
2521 :
2522 : static stmt *
2523 1212 : rel2bin_sql_table(backend *be, sql_table *t, list *aliases)
2524 : {
2525 1212 : mvc *sql = be->mvc;
2526 1212 : list *l = sa_list(sql->sa);
2527 1212 : node *n;
2528 1212 : stmt *dels = stmt_tid(be, t, 0);
2529 :
2530 1212 : if (l == NULL || dels == NULL)
2531 : return NULL;
2532 1212 : if (aliases) {
2533 20486 : for (n = aliases->h; n; n = n->next) {
2534 19274 : sql_exp *e = n->data;
2535 19274 : if (e->type != e_column)
2536 108 : continue;
2537 19166 : assert(e->type == e_column);
2538 19166 : char *name = e->r;
2539 19166 : if (name[0] == '%') {
2540 1206 : if (strcmp(name, TID)==0) {
2541 : /* tid function sql.tid(t) */
2542 :
2543 1206 : stmt *sc = dels?dels:stmt_tid(be, t, 0);
2544 1206 : sc = stmt_alias(be, sc, e->alias.label, sc->tname, TID);
2545 1206 : list_append(l, sc);
2546 : } else {
2547 0 : node *m = ol_find_name(t->idxs, name+1);
2548 0 : if (!m)
2549 0 : assert(0);
2550 0 : sql_idx *i = m->data;
2551 0 : stmt *sc = stmt_idx(be, i, dels, dels->partition);
2552 :
2553 : /* index names are prefixed, to make them independent */
2554 0 : sc = stmt_alias(be, sc, e->alias.label, sc->tname, sa_strconcat(sql->sa, "%", i->base.name));
2555 0 : list_append(l, sc);
2556 : }
2557 : } else {
2558 17960 : node *m = ol_find_name(t->columns, name);
2559 17960 : if (!m)
2560 0 : assert(0);
2561 17960 : sql_column *c = m->data;
2562 17960 : stmt *sc = stmt_col(be, c, dels, dels->partition);
2563 17960 : sc = stmt_alias(be, sc, e->alias.label, exp_relname(e), exp_name(e));
2564 17960 : list_append(l, sc);
2565 : }
2566 : }
2567 : } else {
2568 0 : assert(0);
2569 : sql_exp *e = NULL;
2570 : for (n = ol_first_node(t->columns); n; n = n->next) {
2571 : sql_column *c = n->data;
2572 : stmt *sc = stmt_col(be, c, dels, dels->partition);
2573 :
2574 : list_append(l, sc);
2575 : }
2576 : /* TID column */
2577 : if (ol_first_node(t->columns)) {
2578 : /* tid function sql.tid(t) */
2579 :
2580 : stmt *sc = dels?dels:stmt_tid(be, t, 0);
2581 : sc = stmt_alias(be, sc, e->alias.label, sc->tname, TID);
2582 : list_append(l, sc);
2583 : }
2584 : if (t->idxs) {
2585 : for (n = ol_first_node(t->idxs); n; n = n->next) {
2586 : sql_idx *i = n->data;
2587 : stmt *sc = stmt_idx(be, i, dels, dels->partition);
2588 :
2589 : /* index names are prefixed, to make them independent */
2590 : sc = stmt_alias(be, sc, e->alias.label, sc->tname, sa_strconcat(sql->sa, "%", i->base.name));
2591 : list_append(l, sc);
2592 : }
2593 : }
2594 : }
2595 1212 : return stmt_list(be, l);
2596 : }
2597 :
2598 : static node *
2599 487281 : find_next_sql_column(sql_table *t, node *n, const char *name)
2600 : {
2601 487281 : if (!n)
2602 148212 : n = t->columns->l->h;
2603 942092 : for(; n; n = n->next) {
2604 942091 : sql_column *c = n->data;
2605 942091 : if (strcmp(c->base.name, name) == 0)
2606 : break;
2607 : }
2608 487281 : return n;
2609 : }
2610 :
2611 : static stmt *
2612 57 : rel2bin_subtable(backend *be, sql_table *t, stmt *dels, sql_column *c, node *cn, list *exps)
2613 : {
2614 57 : mvc *sql = be->mvc;
2615 57 : list *l = sa_list(sql->sa);
2616 57 : stmt *col = NULL;
2617 :
2618 57 : if (c->type.multiset) {
2619 27 : t = mvc_bind_table(sql, c->t->s, c->storage_type);
2620 27 : if (!t)
2621 : return NULL;
2622 27 : dels = stmt_tid(be, t, false);
2623 27 : cn = NULL;
2624 : }
2625 242 : for (node *en = exps->h; en; en = en->next) {
2626 185 : sql_exp *exp = en->data;
2627 185 : sql_alias *rname = exp_relname(exp)?exp_relname(exp):exp->l;
2628 185 : const char *oname = exp->r;
2629 185 : stmt *s = NULL;
2630 :
2631 185 : assert(!is_func(exp->type));
2632 185 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
2633 : /* tid function sql.tid(t) */
2634 :
2635 0 : if (col)
2636 : s = stmt_mirror(be, col);
2637 : else {
2638 0 : s = dels?dels:stmt_tid(be, t, 0);
2639 : dels = NULL;
2640 : }
2641 185 : } else if (oname[0] == '%') {
2642 0 : sql_idx *i = find_sql_idx(t, oname+1);
2643 :
2644 : /* do not include empty indices in the plan */
2645 0 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2646 0 : continue;
2647 0 : s = stmt_idx(be, i, dels, dels->partition);
2648 : } else {
2649 185 : cn = find_next_sql_column(t, cn, oname);
2650 185 : assert(cn);
2651 185 : sql_column *c = cn->data;
2652 185 : if (exp->f && (c->type.multiset || c->type.type->composite)) {
2653 22 : s = rel2bin_subtable(be, t, dels, c, cn, exp->f);
2654 22 : if (!s)
2655 : return s;
2656 22 : s->nested = true;
2657 22 : if (s && s->type == st_list && c->type.multiset) { /* keep rowid at the end */
2658 10 : stmt *ls = s->op4.lval->t->data;
2659 10 : stmt *ns = stmt_col(be, c, dels, dels->partition);
2660 10 : ns->subtype = ls->subtype;
2661 10 : list_append(s->op4.lval, ns);
2662 10 : s->nr = ns->nr;
2663 10 : s->subtype = *exp_subtype(exp);
2664 10 : s->multiset = s->subtype.multiset;
2665 12 : } else if (s && s->type == st_list && c->type.type->composite) {
2666 12 : s->subtype = *exp_subtype(exp);
2667 : }
2668 : } else {
2669 163 : s = stmt_col(be, c, dels, dels->partition);
2670 : }
2671 : }
2672 185 : s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
2673 185 : list_append(l, s);
2674 : }
2675 57 : return stmt_list(be, l);
2676 : }
2677 :
2678 : static stmt *
2679 149157 : rel2bin_basetable(backend *be, sql_rel *rel)
2680 : {
2681 149157 : mvc *sql = be->mvc;
2682 149157 : sql_table *t = rel->l;
2683 149157 : sql_column *fcol = NULL;
2684 149157 : sql_idx *fi = NULL;
2685 149157 : list *l = sa_list(sql->sa);
2686 149164 : bool complex = (t->multiset || t->composite);
2687 149164 : stmt *dels = stmt_tid(be, t, !complex?rel->flag == REL_PARTITION:false), *col = NULL;
2688 149172 : node *en, *cn = NULL;
2689 :
2690 149172 : if (l == NULL || dels == NULL)
2691 : return NULL;
2692 : /* add aliases */
2693 149172 : assert(rel->exps);
2694 298365 : for (en = rel->exps->h; en && !col; en = en->next) {
2695 149195 : sql_exp *exp = en->data;
2696 149195 : const char *oname = exp->r;
2697 :
2698 149195 : if (is_func(exp->type) || (oname[0] == '%' && strcmp(oname, TID) == 0))
2699 935 : continue;
2700 148260 : if (oname[0] == '%') {
2701 61 : sql_idx *i = find_sql_idx(t, oname+1);
2702 :
2703 : /* do not include empty indices in the plan */
2704 61 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2705 0 : continue;
2706 61 : fi = i;
2707 122 : col = stmt_idx(be, i, complex?dels:NULL, dels->partition);
2708 : } else {
2709 148199 : sql_column *c = find_sql_column(t, oname);
2710 :
2711 148195 : if (!c || c->type.multiset || c->type.type->composite)
2712 30 : continue;
2713 148165 : fcol = c;
2714 296317 : col = stmt_col(be, c, complex?dels:NULL, dels->partition);
2715 : }
2716 : }
2717 653970 : for (en = rel->exps->h; en; en = en->next) {
2718 504801 : sql_exp *exp = en->data;
2719 504801 : sql_alias *rname = exp_relname(exp)?exp_relname(exp):exp->l;
2720 504806 : const char *oname = exp->r;
2721 504806 : stmt *s = NULL;
2722 :
2723 504806 : assert(!is_func(exp->type));
2724 504806 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
2725 : /* tid function sql.tid(t) */
2726 :
2727 15047 : if (col)
2728 14125 : s = stmt_mirror(be, col);
2729 : else {
2730 922 : s = dels?dels:stmt_tid(be, t, 0);
2731 : dels = NULL;
2732 : }
2733 489759 : } else if (oname[0] == '%') {
2734 2663 : sql_idx *i = find_sql_idx(t, oname+1);
2735 :
2736 : /* do not include empty indices in the plan */
2737 2663 : if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
2738 0 : continue;
2739 2663 : s = (i == fi) ? col : stmt_idx(be, i, complex?dels:NULL, dels->partition);
2740 : } else {
2741 487096 : cn = find_next_sql_column(t, cn, oname);
2742 487100 : assert(cn);
2743 487100 : sql_column *c = cn->data;
2744 487100 : if (exp->f && (c->type.multiset || c->type.type->composite)) {
2745 35 : s = rel2bin_subtable(be, t, dels, c, cn, exp->f);
2746 35 : if (!s)
2747 : return s;
2748 35 : s->nested = true;
2749 35 : if (s && s->type == st_list && c->type.multiset) { /* keep rowid at the end */
2750 17 : stmt *ls = s->op4.lval->t->data;
2751 34 : stmt *ns = (c == fcol) ? col : stmt_col(be, c, complex?dels:NULL, dels->partition);
2752 17 : ns->subtype = ls->subtype;
2753 17 : list_append(s->op4.lval, ns);
2754 17 : s->nr = ns->nr;
2755 17 : s->subtype = *exp_subtype(exp);
2756 17 : s->multiset = s->subtype.multiset;
2757 18 : } else if (s && s->type == st_list && c->type.type->composite) {
2758 18 : s->subtype = *exp_subtype(exp);
2759 : }
2760 : } else {
2761 487069 : s = (c == fcol) ? col : stmt_col(be, c, complex?dels:NULL, dels->partition);
2762 : }
2763 : }
2764 504809 : s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
2765 504814 : list_append(l, s);
2766 : }
2767 149169 : stmt *res = stmt_list(be, l);
2768 149169 : if (res && !complex && dels)
2769 148212 : res->cand = dels;
2770 : return res;
2771 : }
2772 :
2773 : static int
2774 21 : alias_cmp(stmt *s, const char *nme)
2775 : {
2776 21 : return strcmp(s->cname, nme);
2777 : }
2778 :
2779 : static list* exps2bin_args(backend *be, list *exps, list *args);
2780 :
2781 : static list *
2782 1946 : exp2bin_args(backend *be, sql_exp *e, list *args)
2783 : {
2784 2017 : mvc *sql = be->mvc;
2785 :
2786 2017 : if (mvc_highwater(sql))
2787 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2788 :
2789 2017 : if (!e || !args)
2790 : return args;
2791 2017 : switch(e->type){
2792 : case e_column:
2793 : case e_psm:
2794 : return args;
2795 79 : case e_cmp:
2796 79 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2797 7 : args = exps2bin_args(be, e->l, args);
2798 7 : args = exps2bin_args(be, e->r, args);
2799 72 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2800 2 : args = exp2bin_args(be, e->l, args);
2801 2 : args = exps2bin_args(be, e->r, args);
2802 : } else {
2803 70 : args = exp2bin_args(be, e->l, args);
2804 70 : args = exp2bin_args(be, e->r, args);
2805 70 : if (e->f)
2806 : args = exp2bin_args(be, e->f, args);
2807 : }
2808 : return args;
2809 54 : case e_convert:
2810 54 : if (e->l)
2811 : return exp2bin_args(be, e->l, args);
2812 : break;
2813 150 : case e_aggr:
2814 : case e_func:
2815 150 : if (e->l)
2816 117 : return exps2bin_args(be, e->l, args);
2817 : break;
2818 337 : case e_atom:
2819 337 : if (e->l) {
2820 : return args;
2821 22 : } else if (e->f) {
2822 0 : return exps2bin_args(be, e->f, args);
2823 22 : } else if (e->r) {
2824 22 : sql_var_name *vname = (sql_var_name*) e->r;
2825 22 : const char *nme = sql_escape_ident(sql->sa, vname->name);
2826 22 : char *buf = NULL;
2827 :
2828 22 : if (vname->sname) { /* Global variable */
2829 3 : const char *sname = sql_escape_ident(sql->sa, vname->sname);
2830 6 : if (!nme || !sname || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(sname) + strlen(nme) + 6)))
2831 0 : return NULL;
2832 3 : stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(buf, "0\""), sname), "\"\""), nme), "\""); /* escape variable name */
2833 : } else { /* Parameter or local variable */
2834 19 : char levelstr[16];
2835 19 : snprintf(levelstr, sizeof(levelstr), "%u", e->flag);
2836 38 : if (!nme || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(nme) + 3)))
2837 0 : return NULL;
2838 19 : stpcpy(stpcpy(stpcpy(stpcpy(buf, levelstr), "\""), nme), "\""); /* escape variable name */
2839 : }
2840 22 : if (!list_find(args, buf, (fcmp)&alias_cmp)) {
2841 22 : stmt *s = stmt_var(be, vname->sname?a_create(be->mvc->sa, vname->sname):NULL, vname->name, &e->tpe, 0, e->flag);
2842 :
2843 22 : if (!e->alias.label)
2844 18 : exp_label(be->mvc->sa, e, ++be->mvc->label);
2845 22 : s = stmt_alias(be, s, e->alias.label, NULL, sa_strdup(sql->sa, buf));
2846 22 : list_append(args, s);
2847 : }
2848 : }
2849 : }
2850 : return args;
2851 : }
2852 :
2853 : static list *
2854 417 : exps2bin_args(backend *be, list *exps, list *args)
2855 : {
2856 417 : node *n;
2857 :
2858 417 : if (!exps)
2859 : return args;
2860 2221 : for (n = exps->h; n; n = n->next)
2861 1804 : args = exp2bin_args(be, n->data, args);
2862 : return args;
2863 : }
2864 :
2865 : static list *
2866 197 : rel2bin_args(backend *be, sql_rel *rel, list *args)
2867 : {
2868 479 : if (mvc_highwater(be->mvc))
2869 0 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2870 :
2871 479 : if (!rel || !args)
2872 : return args;
2873 479 : switch(rel->op) {
2874 : case op_basetable:
2875 : case op_table:
2876 : break;
2877 11 : case op_join:
2878 : case op_left:
2879 : case op_right:
2880 : case op_full:
2881 :
2882 : case op_semi:
2883 : case op_anti:
2884 :
2885 : case op_union:
2886 : case op_inter:
2887 : case op_except:
2888 : case op_merge:
2889 11 : args = rel2bin_args(be, rel->l, args);
2890 11 : args = rel2bin_args(be, rel->r, args);
2891 11 : break;
2892 0 : case op_munion:
2893 0 : if (rel->l) {
2894 0 : for (node* n = ((list*)rel->l)->h; n; n = n->next) {
2895 0 : args = rel2bin_args(be, n->data, args);
2896 : }
2897 : }
2898 : break;
2899 49 : case op_groupby:
2900 49 : if (rel->r)
2901 13 : args = exps2bin_args(be, rel->r, args);
2902 : /* fall through */
2903 : case op_project:
2904 : case op_select:
2905 : case op_topn:
2906 : case op_sample:
2907 271 : if (rel->exps)
2908 271 : args = exps2bin_args(be, rel->exps, args);
2909 271 : args = rel2bin_args(be, rel->l, args);
2910 271 : break;
2911 0 : case op_ddl:
2912 0 : args = rel2bin_args(be, rel->l, args);
2913 0 : if (rel->r)
2914 : args = rel2bin_args(be, rel->r, args);
2915 : break;
2916 0 : case op_insert:
2917 : case op_update:
2918 : case op_delete:
2919 : case op_truncate:
2920 0 : args = rel2bin_args(be, rel->r, args);
2921 0 : break;
2922 : }
2923 : return args;
2924 : }
2925 :
2926 : typedef struct trigger_input {
2927 : sql_table *t;
2928 : stmt *tids;
2929 : stmt **updates;
2930 : int type; /* insert 1, update 2, delete 3, truncate 4 */
2931 : const char *on;
2932 : const char *nn;
2933 : } trigger_input;
2934 :
2935 : static stmt *
2936 3185 : rel2bin_table(backend *be, sql_rel *rel, list *refs)
2937 : {
2938 3185 : mvc *sql = be->mvc;
2939 3185 : list *l;
2940 3185 : stmt *sub = NULL, *osub = NULL;
2941 3185 : node *en, *n;
2942 3185 : sql_exp *op = rel->r;
2943 :
2944 3185 : if (rel->flag == TRIGGER_WRAPPER) {
2945 11 : trigger_input *ti = rel->l;
2946 11 : l = sa_list(sql->sa);
2947 11 : if (l == NULL)
2948 : return NULL;
2949 :
2950 20 : assert(list_length(rel->exps) == ((ti->type == 2)?2:1) * ol_length(ti->t->columns));
2951 11 : sql_alias *oname = a_create(be->mvc->sa, ti->on);
2952 11 : sql_alias *nname = a_create(be->mvc->sa, ti->nn);
2953 30 : for (n = ol_first_node(ti->t->columns), en = rel->exps->h; n && en; n = n->next, en = en->next) {
2954 19 : sql_column *c = n->data;
2955 19 : sql_exp *e = en->data;
2956 :
2957 19 : if (ti->type == 2) { /* updates */
2958 4 : stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
2959 4 : append(l, stmt_alias(be, s, e->alias.label, oname, c->base.name));
2960 4 : en = en->next;
2961 4 : e = en->data;
2962 : }
2963 19 : if (ti->updates && ti->updates[c->colnr]) {
2964 17 : append(l, stmt_alias(be, ti->updates[c->colnr], e->alias.label, nname, c->base.name));
2965 : } else {
2966 2 : stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
2967 2 : append(l, stmt_alias(be, s, e->alias.label, nname, c->base.name));
2968 2 : assert(ti->type != 1);
2969 : }
2970 : }
2971 11 : sub = stmt_list(be, l);
2972 11 : return sub;
2973 3174 : } else if (op) {
2974 2988 : int i;
2975 2988 : sql_subfunc *f = op->f;
2976 2988 : stmt *psub = NULL;
2977 2988 : list *ops = NULL;
2978 2988 : stmt *ids = NULL;
2979 :
2980 2988 : if (rel->l) { /* first construct the sub relation */
2981 75 : sql_rel *l = rel->l;
2982 75 : if (l->op == op_ddl) {
2983 0 : sql_table *t = rel_ddl_table_get(l);
2984 :
2985 0 : if (t)
2986 0 : sub = rel2bin_sql_table(be, t, NULL);
2987 : } else {
2988 75 : sub = subrel_bin(be, rel->l, refs);
2989 : }
2990 75 : sub = subrel_project(be, sub, refs, rel->l);
2991 75 : if (!sub)
2992 : return NULL;
2993 : }
2994 :
2995 2988 : assert(f);
2996 2988 : if (f->func->res && list_length(f->func->res) + 1 == list_length(rel->exps) && !f->func->varres) {
2997 : /* add inputs in correct order ie loop through args of f and pass column */
2998 23 : list *exps = op->l;
2999 23 : ops = sa_list(be->mvc->sa);
3000 23 : if (exps) {
3001 83 : for (node *en = exps->h; en; en = en->next) {
3002 60 : sql_exp *e = en->data;
3003 :
3004 : /* find column */
3005 60 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
3006 60 : if (!s)
3007 : return NULL;
3008 60 : if (en->next)
3009 37 : append(ops, s);
3010 : else /* last added exp is the ids (todo use name base lookup !!) */
3011 : ids = s;
3012 : }
3013 : }
3014 : } else {
3015 2965 : psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0); /* table function */
3016 2965 : if (!psub)
3017 : return NULL;
3018 : }
3019 2988 : l = sa_list(sql->sa);
3020 2988 : if (l == NULL)
3021 : return NULL;
3022 2988 : if (f->func->res) {
3023 2963 : if (f->func->varres) {
3024 12096 : for (i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++) {
3025 10810 : sql_exp *exp = en->data;
3026 10810 : sql_subtype *st = n->data;
3027 10810 : sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
3028 10810 : stmt *s = stmt_rs_column(be, psub, i, st);
3029 :
3030 10810 : s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
3031 10810 : list_append(l, s);
3032 : }
3033 : } else {
3034 1677 : node *m = rel->exps->h;
3035 1677 : int i = 0;
3036 :
3037 : /* correlated table returning function */
3038 1677 : if (list_length(f->func->res) + 1 == list_length(rel->exps)) {
3039 : /* use a simple nested loop solution for this case, ie
3040 : * output a table of (input) row-ids, the output of the table producing function
3041 : */
3042 : /* make sure the input for sql.unionfunc are bats */
3043 23 : if (ids)
3044 23 : ids = column(be, ids);
3045 23 : if (ops)
3046 60 : for (node *en = ops->h; en; en = en->next)
3047 37 : en->data = column(be, (stmt *) en->data);
3048 :
3049 23 : int narg = 3 + list_length(rel->exps);
3050 23 : if (ops)
3051 23 : narg += list_length(ops);
3052 23 : InstrPtr q = newStmtArgs(be->mb, sqlRef, "unionfunc", narg);
3053 23 : if (q == NULL) {
3054 0 : if (be->mvc->sa->eb.enabled)
3055 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);
3056 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
3057 : }
3058 : /* Generate output rowid column and output of function f */
3059 69 : for (i=0; m; m = m->next, i++) {
3060 46 : sql_exp *e = m->data;
3061 46 : int type = exp_subtype(e)->type->localtype;
3062 :
3063 46 : type = newBatType(type);
3064 46 : if (i)
3065 23 : q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
3066 : else
3067 23 : getArg(q, 0) = newTmpVariable(be->mb, type);
3068 : }
3069 23 : if (backend_create_subfunc(be, f, ops) < 0) {
3070 0 : freeInstruction(q);
3071 0 : return NULL;
3072 : }
3073 23 : str mod = sql_func_mod(f->func);
3074 23 : str fcn = backend_function_imp(be, f->func);
3075 23 : q = pushStr(be->mb, q, mod);
3076 23 : q = pushStr(be->mb, q, fcn);
3077 23 : psub = stmt_direct_func(be, q);
3078 23 : if (psub == NULL) {
3079 0 : freeInstruction(q);
3080 0 : return NULL;
3081 : }
3082 :
3083 23 : if (ids) /* push input rowids column */
3084 23 : q = pushArgument(be->mb, q, ids->nr);
3085 :
3086 : /* add inputs in correct order ie loop through args of f and pass column */
3087 23 : if (ops) {
3088 60 : for (node *en = ops->h; en; en = en->next) {
3089 37 : stmt *op = en->data;
3090 :
3091 37 : q = pushArgument(be->mb, q, op->nr);
3092 : }
3093 : }
3094 23 : pushInstruction(be->mb, q);
3095 :
3096 : /* name output of dependent columns, output of function is handled the same as without correlation */
3097 23 : int len = list_length(rel->exps)-list_length(f->func->res);
3098 23 : assert(len== 1);
3099 46 : for (i=0, m=rel->exps->h; m && i<len; m = m->next, i++) {
3100 23 : sql_exp *exp = m->data;
3101 23 : stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp));
3102 :
3103 23 : s = stmt_alias(be, s, exp->alias.label, exp->l, exp->r);
3104 23 : list_append(l, s);
3105 : }
3106 : }
3107 15460 : for (n = f->func->res->h; n && m; n = n->next, m = m->next, i++) {
3108 13783 : sql_arg *a = n->data;
3109 13783 : sql_exp *exp = m->data;
3110 13783 : stmt *s = stmt_rs_column(be, psub, i, &a->type);
3111 13783 : sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp_find_rel_name(op);
3112 :
3113 13783 : s = stmt_alias(be, s, exp->alias.label, rnme, a->name);
3114 13783 : list_append(l, s);
3115 : }
3116 : }
3117 : }
3118 : //assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
3119 2988 : sub = stmt_list(be, l);
3120 2988 : return sub;
3121 186 : } else if (rel->l) { /* handle sub query via function */
3122 186 : int i;
3123 186 : char name[16], *nme;
3124 :
3125 186 : nme = number2name(name, sizeof(name), ++be->remote);
3126 :
3127 186 : l = rel2bin_args(be, rel->l, sa_list(sql->sa));
3128 186 : if (!l)
3129 0 : return NULL;
3130 186 : sub = stmt_list(be, l);
3131 186 : if (!(sub = stmt_func(be, sub, sa_strdup(sql->sa, nme), rel->l, 0)))
3132 : return NULL;
3133 186 : rel->l = sub->op4.rel; /* rel->l may get rewritten */
3134 186 : l = sa_list(sql->sa);
3135 1593 : for (i = 0, n = rel->exps->h; n; n = n->next, i++) {
3136 1407 : sql_exp *c = n->data;
3137 1407 : stmt *s = stmt_rs_column(be, sub, i, exp_subtype(c));
3138 1407 : const char *nme = exp_name(c);
3139 1407 : sql_alias *rnme = exp_relname(c);
3140 :
3141 1407 : s = stmt_alias(be, s, c->alias.label, rnme, nme);
3142 1407 : list_append(l, s);
3143 : }
3144 186 : sub = stmt_list(be, l);
3145 : }
3146 186 : if (!sub) {
3147 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3148 : return NULL;
3149 : }
3150 186 : l = sa_list(sql->sa);
3151 186 : if (l == NULL)
3152 : return NULL;
3153 1593 : for (en = rel->exps->h; en; en = en->next) {
3154 1407 : sql_exp *exp = en->data;
3155 1407 : sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
3156 1407 : stmt *s = bin_find_column_nid(be, sub, exp->nid);
3157 :
3158 1407 : if (!s) {
3159 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3160 : return NULL;
3161 : }
3162 1407 : if (sub && sub->nrcols >= 1 && s->nrcols == 0)
3163 0 : s = stmt_const(be, bin_find_smallest_column(be, sub), s);
3164 1407 : s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
3165 1407 : list_append(l, s);
3166 : }
3167 186 : if (osub && osub->nrcols)
3168 : list_merge(l, osub->op4.lval, NULL);
3169 186 : sub = stmt_list(be, l);
3170 186 : return sub;
3171 : }
3172 :
3173 : static stmt *
3174 90 : rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en)
3175 : {
3176 90 : mvc *sql = be->mvc;
3177 90 : node *n;
3178 90 : sql_subtype *it = sql_bind_localtype("int");
3179 90 : sql_subtype *lng = sql_bind_localtype("lng");
3180 90 : stmt *h = NULL;
3181 90 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
3182 90 : sql_exp *e = en->data;
3183 90 : sql_exp *l = e->l;
3184 90 : stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
3185 90 : int swap_exp = 0, swap_rel = 0, semantics = 0;
3186 :
3187 90 : if (!idx) {
3188 49 : swap_exp = 1;
3189 49 : l = e->r;
3190 49 : idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
3191 : }
3192 90 : if (!idx && right) {
3193 47 : swap_exp = 0;
3194 47 : swap_rel = 1;
3195 47 : l = e->l;
3196 47 : idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
3197 : }
3198 90 : if (!idx && right) {
3199 0 : swap_exp = 1;
3200 0 : swap_rel = 1;
3201 0 : l = e->r;
3202 0 : idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
3203 : }
3204 90 : if (!idx)
3205 : return NULL;
3206 : /* should be in key order! */
3207 314 : for (en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next) {
3208 226 : sql_exp *e = en->data;
3209 226 : stmt *s = NULL;
3210 :
3211 226 : if (e->type == e_cmp && e->flag == cmp_equal) {
3212 226 : sql_exp *ee = (swap_exp)?e->l:e->r;
3213 226 : if (swap_rel)
3214 109 : s = exp_bin(be, ee, left, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
3215 : else
3216 117 : s = exp_bin(be, ee, right, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
3217 : }
3218 :
3219 226 : if (!s)
3220 2 : return NULL;
3221 224 : if (h) {
3222 136 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
3223 :
3224 136 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(
3225 : list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
3226 136 : semantics = 1;
3227 : } else {
3228 88 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
3229 :
3230 88 : h = stmt_unop(be, s, NULL, hf);
3231 : }
3232 : }
3233 88 : if (n != NULL) /* need to use all cols of the index */
3234 : return NULL;
3235 87 : if (h && h->nrcols) {
3236 78 : if (!swap_rel) {
3237 31 : return stmt_join(be, idx, h, 0, cmp_equal, 0, semantics, false);
3238 : } else {
3239 47 : return stmt_join(be, h, idx, 0, cmp_equal, 0, semantics, false);
3240 : }
3241 : } else {
3242 9 : return stmt_uselect(be, idx, h, cmp_equal, NULL, 0, semantics);
3243 : }
3244 : }
3245 :
3246 : static stmt *
3247 5816 : join_hash_key(backend *be, list *l)
3248 : {
3249 5816 : mvc *sql = be->mvc;
3250 5816 : node *m;
3251 5816 : sql_subtype *it, *lng;
3252 5816 : stmt *h = NULL;
3253 5816 : stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
3254 :
3255 5816 : it = sql_bind_localtype("int");
3256 5816 : lng = sql_bind_localtype("lng");
3257 18384 : for (m = l->h; m; m = m->next) {
3258 12568 : stmt *s = m->data;
3259 :
3260 12568 : if (h) {
3261 6752 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
3262 :
3263 6752 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
3264 : } else {
3265 5816 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
3266 5816 : h = stmt_unop(be, s, NULL, hf);
3267 : }
3268 : }
3269 5816 : return h;
3270 : }
3271 :
3272 : static stmt *
3273 5571 : releqjoin(backend *be, list *l1, list *l2, list *exps, int used_hash, int need_left, int is_semantics)
3274 : {
3275 5571 : node *n1 = l1->h, *n2 = l2->h, *n3 = NULL;
3276 5571 : stmt *l, *r, *res;
3277 5571 : sql_exp *e;
3278 :
3279 5571 : if (exps)
3280 2837 : n3 = exps->h;
3281 5571 : if (list_length(l1) <= 1) {
3282 2333 : l = l1->h->data;
3283 2333 : r = l2->h->data;
3284 2333 : if (!is_semantics && exps) {
3285 0 : e = n3->data;
3286 0 : is_semantics = is_semantics(e);
3287 : }
3288 2333 : r = stmt_join(be, l, r, 0, cmp_equal, need_left, is_semantics, false);
3289 2333 : return r;
3290 : }
3291 3238 : if (used_hash) {
3292 330 : l = n1->data;
3293 330 : r = n2->data;
3294 330 : n1 = n1->next;
3295 330 : n2 = n2->next;
3296 330 : n3 = n3?n3->next:NULL;
3297 330 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
3298 : } else { /* need hash */
3299 2908 : l = join_hash_key(be, l1);
3300 2908 : r = join_hash_key(be, l2);
3301 2908 : res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
3302 : }
3303 3238 : l = stmt_result(be, res, 0);
3304 3238 : r = stmt_result(be, res, 1);
3305 19561 : for (; n1 && n2; n1 = n1->next, n2 = n2->next, n3 = n3?n3->next:NULL) {
3306 7038 : int semantics = is_semantics;
3307 7038 : stmt *ld = n1->data;
3308 7038 : stmt *rd = n2->data;
3309 7038 : stmt *le = stmt_project(be, l, ld);
3310 7038 : stmt *re = stmt_project(be, r, rd);
3311 7038 : stmt *cmp;
3312 : /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
3313 :
3314 7038 : if (!semantics && exps) {
3315 6047 : e = n3->data;
3316 6047 : semantics = is_semantics(e);
3317 : }
3318 7038 : cmp = stmt_uselect(be, le, re, cmp_equal, NULL, 0, semantics);
3319 7038 : l = stmt_project(be, cmp, l);
3320 7038 : r = stmt_project(be, cmp, r);
3321 : }
3322 3238 : res = stmt_join(be, l, r, 0, cmp_joined, 0, 0, false);
3323 3238 : return res;
3324 : }
3325 :
3326 : static bool
3327 80337 : can_join_exp(sql_rel *rel, sql_exp *e, bool anti)
3328 : {
3329 80337 : bool can_join = 0;
3330 :
3331 80337 : if (e->type == e_cmp) {
3332 80217 : int flag = e->flag;
3333 : /* check if its a select or join expression, ie use only expressions of one relation left and of the other right (than join) */
3334 80217 : if (flag < cmp_filter) { /* theta and range joins */
3335 : /* join or select ? */
3336 80127 : sql_exp *l = e->l, *r = e->r, *f = e->f;
3337 :
3338 80127 : if (f) {
3339 100 : int ll = rel_has_exp(rel->l, l, true) == 0;
3340 100 : int rl = rel_has_exp(rel->r, l, true) == 0;
3341 100 : int lr = rel_has_exp(rel->l, r, true) == 0;
3342 100 : int rr = rel_has_exp(rel->r, r, true) == 0;
3343 100 : int lf = rel_has_exp(rel->l, f, true) == 0;
3344 100 : int rf = rel_has_exp(rel->r, f, true) == 0;
3345 100 : int nrcr1 = 0, nrcr2 = 0, nrcl1 = 0, nrcl2 = 0;
3346 :
3347 100 : if ((ll && !rl &&
3348 82 : ((rr && !lr) || (nrcr1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
3349 70 : ((rf && !lf) || (nrcr2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcr1+nrcr2) <= 1) ||
3350 31 : (rl && !ll &&
3351 16 : ((lr && !rr) || (nrcl1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
3352 15 : ((lf && !rf) || (nrcl2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcl1+nrcl2) <= 1)) {
3353 : can_join = 1;
3354 : }
3355 : } else {
3356 80027 : int ll = 0, lr = 0, rl = 0, rr = 0, cst = 0;
3357 80027 : if (l->card != CARD_ATOM || !exp_is_atom(l)) {
3358 79826 : ll = rel_has_exp(rel->l, l, true) == 0;
3359 79826 : rl = rel_has_exp(rel->r, l, true) == 0;
3360 201 : } else if (anti) {
3361 15 : ll = 1;
3362 15 : cst = 1;
3363 : }
3364 80027 : if (r->card != CARD_ATOM || !exp_is_atom(r)) {
3365 79862 : lr = rel_has_exp(rel->l, r, true) == 0;
3366 79862 : rr = rel_has_exp(rel->r, r, true) == 0;
3367 165 : } else if (anti) {
3368 5 : rr = cst?0:1;
3369 : }
3370 80027 : if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
3371 79692 : can_join = 1;
3372 : }
3373 90 : } else if (flag == cmp_filter) {
3374 60 : list *l = e->l, *r = e->r;
3375 60 : int ll = 0, lr = 0, rl = 0, rr = 0;
3376 :
3377 120 : for (node *n = l->h ; n ; n = n->next) {
3378 60 : sql_exp *ee = n->data;
3379 :
3380 60 : if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
3381 57 : ll |= rel_has_exp(rel->l, ee, true) == 0;
3382 57 : rl |= rel_has_exp(rel->r, ee, true) == 0;
3383 : }
3384 : }
3385 203 : for (node *n = r->h ; n ; n = n->next) {
3386 143 : sql_exp *ee = n->data;
3387 :
3388 143 : if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
3389 62 : lr |= rel_has_exp(rel->l, ee, true) == 0;
3390 62 : rr |= rel_has_exp(rel->r, ee, true) == 0;
3391 : }
3392 : }
3393 60 : if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
3394 79692 : can_join = 1;
3395 : }
3396 : }
3397 80337 : return can_join;
3398 : }
3399 :
3400 : static void
3401 66925 : split_join_exps(sql_rel *rel, list *joinable, list *not_joinable, bool anti)
3402 : {
3403 66925 : if (!list_empty(rel->exps)) {
3404 138485 : for (node *n = rel->exps->h; n; n = n->next) {
3405 71566 : sql_exp *e = n->data;
3406 :
3407 : /* we can handle thetajoins, rangejoins and filter joins (like) */
3408 : /* ToDo how about atom expressions? */
3409 71566 : if (can_join_exp(rel, e, anti)) {
3410 71150 : append(joinable, e);
3411 : } else {
3412 416 : append(not_joinable, e);
3413 : }
3414 : }
3415 : }
3416 66925 : }
3417 :
3418 :
3419 : #define is_equi_exp_(e) ((e)->flag == cmp_equal)
3420 :
3421 : static list *
3422 3139 : get_simple_equi_joins_first(mvc *sql, sql_rel *rel, list *exps, bool *equality_only)
3423 : {
3424 3139 : list *new_exps = sa_list(sql->sa);
3425 3139 : *equality_only = true;
3426 :
3427 3139 : if (!exps)
3428 : return new_exps;
3429 :
3430 6180 : for (node *n = exps->h; n; n = n->next) {
3431 3144 : sql_exp *e = n->data;
3432 :
3433 3144 : if (can_join_exp(rel, e, false) && is_equi_exp_(e) && !is_any(e))
3434 219 : list_append(new_exps, e);
3435 : else
3436 2925 : *equality_only = false;
3437 : }
3438 6180 : for (node *n = exps->h; n; n = n->next) {
3439 3144 : sql_exp *e = n->data;
3440 :
3441 3144 : if (!is_equi_exp_(e) || !can_join_exp(rel, e, false) || is_any(e))
3442 2925 : list_append(new_exps, e);
3443 : }
3444 : return new_exps;
3445 : }
3446 :
3447 : static stmt *
3448 3139 : rel2bin_groupjoin(backend *be, sql_rel *rel, list *refs)
3449 : {
3450 3139 : mvc *sql = be->mvc;
3451 3139 : list *l;
3452 3139 : node *n , *en;
3453 3139 : stmt *left = NULL, *right = NULL, *join = NULL, *jl = NULL, *jr = NULL, *m = NULL, *ls = NULL, *res;
3454 3139 : bool need_project = false, exist = true, mark = false;
3455 :
3456 3139 : if (rel->op == op_left) { /* left outer group join */
3457 3052 : if (list_length(rel->attr) == 1) {
3458 3052 : sql_exp *e = rel->attr->h->data;
3459 3052 : if (exp_is_atom(e))
3460 3052 : mark = true;
3461 3052 : if (exp_is_atom(e) && exp_is_false(e))
3462 3139 : exist = false;
3463 : }
3464 : }
3465 :
3466 3139 : if (rel->l) /* first construct the left sub relation */
3467 3139 : left = subrel_bin(be, rel->l, refs);
3468 3139 : if (rel->r) /* first construct the right sub relation */
3469 3139 : right = subrel_bin(be, rel->r, refs);
3470 3139 : left = subrel_project(be, left, refs, rel->l);
3471 3139 : right = subrel_project(be, right, refs, rel->r);
3472 3139 : if (!left || !right)
3473 : return NULL;
3474 3139 : left = row2cols(be, left);
3475 3139 : right = row2cols(be, right);
3476 :
3477 3139 : bool equality_only = true;
3478 3139 : list *jexps = get_simple_equi_joins_first(sql, rel, rel->exps, &equality_only);
3479 :
3480 3139 : en = jexps?jexps->h:NULL;
3481 3574 : if (list_empty(jexps) || !(is_equi_exp_((sql_exp*)en->data) && can_join_exp(rel, en->data, false))) {
3482 435 : stmt *l = bin_find_smallest_column(be, left);
3483 435 : stmt *r = bin_find_smallest_column(be, right);
3484 435 : if (list_empty(jexps)) {
3485 114 : stmt *limit = stmt_limit(be, r, NULL, NULL, stmt_atom_lng(be, 0), stmt_atom_lng(be, 1), 0, 0, 0, 0, 0);
3486 114 : r = stmt_project(be, limit, r);
3487 : }
3488 435 : 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);
3489 435 : need_project = true;
3490 435 : jl = stmt_result(be, join, 0);
3491 435 : jr = stmt_result(be, join, 1);
3492 : } else {
3493 2704 : sql_exp *e = en->data;
3494 2704 : en = en->next;
3495 2704 : stmt *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 0, 1, 0), *r = NULL;
3496 2704 : bool swap = false;
3497 :
3498 2704 : if (!l) {
3499 17 : swap = true;
3500 17 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 0, 1, 0);
3501 : }
3502 17 : if (!l)
3503 : return NULL;
3504 2704 : if ((r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 0, 1, 0)) == NULL)
3505 : return NULL;
3506 :
3507 2704 : if (l && l->nrcols == 0)
3508 0 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
3509 2704 : if (r && r->nrcols == 0)
3510 0 : r = stmt_const(be, bin_find_smallest_column(be, right), r);
3511 2704 : if (swap) {
3512 17 : stmt *t = l;
3513 17 : l = r;
3514 17 : r = t;
3515 : }
3516 2704 : if ((!is_semantics(e) && is_anti(e)) || !mark)
3517 87 : ls = l;
3518 2704 : if (en || !mark) {
3519 : /* split out (left)join vs (left)mark-join */
3520 : /* call 3 result version */
3521 168 : if (mark && is_any(e)) {
3522 5 : join = stmt_markjoin(be, l, r, 0);
3523 : } else
3524 163 : join = stmt_join_cand(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_anti(e), (comp_type) cmp_equal/*e->flag*/, 0, is_any(e)|is_semantics(e), false, rel->op == op_left?false:true);
3525 168 : jl = stmt_result(be, join, 0);
3526 168 : jr = stmt_result(be, join, 1);
3527 168 : if (mark && is_any(e))
3528 5 : m = stmt_result(be, join, 2);
3529 : } else {
3530 2536 : join = stmt_markjoin(be, l, r, 1);
3531 2536 : jl = stmt_result(be, join, 0);
3532 2536 : m = stmt_result(be, join, 1);
3533 : }
3534 : }
3535 :
3536 3139 : if (en) {
3537 402 : stmt *sub, *sel = NULL, *osel = NULL;
3538 402 : list *nl;
3539 :
3540 402 : need_project = false;
3541 :
3542 : /* construct relation */
3543 402 : nl = sa_list(sql->sa);
3544 :
3545 : /* first project using equi-joins */
3546 2085 : for (n = left->op4.lval->h; n; n = n->next) {
3547 1683 : stmt *c = n->data;
3548 1683 : assert(c->type == st_alias);
3549 1683 : sql_alias *rnme = table_name(sql->sa, c);
3550 1683 : const char *nme = column_name(sql->sa, c);
3551 1683 : stmt *s = stmt_project(be, jl, column(be, c));
3552 :
3553 1683 : s = stmt_alias(be, s, c->label, rnme, nme);
3554 1683 : list_append(nl, s);
3555 : }
3556 1027 : for (n = right->op4.lval->h; n; n = n->next) {
3557 625 : stmt *c = n->data;
3558 625 : assert(c->type == st_alias);
3559 625 : sql_alias *rnme = table_name(sql->sa, c);
3560 625 : const char *nme = column_name(sql->sa, c);
3561 625 : stmt *s = stmt_project(be, jr, column(be, c));
3562 :
3563 625 : s = stmt_alias(be, s, c->label, rnme, nme);
3564 625 : list_append(nl, s);
3565 : }
3566 402 : left = sub = stmt_list(be, nl);
3567 :
3568 402 : if (!m) {
3569 397 : if (ls) {
3570 0 : stmt *nls = stmt_project(be, jl, ls);
3571 0 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", nls), stmt_bool(be, bit_nil),
3572 : sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL),
3573 : NULL);
3574 : } else {
3575 : /* 0 == empty (no matches possible), nil - no match (but has nil), 1 match */
3576 397 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL);
3577 : }
3578 : }
3579 :
3580 : /* continue with non equi-joins */
3581 842 : for ( ; en; en = en->next) {
3582 440 : sql_exp *e = en->data;
3583 440 : stmt *p = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
3584 :
3585 440 : if (!p) {
3586 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3587 : return NULL;
3588 : }
3589 440 : if (p->nrcols == 0)
3590 1 : p = stmt_const(be, bin_find_smallest_column(be, sub), p);
3591 440 : if (sel)
3592 38 : p = stmt_project(be, sel, column(be, p));
3593 38 : stmt *li = jl;
3594 38 : if (sel)
3595 38 : li = stmt_project(be, sel, li);
3596 440 : osel = sel;
3597 440 : if (en->next) {
3598 38 : join = stmt_outerselect(be, li, m, p, is_any(e));
3599 : } else {
3600 402 : join = stmt_markselect(be, li, m, p, is_any(e));
3601 : }
3602 440 : sel = stmt_result(be, join, 0);
3603 440 : m = stmt_result(be, join, 1);
3604 : /* go back to offset in the table */
3605 440 : if (sel && osel)
3606 38 : sel = stmt_project(be, sel, osel);
3607 440 : if (!en->next)
3608 402 : jl = sel;
3609 : }
3610 : }
3611 : /* construct relation */
3612 3139 : l = sa_list(sql->sa);
3613 14027 : for (n = left->op4.lval->h; n; n = n->next) {
3614 10888 : stmt *c = n->data;
3615 10888 : assert(c->type == st_alias);
3616 10888 : sql_alias *rnme = table_name(sql->sa, c);
3617 10888 : const char *nme = column_name(sql->sa, c);
3618 10888 : stmt *s = stmt_project(be, jl, column(be, c));
3619 :
3620 10888 : s = stmt_alias(be, s, c->label, rnme, nme);
3621 10888 : list_append(l, s);
3622 : }
3623 3139 : if (!mark && jr) {
3624 178 : for (n = right->op4.lval->h; n; n = n->next) {
3625 91 : stmt *c = n->data;
3626 91 : assert(c->type == st_alias);
3627 91 : sql_alias *rnme = table_name(sql->sa, c);
3628 91 : const char *nme = column_name(sql->sa, c);
3629 91 : stmt *s = stmt_project(be, jr, column(be, c));
3630 :
3631 91 : s = stmt_alias(be, s, c->label, rnme, nme);
3632 91 : list_append(l, s);
3633 : }
3634 87 : left = stmt_list(be, l);
3635 87 : l = sa_list(sql->sa);
3636 : }
3637 3139 : if (rel->attr) {
3638 3139 : sql_exp *e = rel->attr->h->data;
3639 3139 : sql_alias *rnme = exp_relname(e);
3640 3139 : const char *nme = exp_name(e);
3641 :
3642 3139 : if (mark) {
3643 3052 : if (need_project) {
3644 114 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, !exist), stmt_bool(be, exist), NULL);
3645 : } else {
3646 2938 : assert(m);
3647 2938 : sql_exp *e = rel->attr->h->data;
3648 2938 : if (exp_is_atom(e) && need_no_nil(e))
3649 298 : m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", m), stmt_bool(be, false), m, NULL);
3650 2938 : if (!exist) {
3651 42 : sql_subtype *bt = sql_bind_localtype("bit");
3652 42 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3653 42 : m = stmt_unop(be, m, NULL, not);
3654 : }
3655 : }
3656 3052 : stmt *s = stmt_alias(be, m, e->alias.label, rnme, nme);
3657 3052 : append(l, s);
3658 : } else {
3659 : /* group / aggrs */
3660 87 : stmt *nls = stmt_project(be, jl, ls);
3661 87 : stmt *groupby = stmt_group(be, nls, NULL, NULL, NULL, true);
3662 87 : stmt *grp = stmt_result(be, groupby, 0);
3663 87 : stmt *ext = stmt_result(be, groupby, 1);
3664 87 : stmt *cnt = stmt_result(be, groupby, 2);
3665 174 : for(node *n = rel->attr->h; n; n = n->next) {
3666 87 : sql_exp *e = n->data;
3667 87 : sql_alias *rnme = exp_relname(e);
3668 87 : const char *nme = exp_name(e);
3669 87 : stmt *s = exp_bin(be, e, left, NULL, grp, ext, cnt, NULL, 0, 0, 0);
3670 87 : s = stmt_alias(be, s, e->alias.label, rnme, nme);
3671 87 : append(l, s);
3672 : }
3673 : }
3674 : }
3675 3139 : res = stmt_list(be, l);
3676 3139 : return res;
3677 : }
3678 :
3679 : static list *
3680 65068 : get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
3681 : {
3682 65068 : list *new_exps = sa_list(sql->sa);
3683 :
3684 134506 : for (node *n = exps->h; n; n = n->next) {
3685 69438 : sql_exp *e = n->data;
3686 :
3687 69438 : assert(e->type == e_cmp && e->flag != cmp_in && e->flag != cmp_notin && e->flag != cmp_or);
3688 69438 : if (is_equi_exp_(e))
3689 65565 : list_append(new_exps, e);
3690 : else
3691 3873 : *equality_only = 0;
3692 : }
3693 134506 : for (node *n = exps->h; n; n = n->next) {
3694 69438 : sql_exp *e = n->data;
3695 :
3696 69438 : if (!is_equi_exp_(e))
3697 3873 : list_append(new_exps, e);
3698 : }
3699 65068 : return new_exps;
3700 : }
3701 :
3702 : static stmt *
3703 18749 : stmt_append_nil(backend *be, stmt *s, stmt *rows)
3704 : {
3705 18749 : if (s->nested)
3706 0 : return stmt_nest(be, s, rows, &stmt_append_nil);
3707 18749 : return stmt_append(be, s, stmt_const(be, rows, (s->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(be->mvc->sa, tail_type(s), NULL, 0))));
3708 : }
3709 :
3710 : static stmt *
3711 76625 : rel2bin_join(backend *be, sql_rel *rel, list *refs)
3712 : {
3713 76625 : mvc *sql = be->mvc;
3714 76625 : list *l, *sexps = NULL, *l2 = NULL;
3715 76625 : node *en = NULL, *n;
3716 76625 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *ld = NULL, *rd = NULL, *res;
3717 76625 : int need_left = (rel->flag & LEFT_JOIN);
3718 :
3719 76625 : if (rel->attr && list_length(rel->attr) > 0)
3720 3139 : return rel2bin_groupjoin(be, rel, refs);
3721 :
3722 73486 : if (rel->l) /* first construct the left sub relation */
3723 73486 : left = subrel_bin(be, rel->l, refs);
3724 73486 : if (rel->r) /* first construct the right sub relation */
3725 73486 : right = subrel_bin(be, rel->r, refs);
3726 73486 : left = subrel_project(be, left, refs, rel->l);
3727 73486 : right = subrel_project(be, right, refs, rel->r);
3728 73486 : if (!left || !right)
3729 : return NULL;
3730 73486 : left = row2cols(be, left);
3731 73486 : right = row2cols(be, right);
3732 : /*
3733 : * split in 2 steps,
3734 : * first cheap join(s) (equality or idx)
3735 : * second selects/filters
3736 : */
3737 73486 : if (!list_empty(rel->exps)) {
3738 62225 : list *jexps = sa_list(sql->sa);
3739 62225 : sexps = sa_list(sql->sa);
3740 :
3741 62225 : split_join_exps(rel, jexps, sexps, false);
3742 62225 : if (list_empty(jexps)) { /* cross product and continue after project */
3743 273 : stmt *l = bin_find_smallest_column(be, left);
3744 273 : stmt *r = bin_find_smallest_column(be, right);
3745 273 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3746 : }
3747 :
3748 273 : if (join) {
3749 273 : en = jexps->h;
3750 : } else {
3751 61952 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
3752 61952 : int used_hash = 0, idx = 0, equality_only = 1;
3753 :
3754 61952 : (void) equality_only;
3755 61952 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
3756 : /* generate a relational join (releqjoin) which does a multi attribute (equi) join */
3757 124072 : for (en = jexps->h; en ; en = en->next) {
3758 64469 : int join_idx = be->join_idx;
3759 64469 : sql_exp *e = en->data;
3760 64469 : stmt *s = NULL;
3761 64469 : prop *p;
3762 :
3763 : /* stop search for equi joins on first non equi */
3764 64469 : if (list_length(lje) && (idx || e->type != e_cmp || e->flag != cmp_equal))
3765 : break;
3766 :
3767 : /* handle possible index lookups, expressions are in index order! */
3768 64375 : if (!join && (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
3769 78 : sql_idx *i = p->value.pval;
3770 78 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
3771 :
3772 78 : join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
3773 78 : if (s) {
3774 78 : list_append(lje, s->op1);
3775 78 : list_append(rje, s->op2);
3776 78 : list_append(exps, NULL);
3777 78 : used_hash = 1;
3778 : } else {
3779 : /* hash lookup cannot be used, clean leftover mal statements */
3780 0 : clean_mal_statements(be, oldstop, oldvtop);
3781 : }
3782 : }
3783 :
3784 64375 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
3785 64375 : if (!s) {
3786 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3787 0 : return NULL;
3788 : }
3789 64375 : if (join_idx != be->join_idx)
3790 623 : idx = 1;
3791 64375 : assert(s->type == st_join || s->type == st_join2 || s->type == st_joinN);
3792 64375 : if (!join)
3793 61874 : join = s;
3794 64375 : if (e->flag != cmp_equal) { /* only collect equi joins */
3795 2255 : en = en->next;
3796 2255 : break;
3797 : }
3798 62120 : list_append(lje, s->op1);
3799 62120 : list_append(rje, s->op2);
3800 62120 : list_append(exps, e);
3801 : }
3802 61952 : if (list_length(lje) > 1) {
3803 2176 : join = releqjoin(be, lje, rje, exps, used_hash, need_left, 0);
3804 59776 : } else if (!join || need_left) {
3805 632 : sql_exp *e = exps->h->data;
3806 632 : join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, need_left, is_semantics(e), false);
3807 : }
3808 : }
3809 : } else {
3810 11261 : stmt *l = bin_find_smallest_column(be, left);
3811 11261 : stmt *r = bin_find_smallest_column(be, right);
3812 11261 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, is_single(rel));
3813 : }
3814 73486 : jl = stmt_result(be, join, 0);
3815 73486 : jr = stmt_result(be, join, 1);
3816 73486 : if (en || (sexps && list_length(sexps))) {
3817 1447 : stmt *sub, *sel = NULL;
3818 1447 : list *nl;
3819 :
3820 : /* construct relation */
3821 1447 : nl = sa_list(sql->sa);
3822 :
3823 : /* first project using equi-joins */
3824 6872 : for (n = left->op4.lval->h; n; n = n->next) {
3825 5425 : stmt *c = n->data;
3826 5425 : assert(c->type == st_alias);
3827 5425 : sql_alias *rnme = table_name(sql->sa, c);
3828 5425 : const char *nme = column_name(sql->sa, c);
3829 5425 : stmt *s = stmt_project(be, jl, column(be, c));
3830 :
3831 5425 : s = stmt_alias(be, s, c->label, rnme, nme);
3832 5425 : list_append(nl, s);
3833 : }
3834 4671 : for (n = right->op4.lval->h; n; n = n->next) {
3835 3224 : stmt *c = n->data;
3836 3224 : assert(c->type == st_alias);
3837 3224 : sql_alias *rnme = table_name(sql->sa, c);
3838 3224 : const char *nme = column_name(sql->sa, c);
3839 3224 : stmt *s = stmt_project(be, jr, column(be, c));
3840 :
3841 3224 : s = stmt_alias(be, s, c->label, rnme, nme);
3842 3224 : list_append(nl, s);
3843 : }
3844 1447 : sub = stmt_list(be, nl);
3845 :
3846 : /* continue with non equi-joins */
3847 4034 : while(sexps) {
3848 2587 : if (!en) {
3849 1447 : en = sexps->h;
3850 1447 : sexps = NULL;
3851 : }
3852 4056 : for ( ; en; en = en->next) {
3853 1469 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
3854 :
3855 1469 : if (!s) {
3856 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
3857 : return NULL;
3858 : }
3859 1469 : if (s->nrcols == 0) {
3860 123 : stmt *l = bin_find_smallest_column(be, sub);
3861 123 : s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
3862 : }
3863 1469 : sel = s;
3864 : }
3865 : }
3866 : /* recreate join output */
3867 1447 : jl = stmt_project(be, sel, jl);
3868 1447 : jr = stmt_project(be, sel, jr);
3869 : }
3870 :
3871 : /* construct relation */
3872 73486 : l = sa_list(sql->sa);
3873 :
3874 73486 : if (rel->op == op_left || rel->op == op_full || is_single(rel)) {
3875 : /* we need to add the missing oid's */
3876 11468 : stmt *l = ld = stmt_mirror(be, bin_find_smallest_column(be, left));
3877 11468 : if (rel->op == op_left || rel->op == op_full)
3878 8275 : ld = stmt_tdiff(be, ld, jl, NULL);
3879 11468 : if (is_single(rel) && !list_empty(rel->exps)) {
3880 284 : join = stmt_semijoin(be, l, jl, NULL, NULL, 0, true);
3881 284 : jl = stmt_result(be, join, 0);
3882 284 : jr = stmt_project(be, stmt_result(be, join, 1), jr);
3883 : }
3884 : }
3885 73486 : if (rel->op == op_right || rel->op == op_full) {
3886 : /* we need to add the missing oid's */
3887 169 : rd = stmt_mirror(be, bin_find_smallest_column(be, right));
3888 169 : rd = stmt_tdiff(be, rd, jr, NULL);
3889 : }
3890 :
3891 73486 : if (rel->op == op_left) { /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3892 8203 : l2 = sa_list(sql->sa);
3893 8203 : list_append(l2, left);
3894 8203 : list_append(l2, right);
3895 8203 : list_append(l2, jl);
3896 8203 : list_append(l2, jr);
3897 8203 : list_append(l2, ld);
3898 : }
3899 :
3900 73486 : int op = rel->op;
3901 1942112 : for (n = left->op4.lval->h; n; n = n->next) {
3902 1868626 : stmt *c = n->data;
3903 1868626 : sql_alias *rnme = table_name(sql->sa, c);
3904 1868626 : const char *nme = column_name(sql->sa, c);
3905 1868626 : stmt *s = stmt_project(be, jl, column(be, c));
3906 :
3907 : /* as append isn't save, we append to a new copy */
3908 1868626 : if (op == op_left || op == op_full || op == op_right)
3909 61116 : s = create_const_column(be, s, NULL);
3910 1868626 : if (op == op_left || op == op_full)
3911 60910 : s = stmt_append(be, s, stmt_project(be, ld, c));
3912 1868626 : if (op == op_right || op == op_full) {
3913 329 : s->flag = c->flag; /* push OUTER_ZERO */
3914 329 : s = stmt_append_nil(be, s, rd);
3915 : }
3916 1868626 : s = stmt_alias(be, s, c->label, rnme, nme);
3917 1868626 : list_append(l, s);
3918 : }
3919 279995 : for (n = right->op4.lval->h; n; n = n->next) {
3920 206509 : stmt *c = n->data;
3921 206509 : sql_alias *rnme = table_name(sql->sa, c);
3922 206509 : const char *nme = column_name(sql->sa, c);
3923 206509 : stmt *s = stmt_project(be, jr, column(be, c));
3924 :
3925 : /* as append isn't save, we append to a new copy */
3926 206509 : if (op == op_left || op == op_full || op == op_right)
3927 18682 : s = create_const_column(be, s, NULL);
3928 206509 : if (op == op_left || op == op_full) {
3929 18420 : s->flag = c->flag; /* push OUTER_ZERO */
3930 18420 : s = stmt_append_nil(be, s, ld);
3931 : }
3932 206509 : if (op == op_right || op == op_full)
3933 375 : s = stmt_append(be, s, stmt_project(be, rd, c));
3934 :
3935 206509 : s = stmt_alias(be, s, c->label, rnme, nme);
3936 206509 : list_append(l, s);
3937 : }
3938 73486 : if (rel->attr) {
3939 0 : sql_exp *e = rel->attr->h->data;
3940 0 : sql_alias *rnme = exp_relname(e);
3941 0 : const char *nme = exp_name(e);
3942 0 : stmt *last = l->t->data;
3943 0 : sql_subtype *tp = tail_type(last);
3944 :
3945 0 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", tp, NULL, F_FUNC, true, true);
3946 :
3947 0 : stmt *s = stmt_unop(be, last, NULL, isnil);
3948 :
3949 0 : sql_subtype *bt = sql_bind_localtype("bit");
3950 0 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
3951 :
3952 0 : s = stmt_unop(be, s, NULL, not);
3953 0 : s = stmt_alias(be, s, e->alias.label, rnme, nme);
3954 0 : list_append(l, s);
3955 : }
3956 :
3957 73486 : res = stmt_list(be, l);
3958 73486 : res->extra = l2; /* used for merge statements, this will be cleaned out on the pushcands branch :) */
3959 73486 : return res;
3960 : }
3961 :
3962 : static stmt *
3963 1531 : rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
3964 : {
3965 1531 : mvc *sql = be->mvc;
3966 1531 : list *l, *jexps = NULL, *sexps = NULL;
3967 1531 : node *en = NULL, *n;
3968 1531 : stmt *left = NULL, *right = NULL, *join = NULL, *sel = NULL, *sub = NULL;
3969 :
3970 1531 : if (rel->l) /* first construct the left sub relation */
3971 1531 : left = subrel_bin(be, rel->l, refs);
3972 1531 : if (rel->r) /* first construct the right sub relation */
3973 1531 : right = subrel_bin(be, rel->r, refs);
3974 1531 : left = subrel_project(be, left, refs, rel->l);
3975 1531 : right = subrel_project(be, right, refs, rel->r);
3976 1531 : if (!left || !right)
3977 : return NULL;
3978 1531 : left = row2cols(be, left);
3979 1531 : right = row2cols(be, right);
3980 :
3981 1531 : stmt *li = NULL;
3982 1531 : bool swap = false;
3983 :
3984 1531 : jexps = sa_list(sql->sa);
3985 1531 : sexps = sa_list(sql->sa);
3986 :
3987 1531 : split_join_exps(rel, jexps, sexps, true);
3988 1531 : if (list_empty(jexps)) {
3989 16 : stmt *l = bin_find_smallest_column(be, left);
3990 16 : stmt *r = bin_find_smallest_column(be, right);
3991 16 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
3992 :
3993 16 : jexps = sexps;
3994 16 : sexps = NULL;
3995 16 : en = jexps->h;
3996 : } else {
3997 1515 : if (list_length(sexps))
3998 3 : list_merge(jexps, sexps, NULL);
3999 1515 : en = jexps->h;
4000 1515 : sql_exp *e = en->data;
4001 1515 : assert(e->type == e_cmp);
4002 1515 : stmt *ls = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0), *rs;
4003 1515 : bool constval = false;
4004 1515 : if (!ls) {
4005 12 : swap = true;
4006 12 : ls = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
4007 : }
4008 12 : if (!ls)
4009 : return NULL;
4010 :
4011 1515 : if (!(rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0)))
4012 : return NULL;
4013 :
4014 1515 : if (swap) {
4015 12 : stmt *t = ls;
4016 12 : ls = rs;
4017 12 : rs = t;
4018 : }
4019 1515 : if (ls->nrcols == 0) {
4020 10 : constval = true;
4021 10 : ls = stmt_const(be, bin_find_smallest_column(be, left), ls);
4022 : }
4023 1515 : if (rs->nrcols == 0)
4024 4 : rs = stmt_const(be, bin_find_smallest_column(be, right), rs);
4025 :
4026 1515 : if (!li)
4027 1515 : li = ls;
4028 :
4029 1515 : if (!en->next && (constval || stmt_has_null(ls) /*|| stmt_has_null(rs) (change into check for fk)*/)) {
4030 1295 : assert(e->flag == cmp_equal);
4031 1295 : join = stmt_tdiff2(be, ls, rs, NULL);
4032 1295 : jexps = NULL;
4033 : } else {
4034 220 : join = stmt_join_cand(be, ls, rs, NULL, NULL, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false, true);
4035 : }
4036 1515 : en = en->next;
4037 : }
4038 1531 : if (en || jexps) {
4039 236 : stmt *jl = stmt_result(be, join, 0);
4040 236 : stmt *jr = stmt_result(be, join, 1);
4041 236 : stmt *nulls = NULL;
4042 :
4043 236 : if (li && stmt_has_null(li)) {
4044 123 : nulls = stmt_selectnil(be, li);
4045 : }
4046 : /* construct relation */
4047 236 : list *nl = sa_list(sql->sa);
4048 : /* first project after equi-joins */
4049 2261 : for (n = left->op4.lval->h; n; n = n->next) {
4050 2025 : stmt *c = n->data;
4051 2025 : assert(c->type == st_alias);
4052 2025 : sql_alias *rnme = table_name(sql->sa, c);
4053 2025 : const char *nme = column_name(sql->sa, c);
4054 2025 : stmt *s = stmt_project(be, jl, column(be, c));
4055 :
4056 2025 : s = stmt_alias(be, s, c->label, rnme, nme);
4057 2025 : list_append(nl, s);
4058 : }
4059 679 : for (n = right->op4.lval->h; n; n = n->next) {
4060 443 : stmt *c = n->data;
4061 443 : assert(c->type == st_alias);
4062 443 : sql_alias *rnme = table_name(sql->sa, c);
4063 443 : const char *nme = column_name(sql->sa, c);
4064 443 : stmt *s = stmt_project(be, jr, column(be, c));
4065 :
4066 443 : s = stmt_alias(be, s, c->label, rnme, nme);
4067 443 : list_append(nl, s);
4068 : }
4069 236 : sub = stmt_list(be, nl);
4070 :
4071 : /* continue with non equi-joins */
4072 682 : for (; en; en = en->next) {
4073 210 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, NULL /* sel */, 0, 0/* just the project call not the select*/, 0);
4074 :
4075 : /* ifthenelse if (not(predicate)) then false else true (needed for antijoin) */
4076 210 : sql_subtype *bt = sql_bind_localtype("bit");
4077 210 : sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
4078 210 : s = stmt_unop(be, s, NULL, not);
4079 210 : s = sql_Nop_(be, "ifthenelse", s, stmt_bool(be, 0), stmt_bool(be, 1), NULL);
4080 :
4081 210 : if (s->nrcols == 0) {
4082 0 : stmt *l = bin_find_smallest_column(be, sub);
4083 0 : s = stmt_uselect(be, stmt_const(be, l, s), stmt_bool(be, 1), cmp_equal, sel, 0, 0);
4084 : } else {
4085 210 : s = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
4086 : }
4087 :
4088 210 : if (!s) {
4089 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4090 : return NULL;
4091 : }
4092 :
4093 210 : sel = s;
4094 : }
4095 236 : stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
4096 236 : if (nulls) {
4097 123 : stmt *nonilcand = stmt_tdiff(be, c, nulls, NULL);
4098 123 : c = stmt_project(be, nonilcand, c);
4099 : }
4100 236 : if (join && sel) {
4101 : /* recreate join output */
4102 153 : jl = stmt_project(be, sel, jl);
4103 153 : join = stmt_tdiff(be, c, jl, NULL);
4104 : } else {
4105 83 : join = stmt_tdiff2(be, c, jl, NULL);
4106 : }
4107 236 : if (nulls)
4108 123 : join = stmt_project(be, join, c);
4109 :
4110 : } else if (jexps && list_empty(jexps)) {
4111 : stmt *jl = stmt_result(be, join, 0);
4112 : stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
4113 : join = stmt_tdiff2(be, c, jl, NULL);
4114 : }
4115 :
4116 : /* construct relation */
4117 1531 : l = sa_list(sql->sa);
4118 :
4119 : /* project all the left columns */
4120 13210 : for (n = left->op4.lval->h; n; n = n->next) {
4121 11679 : stmt *c = n->data;
4122 11679 : assert(c->type == st_alias);
4123 11679 : sql_alias *rnme = table_name(sql->sa, c);
4124 11679 : const char *nme = column_name(sql->sa, c);
4125 11679 : stmt *s = stmt_project(be, join, column(be, c));
4126 :
4127 11679 : s = stmt_alias(be, s, c->label, rnme, nme);
4128 11679 : list_append(l, s);
4129 : }
4130 1531 : return stmt_list(be, l);
4131 : }
4132 :
4133 : static stmt *
4134 3203 : rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
4135 : {
4136 3203 : mvc *sql = be->mvc;
4137 3203 : list *l, *sexps = NULL;
4138 3203 : node *en = NULL, *n;
4139 3203 : stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c, *lcand = NULL;
4140 3203 : int semijoin_only = 0, l_is_base = 0;
4141 :
4142 3203 : assert(rel->op != op_anti);
4143 :
4144 3203 : if (rel->l) { /* first construct the left sub relation */
4145 3203 : sql_rel *l = rel->l;
4146 3203 : l_is_base = is_basetable(l->op);
4147 3203 : left = subrel_bin(be, l, refs);
4148 : }
4149 3203 : if (rel->r) /* first construct the right sub relation */
4150 3203 : right = subrel_bin(be, rel->r, refs);
4151 3203 : if (!left || !right)
4152 : return NULL;
4153 3203 : left = row2cols(be, left);
4154 3203 : right = row2cols(be, right);
4155 : /*
4156 : * split in 2 steps,
4157 : * first cheap join(s) (equality or idx)
4158 : * second selects/filters
4159 : */
4160 3203 : if (!list_empty(rel->exps)) {
4161 3169 : list *jexps = sa_list(sql->sa);
4162 3169 : sexps = sa_list(sql->sa);
4163 :
4164 3169 : split_join_exps(rel, jexps, sexps, false);
4165 3169 : if (list_empty(jexps)) { /* cross product and continue after project */
4166 53 : right = subrel_project(be, right, refs, rel->r);
4167 53 : stmt *l = bin_find_smallest_column(be, left);
4168 53 : stmt *r = bin_find_smallest_column(be, right);
4169 53 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
4170 53 : lcand = left->cand;
4171 : }
4172 :
4173 3169 : if (join) {
4174 53 : en = jexps->h;
4175 : } else {
4176 3116 : list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
4177 3116 : int idx = 0, equality_only = 1;
4178 :
4179 3116 : jexps = get_equi_joins_first(sql, jexps, &equality_only);
4180 3116 : if (!equality_only || list_length(jexps) > 1 || exp_has_func((sql_exp*)jexps->h->data))
4181 1131 : left = subrel_project(be, left, refs, rel->l);
4182 3116 : right = subrel_project(be, right, refs, rel->r);
4183 :
4184 7016 : for (en = jexps->h; en; en = en->next) {
4185 3913 : int join_idx = be->join_idx;
4186 3913 : sql_exp *e = en->data;
4187 3913 : stmt *s = NULL;
4188 :
4189 : /* only handle simple joins here */
4190 3913 : if ((exp_has_func(e) && e->flag != cmp_filter) || e->flag == cmp_or || (e->f && is_anti(e))) {
4191 3 : if (!join && !list_length(lje)) {
4192 3 : stmt *l = bin_find_smallest_column(be, left);
4193 3 : stmt *r = bin_find_smallest_column(be, right);
4194 3 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
4195 : }
4196 : break;
4197 : }
4198 3910 : if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
4199 787 : (join && e->flag == cmp_filter)))
4200 : break;
4201 :
4202 3900 : if (equality_only) {
4203 3431 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop, swap = 0;
4204 3431 : stmt *r, *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
4205 :
4206 3431 : if (l && left && l->nrcols==0 && left->nrcols >0)
4207 1 : l = stmt_const(be, bin_find_smallest_column(be, left), l);
4208 439 : if (!l) {
4209 438 : swap = 1;
4210 438 : clean_mal_statements(be, oldstop, oldvtop);
4211 438 : l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
4212 : }
4213 3431 : r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0);
4214 :
4215 3431 : if (swap) {
4216 438 : stmt *t = l;
4217 438 : l = r;
4218 438 : r = t;
4219 : }
4220 :
4221 3431 : if (!l || !r)
4222 0 : return NULL;
4223 3431 : if (be->no_mitosis && list_length(jexps) == 1 && list_empty(sexps) && rel->op == op_semi && !is_anti(e) && is_equi_exp_(e)) {
4224 0 : join = stmt_semijoin(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_semantics(e), false);
4225 0 : semijoin_only = 1;
4226 0 : en = NULL;
4227 0 : break;
4228 : } else
4229 3431 : 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);
4230 3431 : lcand = left->cand;
4231 : } else {
4232 469 : s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
4233 : }
4234 3900 : if (!s) {
4235 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4236 : return NULL;
4237 : }
4238 3900 : if (join_idx != be->join_idx)
4239 0 : idx = 1;
4240 : /* stop on first non equality join */
4241 3900 : if (!join) {
4242 3113 : if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
4243 0 : if (!en->next && (s->type == st_uselect || s->type == st_uselect2))
4244 : join = s;
4245 : else
4246 : break;
4247 : }
4248 : join = s;
4249 787 : } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
4250 : /* handle select expressions */
4251 : break;
4252 : }
4253 3900 : if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
4254 3900 : list_append(lje, s->op1);
4255 3900 : list_append(rje, s->op2);
4256 3900 : list_append(exps, e);
4257 : }
4258 : }
4259 3116 : if (list_length(lje) > 1) {
4260 661 : join = releqjoin(be, lje, rje, exps, 0 /* use hash */, 0, rel->op == op_anti?1:0);
4261 2455 : } else if (!join && list_length(lje) == list_length(rje) && list_length(lje)) {
4262 0 : sql_exp *e = exps->h->data;
4263 0 : join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, 0, is_semantics(e), false);
4264 0 : } else if (!join) {
4265 0 : stmt *l = bin_find_smallest_column(be, left);
4266 0 : stmt *r = bin_find_smallest_column(be, right);
4267 0 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
4268 : }
4269 : }
4270 : } else {
4271 34 : right = subrel_project(be, right, refs, rel->r);
4272 34 : stmt *l = bin_find_smallest_column(be, left);
4273 34 : stmt *r = bin_find_smallest_column(be, right);
4274 34 : join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
4275 34 : lcand = left->cand;
4276 : }
4277 3203 : jl = stmt_result(be, join, 0);
4278 3203 : if (en || (sexps && list_length(sexps))) {
4279 87 : stmt *sub, *sel = NULL;
4280 87 : list *nl;
4281 :
4282 87 : jr = stmt_result(be, join, 1);
4283 : /* construct relation */
4284 87 : nl = sa_list(sql->sa);
4285 :
4286 : /* first project after equi-joins */
4287 430 : for (n = left->op4.lval->h; n; n = n->next) {
4288 343 : stmt *c = n->data;
4289 343 : assert(c->type == st_alias);
4290 343 : sql_alias *rnme = table_name(sql->sa, c);
4291 343 : const char *nme = column_name(sql->sa, c);
4292 343 : stmt *s = stmt_project(be, jl, column(be, c));
4293 :
4294 343 : s = stmt_alias(be, s, c->label, rnme, nme);
4295 343 : list_append(nl, s);
4296 : }
4297 245 : for (n = right->op4.lval->h; n; n = n->next) {
4298 158 : stmt *c = n->data;
4299 158 : assert(c->type == st_alias);
4300 158 : sql_alias *rnme = table_name(sql->sa, c);
4301 158 : const char *nme = column_name(sql->sa, c);
4302 158 : stmt *s = stmt_project(be, jr, column(be, c));
4303 :
4304 158 : s = stmt_alias(be, s, c->label, rnme, nme);
4305 158 : list_append(nl, s);
4306 : }
4307 87 : sub = stmt_list(be, nl);
4308 :
4309 : /* continue with non equi-joins */
4310 187 : while(sexps) {
4311 100 : if (!en) {
4312 87 : en = sexps->h;
4313 87 : sexps = NULL;
4314 : }
4315 197 : for ( ; en; en = en->next) {
4316 97 : stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
4317 :
4318 97 : if (!s) {
4319 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4320 : return NULL;
4321 : }
4322 97 : if (s->nrcols == 0) {
4323 2 : stmt *l = bin_find_smallest_column(be, sub);
4324 2 : s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
4325 : }
4326 97 : sel = s;
4327 : }
4328 : }
4329 : /* recreate join output */
4330 87 : jl = stmt_project(be, sel, jl);
4331 : }
4332 :
4333 : /* construct relation */
4334 3203 : l = sa_list(sql->sa);
4335 :
4336 : /* We did a full join, that's too much.
4337 : Reduce this using difference and intersect */
4338 3203 : if (!semijoin_only) {
4339 3203 : c = stmt_mirror(be, bin_find_smallest_column(be, left));
4340 3203 : if (rel->op == op_anti) {
4341 0 : assert(0);
4342 : join = stmt_tdiff(be, c, jl, lcand);
4343 : } else {
4344 3203 : if (lcand)
4345 1143 : join = stmt_semijoin(be, c, jl, lcand, NULL/*right->cand*/, 0, false);
4346 : else
4347 2060 : join = stmt_tinter(be, c, jl, false);
4348 : }
4349 : }
4350 :
4351 : /* project all the left columns */
4352 24943 : for (n = left->op4.lval->h; n; n = n->next) {
4353 21740 : stmt *c = n->data, *s;
4354 21740 : sql_alias *rnme = table_name(sql->sa, c);
4355 21740 : const char *nme = column_name(sql->sa, c);
4356 :
4357 21740 : if (semijoin_only && l_is_base && nme[0] == '%' && strcmp(nme, TID) == 0)
4358 : s = join;
4359 : else
4360 21740 : s = stmt_project(be, join, column(be, c));
4361 :
4362 21740 : s = stmt_alias(be, s, c->label, rnme, nme);
4363 21740 : list_append(l, s);
4364 : }
4365 3203 : return stmt_list(be, l);
4366 : }
4367 :
4368 : static stmt *
4369 1882 : rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
4370 : {
4371 1882 : mvc *sql = be->mvc;
4372 1882 : node *n;
4373 1882 : stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
4374 1882 : list *rl = sa_list(sql->sa), *tids;
4375 :
4376 : /* single values are unique */
4377 1882 : if (s->key && s->nrcols == 0)
4378 : return s;
4379 :
4380 : /* Use 'all' tid columns */
4381 1867 : if (/* DISABLES CODE */ (0) && (tids = bin_find_columns(be, s, TID)) != NULL) {
4382 : for (n = tids->h; n; n = n->next) {
4383 : stmt *t = n->data;
4384 :
4385 : g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
4386 : grp = stmt_result(be, g, 0);
4387 : ext = stmt_result(be, g, 1);
4388 : cnt = stmt_result(be, g, 2);
4389 : }
4390 : } else {
4391 4133 : for (n = s->op4.lval->h; n; n = n->next) {
4392 2266 : stmt *t = n->data;
4393 :
4394 2266 : g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
4395 2266 : grp = stmt_result(be, g, 0);
4396 2266 : ext = stmt_result(be, g, 1);
4397 2266 : cnt = stmt_result(be, g, 2);
4398 : }
4399 : }
4400 1867 : if (!ext)
4401 : return NULL;
4402 :
4403 4133 : for (n = s->op4.lval->h; n; n = n->next) {
4404 2266 : stmt *t = n->data;
4405 :
4406 2266 : stmt *s = stmt_project(be, ext, t);
4407 2266 : t = stmt_alias(be, s, t->label, table_name(sql->sa, t), column_name(sql->sa, t));
4408 2266 : list_append(rl, t);
4409 : }
4410 :
4411 1867 : if (distinct)
4412 113 : *distinct = ext;
4413 1867 : s = stmt_list(be, rl);
4414 1867 : return s;
4415 : }
4416 :
4417 : static stmt *
4418 11 : rel2bin_single(backend *be, stmt *s)
4419 : {
4420 11 : if (!s || (s->key && s->nrcols == 0))
4421 : return s;
4422 :
4423 11 : mvc *sql = be->mvc;
4424 11 : list *rl = sa_list(sql->sa);
4425 :
4426 25 : for (node *n = s->op4.lval->h; n; n = n->next) {
4427 14 : stmt *t = n->data;
4428 14 : assert(t->type == st_alias);
4429 14 : sql_alias *rnme = table_name(sql->sa, t);
4430 14 : const char *nme = column_name(sql->sa, t);
4431 14 : int label = t->label;
4432 14 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", tail_type(t), NULL, F_AGGR, true, true);
4433 :
4434 14 : t = stmt_aggr(be, t, NULL, NULL, zero_or_one, 1, 0, 1);
4435 14 : t = stmt_alias(be, t, label, rnme, nme);
4436 14 : list_append(rl, t);
4437 : }
4438 11 : s = stmt_list(be, rl);
4439 11 : return s;
4440 : }
4441 :
4442 : static stmt *
4443 6955 : rel_rename(backend *be, sql_rel *rel, stmt *sub)
4444 : {
4445 6955 : if (rel->exps) {
4446 6955 : node *en, *n;
4447 6955 : list *l = sa_list(be->mvc->sa);
4448 :
4449 32130 : for (en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next) {
4450 25175 : sql_exp *exp = en->data;
4451 25175 : stmt *s = n->data;
4452 :
4453 25175 : if (!s) {
4454 0 : assert(be->mvc->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
4455 : return NULL;
4456 : }
4457 25175 : s = stmt_rename(be, exp, s);
4458 25175 : list_append(l, s);
4459 : }
4460 6955 : sub = stmt_list(be, l);
4461 : }
4462 : return sub;
4463 : }
4464 :
4465 : static stmt*
4466 71 : subres_assign_newresultvars(backend *be, stmt *rel_stmt)
4467 : {
4468 71 : list *stmts = rel_stmt->op4.lval;
4469 71 : list *nstmt = sa_list(be->mvc->sa);
4470 187 : for (node *n = stmts->h; n; n = n->next) {
4471 116 : stmt *r = n->data;
4472 116 : InstrPtr a = newAssignment(be->mb);
4473 116 : stmt *ns = NULL;
4474 116 : sql_alias *rnme = table_name(be->mvc->sa, r);
4475 116 : const char *nme = column_name(be->mvc->sa, r);
4476 116 : int label = r->label;
4477 :
4478 116 : if (r->nrcols == 0)
4479 43 : r = const_column(be, r);
4480 116 : ns = stmt_alias(be, r, label, rnme, nme);
4481 116 : ns->flag = cmp_project; /* mark as special */
4482 116 : a = pushArgument(be->mb, a, ns->nr);
4483 116 : pushInstruction(be->mb, a);
4484 116 : ns->q = a;
4485 116 : ns->nr = a->argv[0];
4486 116 : append(nstmt, ns);
4487 : }
4488 71 : return stmt_list(be, nstmt);
4489 : }
4490 :
4491 : static stmt*
4492 102 : subres_assign_resultvars(backend *be, stmt *rel_stmt, list *vars)
4493 : {
4494 102 : list *stmts = rel_stmt->op4.lval;
4495 102 : list *nstmt = sa_list(be->mvc->sa);
4496 262 : for (node *n = stmts->h, *m = vars->h; n && m; n = n->next, m = m->next) {
4497 160 : stmt *r = n->data;
4498 160 : stmt *v = m->data;
4499 160 : InstrPtr a = newAssignment(be->mb);
4500 160 : stmt *ns = NULL;
4501 160 : sql_alias *rnme = table_name(be->mvc->sa, r);
4502 160 : const char *nme = column_name(be->mvc->sa, r);
4503 160 : int label = r->label;
4504 :
4505 160 : if (r->nrcols == 0)
4506 4 : r = const_column(be, r);
4507 160 : ns = stmt_alias(be, r, label, rnme, nme);
4508 160 : a->argv[0] = v->nr;
4509 160 : a = pushArgument(be->mb, a, ns->nr);
4510 160 : pushInstruction(be->mb, a);
4511 160 : ns->q = a;
4512 160 : ns->nr = a->argv[0];
4513 160 : append(nstmt, ns);
4514 : }
4515 102 : return stmt_list(be, nstmt);
4516 : }
4517 :
4518 : static sql_exp*
4519 17306 : topn_limit(sql_rel *rel)
4520 : {
4521 17306 : if (rel->exps) {
4522 17306 : sql_exp *limit = rel->exps->h->data;
4523 17306 : if (exp_is_null(limit)) /* If the limit is NULL, ignore the value */
4524 : return NULL;
4525 : return limit;
4526 : }
4527 : return NULL;
4528 : }
4529 :
4530 : static sql_exp*
4531 17306 : topn_offset(sql_rel *rel)
4532 : {
4533 17306 : if (rel->exps && list_length(rel->exps) > 1) {
4534 150 : sql_exp *offset = rel->exps->h->next->data;
4535 :
4536 150 : return offset;
4537 : }
4538 : return NULL;
4539 : }
4540 :
4541 : static stmt *
4542 400788 : stmt_limit_value(backend *be, sql_rel *topn)
4543 : {
4544 400788 : stmt *l = NULL;
4545 :
4546 400788 : if (topn) {
4547 331 : sql_exp *le = topn_limit(topn);
4548 331 : sql_exp *oe = topn_offset(topn);
4549 :
4550 331 : if (le) {
4551 306 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4552 306 : if(!l)
4553 : return NULL;
4554 306 : if (oe) {
4555 42 : sql_subtype *lng = sql_bind_localtype("lng");
4556 42 : sql_subfunc *add = sql_bind_func_result(be->mvc, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
4557 42 : stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
4558 42 : if(!o)
4559 : return NULL;
4560 42 : l = stmt_binop(be, l, o, NULL, add);
4561 : }
4562 : }
4563 : }
4564 : return l;
4565 : }
4566 :
4567 : static stmt *
4568 71 : rel2bin_recursive_munion(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
4569 : {
4570 71 : mvc *sql = be->mvc;
4571 71 : stmt *rel_stmt = NULL, *sub = NULL;
4572 71 : int nr_unions = list_length((list*)rel->l);
4573 71 : if (nr_unions != 2)
4574 0 : return sql_error(sql, 10, SQLSTATE(27000) "UNION: recursive unions need a base and recursive part");
4575 71 : stmt *l = stmt_limit_value(be, topn);
4576 :
4577 71 : bool distinct = need_distinct(rel);
4578 71 : sql_rel *base = ((list*)rel->l)->h->data;
4579 71 : sql_rel *recursive = ((list*)rel->l)->h->next->data;
4580 :
4581 : /* base part */
4582 71 : rel_stmt = subrel_bin(be, base, refs);
4583 71 : rel_stmt = subrel_project(be, rel_stmt, refs, base);
4584 71 : if (!rel_stmt)
4585 : return NULL;
4586 :
4587 71 : if (recursive) {
4588 71 : int gcnt = 0;
4589 71 : list *result_table = sa_list(be->mvc->sa);
4590 187 : for(node *n = rel->exps->h; n; n = n->next) {
4591 116 : sql_exp *e = n->data;
4592 116 : stmt *s = stmt_bat_new(be, exp_subtype(e), -1);
4593 116 : append(result_table, s);
4594 : }
4595 71 : rel_stmt = subres_assign_newresultvars(be, rel_stmt);
4596 71 : if (distinct)
4597 31 : rel_stmt = rel2bin_distinct(be, rel_stmt, NULL);
4598 71 : refs_update_stmt(refs, base, rel_stmt);
4599 :
4600 : /* cnt = count(temptable) */
4601 71 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
4602 71 : stmt *cnts = stmt_aggr(be, rel_stmt->op4.lval->h->data, NULL, NULL, cnt, 1, 0, 1);
4603 :
4604 : /* if topn keep total count */
4605 71 : if (l) {
4606 4 : InstrPtr r = newAssignment(be->mb);
4607 4 : gcnt = r->argv[0];
4608 4 : r->argc = r->retc = 1;
4609 4 : r = pushArgument(be->mb, r, cnts->nr);
4610 4 : pushInstruction(be->mb, r);
4611 : }
4612 :
4613 : /* while cnt > 0 (and total < limit): */
4614 71 : InstrPtr r = newAssignment(be->mb);
4615 71 : if (r == NULL)
4616 : return NULL;
4617 71 : int barrier_var = r->argv[0];
4618 71 : r->argc = r->retc = 1;
4619 71 : r->barrier = BARRIERsymbol;
4620 71 : r = pushBit(be->mb, r, TRUE);
4621 71 : pushInstruction(be->mb, r);
4622 :
4623 71 : if (l)
4624 4 : r = newStmtArgs(be->mb, calcRef, "between", 9);
4625 : else
4626 67 : r = newStmtArgs(be->mb, calcRef, "<=", 3);
4627 71 : if (r == NULL)
4628 : return NULL;
4629 71 : getArg(r, 0) = barrier_var;
4630 71 : r->barrier = LEAVEsymbol;
4631 71 : r = pushArgument(be->mb, r, cnts->nr);
4632 71 : r = pushLng(be->mb, r, 0);
4633 71 : if (l) {
4634 4 : r = pushArgument(be->mb, r, l->nr);
4635 4 : r = pushBit(be->mb, r, FALSE); /* not symmetrical */
4636 4 : r = pushBit(be->mb, r, TRUE); /* including lower bound */
4637 4 : r = pushBit(be->mb, r, FALSE); /* excluding upper bound */
4638 4 : r = pushBit(be->mb, r, FALSE); /* nils_false */
4639 4 : r = pushBit(be->mb, r, TRUE); /* anti */
4640 : }
4641 71 : pushInstruction(be->mb, r);
4642 :
4643 : /* insert temptable into result_table and make link between result_table and table name */
4644 187 : for(node *n = result_table->h, *m = rel_stmt->op4.lval->h; n && m; n = n->next, m = m->next) {
4645 116 : stmt *a = m->data;
4646 116 : stmt *v = n->data;
4647 116 : stmt *r = stmt_append(be, v, a);
4648 116 : r->nr = r->q->argv[0] = v->nr;
4649 116 : n->data = stmt_alias(be, r, a->label, a->tname, a->cname);
4650 : }
4651 :
4652 71 : if (l) {
4653 4 : InstrPtr r = newStmtArgs(be->mb, calcRef, "+", 3);
4654 4 : r->argv[0] = gcnt;
4655 4 : r->argc = r->retc = 1;
4656 4 : r = pushArgument(be->mb, r, cnts->nr);
4657 4 : r = pushArgument(be->mb, r, gcnt);
4658 4 : pushInstruction(be->mb, r);
4659 :
4660 4 : r = newStmtArgs(be->mb, calcRef, ">", 3);
4661 4 : if (r == NULL)
4662 : return NULL;
4663 4 : getArg(r, 0) = barrier_var;
4664 4 : r->barrier = LEAVEsymbol;
4665 4 : r = pushArgument(be->mb, r, gcnt);
4666 4 : r = pushArgument(be->mb, r, l->nr);
4667 4 : pushInstruction(be->mb, r);
4668 : }
4669 :
4670 : /* recursive part */
4671 71 : stmt *rec = subrel_bin(be, recursive, refs);
4672 71 : if (!rec)
4673 : return NULL;
4674 71 : rec = subrel_project(be, rec, refs, recursive);
4675 71 : rec = subres_assign_resultvars(be, rec, rel_stmt->op4.lval);
4676 71 : if (distinct) {
4677 31 : rec = rel2bin_distinct(be, rec, NULL);
4678 : /* remove values already in the result table */
4679 31 : stmt *s = releqjoin(be, rec->op4.lval, result_table, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
4680 31 : stmt *lm = stmt_result(be, s, 0);
4681 :
4682 31 : s = stmt_mirror(be, rec->op4.lval->h->data);
4683 31 : s = stmt_tdiff(be, s, lm, NULL);
4684 31 : rec->cand = s;
4685 31 : rec = subrel_project(be, rec, refs, recursive);
4686 31 : rec = subres_assign_resultvars(be, rec, rel_stmt->op4.lval);
4687 : }
4688 :
4689 : /* cnt = count(temptable) */
4690 71 : stmt *s = stmt_aggr(be, rec->op4.lval->h->data, NULL, NULL, cnt, 1, 0, 1);
4691 71 : s->nr = s->q->argv[0] = cnts->nr;
4692 :
4693 : /* jump back */
4694 71 : r = newStmtArgs(be->mb, calcRef, ">", 3);
4695 71 : if (r == NULL)
4696 : return NULL;
4697 71 : getArg(r, 0) = barrier_var;
4698 71 : r->argc = r->retc = 1;
4699 71 : r = pushArgument(be->mb, r, cnts->nr);
4700 71 : r = pushLng(be->mb, r, 0);
4701 71 : r->barrier = REDOsymbol;
4702 71 : pushInstruction(be->mb, r);
4703 :
4704 71 : r = newAssignment(be->mb);
4705 71 : if (r == NULL)
4706 : return NULL;
4707 71 : getArg(r, 0) = barrier_var;
4708 71 : r->argc = r->retc = 1;
4709 71 : r->barrier = EXITsymbol;
4710 71 : pushInstruction(be->mb, r);
4711 :
4712 : /* relabel */
4713 187 : for(node *n = result_table->h, *m = rel->exps->h; n && m; n = n->next, m = m->next) {
4714 116 : stmt *r = n->data;
4715 116 : sql_exp *e = m->data;
4716 116 : const char *cname = exp_name(e);
4717 116 : sql_alias *tname = exp_relname(e);
4718 :
4719 116 : n->data = stmt_alias(be, r, e->alias.label, tname, cname);
4720 : }
4721 71 : sub = stmt_list(be, result_table);
4722 : }
4723 :
4724 71 : if (is_single(rel))
4725 0 : sub = rel2bin_single(be, sub);
4726 : return sub;
4727 : }
4728 :
4729 : static stmt *
4730 4319 : rel2bin_munion(backend *be, sql_rel *rel, list *refs)
4731 : {
4732 4319 : if (is_recursive(rel))
4733 67 : return rel2bin_recursive_munion(be, rel, refs, NULL);
4734 :
4735 4252 : mvc *sql = be->mvc;
4736 4252 : list *l, *rstmts;
4737 4252 : node *n, *m;
4738 4252 : stmt *rel_stmt = NULL, *sub;
4739 4252 : int i, len = 0, nr_unions = list_length((list*)rel->l);
4740 :
4741 : /* convert to stmt and store the munion operands in rstmts list */
4742 4252 : rstmts = sa_list(sql->sa);
4743 15665 : for (n = ((list*)rel->l)->h; n; n = n->next) {
4744 11413 : rel_stmt = subrel_bin(be, n->data, refs);
4745 11413 : rel_stmt = subrel_project(be, rel_stmt, refs, n->data);
4746 11413 : if (!rel_stmt)
4747 : return NULL;
4748 11413 : list_append(rstmts, rel_stmt);
4749 11413 : if (!len || len > list_length(rel_stmt->op4.lval))
4750 4252 : len = list_length(rel_stmt->op4.lval);
4751 : }
4752 :
4753 : /* construct relation */
4754 4252 : l = sa_list(sql->sa);
4755 :
4756 : /* for every op4 lval node */
4757 24974 : for (i = 0; i < len; i++) {
4758 : /* extract t and c name from the first stmt */
4759 16470 : stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
4760 16470 : if (s == NULL)
4761 : return NULL;
4762 16470 : sql_alias *rnme = table_name(sql->sa, s);
4763 16470 : const char *nme = column_name(sql->sa, s);
4764 16470 : int label = s->label;
4765 : /* create a const column also from the first stmt */
4766 16470 : s = stmt_pack(be, column(be, s), nr_unions);
4767 : /* for every other rstmt */
4768 46639 : for (m = rstmts->h->next; m; m = m->next) {
4769 30169 : stmt *t = list_fetch(((stmt*)m->data)->op4.lval, i);
4770 30169 : if (t == NULL)
4771 : return NULL;
4772 30169 : s = stmt_pack_add(be, s, column(be, t));
4773 30169 : if (s == NULL)
4774 : return NULL;
4775 : }
4776 16470 : s = stmt_alias(be, s, label, rnme, nme);
4777 16470 : if (s == NULL)
4778 : return NULL;
4779 16470 : list_append(l, s);
4780 : }
4781 4252 : sub = stmt_list(be, l);
4782 :
4783 4252 : sub = rel_rename(be, rel, sub);
4784 4252 : if (need_distinct(rel))
4785 1692 : sub = rel2bin_distinct(be, sub, NULL);
4786 4252 : if (is_single(rel))
4787 11 : sub = rel2bin_single(be, sub);
4788 : return sub;
4789 : }
4790 :
4791 : static stmt *
4792 303 : rel2bin_union(backend *be, sql_rel *rel, list *refs)
4793 : {
4794 303 : mvc *sql = be->mvc;
4795 303 : list *l;
4796 303 : node *n, *m;
4797 303 : stmt *left = NULL, *right = NULL, *sub;
4798 :
4799 303 : if (rel->l) /* first construct the left sub relation */
4800 303 : left = subrel_bin(be, rel->l, refs);
4801 303 : if (rel->r) /* first construct the right sub relation */
4802 303 : right = subrel_bin(be, rel->r, refs);
4803 303 : left = subrel_project(be, left, refs, rel->l);
4804 303 : right = subrel_project(be, right, refs, rel->r);
4805 303 : if (!left || !right)
4806 : return NULL;
4807 :
4808 : /* construct relation */
4809 303 : l = sa_list(sql->sa);
4810 6331 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m;
4811 6028 : n = n->next, m = m->next) {
4812 6028 : stmt *c1 = n->data;
4813 6028 : assert(c1->type == st_alias);
4814 6028 : stmt *c2 = m->data;
4815 6028 : sql_alias *rnme = table_name(sql->sa, c1);
4816 6028 : const char *nme = column_name(sql->sa, c1);
4817 6028 : stmt *s;
4818 :
4819 6028 : s = stmt_append(be, create_const_column(be, c1, NULL), c2);
4820 6028 : if (s == NULL)
4821 : return NULL;
4822 6028 : s = stmt_alias(be, s, c1->label, rnme, nme);
4823 6028 : if (s == NULL)
4824 : return NULL;
4825 6028 : list_append(l, s);
4826 : }
4827 303 : sub = stmt_list(be, l);
4828 :
4829 303 : sub = rel_rename(be, rel, sub);
4830 303 : if (need_distinct(rel))
4831 0 : sub = rel2bin_distinct(be, sub, NULL);
4832 303 : if (is_single(rel))
4833 0 : sub = rel2bin_single(be, sub);
4834 : return sub;
4835 : }
4836 :
4837 : static stmt *
4838 2025 : rel2bin_except(backend *be, sql_rel *rel, list *refs)
4839 : {
4840 2025 : mvc *sql = be->mvc;
4841 2025 : sql_subtype *lng = sql_bind_localtype("lng");
4842 2025 : list *stmts;
4843 2025 : node *n, *m;
4844 2025 : stmt *left = NULL, *right = NULL, *sub;
4845 2025 : sql_subfunc *min;
4846 :
4847 2025 : stmt *lg = NULL, *rg = NULL;
4848 2025 : stmt *lgrp = NULL, *rgrp = NULL;
4849 2025 : stmt *lext = NULL, *rext = NULL, *next = NULL;
4850 2025 : stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
4851 2025 : stmt *s, *lm, *rm;
4852 2025 : list *lje = sa_list(sql->sa);
4853 2025 : list *rje = sa_list(sql->sa);
4854 :
4855 2025 : if (rel->l) /* first construct the left sub relation */
4856 2025 : left = subrel_bin(be, rel->l, refs);
4857 2025 : if (rel->r) /* first construct the right sub relation */
4858 2025 : right = subrel_bin(be, rel->r, refs);
4859 2025 : if (!left || !right)
4860 : return NULL;
4861 2025 : left = subrel_project(be, left, refs, rel->l);
4862 2025 : right = subrel_project(be, right, refs, rel->r);
4863 2025 : left = row2cols(be, left);
4864 2025 : right = row2cols(be, right);
4865 :
4866 : /*
4867 : * The multi column except is handled using group by's and
4868 : * group size counts on both sides of the intersect. We then
4869 : * return for each group of L with min(L.count,R.count),
4870 : * number of rows.
4871 : */
4872 4239 : for (n = left->op4.lval->h; n; n = n->next) {
4873 2214 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4874 2214 : lgrp = stmt_result(be, lg, 0);
4875 2214 : lext = stmt_result(be, lg, 1);
4876 2214 : lcnt = stmt_result(be, lg, 2);
4877 : }
4878 4239 : for (n = right->op4.lval->h; n; n = n->next) {
4879 2214 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4880 2214 : rgrp = stmt_result(be, rg, 0);
4881 2214 : rext = stmt_result(be, rg, 1);
4882 2214 : rcnt = stmt_result(be, rg, 2);
4883 : }
4884 :
4885 2025 : if (!lg || !rg)
4886 : return NULL;
4887 :
4888 2025 : if (need_distinct(rel)) {
4889 1943 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
4890 1943 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
4891 : }
4892 :
4893 : /* now find the matching groups */
4894 4239 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
4895 2214 : stmt *l = column(be, n->data);
4896 2214 : stmt *r = column(be, m->data);
4897 :
4898 2214 : l = stmt_project(be, lext, l);
4899 2214 : r = stmt_project(be, rext, r);
4900 2214 : list_append(lje, l);
4901 2214 : list_append(rje, r);
4902 : }
4903 2025 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
4904 2025 : lm = stmt_result(be, s, 0);
4905 2025 : rm = stmt_result(be, s, 1);
4906 :
4907 2025 : s = stmt_mirror(be, lext);
4908 2025 : s = stmt_tdiff(be, s, lm, NULL);
4909 :
4910 : /* first we find those missing in R */
4911 2025 : next = stmt_project(be, s, lext);
4912 2025 : ncnt = stmt_project(be, s, lcnt);
4913 2025 : zero = stmt_const(be, s, stmt_atom_lng(be, 0));
4914 :
4915 : /* ext, lcount, rcount */
4916 2025 : lext = stmt_project(be, lm, lext);
4917 2025 : lcnt = stmt_project(be, lm, lcnt);
4918 2025 : rcnt = stmt_project(be, rm, rcnt);
4919 :
4920 : /* append those missing in L */
4921 2025 : lext = stmt_append(be, lext, next);
4922 2025 : lcnt = stmt_append(be, lcnt, ncnt);
4923 2025 : rcnt = stmt_append(be, rcnt, zero);
4924 :
4925 2025 : min = sql_bind_func_result(sql, "sys", "sql_sub", F_FUNC, true, lng, 2, lng, lng);
4926 2025 : s = stmt_binop(be, lcnt, rcnt, NULL, min); /* use count */
4927 :
4928 : /* now we have gid,cnt, blowup to full groupsizes */
4929 2025 : s = stmt_gen_group(be, lext, s);
4930 :
4931 : /* project columns of left hand expression */
4932 2025 : stmts = sa_list(sql->sa);
4933 4239 : for (n = left->op4.lval->h; n; n = n->next) {
4934 2214 : stmt *c1 = column(be, n->data);
4935 2214 : assert(c1->type == st_alias);
4936 2214 : sql_alias *rnme = NULL;
4937 2214 : const char *nme = column_name(sql->sa, c1);
4938 2214 : int label = c1->label;
4939 :
4940 : /* retain name via the stmt_alias */
4941 2214 : c1 = stmt_project(be, s, c1);
4942 :
4943 2214 : rnme = table_name(sql->sa, c1);
4944 2214 : c1 = stmt_alias(be, c1, label, rnme, nme);
4945 2214 : list_append(stmts, c1);
4946 : }
4947 2025 : sub = stmt_list(be, stmts);
4948 2025 : return rel_rename(be, rel, sub);
4949 : }
4950 :
4951 : static stmt *
4952 375 : rel2bin_inter(backend *be, sql_rel *rel, list *refs)
4953 : {
4954 375 : mvc *sql = be->mvc;
4955 375 : sql_subtype *lng = sql_bind_localtype("lng");
4956 375 : list *stmts;
4957 375 : node *n, *m;
4958 375 : stmt *left = NULL, *right = NULL, *sub;
4959 375 : sql_subfunc *min;
4960 :
4961 375 : stmt *lg = NULL, *rg = NULL;
4962 375 : stmt *lgrp = NULL, *rgrp = NULL;
4963 375 : stmt *lext = NULL, *rext = NULL;
4964 375 : stmt *lcnt = NULL, *rcnt = NULL;
4965 375 : stmt *s, *lm, *rm;
4966 375 : list *lje = sa_list(sql->sa);
4967 375 : list *rje = sa_list(sql->sa);
4968 :
4969 375 : if (rel->l) /* first construct the left sub relation */
4970 375 : left = subrel_bin(be, rel->l, refs);
4971 375 : if (rel->r) /* first construct the right sub relation */
4972 375 : right = subrel_bin(be, rel->r, refs);
4973 375 : left = subrel_project(be, left, refs, rel->l);
4974 375 : right = subrel_project(be, right, refs, rel->r);
4975 375 : if (!left || !right)
4976 : return NULL;
4977 375 : left = row2cols(be, left);
4978 :
4979 : /*
4980 : * The multi column intersect is handled using group by's and
4981 : * group size counts on both sides of the intersect. We then
4982 : * return for each group of L with min(L.count,R.count),
4983 : * number of rows.
4984 : */
4985 839 : for (n = left->op4.lval->h; n; n = n->next) {
4986 464 : lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
4987 464 : lgrp = stmt_result(be, lg, 0);
4988 464 : lext = stmt_result(be, lg, 1);
4989 464 : lcnt = stmt_result(be, lg, 2);
4990 : }
4991 839 : for (n = right->op4.lval->h; n; n = n->next) {
4992 464 : rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
4993 464 : rgrp = stmt_result(be, rg, 0);
4994 464 : rext = stmt_result(be, rg, 1);
4995 464 : rcnt = stmt_result(be, rg, 2);
4996 : }
4997 :
4998 375 : if (!lg || !rg)
4999 : return NULL;
5000 :
5001 375 : if (need_distinct(rel)) {
5002 364 : lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
5003 364 : rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
5004 : }
5005 :
5006 : /* now find the matching groups */
5007 839 : for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
5008 464 : stmt *l = column(be, n->data);
5009 464 : stmt *r = column(be, m->data);
5010 :
5011 464 : l = stmt_project(be, lext, l);
5012 464 : r = stmt_project(be, rext, r);
5013 464 : list_append(lje, l);
5014 464 : list_append(rje, r);
5015 : }
5016 375 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /* is_semantics */);
5017 375 : lm = stmt_result(be, s, 0);
5018 375 : rm = stmt_result(be, s, 1);
5019 :
5020 : /* ext, lcount, rcount */
5021 375 : lext = stmt_project(be, lm, lext);
5022 375 : lcnt = stmt_project(be, lm, lcnt);
5023 375 : rcnt = stmt_project(be, rm, rcnt);
5024 :
5025 375 : min = sql_bind_func(sql, "sys", "sql_min", lng, lng, F_FUNC, true, true);
5026 375 : s = stmt_binop(be, lcnt, rcnt, NULL, min);
5027 :
5028 : /* now we have gid,cnt, blowup to full groupsizes */
5029 375 : s = stmt_gen_group(be, lext, s);
5030 :
5031 : /* project columns of left hand expression */
5032 375 : stmts = sa_list(sql->sa);
5033 839 : for (n = left->op4.lval->h; n; n = n->next) {
5034 464 : stmt *c1 = column(be, n->data);
5035 464 : assert(c1->type == st_alias);
5036 464 : sql_alias *rnme = NULL;
5037 464 : const char *nme = column_name(sql->sa, c1);
5038 464 : int label = c1->label;
5039 :
5040 : /* retain name via the stmt_alias */
5041 464 : c1 = stmt_project(be, s, c1);
5042 :
5043 464 : rnme = table_name(sql->sa, c1);
5044 464 : c1 = stmt_alias(be, c1, label, rnme, nme);
5045 464 : list_append(stmts, c1);
5046 : }
5047 375 : sub = stmt_list(be, stmts);
5048 375 : return rel_rename(be, rel, sub);
5049 : }
5050 :
5051 : static int
5052 47228 : find_matching_exp(list *exps, sql_exp *e)
5053 : {
5054 47228 : int i = 0;
5055 162675 : for (node *n = exps->h; n; n = n->next, i++) {
5056 137150 : if (exp_match(n->data, e))
5057 21703 : return i;
5058 : }
5059 : return -1;
5060 : }
5061 :
5062 : static stmt *
5063 12723 : sql_reorder(backend *be, stmt *order, list *exps, stmt *s, list *oexps, list *ostmts)
5064 : {
5065 12723 : list *l = sa_list(be->mvc->sa);
5066 :
5067 59951 : for (node *n = s->op4.lval->h, *m = exps->h; n && m; n = n->next, m = m->next) {
5068 47228 : int pos = 0;
5069 47228 : stmt *sc = n->data;
5070 47228 : sql_exp *pe = m->data;
5071 47228 : const char *cname = column_name(be->mvc->sa, sc);
5072 47228 : sql_alias *tname = table_name(be->mvc->sa, sc);
5073 :
5074 47228 : if (oexps && (pos = find_matching_exp(oexps, pe)) >= 0 && list_fetch(ostmts, pos)) {
5075 21703 : sc = list_fetch(ostmts, pos);
5076 : } else {
5077 25525 : sc = stmt_project(be, order, sc);
5078 : }
5079 47228 : sc = stmt_alias(be, sc, pe->alias.label, tname, cname);
5080 47228 : list_append(l, sc);
5081 : }
5082 12723 : return stmt_list(be, l);
5083 : }
5084 :
5085 : static stmt *
5086 400732 : rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
5087 : {
5088 400732 : mvc *sql = be->mvc;
5089 400732 : list *pl;
5090 400732 : node *en, *n;
5091 400732 : stmt *sub = NULL, *psub = NULL;
5092 400732 : stmt *l = NULL;
5093 :
5094 400732 : if (!rel->exps)
5095 0 : return stmt_none(be);
5096 :
5097 400732 : l = stmt_limit_value(be, topn);
5098 400747 : if (!l)
5099 400414 : topn = NULL;
5100 :
5101 400747 : if (rel->l) { /* first construct the sub relation */
5102 224645 : sql_rel *l = rel->l;
5103 224645 : if (l->op == op_ddl) {
5104 1212 : sql_table *t = rel_ddl_table_get(l);
5105 :
5106 1212 : if (t)
5107 1212 : sub = rel2bin_sql_table(be, t, rel->exps);
5108 : } else {
5109 223433 : sub = subrel_bin(be, rel->l, refs);
5110 : }
5111 224602 : sub = subrel_project(be, sub, refs, rel->l);
5112 224546 : if (!sub)
5113 : return NULL;
5114 : }
5115 :
5116 400648 : pl = sa_list(sql->sa);
5117 400701 : if (pl == NULL)
5118 : return NULL;
5119 400701 : if (sub)
5120 224607 : pl->expected_cnt = list_length(sub->op4.lval);
5121 400685 : psub = stmt_list(be, pl);
5122 400564 : if (psub == NULL)
5123 : return NULL;
5124 2025051 : for (en = rel->exps->h; en; en = en->next) {
5125 1624340 : sql_exp *exp = en->data;
5126 :
5127 1624340 : if (exp->virt) {
5128 : /* we need to ouput composite properly, for insert statements */
5129 0 : continue;
5130 : }
5131 1624340 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
5132 1624340 : stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL, 0, 0, 0);
5133 :
5134 1624265 : if (!s) { /* try with own projection as well, but first clean leftover statements */
5135 11254 : clean_mal_statements(be, oldstop, oldvtop);
5136 11254 : s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
5137 : }
5138 11254 : if (!s) /* error */
5139 : return NULL;
5140 : /* single value with limit */
5141 1624265 : if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
5142 14 : s = const_column(be, s);
5143 1624251 : else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
5144 31690 : s = stmt_const(be, bin_find_smallest_column(be, sub), s);
5145 :
5146 1624265 : if (!exp_name(exp))
5147 80172 : exp_label(sql->sa, exp, ++sql->label);
5148 1624179 : if (exp_name(exp)) {
5149 1624255 : s = stmt_rename(be, exp, s);
5150 : //column_name(sql->sa, s); /* save column name */
5151 1624575 : s->label = exp->alias.label;
5152 : }
5153 1624575 : list_append(pl, s);
5154 : }
5155 400711 : stmt_set_nrcols(psub);
5156 :
5157 : /* In case of a topn
5158 : if both order by and distinct: then get first order by col
5159 : do topn on it. Project all again! Then rest
5160 : */
5161 400602 : if (topn && rel->r) {
5162 282 : list *oexps = rel->r, *npl = sa_list(sql->sa);
5163 : /* distinct, topn returns at least N (unique groups) */
5164 282 : int distinct = need_distinct(rel);
5165 282 : stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
5166 282 : int nr_obe = list_length(oexps);
5167 :
5168 : /* check for partition columns */
5169 282 : stmt *grp = NULL, *ext = NULL, *cnt = NULL;
5170 288 : for (n=oexps->h; n; n = n->next, nr_obe--) {
5171 288 : sql_exp *gbe = n->data;
5172 288 : bool last = (!n->next || !is_partitioning((sql_exp*)n->next->data));
5173 :
5174 288 : if (!topn->grouped || !is_partitioning(gbe))
5175 : break;
5176 : /* create group by */
5177 6 : stmt *gbcol = exp_bin(be, gbe, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5178 :
5179 6 : if (!gbcol) {
5180 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
5181 : return NULL;
5182 : }
5183 6 : if (!gbcol->nrcols)
5184 0 : gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
5185 6 : stmt *groupby = stmt_group(be, gbcol, grp, ext, cnt, last);
5186 6 : grp = stmt_result(be, groupby, 0);
5187 6 : ext = stmt_result(be, groupby, 1);
5188 6 : cnt = stmt_result(be, groupby, 2);
5189 6 : gbcol = stmt_alias(be, gbcol, gbe->alias.label, exp_find_rel_name(gbe), exp_name(gbe));
5190 : }
5191 :
5192 282 : if (grp)
5193 : lgid = grp;
5194 874 : for (; n; n = n->next, nr_obe--) {
5195 592 : sql_exp *orderbycole = n->data;
5196 :
5197 592 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
5198 :
5199 592 : if (!orderbycolstmt)
5200 : return NULL;
5201 :
5202 : /* handle constants */
5203 592 : if (orderbycolstmt->nrcols == 0 && n->next) /* no need to sort on constant */
5204 0 : continue;
5205 592 : orderbycolstmt = column(be, orderbycolstmt);
5206 592 : if (!limit) { /* topn based on a single column */
5207 282 : limit = stmt_limit(be, orderbycolstmt, NULL, grp, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), nr_obe, 1);
5208 : } else { /* topn based on 2 columns */
5209 310 : limit = stmt_limit(be, orderbycolstmt, lpiv, lgid, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), nr_obe, 1);
5210 : }
5211 592 : if (!limit)
5212 : return NULL;
5213 592 : lpiv = limit;
5214 592 : if (!grp && nr_obe > 1) {
5215 310 : lpiv = stmt_result(be, limit, 0);
5216 310 : lgid = stmt_result(be, limit, 1);
5217 310 : if (lpiv == NULL || lgid == NULL)
5218 : return NULL;
5219 : }
5220 : }
5221 :
5222 282 : limit = lpiv;
5223 282 : if (limit && grp)
5224 6 : limit = stmt_project(be, stmt_selectnonil(be, limit, NULL), limit);
5225 282 : stmt *s;
5226 1514 : for (n=pl->h ; n; n = n->next) {
5227 1232 : stmt *os = n->data;
5228 1232 : list_append(npl, s=stmt_project(be, limit, column(be, os)));
5229 1232 : s->label = os->label;
5230 : }
5231 282 : psub = stmt_list(be, npl);
5232 :
5233 : /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
5234 282 : pl = sub->op4.lval;
5235 282 : npl = sa_list(sql->sa);
5236 1662 : for (n=pl->h ; n; n = n->next) {
5237 1380 : stmt *os = n->data;
5238 1380 : list_append(npl, s = stmt_project(be, limit, column(be, os)));
5239 1380 : s->label = os->label;
5240 : }
5241 282 : sub = stmt_list(be, npl);
5242 : }
5243 400602 : if (need_distinct(rel)) {
5244 128 : stmt *distinct = NULL;
5245 128 : psub = rel2bin_distinct(be, psub, &distinct);
5246 : /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
5247 128 : if (sub && distinct) {
5248 113 : list *npl = sa_list(sql->sa);
5249 :
5250 113 : pl = sub->op4.lval;
5251 237 : for (n=pl->h ; n; n = n->next)
5252 124 : list_append(npl, stmt_project(be, distinct, column(be, n->data)));
5253 113 : sub = stmt_list(be, npl);
5254 : }
5255 : }
5256 400602 : if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
5257 12797 : list *oexps = rel->r;
5258 12797 : stmt *orderby_ids = NULL, *orderby_grp = NULL;
5259 :
5260 12797 : list *ostmts = sa_list(be->mvc->sa);
5261 39104 : for (en = oexps->h; en; en = en->next) {
5262 26307 : stmt *orderby = NULL;
5263 26307 : sql_exp *orderbycole = en->data;
5264 26307 : stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
5265 :
5266 26307 : if (!orderbycolstmt) {
5267 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
5268 : return NULL;
5269 : }
5270 : /* single values don't need sorting */
5271 26307 : if (orderbycolstmt->nrcols == 0) {
5272 68 : append(ostmts, NULL);
5273 68 : continue;
5274 : }
5275 26239 : if (orderby_ids)
5276 13516 : orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
5277 : else
5278 12723 : orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
5279 26239 : stmt *orderby_vals = stmt_result(be, orderby, 0);
5280 26239 : append(ostmts, orderby_vals);
5281 26239 : orderby_ids = stmt_result(be, orderby, 1);
5282 26239 : orderby_grp = stmt_result(be, orderby, 2);
5283 : }
5284 12797 : if (orderby_ids)
5285 12723 : psub = sql_reorder(be, orderby_ids, rel->exps, psub, oexps, ostmts);
5286 : }
5287 : return psub;
5288 : }
5289 :
5290 : static stmt *
5291 0 : rel2bin_predicate(backend *be)
5292 : {
5293 0 : return const_column(be, stmt_bool(be, 1));
5294 : }
5295 :
5296 : static stmt *
5297 73580 : rel2bin_select(backend *be, sql_rel *rel, list *refs)
5298 : {
5299 73580 : mvc *sql = be->mvc;
5300 73580 : node *en;
5301 73580 : stmt *sub = NULL, *sel = NULL;
5302 73580 : stmt *predicate = NULL;
5303 :
5304 73580 : if (rel->l) { /* first construct the sub relation */
5305 73580 : sub = subrel_bin(be, rel->l, refs);
5306 73580 : if (!sub)
5307 : return NULL;
5308 73580 : sel = sub->cand;
5309 73580 : sub = row2cols(be, sub);
5310 : }
5311 73580 : if (!sub && !predicate)
5312 0 : predicate = rel2bin_predicate(be);
5313 73580 : if (list_empty(rel->exps)) {
5314 1482 : if (sub)
5315 : return sub;
5316 0 : if (predicate)
5317 : return predicate;
5318 0 : assert(0);
5319 : }
5320 72098 : en = rel->exps->h;
5321 72098 : if (!sub && predicate) {
5322 0 : list *l = sa_list(sql->sa);
5323 0 : assert(predicate);
5324 0 : append(l, predicate);
5325 0 : sub = stmt_list(be, l);
5326 : }
5327 : /* handle possible index lookups */
5328 : /* expressions are in index order ! */
5329 72098 : if (sub && en) {
5330 72098 : sql_exp *e = en->data;
5331 72098 : prop *p;
5332 :
5333 72098 : if ((p=find_prop(e->p, PROP_HASHCOL)) != NULL && !is_anti(e)) {
5334 12 : sql_idx *i = p->value.pval;
5335 12 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
5336 :
5337 12 : if (!(sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, en))) {
5338 : /* hash lookup cannot be used, clean leftover mal statements */
5339 3 : clean_mal_statements(be, oldstop, oldvtop);
5340 : }
5341 : }
5342 : }
5343 153188 : for (en = rel->exps->h; en; en = en->next) {
5344 81090 : sql_exp *e = en->data;
5345 81090 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
5346 :
5347 81090 : if (!s) {
5348 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
5349 : return NULL;
5350 : }
5351 81090 : if (s->nrcols == 0){
5352 4783 : if (!predicate && sub && !list_empty(sub->op4.lval))
5353 4775 : predicate = stmt_const(be, bin_find_smallest_column(be, sub), stmt_bool(be, 1));
5354 8 : else if (!predicate)
5355 0 : predicate = const_column(be, stmt_bool(be, 1));
5356 4783 : if (e->type != e_cmp) {
5357 4655 : sql_subtype *bt = sql_bind_localtype("bit");
5358 :
5359 4655 : s = stmt_convert(be, s, NULL, exp_subtype(e), bt);
5360 : }
5361 4783 : sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0, 0);
5362 76307 : } else if (e->type != e_cmp) {
5363 0 : sel = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
5364 : } else {
5365 : sel = s;
5366 : }
5367 : }
5368 :
5369 72098 : if (sub && sel) {
5370 72098 : sub = stmt_list(be, sub->op4.lval); /* protect against references */
5371 72098 : sub->cand = sel;
5372 : }
5373 : return sub;
5374 : }
5375 :
5376 : static stmt *
5377 13611 : rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
5378 : {
5379 13611 : mvc *sql = be->mvc;
5380 13611 : list *l, *aggrs, *gbexps = sa_list(sql->sa);
5381 13611 : node *n, *en;
5382 13611 : stmt *sub = NULL, *cursub;
5383 13611 : stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
5384 :
5385 13611 : if (rel->l) { /* first construct the sub relation */
5386 13611 : sub = subrel_bin(be, rel->l, refs);
5387 13611 : sub = subrel_project(be, sub, refs, rel->l);
5388 13611 : if (!sub)
5389 : return NULL;
5390 : }
5391 :
5392 13611 : if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
5393 337 : list *newl = sa_list(sql->sa);
5394 337 : node *n;
5395 :
5396 766 : for (n=sub->op4.lval->h; n; n = n->next) {
5397 429 : stmt *s = n->data;
5398 429 : assert(s->type == st_alias);
5399 429 : const char *cname = column_name(sql->sa, s);
5400 429 : sql_alias *tname = table_name(sql->sa, s);
5401 429 : int label = s->label;
5402 :
5403 429 : s = column(be, s);
5404 429 : s = stmt_alias(be, s, label, tname, cname);
5405 429 : append(newl, s);
5406 : }
5407 337 : sub = stmt_list(be, newl);
5408 : }
5409 :
5410 : /* groupby columns */
5411 :
5412 : /* Keep groupby columns, so that they can be looked up in the aggr list */
5413 13611 : if (rel->r) {
5414 10021 : list *exps = rel->r;
5415 :
5416 25246 : for (en = exps->h; en; en = en->next) {
5417 15225 : sql_exp *e = en->data;
5418 15225 : stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5419 :
5420 15225 : if (!gbcol) {
5421 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
5422 : return NULL;
5423 : }
5424 15225 : if (!gbcol->nrcols)
5425 11 : gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
5426 15225 : groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
5427 15225 : grp = stmt_result(be, groupby, 0);
5428 15225 : ext = stmt_result(be, groupby, 1);
5429 15225 : cnt = stmt_result(be, groupby, 2);
5430 15225 : gbcol = stmt_alias(be, gbcol, e->alias.label, exp_find_rel_name(e), exp_name(e));
5431 15225 : list_append(gbexps, gbcol);
5432 : }
5433 : }
5434 : /* now aggregate */
5435 13611 : l = sa_list(sql->sa);
5436 13611 : if (l == NULL)
5437 : return NULL;
5438 13611 : aggrs = rel->exps;
5439 13611 : cursub = stmt_list(be, l);
5440 13611 : if (cursub == NULL)
5441 : return NULL;
5442 13611 : if (aggrs && !aggrs->h && ext)
5443 0 : list_append(l, ext);
5444 39247 : for (n = aggrs->h; n; n = n->next) {
5445 25636 : sql_exp *aggrexp = n->data;
5446 25636 : stmt *aggrstmt = NULL;
5447 25636 : int oldvtop, oldstop;
5448 :
5449 : /* first look in the current aggr list (l) and group by column list */
5450 25636 : if (l && !aggrstmt && aggrexp->type == e_column)
5451 : //aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
5452 14772 : aggrstmt = list_find_column_nid(be, l, aggrexp->nid);
5453 25636 : if (gbexps && !aggrstmt && aggrexp->type == e_column) {
5454 : //aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
5455 14746 : aggrstmt = list_find_column_nid(be, gbexps, aggrexp->nid);
5456 14746 : if (aggrstmt && groupby) {
5457 14543 : aggrstmt = stmt_project(be, ext, aggrstmt);
5458 14543 : if (list_length(gbexps) == 1)
5459 5962 : aggrstmt->key = 1;
5460 : }
5461 : }
5462 :
5463 25636 : oldvtop = be->mb->vtop;
5464 25636 : oldstop = be->mb->stop;
5465 25636 : if (!aggrstmt)
5466 11067 : aggrstmt = exp_bin(be, aggrexp, sub, NULL, grp, ext, cnt, NULL, 0, 0, 0);
5467 : /* maybe the aggr uses intermediate results of this group by,
5468 : therefore we pass the group by columns too
5469 : */
5470 11067 : if (!aggrstmt) {
5471 1 : clean_mal_statements(be, oldstop, oldvtop);
5472 1 : aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL, 0, 0, 0);
5473 : }
5474 1 : if (!aggrstmt) {
5475 0 : assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
5476 : return NULL;
5477 : }
5478 :
5479 25636 : if (!aggrstmt->nrcols && ext && ext->nrcols)
5480 0 : aggrstmt = stmt_const(be, ext, aggrstmt);
5481 :
5482 25636 : aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
5483 25636 : list_append(l, aggrstmt);
5484 : }
5485 13611 : stmt_set_nrcols(cursub);
5486 13611 : return cursub;
5487 : }
5488 :
5489 : static bool
5490 8 : has_partitioning( list *exps )
5491 : {
5492 10 : for(node *n = exps->h; n; n = n->next){
5493 8 : sql_exp *gbe = n->data;
5494 8 : if (is_partitioning(gbe))
5495 : return true;
5496 : }
5497 : return false;
5498 : }
5499 :
5500 : static stmt *
5501 16973 : rel2bin_topn(backend *be, sql_rel *rel, list *refs)
5502 : {
5503 16973 : mvc *sql = be->mvc;
5504 16973 : sql_exp *oe = NULL, *le = NULL;
5505 16973 : stmt *sub = NULL, *l = NULL, *o = NULL;
5506 16973 : node *n;
5507 :
5508 16973 : if (rel->l) { /* first construct the sub relation */
5509 16973 : sql_rel *rl = rel->l;
5510 :
5511 16973 : if (rl->op == op_munion && is_recursive(rl)) {
5512 4 : if (rel_is_ref(rl)) {
5513 0 : sub = refs_find_rel(refs, rl);
5514 0 : if (!sub)
5515 0 : sub = rel2bin_recursive_munion(be, rl, refs, rel);
5516 : } else
5517 4 : sub = rel2bin_recursive_munion(be, rl, refs, rel);
5518 16969 : } else if (rl->op == op_project) {
5519 332 : if (rel_is_ref(rl)) {
5520 5 : sub = refs_find_rel(refs, rl);
5521 5 : if (!sub)
5522 0 : sub = rel2bin_project(be, rl, refs, rel);
5523 : } else
5524 327 : sub = rel2bin_project(be, rl, refs, rel);
5525 340 : if (rel->grouped && rl->r && has_partitioning(rl->r))
5526 : return sub;
5527 : } else {
5528 16637 : sub = subrel_bin(be, rl, refs);
5529 : }
5530 16970 : sub = subrel_project(be, sub, refs, rl);
5531 : }
5532 16975 : if (!sub)
5533 0 : return NULL;
5534 :
5535 16975 : le = topn_limit(rel);
5536 16975 : oe = topn_offset(rel);
5537 :
5538 16974 : n = sub->op4.lval->h;
5539 16974 : if (n) {
5540 16974 : stmt *limit = NULL, *sc = n->data;
5541 16974 : list *newl = sa_list(sql->sa);
5542 16974 : int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
5543 :
5544 16974 : if (le)
5545 16948 : l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5546 16946 : if (!l) {
5547 26 : clean_mal_statements(be, oldstop, oldvtop);
5548 26 : l = stmt_atom_lng_nil(be);
5549 : }
5550 :
5551 16970 : oldvtop = be->mb->vtop;
5552 16970 : oldstop = be->mb->stop;
5553 16970 : if (oe)
5554 83 : o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5555 83 : if (!o) {
5556 16887 : clean_mal_statements(be, oldstop, oldvtop);
5557 16889 : o = stmt_atom_lng(be, 0);
5558 : }
5559 16970 : if (!l || !o)
5560 : return NULL;
5561 :
5562 :
5563 16970 : sc = column(be, sc);
5564 16966 : limit = stmt_limit(be, sc, NULL, NULL, o, l, 0,0,0,0,0);
5565 :
5566 118873 : for ( ; n; n = n->next) {
5567 84933 : stmt *sc = n->data;
5568 84933 : assert(sc->type == st_alias);
5569 84933 : const char *cname = column_name(sql->sa, sc);
5570 84934 : sql_alias *tname = table_name(sql->sa, sc);
5571 84934 : int label = sc->label;
5572 :
5573 84934 : sc = column(be, sc);
5574 84934 : sc = stmt_project(be, limit, sc);
5575 84926 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
5576 : }
5577 16974 : sub = stmt_list(be, newl);
5578 : }
5579 : return sub;
5580 : }
5581 :
5582 : static stmt *
5583 21 : rel2bin_sample(backend *be, sql_rel *rel, list *refs)
5584 : {
5585 21 : mvc *sql = be->mvc;
5586 21 : list *newl;
5587 21 : stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
5588 21 : node *n;
5589 :
5590 21 : if (rel->l) /* first construct the sub relation */
5591 21 : sub = subrel_bin(be, rel->l, refs);
5592 21 : sub = subrel_project(be, sub, refs, rel->l);
5593 21 : if (!sub)
5594 : return NULL;
5595 :
5596 21 : n = sub->op4.lval->h;
5597 21 : newl = sa_list(sql->sa);
5598 :
5599 21 : if (n) {
5600 21 : stmt *sc = n->data;
5601 : //const char *cname = column_name(sql->sa, sc);
5602 : //sql_alias *tname = table_name(sql->sa, sc);
5603 :
5604 21 : if (!(sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0)))
5605 : return NULL;
5606 :
5607 21 : if (rel->exps->cnt == 2) {
5608 12 : seed = exp_bin(be, rel->exps->h->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5609 12 : if (!seed)
5610 : return NULL;
5611 : }
5612 :
5613 21 : sc = column(be, sc);
5614 21 : sample = stmt_sample(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/,sample_size, seed);
5615 :
5616 63 : for ( ; n; n = n->next) {
5617 21 : stmt *sc = n->data;
5618 21 : assert(sc->type == st_alias);
5619 21 : const char *cname = column_name(sql->sa, sc);
5620 21 : sql_alias *tname = table_name(sql->sa, sc);
5621 21 : int label = sc->label;
5622 :
5623 21 : sc = column(be, sc);
5624 21 : sc = stmt_project(be, sample, sc);
5625 21 : list_append(newl, stmt_alias(be, sc, label, tname, cname));
5626 : }
5627 : }
5628 21 : sub = stmt_list(be, newl);
5629 21 : return sub;
5630 : }
5631 :
5632 : static stmt *
5633 5206 : sql_parse(backend *be, sql_schema *s, const char *query, char mode)
5634 : {
5635 5206 : sql_rel *rel = rel_parse(be->mvc, s, query, mode);
5636 5206 : stmt *sq = NULL;
5637 :
5638 5206 : if (rel && (rel = sql_processrelation(be->mvc, rel, 0, 1, 1, 1)))
5639 5203 : sq = rel_bin(be, rel);
5640 5206 : return sq;
5641 : }
5642 :
5643 : static stmt *
5644 12870 : insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
5645 : {
5646 12870 : mvc *sql = be->mvc;
5647 : /* pkey's cannot have NULLs, ukeys however can
5648 : current implementation switches on 'NOT NULL' on primary key columns */
5649 :
5650 12870 : char *msg = NULL;
5651 12870 : stmt *res;
5652 :
5653 12870 : sql_subtype *lng = sql_bind_localtype("lng");
5654 12902 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5655 12899 : sql_subtype *bt = sql_bind_localtype("bit");
5656 12903 : stmt *dels = stmt_tid(be, k->t, 0);
5657 12902 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5658 :
5659 12904 : if (list_length(k->columns) > 1) {
5660 825 : node *m;
5661 825 : stmt *s = list_fetch(inserts, 0), *ins = s;
5662 825 : sql_subfunc *sum;
5663 825 : stmt *ssum = NULL;
5664 825 : stmt *col = NULL;
5665 :
5666 825 : s = ins;
5667 : /* 1st stage: find out if original contains same values */
5668 825 : if (/*s->key &&*/ s->nrcols == 0) {
5669 586 : s = NULL;
5670 586 : if (k->idx && hash_index(k->idx->type))
5671 586 : s = stmt_uselect(be, stmt_idx(be, k->idx, dels, dels->partition), idx_inserts, cmp_equal, s, 0, 1 /* is_semantics*/);
5672 2149 : for (m = k->columns->h; m; m = m->next) {
5673 1563 : sql_kc *c = m->data;
5674 1563 : stmt *cs = list_fetch(inserts, c->c->colnr);
5675 :
5676 : /* foreach column add predicate */
5677 1563 : stmt_add_column_predicate(be, c->c);
5678 :
5679 1563 : col = stmt_col(be, c->c, dels, dels->partition);
5680 1563 : if (k->type == unndkey)
5681 8 : s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 1);
5682 1664 : else if ((k->type == ukey) && stmt_has_null(col)) {
5683 109 : stmt *nn = stmt_selectnonil(be, col, s);
5684 109 : s = stmt_uselect(be, col, cs, cmp_equal, nn, 0, 0);
5685 : } else {
5686 1446 : s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 0);
5687 : }
5688 : }
5689 : } else {
5690 239 : list *lje = sa_list(sql->sa);
5691 239 : list *rje = sa_list(sql->sa);
5692 239 : if (k->idx && hash_index(k->idx->type)) {
5693 239 : list_append(lje, stmt_idx(be, k->idx, dels, dels->partition));
5694 239 : list_append(rje, idx_inserts);
5695 : }
5696 764 : for (m = k->columns->h; m; m = m->next) {
5697 525 : sql_kc *c = m->data;
5698 525 : stmt *cs = list_fetch(inserts, c->c->colnr);
5699 :
5700 : /* foreach column add predicate */
5701 525 : stmt_add_column_predicate(be, c->c);
5702 :
5703 525 : col = stmt_col(be, c->c, dels, dels->partition);
5704 525 : list_append(lje, col);
5705 525 : list_append(rje, cs);
5706 : }
5707 239 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, k->type == unndkey? 1: 0);
5708 239 : s = stmt_result(be, s, 0);
5709 : }
5710 825 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
5711 :
5712 : /* 2nd stage: find out if inserted are unique */
5713 825 : if ((!idx_inserts && ins->nrcols) || (idx_inserts && idx_inserts->nrcols)) { /* insert columns not atoms */
5714 239 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5715 239 : stmt *orderby_ids = NULL, *orderby_grp = NULL;
5716 239 : stmt *sel = NULL;
5717 :
5718 : /* remove any nils as in stmt_order NULL = NULL, instead of NULL != NULL */
5719 239 : if (k->type == ukey) {
5720 153 : for (m = k->columns->h; m; m = m->next) {
5721 105 : sql_kc *c = m->data;
5722 105 : stmt *cs = list_fetch(inserts, c->c->colnr);
5723 105 : if (stmt_has_null(cs))
5724 102 : sel = stmt_selectnonil(be, cs, sel);
5725 : }
5726 : }
5727 : /* implementation uses sort key check */
5728 764 : for (m = k->columns->h; m; m = m->next) {
5729 525 : sql_kc *c = m->data;
5730 525 : stmt *orderby;
5731 525 : stmt *cs = list_fetch(inserts, c->c->colnr);
5732 :
5733 525 : if (sel)
5734 102 : cs = stmt_project(be, sel, cs);
5735 525 : if (orderby_grp)
5736 286 : orderby = stmt_reorder(be, cs, 1, 0, orderby_ids, orderby_grp);
5737 : else
5738 239 : orderby = stmt_order(be, cs, 1, 0);
5739 525 : orderby_ids = stmt_result(be, orderby, 1);
5740 525 : orderby_grp = stmt_result(be, orderby, 2);
5741 : }
5742 :
5743 239 : if (!orderby_grp || !orderby_ids)
5744 : return NULL;
5745 :
5746 239 : sum = sql_bind_func(sql, "sys", "not_unique", tail_type(orderby_grp), NULL, F_AGGR, true, true);
5747 239 : ssum = stmt_aggr(be, orderby_grp, NULL, NULL, sum, 1, 0, 1);
5748 : /* combine results */
5749 239 : s = stmt_binop(be, s, ssum, NULL, or);
5750 : }
5751 :
5752 825 : if (k->type == pkey) {
5753 330 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5754 : } else {
5755 495 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5756 : }
5757 825 : res = stmt_exception(be, s, msg, 00001);
5758 : } else { /* single column key */
5759 12045 : sql_kc *c = k->columns->h->data;
5760 12045 : stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
5761 :
5762 : /* add predicate for this column */
5763 12036 : stmt_add_column_predicate(be, c->c);
5764 :
5765 12080 : s = stmt_col(be, c->c, dels, dels->partition);
5766 12075 : if ((k->type == ukey) && stmt_has_null(s)) {
5767 202 : stmt *nn = stmt_selectnonil(be, s, NULL);
5768 202 : s = stmt_project(be, nn, s);
5769 : }
5770 12075 : if (h->nrcols) {
5771 4853 : s = stmt_join(be, s, h, 0, cmp_equal, 0, k->type == unndkey? 1: 0, false);
5772 : /* s should be empty */
5773 4853 : s = stmt_result(be, s, 0);
5774 4853 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5775 : } else {
5776 7222 : s = stmt_uselect(be, s, h, cmp_equal, NULL, 0, k->type == unndkey? 1: 0);
5777 : /* s should be empty */
5778 7227 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5779 : }
5780 : /* s should be empty */
5781 12080 : s = stmt_binop(be, s, stmt_atom_lng(be, 0), NULL, ne);
5782 :
5783 : /* 2e stage: find out if inserts are unique */
5784 12080 : if (h->nrcols) { /* insert multiple atoms */
5785 4853 : sql_subfunc *sum;
5786 4853 : stmt *count_sum = NULL;
5787 4853 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
5788 4853 : stmt *ssum, *ss;
5789 :
5790 4853 : stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
5791 :
5792 : /* inserted values may be null */
5793 4853 : if ((k->type == ukey) && stmt_has_null(ins)) {
5794 1783 : stmt *nn = stmt_selectnonil(be, ins, NULL);
5795 1783 : ins = stmt_project(be, nn, ins);
5796 : }
5797 :
5798 4853 : g = stmt_group(be, ins, NULL, NULL, NULL, 1);
5799 4853 : ss = stmt_result(be, g, 2); /* use count */
5800 : /* (count(ss) <> sum(ss)) */
5801 4853 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
5802 4853 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
5803 4853 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
5804 4853 : count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
5805 :
5806 : /* combine results */
5807 4853 : s = stmt_binop(be, s, count_sum, NULL, or);
5808 : }
5809 12080 : if (k->type == pkey) {
5810 10136 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5811 : } else {
5812 1944 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
5813 : }
5814 12079 : res = stmt_exception(be, s, msg, 00001);
5815 : }
5816 : return res;
5817 : }
5818 :
5819 : static stmt *
5820 777 : insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
5821 : {
5822 777 : mvc *sql = be->mvc;
5823 777 : char *msg = NULL;
5824 777 : stmt *cs = list_fetch(inserts, 0), *s = cs;
5825 777 : sql_subtype *lng = sql_bind_localtype("lng");
5826 777 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5827 777 : sql_subtype *bt = sql_bind_localtype("bit");
5828 777 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
5829 :
5830 777 : stmt *nonil_rows = NULL;
5831 1589 : for (node *m = k->columns->h; m; m = m->next) {
5832 812 : sql_kc *c = m->data;
5833 :
5834 : /* foreach column add predicate */
5835 812 : stmt_add_column_predicate(be, c->c);
5836 :
5837 : // foreach column aggregate the nonil (literally 'null') values.
5838 : // mind that null values are valid fkeys with undefined value so
5839 : // we won't have an entry for them in the idx_inserts col
5840 812 : s = list_fetch(inserts, c->c->colnr);
5841 812 : nonil_rows = stmt_selectnonil(be, s, nonil_rows);
5842 : }
5843 :
5844 777 : if (!s && pin && list_length(pin->op4.lval))
5845 0 : s = pin->op4.lval->h->data;
5846 :
5847 : // we want to make sure that the data column(s) has the same number
5848 : // of (nonil) rows as the index column. if that is **not** the case
5849 : // then we are obviously dealing with an invalid foreign key
5850 777 : if (s->key && s->nrcols == 0) {
5851 0 : s = stmt_binop(be,
5852 : stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
5853 : stmt_aggr(be, const_column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
5854 : NULL, ne);
5855 : } else {
5856 : /* relThetaJoin.notNull.count <> inserts[notNull(col1) && ... && notNull(colN)].count */
5857 777 : s = stmt_binop(be,
5858 : stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
5859 : stmt_aggr(be, column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
5860 : NULL, ne);
5861 : }
5862 :
5863 : /* s should be empty */
5864 777 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
5865 777 : return stmt_exception(be, s, msg, 00001);
5866 : }
5867 :
5868 : static stmt *
5869 13647 : sql_insert_key(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
5870 : {
5871 : /* int insert = 1;
5872 : * while insert and has u/pkey and not deferred then
5873 : * if u/pkey values exist then
5874 : * insert = 0
5875 : * while insert and has fkey and not deferred then
5876 : * find id of corresponding u/pkey
5877 : * if (!found)
5878 : * insert = 0
5879 : * if insert
5880 : * insert values
5881 : * insert fkey/pkey index
5882 : */
5883 13647 : if (k->type == pkey || k->type == ukey || k->type == unndkey) {
5884 12870 : return insert_check_ukey(be, inserts, k, idx_inserts);
5885 : } else { /* foreign keys */
5886 777 : return insert_check_fkey(be, inserts, k, idx_inserts, pin);
5887 : }
5888 : }
5889 :
5890 : static int
5891 4921 : sql_stack_add_inserted(mvc *sql, const char *name, sql_table *t, stmt **updates)
5892 : {
5893 : /* Put single relation of updates and old values on to the stack */
5894 4921 : sql_rel *r = NULL;
5895 4921 : node *n;
5896 4921 : list *exps = sa_list(sql->sa);
5897 4921 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
5898 :
5899 4921 : ti->t = t;
5900 4921 : ti->tids = NULL;
5901 4921 : ti->updates = updates;
5902 4921 : ti->type = 1;
5903 4921 : ti->nn = name;
5904 4921 : sql_alias *aname = a_create(sql->sa, name);
5905 :
5906 13129 : for (n = ol_first_node(t->columns); n; n = n->next) {
5907 8208 : sql_column *c = n->data;
5908 8208 : sql_exp *ne = exp_column(sql->sa, aname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
5909 8208 : ne->alias.label = -(sql->nid++);
5910 :
5911 8208 : append(exps, ne);
5912 : }
5913 4921 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
5914 4921 : r->l = ti;
5915 :
5916 4921 : return stack_push_rel_view(sql, name, r) ? 1 : 0;
5917 : }
5918 :
5919 : static int
5920 216232 : sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
5921 : {
5922 216232 : mvc *sql = be->mvc;
5923 216232 : node *n;
5924 216232 : int res = 1;
5925 :
5926 216232 : if (!ol_length(t->triggers))
5927 : return res;
5928 :
5929 8451 : for (n = ol_first_node(t->triggers); n; n = n->next) {
5930 6742 : sql_trigger *trigger = n->data;
5931 :
5932 6742 : if (!stack_push_frame(sql, "%OLD-NEW"))
5933 : return 0;
5934 6742 : if (trigger->event == 0 && trigger->time == time) {
5935 4921 : const char *n = trigger->new_name;
5936 :
5937 : /* add name for the 'inserted' to the stack */
5938 4921 : if (!n) n = "new";
5939 :
5940 4921 : if(!sql_stack_add_inserted(sql, n, t, updates)) {
5941 0 : stack_pop_frame(sql);
5942 0 : return 0;
5943 : }
5944 4921 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
5945 4893 : stack_pop_frame(sql);
5946 4893 : return 0;
5947 : }
5948 : }
5949 1849 : stack_pop_frame(sql);
5950 : }
5951 : return res;
5952 : }
5953 :
5954 : static void
5955 83 : sql_insert_check(backend *be, sql_key *key, list *inserts)
5956 : {
5957 83 : mvc *sql = be->mvc;
5958 83 : int pos = 0;
5959 83 : sql_alias *rname = table_alias(be->mvc->sa, key->t, NULL);
5960 83 : sql_rel *rel = rel_basetable(sql, key->t, rname);
5961 83 : sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
5962 83 : rel->exps = rel_base_projection(sql, rel, 0);
5963 :
5964 : /* create new sub stmt with needed inserts */
5965 83 : list *ins = sa_list(sql->sa);
5966 173 : for(node *n = key->columns->h; n; n = n->next) {
5967 90 : sql_kc *kc = n->data;
5968 90 : stmt *in = list_fetch(inserts, kc->c->colnr);
5969 :
5970 90 : sql_exp *e = rel_base_bind_column2(sql, rel, rname, kc->c->base.name);
5971 90 : in = stmt_alias(be, in, e->alias.label, rname, kc->c->base.name);
5972 90 : append(ins, in);
5973 : }
5974 83 : stmt *sub = stmt_list(be, ins);
5975 83 : stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
5976 83 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
5977 83 : s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
5978 83 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
5979 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);
5980 83 : (void)stmt_exception(be, s, msg, 00001);
5981 83 : }
5982 :
5983 : static sql_table *
5984 109783 : sql_insert_check_null(backend *be, sql_table *t, list *inserts)
5985 : {
5986 109783 : mvc *sql = be->mvc;
5987 109783 : node *m, *n;
5988 109783 : sql_subfunc *cnt = NULL;
5989 :
5990 822944 : for (n = ol_first_node(t->columns), m = inserts->h; n && m;
5991 713161 : n = n->next, m = m->next) {
5992 713110 : stmt *i = m->data;
5993 713110 : sql_column *c = n->data;
5994 :
5995 713110 : if (!c->null) {
5996 24620 : stmt *s = i;
5997 24620 : char *msg = NULL;
5998 :
5999 24620 : if (!(s->key && s->nrcols == 0)) {
6000 11588 : s = stmt_selectnil(be, column(be, i));
6001 11588 : if (!cnt)
6002 3686 : cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6003 11588 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6004 : } else {
6005 13032 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
6006 :
6007 13020 : s = stmt_unop(be, i, NULL, isnil);
6008 : }
6009 24643 : msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
6010 24639 : (void)stmt_exception(be, s, msg, 00001);
6011 : }
6012 : }
6013 109834 : return t; /* return something to say it succeeded */
6014 : }
6015 :
6016 : static stmt **
6017 114216 : table_update_stmts(mvc *sql, sql_table *t, int *Len)
6018 : {
6019 114216 : *Len = ol_length(t->columns);
6020 114206 : return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
6021 : }
6022 :
6023 : static stmt *insert_ms(backend *be, sql_table *st, sql_subtype *ct, stmt *ms);
6024 :
6025 : static node *
6026 34 : insert_composite(backend *be, stmt **updates, sql_table *st, sql_column *c, node *n, node *m)
6027 : {
6028 34 : mvc *sql = be->mvc;
6029 34 : node *f;
6030 34 : stmt *input_tuple = m->data;
6031 :
6032 68 : while(input_tuple->type == st_alias)
6033 34 : input_tuple = input_tuple->op1;
6034 34 : if (input_tuple->type != st_list)
6035 : return NULL;
6036 111 : for(n = n->next, f = c->type.type->d.fields->h, m = input_tuple->op4.lval->h; n && m && f; f = f->next) {
6037 77 : sql_column *c = n->data;
6038 :
6039 77 : if (c->type.multiset) {
6040 18 : sql_table *nst = mvc_bind_table(sql, st->s, c->storage_type);
6041 18 : if (!nst)
6042 0 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
6043 18 : updates[c->colnr] = insert_ms(be, nst, &c->type, m->data);
6044 18 : n = n->next;
6045 18 : m = m->next;
6046 59 : } else if (c->type.type->composite && !c->type.multiset) {
6047 4 : n = insert_composite(be, updates, st, c, n, m);
6048 4 : m = m->next;
6049 : } else {
6050 55 : updates[c->colnr] = m->data;
6051 55 : n = n->next;
6052 55 : m = m->next;
6053 : }
6054 : }
6055 : return n;
6056 : }
6057 :
6058 : static stmt *
6059 35 : insert_ms(backend *be, sql_table *st, sql_subtype *ct, stmt *ms)
6060 : {
6061 35 : mvc *sql = be->mvc;
6062 :
6063 54 : while(ms && ms->type == st_alias)
6064 19 : ms = ms->op1;
6065 35 : if (ms->type != st_list)
6066 : return NULL;
6067 :
6068 35 : int len;
6069 35 : stmt **updates = table_update_stmts(sql, st, &len);
6070 35 : stmt *insert = NULL, *cnt, *pos = NULL;
6071 :
6072 35 : node *n, *m;
6073 153 : for (n = ol_first_node(st->columns), m = ms->op4.lval->h; n && m; ) {
6074 118 : sql_column *c = n->data;
6075 :
6076 118 : if (c->type.multiset) {
6077 4 : sql_table *nst = mvc_bind_table(sql, st->s, c->storage_type);
6078 4 : if (!nst)
6079 0 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
6080 4 : updates[c->colnr] = insert_ms(be, nst, &c->type, m->data);
6081 4 : n = n->next;
6082 4 : m = m->next;
6083 114 : } else if (c->type.type->composite && !c->type.multiset) {
6084 6 : n = insert_composite(be, updates, st, c, n, m);
6085 6 : m = m->next;
6086 : } else {
6087 108 : insert = updates[c->colnr] = m->data;
6088 108 : n = n->next;
6089 108 : m = m->next;
6090 : }
6091 : }
6092 :
6093 35 : if (!insert || insert->nrcols == 0) {
6094 0 : cnt = stmt_atom_lng(be, 1);
6095 : } else {
6096 35 : 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);
6097 : }
6098 :
6099 35 : list *l = sa_list(sql->sa);
6100 :
6101 35 : if (st->s) /* only not declared tables, need this */
6102 35 : pos = stmt_claim(be, st, cnt);
6103 :
6104 35 : int mvc_var = be->mvc_var;
6105 35 : stmt *rowids = m->data;
6106 35 : stmt *msid = updates[len-1 -((ct->multiset == MS_ARRAY)?1:0)];
6107 :
6108 : /* nrowids = next_value_for(rowids, "schema?", st->base.name) */
6109 35 : InstrPtr q = newStmt(be->mb, batsqlRef, "next_value_ms");
6110 35 : q = pushArgument(be->mb, q, rowids->nr);
6111 35 : q = pushStr(be->mb, q, st->s->base.name); /* sequence schema name */
6112 35 : q = pushStr(be->mb, q, st->base.name); /* sequence number name */
6113 35 : pushInstruction(be->mb, q);
6114 :
6115 : /* nrowids = batcalc.int(nrowids) */
6116 35 : InstrPtr r = newStmt(be->mb, batcalcRef, "int");
6117 35 : r = pushArgument(be->mb, r, getArg(q, 0));
6118 35 : pushInstruction(be->mb, r);
6119 :
6120 : /* msid = renumber(msid, rowids, nrowids); */
6121 35 : q = newStmt(be->mb, batsqlRef, "renumber");
6122 35 : q = pushArgument(be->mb, q, msid->nr);
6123 35 : q = pushArgument(be->mb, q, rowids->nr);
6124 35 : q = pushArgument(be->mb, q, getArg(r, 0));
6125 35 : pushInstruction(be->mb, q);
6126 :
6127 : /* now update msid and rowids */
6128 35 : rowids->nr = getArg(r, 0);
6129 35 : msid->nr = getArg(q, 0);
6130 :
6131 165 : for (n = ol_first_node(st->columns); n; n = n->next) {
6132 :
6133 130 : sql_column *c = n->data;
6134 130 : stmt *ins = updates[c->colnr];
6135 :
6136 130 : if (ins) {
6137 124 : insert = stmt_append_col(be, c, pos, ins, &mvc_var, false);
6138 124 : if (!insert)
6139 : return NULL;
6140 124 : append(l,insert);
6141 : }
6142 : }
6143 35 : be->mvc_var = mvc_var;
6144 :
6145 35 : return rowids;
6146 : }
6147 :
6148 : static stmt *
6149 37 : rel2bin_insert_ms(backend *be, sql_rel *rel, list *refs)
6150 : {
6151 37 : mvc *sql = be->mvc;
6152 37 : list *l;
6153 37 : stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
6154 37 : int idx_ins = 0, len = 0;
6155 37 : node *n, *m, *idx_m = NULL;
6156 37 : sql_rel *tr = rel->l, *prel = rel->r;
6157 37 : sql_table *t = NULL;
6158 :
6159 37 : if ((rel->flag&UPD_COMP)) { /* special case ! */
6160 0 : assert(0);
6161 : idx_ins = 1;
6162 : prel = rel->l;
6163 : rel = rel->r;
6164 : tr = rel->l;
6165 : }
6166 :
6167 37 : if (tr->op == op_basetable) {
6168 37 : t = tr->l;
6169 : } else {
6170 0 : ddl = subrel_bin(be, tr, refs);
6171 0 : ddl = subrel_project(be, ddl, refs, NULL);
6172 0 : if (!ddl)
6173 : return NULL;
6174 0 : t = rel_ddl_table_get(tr);
6175 : }
6176 :
6177 37 : if (rel->r) /* first construct the inserts relation */
6178 37 : inserts = subrel_bin(be, rel->r, refs);
6179 37 : inserts = subrel_project(be, inserts, refs, rel->r);
6180 :
6181 37 : if (!inserts)
6182 : return NULL;
6183 :
6184 37 : if (idx_ins)
6185 : pin = refs_find_rel(refs, prel);
6186 :
6187 37 : for (n = ol_first_node(t->keys); n; n = n->next) {
6188 0 : sql_key * key = n->data;
6189 0 : if (key->type == ckey)
6190 0 : sql_insert_check(be, key, inserts->op4.lval);
6191 : }
6192 :
6193 37 : if (!sql_insert_check_null(be, t, inserts->op4.lval))
6194 : return NULL;
6195 :
6196 37 : updates = table_update_stmts(sql, t, &len);
6197 :
6198 : /* now recursively insert into the sub tables (for each multiset fetch sequence number and renumber the msids) */
6199 82 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; ) {
6200 45 : sql_column *c = n->data;
6201 :
6202 45 : if (c->type.multiset) {
6203 13 : sql_table *st = mvc_bind_table(sql, t->s, c->storage_type);
6204 13 : if (!st)
6205 0 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
6206 13 : updates[c->colnr] = insert_ms(be, st, &c->type, m->data);
6207 13 : n = n->next;
6208 13 : m = m->next;
6209 32 : } else if (c->type.type->composite && !c->type.multiset) {
6210 24 : n = insert_composite(be, updates, t, c, n, m);
6211 24 : m = m->next;
6212 : } else {
6213 8 : updates[c->colnr] = m->data;
6214 8 : n = n->next;
6215 8 : m = m->next;
6216 : }
6217 : }
6218 :
6219 : /* before */
6220 37 : if (!sql_insert_triggers(be, t, updates, 0))
6221 0 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
6222 :
6223 37 : insert = inserts->op4.lval->h?inserts->op4.lval->h->data:NULL;
6224 37 : if (!insert || insert->nrcols == 0) {
6225 0 : cnt = stmt_atom_lng(be, 1);
6226 : } else {
6227 37 : 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);
6228 : }
6229 37 : insert = NULL;
6230 :
6231 37 : l = sa_list(sql->sa);
6232 37 : if (t->idxs) {
6233 37 : idx_m = m;
6234 37 : for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
6235 0 : stmt *is = m->data;
6236 0 : sql_idx *i = n->data;
6237 :
6238 0 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6239 0 : continue;
6240 0 : if (hash_index(i->type) && list_length(i->columns) <= 1)
6241 0 : is = NULL;
6242 0 : if (i->key) {
6243 0 : stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
6244 :
6245 0 : list_append(l, ckeys);
6246 : }
6247 0 : if (!insert)
6248 0 : insert = is;
6249 : }
6250 37 : assert(!n && !m);
6251 : }
6252 :
6253 37 : if (t->s) /* only not declared tables, need this */
6254 37 : pos = stmt_claim(be, t, cnt);
6255 :
6256 37 : if (t->idxs) {
6257 37 : for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
6258 0 : stmt *is = m->data;
6259 0 : sql_idx *i = n->data;
6260 :
6261 0 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6262 0 : continue;
6263 0 : if (hash_index(i->type) && list_length(i->columns) <= 1)
6264 : is = NULL;
6265 0 : if (is)
6266 0 : is = stmt_append_idx(be, i, pos, is);
6267 : }
6268 37 : assert(!n && !m);
6269 : }
6270 :
6271 37 : int mvc_var = be->mvc_var;
6272 147 : for (n = ol_first_node(t->columns)/*, m = inserts->op4.lval->h*/; n /*&& m*/; n = n->next/*, m = m->next*/) {
6273 :
6274 : //stmt *ins = m->data;
6275 110 : sql_column *c = n->data;
6276 110 : stmt *ins = updates[c->colnr];
6277 :
6278 110 : if (ins) {
6279 82 : insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
6280 82 : append(l,insert);
6281 : }
6282 : }
6283 37 : be->mvc_var = mvc_var;
6284 37 : if (!insert)
6285 : return NULL;
6286 :
6287 37 : if (rel->returning) {
6288 0 : list* il = sa_list(sql->sa);
6289 0 : sql_rel* inner = rel->l;
6290 0 : assert(inner->op == op_basetable);
6291 0 : for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
6292 0 : sql_exp* ce = n->data;
6293 0 : stmt* ins = m->data;
6294 0 : stmt* s = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
6295 0 : append(il, s);
6296 : }
6297 0 : returning = stmt_list(be, il);
6298 0 : sql->type = Q_TABLE;
6299 : }
6300 :
6301 37 : if (!sql_insert_triggers(be, t, updates, 1))
6302 0 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
6303 : /* update predicate list */
6304 37 : if (rel->r && !rel_predicates(be, rel->r))
6305 : return NULL;
6306 :
6307 37 : if (ddl) {
6308 0 : ret = ddl;
6309 0 : list_prepend(l, ddl);
6310 0 : return stmt_list(be, l);
6311 : } else {
6312 37 : ret = cnt;
6313 37 : if (add_to_rowcount_accumulator(be, ret->nr) < 0)
6314 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6315 37 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6316 37 : stmt_add_dependency_change(be, t, ret);
6317 37 : return returning?returning:ret;
6318 : }
6319 : }
6320 :
6321 : static stmt *
6322 109801 : rel2bin_insert(backend *be, sql_rel *rel, list *refs)
6323 : {
6324 109801 : mvc *sql = be->mvc;
6325 109801 : list *l;
6326 109801 : stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
6327 109801 : int idx_ins = 0, len = 0;
6328 109801 : node *n, *m, *idx_m = NULL;
6329 109801 : sql_rel *tr = rel->l, *prel = rel->r;
6330 109801 : sql_table *t = NULL;
6331 :
6332 109801 : if ((rel->flag&UPD_COMP)) { /* special case ! */
6333 0 : idx_ins = 1;
6334 0 : prel = rel->l;
6335 0 : rel = rel->r;
6336 0 : tr = rel->l;
6337 : }
6338 :
6339 109801 : if (tr->op == op_basetable) {
6340 109702 : t = tr->l;
6341 : } else {
6342 99 : ddl = subrel_bin(be, tr, refs);
6343 99 : ddl = subrel_project(be, ddl, refs, NULL);
6344 99 : if (!ddl)
6345 : return NULL;
6346 99 : t = rel_ddl_table_get(tr);
6347 : }
6348 109801 : if (t->multiset || t->composite)
6349 37 : return rel2bin_insert_ms(be, rel, refs);
6350 :
6351 109764 : if (rel->r) /* first construct the inserts relation */
6352 109764 : inserts = subrel_bin(be, rel->r, refs);
6353 109721 : inserts = subrel_project(be, inserts, refs, rel->r);
6354 :
6355 109692 : if (!inserts)
6356 : return NULL;
6357 :
6358 109692 : if (idx_ins)
6359 0 : pin = refs_find_rel(refs, prel);
6360 :
6361 123425 : for (n = ol_first_node(t->keys); n; n = n->next) {
6362 13658 : sql_key * key = n->data;
6363 13658 : if (key->type == ckey)
6364 83 : sql_insert_check(be, key, inserts->op4.lval);
6365 : }
6366 :
6367 109767 : if (!sql_insert_check_null(be, t, inserts->op4.lval))
6368 : return NULL;
6369 :
6370 109796 : updates = table_update_stmts(sql, t, &len);
6371 822806 : for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; ) {
6372 713019 : sql_column *c = n->data;
6373 :
6374 713019 : if (c->type.type->composite && !c->type.multiset) {
6375 0 : n = insert_composite(be, updates, t, c, n, m);
6376 58 : m = m->next;
6377 : } else {
6378 713019 : updates[c->colnr] = m->data;
6379 713019 : n = n->next;
6380 713019 : m = m->next;
6381 : }
6382 : }
6383 :
6384 : /* before */
6385 109787 : if (!sql_insert_triggers(be, t, updates, 0))
6386 3262 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
6387 :
6388 106488 : insert = inserts->op4.lval->h?inserts->op4.lval->h->data:NULL;
6389 106488 : if (!insert || insert->nrcols == 0) {
6390 74867 : cnt = stmt_atom_lng(be, 1);
6391 : } else {
6392 31621 : 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);
6393 : }
6394 106528 : insert = NULL;
6395 :
6396 106528 : l = sa_list(sql->sa);
6397 106525 : if (t->idxs) {
6398 106525 : idx_m = m;
6399 121788 : for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
6400 15262 : stmt *is = m->data;
6401 15262 : sql_idx *i = n->data;
6402 :
6403 15262 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6404 107 : continue;
6405 15155 : if (hash_index(i->type) && list_length(i->columns) <= 1)
6406 15152 : is = NULL;
6407 15152 : if (i->key) {
6408 13678 : stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
6409 :
6410 13681 : list_append(l, ckeys);
6411 : }
6412 15156 : if (!insert)
6413 15263 : insert = is;
6414 : }
6415 106526 : assert(!n && !m);
6416 : }
6417 :
6418 106526 : if (t->s) /* only not declared tables, need this */
6419 106511 : pos = stmt_claim(be, t, cnt);
6420 :
6421 106498 : if (t->idxs) {
6422 121711 : for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
6423 15268 : stmt *is = m->data;
6424 15268 : sql_idx *i = n->data;
6425 :
6426 15268 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
6427 107 : continue;
6428 15161 : if (hash_index(i->type) && list_length(i->columns) <= 1)
6429 : is = NULL;
6430 2225 : if (is)
6431 2225 : is = stmt_append_idx(be, i, pos, is);
6432 : }
6433 106443 : assert(!n && !m);
6434 : }
6435 :
6436 106443 : int mvc_var = be->mvc_var;
6437 812907 : for (n = ol_first_node(t->columns)/*, m = inserts->op4.lval->h*/; n /*&& m*/; n = n->next/*, m = m->next*/) {
6438 :
6439 : //stmt *ins = m->data;
6440 706398 : sql_column *c = n->data;
6441 706398 : stmt *ins = updates[c->colnr];
6442 :
6443 706398 : if (ins) {
6444 706398 : insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
6445 706452 : append(l,insert);
6446 : }
6447 : }
6448 106509 : be->mvc_var = mvc_var;
6449 106509 : if (!insert)
6450 : return NULL;
6451 :
6452 106509 : if (rel->returning) {
6453 5 : list* il = sa_list(sql->sa);
6454 5 : sql_rel* inner = rel->l;
6455 5 : assert(inner->op == op_basetable);
6456 15 : for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
6457 10 : sql_exp* ce = n->data;
6458 10 : stmt* ins = m->data;
6459 10 : stmt* s = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
6460 10 : append(il, s);
6461 : }
6462 5 : returning = stmt_list(be, il);
6463 5 : sql->type = Q_TABLE;
6464 : }
6465 :
6466 106509 : if (!sql_insert_triggers(be, t, updates, 1))
6467 1631 : return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
6468 : /* update predicate list */
6469 104865 : if (rel->r && !rel_predicates(be, rel->r))
6470 : return NULL;
6471 :
6472 104847 : if (ddl) {
6473 99 : ret = ddl;
6474 99 : list_prepend(l, ddl);
6475 99 : return stmt_list(be, l);
6476 : } else {
6477 104748 : ret = cnt;
6478 104748 : if (add_to_rowcount_accumulator(be, ret->nr) < 0)
6479 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
6480 104692 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
6481 104689 : stmt_add_dependency_change(be, t, ret);
6482 104719 : return returning?returning:ret;
6483 : }
6484 : }
6485 :
6486 : static int
6487 1373 : is_idx_updated(sql_idx * i, stmt **updates)
6488 : {
6489 1373 : int update = 0;
6490 1373 : node *m;
6491 :
6492 2710 : for (m = i->columns->h; m; m = m->next) {
6493 1545 : sql_kc *ic = m->data;
6494 :
6495 1545 : if (updates[ic->c->colnr]) {
6496 : update = 1;
6497 : break;
6498 : }
6499 : }
6500 1373 : return update;
6501 : }
6502 :
6503 : static int
6504 14 : is_check_updated(sql_key * k, stmt **updates)
6505 : {
6506 14 : int update = 0;
6507 14 : node *m;
6508 :
6509 16 : for (m = k->columns->h; m; m = m->next) {
6510 14 : sql_kc *kc = m->data;
6511 :
6512 14 : if (updates[kc->c->colnr]) {
6513 : update = 1;
6514 : break;
6515 : }
6516 : }
6517 14 : return update;
6518 : }
6519 :
6520 : static int
6521 4304 : first_updated_col(stmt **updates, int cnt)
6522 : {
6523 4304 : int i;
6524 :
6525 39105 : for (i = 0; i < cnt; i++) {
6526 38007 : if (updates[i])
6527 : return i;
6528 : }
6529 : return -1;
6530 : }
6531 :
6532 : static stmt *
6533 207 : update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *u_tids, stmt *idx_updates, int updcol)
6534 : {
6535 207 : mvc *sql = be->mvc;
6536 207 : char *msg = NULL;
6537 207 : stmt *res = NULL;
6538 :
6539 207 : sql_subtype *lng = sql_bind_localtype("lng");
6540 207 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6541 207 : sql_subtype *bt = sql_bind_localtype("bit");
6542 207 : sql_subfunc *ne;
6543 :
6544 207 : ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
6545 207 : if (list_length(k->columns) > 1) {
6546 48 : stmt *dels = stmt_tid(be, k->t, 0);
6547 48 : node *m;
6548 48 : stmt *s = NULL;
6549 :
6550 : /* 1st stage: find out if original (without the updated)
6551 : do not contain the same values as the updated values.
6552 : This is done using a relation join and a count (which
6553 : should be zero)
6554 : */
6555 48 : if (!isNew(k)) {
6556 11 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
6557 11 : nu_tids = stmt_project(be, nu_tids, dels);
6558 11 : list *lje = sa_list(sql->sa);
6559 11 : list *rje = sa_list(sql->sa);
6560 :
6561 11 : if (k->idx && hash_index(k->idx->type)) {
6562 11 : list_append(lje, stmt_idx(be, k->idx, nu_tids, nu_tids->partition));
6563 11 : list_append(rje, idx_updates);
6564 : }
6565 33 : for (m = k->columns->h; m; m = m->next) {
6566 22 : sql_kc *c = m->data;
6567 22 : stmt *upd;
6568 :
6569 22 : assert(updates);
6570 22 : if (updates[c->c->colnr]) {
6571 : upd = updates[c->c->colnr];
6572 : } else {
6573 8 : upd = stmt_col(be, c->c, u_tids, u_tids->partition);
6574 : }
6575 22 : list_append(lje, stmt_col(be, c->c, nu_tids, nu_tids->partition));
6576 22 : list_append(rje, upd);
6577 : }
6578 11 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
6579 11 : s = stmt_result(be, s, 0);
6580 11 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
6581 : }
6582 :
6583 : /* 2e stage: find out if the updated are unique */
6584 48 : if (!updates || updates[updcol]->nrcols) { /* update columns not atoms */
6585 48 : sql_subfunc *sum;
6586 48 : stmt *count_sum = NULL, *ssum;
6587 48 : stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
6588 48 : stmt *cand = NULL;
6589 48 : stmt *ss;
6590 48 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
6591 :
6592 : /* also take the hopefully unique hash keys, to reduce
6593 : (re)group costs */
6594 48 : if (k->idx && hash_index(k->idx->type)) {
6595 48 : g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
6596 48 : grp = stmt_result(be, g, 0);
6597 48 : ext = stmt_result(be, g, 1);
6598 48 : Cnt = stmt_result(be, g, 2);
6599 :
6600 : /* continue only with groups with a cnt > 1 */
6601 48 : cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0, 0);
6602 : /* project cand on ext and Cnt */
6603 48 : Cnt = stmt_project(be, cand, Cnt);
6604 48 : ext = stmt_project(be, cand, ext);
6605 :
6606 : /* join groups with extend to retrieve all oid's of the original
6607 : * bat that belong to a group with Cnt >1 */
6608 48 : g = stmt_join(be, grp, ext, 0, cmp_equal, 0, 0, false);
6609 48 : cand = stmt_result(be, g, 0);
6610 48 : grp = stmt_project(be, cand, grp);
6611 : }
6612 :
6613 154 : for (m = k->columns->h; m; m = m->next) {
6614 106 : sql_kc *c = m->data;
6615 106 : stmt *upd;
6616 :
6617 106 : if (updates && updates[c->c->colnr]) {
6618 : upd = updates[c->c->colnr];
6619 : } else {
6620 92 : upd = stmt_col(be, c->c, dels, dels->partition);
6621 : }
6622 :
6623 : /* apply cand list first */
6624 106 : if (cand)
6625 106 : upd = stmt_project(be, cand, upd);
6626 :
6627 : /* remove nulls */
6628 106 : if ((k->type == ukey) && stmt_has_null(upd)) {
6629 31 : stmt *nn = stmt_selectnonil(be, upd, NULL);
6630 31 : upd = stmt_project(be, nn, upd);
6631 31 : if (grp)
6632 31 : grp = stmt_project(be, nn, grp);
6633 31 : if (cand)
6634 31 : cand = stmt_project(be, nn, cand);
6635 : }
6636 :
6637 : /* apply group by on groups with Cnt > 1 */
6638 106 : g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
6639 106 : grp = stmt_result(be, g, 0);
6640 106 : ext = stmt_result(be, g, 1);
6641 106 : Cnt = stmt_result(be, g, 2);
6642 : }
6643 48 : ss = Cnt; /* use count */
6644 : /* (count(ss) <> sum(ss)) */
6645 48 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
6646 48 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
6647 48 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
6648 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);
6649 :
6650 : /* combine results */
6651 48 : if (s)
6652 11 : s = stmt_binop(be, s, count_sum, NULL, or);
6653 : else
6654 : s = count_sum;
6655 : }
6656 :
6657 48 : if (k->type == pkey) {
6658 31 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
6659 : } else {
6660 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
6661 : }
6662 48 : res = stmt_exception(be, s, msg, 00001);
6663 : } else { /* single column key */
6664 159 : stmt *dels = stmt_tid(be, k->t, 0);
6665 159 : sql_kc *c = k->columns->h->data;
6666 159 : stmt *s = NULL, *h = NULL, *o;
6667 :
6668 : /* s should be empty */
6669 159 : if (!isNew(k)) {
6670 70 : stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
6671 70 : nu_tids = stmt_project(be, nu_tids, dels);
6672 70 : assert (updates);
6673 :
6674 70 : h = updates[c->c->colnr];
6675 70 : o = stmt_col(be, c->c, nu_tids, nu_tids->partition);
6676 70 : s = stmt_join(be, o, h, 0, cmp_equal, 0, 0, false);
6677 70 : s = stmt_result(be, s, 0);
6678 70 : s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
6679 : }
6680 :
6681 : /* 2e stage: find out if updated are unique */
6682 70 : if (!h || h->nrcols) { /* update columns not atoms */
6683 159 : sql_subfunc *sum;
6684 159 : stmt *count_sum = NULL;
6685 159 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
6686 159 : stmt *ssum, *ss;
6687 159 : stmt *upd;
6688 159 : stmt *g;
6689 :
6690 159 : if (updates) {
6691 72 : upd = updates[c->c->colnr];
6692 : } else {
6693 87 : upd = stmt_col(be, c->c, dels, dels->partition);
6694 : }
6695 :
6696 : /* remove nulls */
6697 159 : if ((k->type == ukey) && stmt_has_null(upd)) {
6698 15 : stmt *nn = stmt_selectnonil(be, upd, NULL);
6699 15 : upd = stmt_project(be, nn, upd);
6700 : }
6701 :
6702 159 : g = stmt_group(be, upd, NULL, NULL, NULL, 1);
6703 159 : ss = stmt_result(be, g, 2); /* use count */
6704 :
6705 : /* (count(ss) <> sum(ss)) */
6706 159 : sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
6707 159 : ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
6708 159 : ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
6709 159 : count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
6710 :
6711 : /* combine results */
6712 159 : if (s)
6713 70 : s = stmt_binop(be, s, count_sum, NULL, or);
6714 : else
6715 : s = count_sum;
6716 : }
6717 :
6718 159 : if (k->type == pkey) {
6719 142 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
6720 : } else {
6721 17 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
6722 : }
6723 159 : res = stmt_exception(be, s, msg, 00001);
6724 : }
6725 207 : return res;
6726 : }
6727 :
6728 : /*
6729 : A referential constraint is satisfied if one of the following con-
6730 : ditions is true, depending on the <match option> specified in the
6731 : <referential constraint definition>:
6732 :
6733 : - If no <match type> was specified then, for each row R1 of the
6734 : referencing table, either at least one of the values of the
6735 : referencing columns in R1 shall be a null value, or the value of
6736 : each referencing column in R1 shall be equal to the value of the
6737 : corresponding referenced column in some row of the referenced
6738 : table.
6739 :
6740 : - If MATCH FULL was specified then, for each row R1 of the refer-
6741 : encing table, either the value of every referencing column in R1
6742 : shall be a null value, or the value of every referencing column
6743 : in R1 shall not be null and there shall be some row R2 of the
6744 : referenced table such that the value of each referencing col-
6745 : umn in R1 is equal to the value of the corresponding referenced
6746 : column in R2.
6747 :
6748 : - If MATCH PARTIAL was specified then, for each row R1 of the
6749 : referencing table, there shall be some row R2 of the refer-
6750 : enced table such that the value of each referencing column in
6751 : R1 is either null or is equal to the value of the corresponding
6752 : referenced column in R2.
6753 : */
6754 :
6755 : static stmt *
6756 698 : update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
6757 : {
6758 698 : mvc *sql = be->mvc;
6759 698 : char *msg = NULL;
6760 698 : stmt *s, *cur, *null = NULL, *cntnulls;
6761 698 : sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
6762 698 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6763 698 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
6764 698 : sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
6765 698 : node *m;
6766 :
6767 698 : if (!idx_updates)
6768 : return NULL;
6769 : /* releqjoin.count <> updates[updcol].count */
6770 698 : if (pup && list_length(pup->op4.lval)) {
6771 655 : cur = pup->op4.lval->h->data;
6772 43 : } else if (updates) {
6773 43 : cur = updates[updcol];
6774 : } else {
6775 0 : sql_kc *c = k->columns->h->data;
6776 0 : stmt *dels = stmt_tid(be, k->t, 0);
6777 0 : assert(0);
6778 : cur = stmt_col(be, c->c, dels, dels->partition);
6779 : }
6780 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);
6781 :
6782 1419 : for (m = k->columns->h; m; m = m->next) {
6783 721 : sql_kc *c = m->data;
6784 :
6785 : /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
6786 : /* Currently only the default MATCH SIMPLE is supported */
6787 721 : if (c->c->null) {
6788 309 : stmt *upd, *nn;
6789 :
6790 309 : if (updates && updates[c->c->colnr]) {
6791 : upd = updates[c->c->colnr];
6792 : } else { /* created idx/key using alter */
6793 277 : upd = stmt_col(be, c->c, tids, tids->partition);
6794 : }
6795 309 : nn = stmt_selectnil(be, upd);
6796 309 : if (null)
6797 11 : null = stmt_tunion(be, null, nn);
6798 : else
6799 : null = nn;
6800 : }
6801 : }
6802 698 : if (null) {
6803 298 : cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
6804 : } else {
6805 400 : cntnulls = stmt_atom_lng(be, 0);
6806 : }
6807 698 : s = stmt_binop(be, s,
6808 : stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls, NULL, ne), NULL, or);
6809 :
6810 : /* s should be empty */
6811 698 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
6812 698 : return stmt_exception(be, s, msg, 00001);
6813 : }
6814 :
6815 : static stmt *
6816 10 : join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
6817 : {
6818 10 : mvc *sql = be->mvc;
6819 10 : sql_trans *tr = sql->session->tr;
6820 10 : char *msg = NULL;
6821 10 : int nulls = 0;
6822 10 : node *m, *o;
6823 10 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
6824 10 : stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
6825 10 : stmt *null = NULL, *rows;
6826 10 : sql_subtype *lng = sql_bind_localtype("lng");
6827 10 : sql_subtype *bt = sql_bind_localtype("bit");
6828 10 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
6829 10 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
6830 10 : list *lje = sa_list(sql->sa);
6831 10 : list *rje = sa_list(sql->sa);
6832 :
6833 10 : fdels = stmt_tid(be, k->idx->t, 0);
6834 10 : rows = stmt_idx(be, k->idx, fdels, fdels->partition);
6835 :
6836 10 : rows = stmt_join(be, rows, tids, 0, cmp_equal, 0, 0, false); /* join over the join index */
6837 10 : rows = stmt_result(be, rows, 0);
6838 :
6839 22 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
6840 12 : sql_kc *fc = m->data;
6841 12 : sql_kc *c = o->data;
6842 12 : stmt *upd, *col;
6843 :
6844 12 : if (updates[c->c->colnr]) {
6845 : upd = updates[c->c->colnr];
6846 : } else {
6847 2 : upd = stmt_project(be, tids, stmt_col(be, c->c, dels, dels->partition));
6848 : }
6849 12 : if (c->c->null) { /* new nulls (MATCH SIMPLE) */
6850 3 : stmt *nn = stmt_selectnil(be, upd);
6851 3 : if (null)
6852 1 : null = stmt_tunion(be, null, nn);
6853 : else
6854 : null = nn;
6855 : nulls = 1;
6856 : }
6857 12 : col = stmt_col(be, fc->c, rows, rows->partition);
6858 12 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
6859 0 : return NULL;
6860 12 : list_append(lje, upd);
6861 12 : list_append(rje, col);
6862 : }
6863 10 : s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
6864 10 : s = stmt_result(be, s, 0);
6865 :
6866 : /* add missing nulls */
6867 10 : cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
6868 10 : if (nulls) {
6869 2 : sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
6870 2 : cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), NULL, add);
6871 : }
6872 :
6873 : /* releqjoin.count <> updates[updcol].count */
6874 10 : s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
6875 :
6876 : /* s should be empty */
6877 10 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
6878 10 : return stmt_exception(be, s, msg, 00001);
6879 : }
6880 :
6881 : static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
6882 :
6883 : static stmt*
6884 11 : sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
6885 : {
6886 11 : mvc *sql = be->mvc;
6887 11 : sql_trans *tr = sql->session->tr;
6888 11 : list *l = NULL;
6889 11 : int len = 0;
6890 11 : node *m, *o;
6891 11 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
6892 11 : stmt **new_updates;
6893 11 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
6894 :
6895 11 : new_updates = table_update_stmts(sql, t, &len);
6896 24 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
6897 13 : sql_kc *fc = m->data;
6898 13 : stmt *upd = NULL;
6899 :
6900 13 : if (action == ACT_SET_DEFAULT) {
6901 4 : if (fc->c->def) {
6902 4 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
6903 4 : if (!sq)
6904 : return NULL;
6905 : upd = sq;
6906 : } else {
6907 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
6908 : }
6909 : } else {
6910 9 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
6911 : }
6912 :
6913 13 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
6914 0 : return NULL;
6915 :
6916 13 : if (upd->nrcols <= 0)
6917 13 : upd = stmt_const(be, ftids, upd);
6918 :
6919 13 : new_updates[fc->c->colnr] = upd;
6920 : }
6921 11 : if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
6922 : return NULL;
6923 11 : return stmt_list(be, l);
6924 : }
6925 :
6926 : static stmt*
6927 32 : sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
6928 : {
6929 32 : mvc *sql = be->mvc;
6930 32 : sql_trans *tr = sql->session->tr;
6931 32 : list *l = NULL;
6932 32 : int len = 0;
6933 32 : node *m, *o;
6934 32 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
6935 32 : stmt **new_updates;
6936 32 : stmt *rows;
6937 32 : sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
6938 32 : stmt *ftids, *upd_ids;
6939 :
6940 32 : ftids = stmt_tid(be, k->idx->t, 0);
6941 32 : rows = stmt_idx(be, k->idx, ftids, ftids->partition);
6942 :
6943 32 : rows = stmt_join(be, rows, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
6944 32 : upd_ids = stmt_result(be, rows, 1);
6945 32 : rows = stmt_result(be, rows, 0);
6946 32 : rows = stmt_project(be, rows, ftids);
6947 :
6948 32 : new_updates = table_update_stmts(sql, t, &len);
6949 64 : for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
6950 32 : sql_kc *fc = m->data;
6951 32 : sql_kc *c = o->data;
6952 32 : stmt *upd = NULL;
6953 :
6954 32 : if (!updates[c->c->colnr]) {
6955 0 : continue;
6956 32 : } else if (action == ACT_CASCADE) {
6957 : upd = updates[c->c->colnr];
6958 16 : } else if (action == ACT_SET_DEFAULT) {
6959 6 : if (fc->c->def) {
6960 6 : stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
6961 6 : if (!sq)
6962 : return NULL;
6963 : upd = sq;
6964 : } else {
6965 0 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
6966 : }
6967 10 : } else if (action == ACT_SET_NULL) {
6968 10 : upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
6969 : }
6970 :
6971 32 : if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
6972 0 : return NULL;
6973 :
6974 32 : if (upd->nrcols <= 0)
6975 16 : upd = stmt_const(be, upd_ids, upd);
6976 : else
6977 16 : upd = stmt_project(be, upd_ids, upd);
6978 :
6979 32 : new_updates[fc->c->colnr] = upd;
6980 : }
6981 :
6982 32 : if ((l = sql_update(be, t, rows, new_updates)) == NULL)
6983 : return NULL;
6984 32 : return stmt_list(be, l);
6985 : }
6986 :
6987 : static int
6988 83 : cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
6989 : {
6990 : /* now iterate over all keys */
6991 83 : sql_trans *tr = be->mvc->session->tr;
6992 83 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
6993 83 : if (keys) {
6994 133 : for (node *n = keys->h; n; n = n->next->next) {
6995 50 : sqlid fkey_id = *(sqlid*)n->data;
6996 50 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
6997 50 : sql_key *fk = (sql_key*)b;
6998 50 : sql_fkey *rk = (sql_fkey*)b;
6999 :
7000 50 : if (fk->type != fkey || rk->rkey != k->base.id)
7001 0 : continue;
7002 :
7003 : /* All rows of the foreign key table which are
7004 : affected by the primary key update should all
7005 : match one of the updated primary keys again.
7006 : */
7007 50 : switch (((sql_fkey*)fk)->on_update) {
7008 : case ACT_NO_ACTION:
7009 : break;
7010 32 : case ACT_SET_NULL:
7011 : case ACT_SET_DEFAULT:
7012 : case ACT_CASCADE:
7013 32 : if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update)) {
7014 0 : list_destroy(keys);
7015 0 : return -1;
7016 : }
7017 : break;
7018 10 : default: /*RESTRICT*/
7019 10 : if (!join_updated_pkey(be, fk, tids, updates)) {
7020 0 : list_destroy(keys);
7021 0 : return -1;
7022 : }
7023 : }
7024 : }
7025 83 : list_destroy(keys);
7026 : }
7027 : return 0;
7028 : }
7029 :
7030 : static void
7031 905 : sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
7032 : {
7033 905 : stmt *ckeys;
7034 :
7035 905 : if (k->type == pkey || k->type == ukey) {
7036 207 : ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
7037 : } else { /* foreign keys */
7038 698 : ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
7039 : }
7040 905 : list_append(l, ckeys);
7041 905 : }
7042 :
7043 : static stmt *
7044 20 : hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
7045 : {
7046 20 : mvc *sql = be->mvc;
7047 : /* calculate new value */
7048 20 : node *m;
7049 20 : sql_subtype *it, *lng;
7050 20 : int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
7051 20 : stmt *h = NULL, *tids;
7052 :
7053 20 : if (list_length(i->columns) <= 1)
7054 : return NULL;
7055 :
7056 0 : tids = stmt_tid(be, i->t, 0);
7057 0 : it = sql_bind_localtype("int");
7058 0 : lng = sql_bind_localtype("lng");
7059 0 : for (m = i->columns->h; m; m = m->next) {
7060 0 : sql_kc *c = m->data;
7061 0 : stmt *upd;
7062 :
7063 0 : if (updates && updates[c->c->colnr]) {
7064 : upd = updates[c->c->colnr];
7065 0 : } else if (updates && updcol >= 0) {
7066 0 : assert(0);
7067 : upd = stmt_col(be, c->c, rows, rows->partition);
7068 : } else { /* created idx/key using alter */
7069 0 : upd = stmt_col(be, c->c, tids, tids->partition);
7070 : }
7071 :
7072 0 : if (h && i->type == hash_idx) {
7073 0 : sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, &c->c->type);
7074 :
7075 0 : h = stmt_Nop(be, stmt_list(be, list_append(list_append(
7076 : list_append(sa_list(sql->sa), h),
7077 0 : stmt_atom_int(be, bits)), upd)), NULL,
7078 : xor, NULL);
7079 0 : } else if (h) {
7080 0 : stmt *h2;
7081 0 : sql_subfunc *lsh = sql_bind_func_result(sql, "sys", "left_shift", F_FUNC, true, lng, 2, lng, it);
7082 0 : sql_subfunc *lor = sql_bind_func_result(sql, "sys", "bit_or", F_FUNC, true, lng, 2, lng, lng);
7083 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
7084 :
7085 0 : h = stmt_binop(be, h, stmt_atom_int(be, bits), NULL, lsh);
7086 0 : h2 = stmt_unop(be, upd, NULL, hf);
7087 0 : h = stmt_binop(be, h, h2, NULL, lor);
7088 : } else {
7089 0 : sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
7090 0 : h = stmt_unop(be, upd, NULL, hf);
7091 0 : if (i->type == oph_idx)
7092 : break;
7093 : }
7094 : }
7095 : return h;
7096 : }
7097 :
7098 : static stmt *
7099 43 : join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
7100 : {
7101 43 : mvc *sql = be->mvc;
7102 43 : sql_trans *tr = sql->session->tr;
7103 43 : node *m, *o;
7104 43 : sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)i->key)->rkey);
7105 43 : stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
7106 43 : list *lje = sa_list(sql->sa);
7107 43 : list *rje = sa_list(sql->sa);
7108 :
7109 88 : for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
7110 45 : sql_kc *c = m->data;
7111 45 : sql_kc *rc = o->data;
7112 45 : stmt *upd;
7113 :
7114 45 : if (updates && updates[c->c->colnr]) {
7115 : upd = updates[c->c->colnr];
7116 0 : } else if (updates && updcol >= 0) {
7117 0 : assert(0);
7118 : upd = stmt_col(be, c->c, ftids, ftids->partition);
7119 : } else { /* created idx/key using alter */
7120 0 : upd = stmt_col(be, c->c, ftids, ftids->partition);
7121 : }
7122 :
7123 45 : if (!upd || (upd = check_types(be, &rc->c->type, upd, type_equal)) == NULL)
7124 0 : return NULL;
7125 45 : list_append(lje, upd);
7126 45 : list_append(rje, stmt_col(be, rc->c, ptids, ptids->partition));
7127 : }
7128 43 : s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 0);
7129 43 : l = stmt_result(be, s, 0);
7130 43 : r = stmt_result(be, s, 1);
7131 43 : r = stmt_project(be, r, ptids);
7132 43 : return stmt_left_project(be, ftids, l, r);
7133 : }
7134 :
7135 : static int
7136 4304 : cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
7137 : {
7138 4304 : mvc *sql = be->mvc;
7139 4304 : node *n;
7140 :
7141 4304 : if (!ol_length(t->idxs))
7142 : return 0;
7143 :
7144 2545 : for (n = ol_first_node(t->idxs); n; n = n->next) {
7145 1310 : sql_idx *i = n->data;
7146 :
7147 : /* check if update is needed,
7148 : * ie at least on of the idx columns is updated
7149 : */
7150 1310 : if (is_idx_updated(i, updates) == 0)
7151 1165 : continue;
7152 :
7153 145 : if (i->key) {
7154 142 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
7155 142 : sql_key *k = i->key;
7156 142 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
7157 142 : if (!sql->cascade_action)
7158 67 : sql->cascade_action = sa_list(sql->sa);
7159 142 : *local_id = i->key->base.id;
7160 142 : list_append(sql->cascade_action, local_id);
7161 142 : if (k->type == pkey || k->type == ukey) {
7162 83 : if (cascade_ukey(be, updates, k, rows))
7163 : return -1;
7164 : }
7165 : }
7166 : }
7167 : }
7168 : return 0;
7169 : }
7170 :
7171 : static list *
7172 43 : update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
7173 : {
7174 43 : mvc *sql = be->mvc;
7175 43 : node *n;
7176 43 : int updcol;
7177 43 : list *idx_updates = sa_list(sql->sa);
7178 :
7179 43 : if (!ol_length(t->idxs))
7180 : return idx_updates;
7181 :
7182 43 : updcol = first_updated_col(updates, ol_length(t->columns));
7183 106 : for (n = ol_first_node(t->idxs); n; n = n->next) {
7184 63 : sql_idx *i = n->data;
7185 63 : stmt *is = NULL;
7186 :
7187 : /* check if update is needed,
7188 : * ie at least on of the idx columns is updated
7189 : */
7190 63 : if (is_idx_updated(i, updates) == 0)
7191 0 : continue;
7192 :
7193 63 : if (hash_index(i->type)) {
7194 20 : is = hash_update(be, i, rows, updates, updcol);
7195 43 : } else if (i->type == join_idx) {
7196 43 : if (updcol < 0)
7197 : return NULL;
7198 43 : if (!(is = join_idx_update(be, i, rows, updates, updcol)))
7199 : return NULL;
7200 : }
7201 63 : if (i->key)
7202 63 : sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
7203 63 : if (is)
7204 43 : list_append(idx_updates, stmt_update_idx(be, i, rows, is));
7205 : }
7206 : return idx_updates;
7207 : }
7208 :
7209 : static int
7210 265 : sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
7211 : {
7212 : /* Put single relation of updates and old values on to the stack */
7213 265 : sql_rel *r = NULL;
7214 265 : node *n;
7215 265 : list *exps = sa_list(sql->sa);
7216 265 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
7217 :
7218 265 : ti->t = t;
7219 265 : ti->tids = tids;
7220 265 : ti->updates = updates;
7221 265 : ti->type = 2;
7222 265 : ti->on = on;
7223 265 : ti->nn = nn;
7224 265 : sql_alias *oname = a_create(sql->sa, ti->on);
7225 265 : sql_alias *nname = a_create(sql->sa, ti->nn);
7226 1483 : for (n = ol_first_node(t->columns); n; n = n->next) {
7227 1218 : sql_column *c = n->data;
7228 :
7229 1218 : if (updates[c->colnr]) {
7230 265 : sql_exp *oe = exp_column(sql->sa, oname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
7231 265 : sql_exp *ne = exp_column(sql->sa, nname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
7232 265 : oe->alias.label = -(sql->nid++);
7233 265 : ne->alias.label = -(sql->nid++);
7234 :
7235 265 : append(exps, oe);
7236 265 : append(exps, ne);
7237 : } else {
7238 953 : sql_exp *oe = exp_column(sql->sa, oname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
7239 953 : sql_exp *ne = exp_column(sql->sa, nname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
7240 953 : oe->alias.label = -(sql->nid++);
7241 953 : ne->alias.label = -(sql->nid++);
7242 :
7243 953 : append(exps, oe);
7244 953 : append(exps, ne);
7245 : }
7246 : }
7247 265 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
7248 265 : r->l = ti;
7249 :
7250 : /* put single table into the stack with 2 names, needed for the psm code */
7251 265 : if (!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
7252 0 : return 0;
7253 : return 1;
7254 : }
7255 :
7256 : static int
7257 8608 : sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time)
7258 : {
7259 8608 : mvc *sql = be->mvc;
7260 8608 : node *n;
7261 8608 : int res = 1;
7262 :
7263 8608 : if (!ol_length(t->triggers))
7264 : return res;
7265 :
7266 1032 : for (n = ol_first_node(t->triggers); n; n = n->next) {
7267 550 : sql_trigger *trigger = n->data;
7268 :
7269 550 : if (!stack_push_frame(sql, "%OLD-NEW"))
7270 : return 0;
7271 550 : if (trigger->event == 2 && trigger->time == time) {
7272 : /* add name for the 'inserted' to the stack */
7273 265 : const char *n = trigger->new_name;
7274 265 : const char *o = trigger->old_name;
7275 :
7276 265 : if (!n) n = "new";
7277 265 : if (!o) o = "old";
7278 :
7279 265 : if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
7280 0 : stack_pop_frame(sql);
7281 0 : return 0;
7282 : }
7283 :
7284 265 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
7285 0 : stack_pop_frame(sql);
7286 0 : return 0;
7287 : }
7288 : }
7289 550 : stack_pop_frame(sql);
7290 : }
7291 : return res;
7292 : }
7293 :
7294 : static void
7295 25 : sql_update_check(backend *be, stmt **updates, sql_key *key, stmt *u_tids)
7296 : {
7297 25 : mvc *sql = be->mvc;
7298 25 : int pos = 0;
7299 25 : sql_rel *rel = rel_basetable(sql, key->t, a_create(be->mvc->sa, key->t->base.name));
7300 25 : sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
7301 25 : rel->exps = rel_base_projection(sql, rel, 0);
7302 :
7303 : /* create sub stmt with needed updates (or projected col from to be updated table) */
7304 25 : list *ups = sa_list(sql->sa);
7305 55 : for(node *n = key->columns->h; n; n = n->next) {
7306 30 : sql_kc *kc = n->data;
7307 30 : stmt *upd = NULL;
7308 :
7309 30 : if (updates && updates[kc->c->colnr]) {
7310 : upd = updates[kc->c->colnr];
7311 : } else {
7312 17 : upd = stmt_col(be, kc->c, u_tids, u_tids->partition);
7313 : }
7314 30 : sql_exp *e = rel_base_bind_column2(sql, rel, a_create(be->mvc->sa, kc->c->t->base.name), kc->c->base.name);
7315 30 : upd = stmt_alias(be, upd, e->alias.label, a_create(be->mvc->sa, kc->c->t->base.name), kc->c->base.name);
7316 30 : append(ups, upd);
7317 : }
7318 :
7319 25 : stmt *sub = stmt_list(be, ups);
7320 25 : stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
7321 :
7322 25 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
7323 25 : s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
7324 25 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
7325 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);
7326 25 : (void)stmt_exception(be, s, msg, 00001);
7327 25 : }
7328 :
7329 : static void
7330 4304 : sql_update_check_null(backend *be, sql_table *t, stmt **updates)
7331 : {
7332 4304 : mvc *sql = be->mvc;
7333 4304 : node *n;
7334 4304 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
7335 :
7336 51143 : for (n = ol_first_node(t->columns); n; n = n->next) {
7337 46839 : sql_column *c = n->data;
7338 :
7339 46839 : if (updates[c->colnr] && !c->null) {
7340 131 : stmt *s = updates[c->colnr];
7341 131 : char *msg = NULL;
7342 :
7343 131 : if (!(s->key && s->nrcols == 0)) {
7344 131 : s = stmt_selectnil(be, updates[c->colnr]);
7345 131 : s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
7346 : } else {
7347 0 : sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
7348 :
7349 0 : s = stmt_unop(be, updates[c->colnr], NULL, isnil);
7350 : }
7351 131 : msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
7352 131 : (void)stmt_exception(be, s, msg, 00001);
7353 : }
7354 : }
7355 4304 : }
7356 :
7357 : /* updates: an array of table width, per column holds the values for the to be updated rows */
7358 : static list *
7359 43 : sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
7360 : {
7361 43 : mvc *sql = be->mvc;
7362 43 : list *idx_updates = NULL;
7363 43 : int i, nr_cols = ol_length(t->columns);
7364 43 : list *l = sa_list(sql->sa);
7365 43 : node *n;
7366 43 : stmt *cnt = NULL;
7367 :
7368 43 : sql_update_check_null(be, t, updates);
7369 :
7370 : /* check keys + get idx */
7371 43 : idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
7372 43 : if (!idx_updates) {
7373 0 : assert(0);
7374 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
7375 : }
7376 :
7377 : /* before */
7378 43 : if (!sql_update_triggers(be, t, rows, updates, 0))
7379 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
7380 :
7381 : /* apply updates */
7382 131 : for (i = 0, n = ol_first_node(t->columns); i < nr_cols && n; i++, n = n->next) {
7383 88 : sql_column *c = n->data;
7384 :
7385 88 : if (updates[i])
7386 45 : append(l, stmt_update_col(be, c, rows, updates[i]));
7387 : }
7388 43 : if (cascade_updates(be, t, rows, updates))
7389 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
7390 :
7391 : /* after */
7392 43 : if (!sql_update_triggers(be, t, rows, updates, 1))
7393 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
7394 :
7395 43 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
7396 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);
7397 43 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
7398 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7399 43 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
7400 43 : stmt_add_dependency_change(be, t, cnt);
7401 : /* cascade ?? */
7402 : return l;
7403 : }
7404 :
7405 : /* updates with empty list is alter with create idx or keys */
7406 : static stmt *
7407 4402 : rel2bin_update(backend *be, sql_rel *rel, list *refs)
7408 : {
7409 4402 : mvc *sql = be->mvc;
7410 4402 : stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL, *cnt;
7411 4402 : list *l = sa_list(sql->sa);
7412 4402 : int nr_cols, updcol, idx_ups = 0;
7413 4402 : node *m;
7414 4402 : sql_rel *tr = rel->l, *prel = rel->r;
7415 4402 : sql_table *t = NULL;
7416 4402 : bool needs_returning = rel->returning;
7417 :
7418 4402 : if ((rel->flag&UPD_COMP)) { /* special case ! */
7419 1166 : idx_ups = 1;
7420 1166 : prel = rel->l;
7421 1166 : rel = rel->r;
7422 1166 : tr = rel->l;
7423 : }
7424 4402 : if (tr->op == op_basetable) {
7425 3055 : t = tr->l;
7426 : } else {
7427 1347 : ddl = subrel_bin(be, tr, refs);
7428 1347 : ddl = subrel_project(be, ddl, refs, NULL);
7429 1347 : if (!ddl)
7430 : return NULL;
7431 1347 : t = rel_ddl_table_get(tr);
7432 :
7433 : /* no columns to update (probably an new pkey or ckey!) */
7434 1347 : if (!rel->exps) {
7435 141 : stmt *tids = stmt_tid(be, t, 0);
7436 154 : for (m = ol_first_node(t->keys); m; m = m->next) {
7437 13 : sql_key * key = m->data;
7438 13 : if (key->type == ckey && key->base.new)
7439 13 : sql_update_check(be, NULL, key, tids);
7440 : }
7441 : return ddl;
7442 : }
7443 : }
7444 :
7445 4261 : if (rel->r) /* first construct the update relation */
7446 4261 : update = subrel_bin(be, rel->r, refs);
7447 4261 : update = subrel_project(be, update, refs, rel->r);
7448 :
7449 4261 : if (!update)
7450 : return NULL;
7451 :
7452 4261 : if (idx_ups)
7453 1166 : pup = refs_find_rel(refs, prel);
7454 :
7455 4261 : updates = table_update_stmts(sql, t, &nr_cols);
7456 4261 : tids = update->op4.lval->h->data;
7457 :
7458 : /* lookup the updates */
7459 11710 : for (m = rel->exps->h; m; m = m->next) {
7460 7449 : sql_exp *ce = m->data;
7461 7449 : sql_column *c = find_sql_column(t, exp_name(ce));
7462 :
7463 7449 : if (c)
7464 3214 : updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
7465 : }
7466 :
7467 5168 : for (m = ol_first_node(t->keys); m; m = m->next) {
7468 907 : sql_key * key = m->data;
7469 907 : if (key->type == ckey && is_check_updated(key, updates))
7470 12 : sql_update_check(be, updates, key, tids);
7471 : }
7472 4261 : sql_update_check_null(be, t, updates);
7473 :
7474 : /* check keys + get idx */
7475 4261 : updcol = first_updated_col(updates, ol_length(t->columns));
7476 11710 : for (m = rel->exps->h; m; m = m->next) {
7477 7449 : sql_exp *ce = m->data;
7478 7449 : sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
7479 7449 : stmt *update_idx, *is = NULL;
7480 :
7481 7449 : if (i) {
7482 1180 : if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
7483 148 : continue;
7484 :
7485 1032 : update_idx = bin_find_column(be, update, ce->l, ce->r);
7486 1032 : if (update_idx)
7487 : is = update_idx;
7488 1032 : if (hash_index(i->type) && list_length(i->columns) <= 1) {
7489 1032 : is = NULL;
7490 1032 : update_idx = NULL;
7491 : }
7492 1032 : if (i->key)
7493 1605 : sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
7494 1032 : if (is)
7495 780 : list_append(l, stmt_update_idx(be, i, tids, is));
7496 : }
7497 : }
7498 :
7499 : /* before */
7500 4261 : if (!sql_update_triggers(be, t, tids, updates, 0)) {
7501 0 : if (sql->cascade_action)
7502 0 : sql->cascade_action = NULL;
7503 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
7504 : }
7505 :
7506 : /* apply the update */
7507 11710 : for (m = rel->exps->h; m; m = m->next) {
7508 7449 : sql_exp *ce = m->data;
7509 7449 : sql_column *c = find_sql_column(t, exp_name(ce));
7510 :
7511 7449 : if (c)
7512 3214 : append(l, stmt_update_col(be, c, tids, updates[c->colnr]));
7513 : }
7514 :
7515 4261 : stmt* returning = NULL;
7516 4261 : if (needs_returning) {
7517 6 : sql_rel* b = rel->l;
7518 6 : int refcnt = b->ref.refcnt; // HACK: forces recalculation of base columns since they are assumed to be updated
7519 6 : b->ref.refcnt = 1;
7520 6 : returning = subrel_bin(be, b, refs);
7521 6 : b->ref.refcnt = refcnt;
7522 6 : returning->cand = tids;
7523 6 : returning = subrel_project(be, returning, refs, b);
7524 6 : sql->type = Q_TABLE;
7525 : }
7526 :
7527 4261 : if (cascade_updates(be, t, tids, updates)) {
7528 0 : if (sql->cascade_action)
7529 0 : sql->cascade_action = NULL;
7530 0 : return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
7531 : }
7532 :
7533 : /* after */
7534 4261 : if (!sql_update_triggers(be, t, tids, updates, 1)) {
7535 0 : if (sql->cascade_action)
7536 0 : sql->cascade_action = NULL;
7537 0 : return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
7538 : }
7539 :
7540 4261 : if (ddl) {
7541 1206 : list_prepend(l, ddl);
7542 1206 : cnt = stmt_list(be, l);
7543 : } else {
7544 3055 : cnt = stmt_aggr(be, tids, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
7545 3055 : if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
7546 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7547 3055 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
7548 3051 : stmt_add_dependency_change(be, t, cnt);
7549 : }
7550 :
7551 4261 : if (sql->cascade_action)
7552 67 : sql->cascade_action = NULL;
7553 4261 : if (rel->r && !rel_predicates(be, rel->r))
7554 : return NULL;
7555 4261 : return returning?returning:cnt;
7556 : }
7557 :
7558 : static int
7559 20 : sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, stmt **deleted_cols, int type)
7560 : {
7561 : /* Put single relation of updates and old values on to the stack */
7562 20 : sql_rel *r = NULL;
7563 20 : node *n;
7564 20 : list *exps = sa_list(sql->sa);
7565 20 : trigger_input *ti = SA_NEW(sql->sa, trigger_input);
7566 :
7567 20 : ti->t = t;
7568 20 : ti->tids = tids;
7569 20 : ti->updates = deleted_cols;
7570 20 : ti->type = type;
7571 20 : ti->nn = name;
7572 20 : sql_alias *aname = a_create(sql->sa, name);
7573 56 : for (n = ol_first_node(t->columns); n; n = n->next) {
7574 36 : sql_column *c = n->data;
7575 36 : sql_exp *ne = exp_column(sql->sa, aname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
7576 36 : ne->alias.label = -(sql->nid++);
7577 :
7578 36 : append(exps, ne);
7579 : }
7580 20 : r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
7581 20 : r->l = ti;
7582 :
7583 20 : return stack_push_rel_view(sql, name, r) ? 1 : 0;
7584 : }
7585 :
7586 : static int
7587 83968 : sql_delete_triggers(backend *be, sql_table *t, stmt *tids, stmt **deleted_cols, int time, int firing_type, int internal_type)
7588 : {
7589 83968 : mvc *sql = be->mvc;
7590 83968 : node *n;
7591 83968 : int res = 1;
7592 :
7593 83968 : if (!ol_length(t->triggers))
7594 : return res;
7595 :
7596 188 : for (n = ol_first_node(t->triggers); n; n = n->next) {
7597 142 : sql_trigger *trigger = n->data;
7598 :
7599 142 : if (!stack_push_frame(sql, "%OLD-NEW"))
7600 : return 0;
7601 142 : if (trigger->event == firing_type && trigger->time == time) {
7602 : /* add name for the 'deleted' to the stack */
7603 20 : const char *o = trigger->old_name;
7604 :
7605 20 : if (!o) o = "old";
7606 :
7607 20 : if(!sql_stack_add_deleted(sql, o, t, tids, deleted_cols, internal_type)) {
7608 0 : stack_pop_frame(sql);
7609 0 : return 0;
7610 : }
7611 :
7612 20 : if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
7613 0 : stack_pop_frame(sql);
7614 0 : return 0;
7615 : }
7616 : }
7617 142 : stack_pop_frame(sql);
7618 : }
7619 : return res;
7620 : }
7621 :
7622 : static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
7623 :
7624 : static stmt *
7625 9 : sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
7626 : {
7627 9 : sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
7628 9 : return sql_delete(be, t, ftids);
7629 : }
7630 :
7631 : static void
7632 130 : sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
7633 : {
7634 130 : mvc *sql = be->mvc;
7635 130 : sql_subtype *lng = sql_bind_localtype("lng");
7636 130 : sql_subtype *bt = sql_bind_localtype("bit");
7637 130 : sql_trans *tr = be->mvc->session->tr;
7638 130 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
7639 :
7640 130 : if (keys) {
7641 190 : for (node *n = keys->h; n; n = n->next->next) {
7642 60 : sqlid fkey_id = *(sqlid*)n->data;
7643 60 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
7644 60 : sql_key *fk = (sql_key*)b;
7645 60 : sql_fkey *rk = (sql_fkey*)b;
7646 :
7647 60 : if (fk->type != fkey || rk->rkey != k->base.id)
7648 0 : continue;
7649 60 : char *msg = NULL;
7650 60 : sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
7651 60 : sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
7652 60 : stmt *s, *tids;
7653 :
7654 60 : tids = stmt_tid(be, fk->idx->t, 0);
7655 60 : s = stmt_idx(be, fk->idx, tids, tids->partition);
7656 60 : s = stmt_join(be, s, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
7657 60 : s = stmt_result(be, s, 0);
7658 60 : tids = stmt_project(be, s, tids);
7659 60 : if(cascade) { /* for truncate statements with the cascade option */
7660 1 : s = sql_delete_cascade_Fkeys(be, fk, tids);
7661 1 : list_prepend(l, s);
7662 : } else {
7663 59 : switch (((sql_fkey*)fk)->on_delete) {
7664 : case ACT_NO_ACTION:
7665 : break;
7666 11 : case ACT_SET_NULL:
7667 : case ACT_SET_DEFAULT:
7668 11 : s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
7669 11 : list_prepend(l, s);
7670 11 : break;
7671 8 : case ACT_CASCADE:
7672 8 : s = sql_delete_cascade_Fkeys(be, fk, tids);
7673 8 : list_prepend(l, s);
7674 8 : break;
7675 38 : default: /*RESTRICT*/
7676 : /* The overlap between deleted primaries and foreign should be empty */
7677 38 : s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
7678 38 : msg = sa_message(sql->sa, SQLSTATE(40002) "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
7679 38 : s = stmt_exception(be, s, msg, 00001);
7680 38 : list_prepend(l, s);
7681 : }
7682 : }
7683 : }
7684 130 : list_destroy(keys);
7685 : }
7686 130 : }
7687 :
7688 : static int
7689 41904 : sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
7690 : {
7691 41904 : mvc *sql = be->mvc;
7692 41904 : int res = 1;
7693 41904 : node *n;
7694 :
7695 41904 : if (!ol_length(t->keys))
7696 : return res;
7697 :
7698 304 : for (n = ol_first_node(t->keys); n; n = n->next) {
7699 173 : sql_key *k = n->data;
7700 :
7701 173 : if (k->type == pkey || k->type == ukey) {
7702 131 : if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
7703 130 : sqlid *local_id = SA_NEW(sql->sa, sqlid);
7704 130 : if (!sql->cascade_action)
7705 120 : sql->cascade_action = sa_list(sql->sa);
7706 :
7707 130 : *local_id = k->base.id;
7708 130 : list_append(sql->cascade_action, local_id);
7709 130 : sql_delete_ukey(be, rows, k, l, which, cascade);
7710 : }
7711 : }
7712 : }
7713 : return res;
7714 : }
7715 :
7716 : static stmt *
7717 511 : sql_delete(backend *be, sql_table *t, stmt *rows)
7718 : {
7719 511 : mvc *sql = be->mvc;
7720 511 : stmt *v = NULL, *s = NULL;
7721 511 : list *l = sa_list(sql->sa);
7722 511 : stmt **deleted_cols = NULL;
7723 :
7724 511 : if (rows) {
7725 : v = rows;
7726 : } else { /* delete all */
7727 128 : v = stmt_tid(be, t, 0);
7728 : }
7729 :
7730 : /* project all columns */
7731 511 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
7732 38 : int nr = 0;
7733 38 : deleted_cols = table_update_stmts(sql, t, &nr);
7734 38 : int i = 0;
7735 105 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
7736 67 : sql_column *c = n->data;
7737 67 : stmt *s = stmt_col(be, c, v, v->partition);
7738 :
7739 67 : deleted_cols[i] = s;
7740 67 : list_append(l, s);
7741 : }
7742 : }
7743 :
7744 : /* before */
7745 511 : if (!sql_delete_triggers(be, t, v, deleted_cols, 0, 1, 3))
7746 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
7747 :
7748 511 : if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
7749 0 : return sql_error(sql, 10, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
7750 :
7751 511 : if (rows) {
7752 383 : s = stmt_delete(be, t, rows);
7753 383 : if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
7754 382 : s = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
7755 : } else { /* delete all */
7756 128 : s = stmt_table_clear(be, t, 0); /* first column */
7757 : }
7758 :
7759 : /* after */
7760 511 : if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
7761 0 : return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
7762 :
7763 511 : if (add_to_rowcount_accumulator(be, s->nr) < 0)
7764 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7765 511 : if (t->s && isGlobal(t) && !isGlobalTemp(t))
7766 509 : stmt_add_dependency_change(be, t, s);
7767 : return s;
7768 : }
7769 :
7770 : static stmt *
7771 502 : rel2bin_delete(backend *be, sql_rel *rel, list *refs)
7772 : {
7773 502 : mvc *sql = be->mvc;
7774 502 : stmt *stdelete = NULL, *tids = NULL, *returning = NULL;
7775 502 : sql_rel *tr = rel->l;
7776 502 : sql_table *t = NULL;
7777 :
7778 502 : if (tr->op == op_basetable)
7779 502 : t = tr->l;
7780 : else
7781 0 : assert(0/*ddl statement*/);
7782 :
7783 502 : if (rel->r) { /* first construct the deletes relation */
7784 374 : stmt *rows = subrel_bin(be, rel->r, refs);
7785 374 : rows = subrel_project(be, rows, refs, rel->r);
7786 374 : if (!rows)
7787 : return NULL;
7788 374 : assert(rows->type == st_list);
7789 374 : tids = rows->op4.lval->h->data; /* TODO this should be the candidate list instead */
7790 : }
7791 :
7792 502 : if (rel->returning) {
7793 4 : returning = subrel_bin(be, rel->l, refs);
7794 4 : returning->cand = tids;
7795 4 : returning = subrel_project(be, returning, refs, rel->l);
7796 4 : sql->type = Q_TABLE;
7797 : }
7798 :
7799 502 : stdelete = sql_delete(be, t, tids);
7800 502 : if (sql->cascade_action)
7801 107 : sql->cascade_action = NULL;
7802 502 : if (!stdelete)
7803 : return NULL;
7804 :
7805 502 : if (rel->r && !rel_predicates(be, rel->r))
7806 : return NULL;
7807 502 : return returning?returning:stdelete;
7808 : }
7809 :
7810 : struct tablelist {
7811 : sql_table *table;
7812 : struct tablelist* next;
7813 : };
7814 :
7815 : static sql_table * /* inspect the other tables recursively for foreign key dependencies */
7816 41678 : check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct tablelist* next_append, sql_table *t, int cascade)
7817 : {
7818 41678 : struct tablelist* new_node;
7819 41678 : sql_trans *tr = sql->session->tr;
7820 41678 : sqlstore *store = sql->session->tr->store;
7821 :
7822 41678 : if (mvc_highwater(sql))
7823 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
7824 :
7825 41692 : if (t->keys) { /* Check for foreign key references */
7826 41710 : for (node *n = ol_first_node(t->keys); n; n = n->next) {
7827 24 : sql_key *k = n->data;
7828 :
7829 24 : if (k->type == ukey || k->type == pkey) {
7830 17 : list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
7831 :
7832 13 : if (keys) {
7833 21 : for (node *nn = keys->h; nn; nn = nn->next->next) {
7834 6 : sqlid fkey_id = *(sqlid*)nn->data;
7835 6 : sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
7836 6 : sql_key *fk = (sql_key*)b;
7837 6 : sql_fkey *rk = (sql_fkey*)b;
7838 :
7839 6 : if (fk->type != fkey || rk->rkey != k->base.id)
7840 1 : continue;
7841 5 : k = fk;
7842 : /* make sure it is not a self referencing key */
7843 5 : if (k->t != t && !cascade && isTable(t)) {
7844 4 : node *nnn = ol_first_node(t->columns);
7845 4 : sql_column *c = nnn->data;
7846 4 : size_t n_rows = store->storage_api.count_col(sql->session->tr, c, 10);
7847 4 : if (n_rows > 0) {
7848 2 : list_destroy(keys);
7849 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);
7850 : }
7851 1 : } else if (k->t != t) {
7852 : int found = 0;
7853 2 : for (struct tablelist *node_check = tlist; node_check; node_check = node_check->next) {
7854 1 : if (node_check->table == k->t)
7855 0 : found = 1;
7856 : }
7857 1 : if (!found) {
7858 2 : if ((new_node = SA_NEW(sql->ta, struct tablelist)) == NULL) {
7859 0 : list_destroy(keys);
7860 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7861 : }
7862 1 : new_node->table = k->t;
7863 1 : new_node->next = NULL;
7864 1 : next_append->next = new_node;
7865 1 : if (!check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade)) {
7866 0 : list_destroy(keys);
7867 0 : return NULL;
7868 : }
7869 : }
7870 : }
7871 : }
7872 15 : list_destroy(keys);
7873 : }
7874 : }
7875 : }
7876 : }
7877 : return t;
7878 : }
7879 :
7880 : static stmt *
7881 41676 : sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
7882 : {
7883 41676 : mvc *sql = be->mvc;
7884 41676 : list *l = sa_list(sql->sa);
7885 41678 : if (t->multiset) {
7886 0 : for (node *n = t->columns->l->h; n; n = n->next) {
7887 0 : sql_column *c = n->data;
7888 :
7889 0 : if (c->type.multiset) {
7890 0 : sql_table *st = mvc_bind_table(sql, c->t->s, c->storage_type);
7891 0 : if (st) {
7892 0 : stmt *trunc = sql_truncate(be, st, restart_sequences, cascade);
7893 0 : if (!trunc)
7894 : return trunc;
7895 0 : append(l, trunc);
7896 : }
7897 : }
7898 : }
7899 : }
7900 41678 : stmt *ret = NULL, *other = NULL;
7901 41678 : struct tablelist *new_list = SA_NEW(sql->ta, struct tablelist);
7902 41690 : stmt **deleted_cols = NULL;
7903 :
7904 41690 : if (!new_list)
7905 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7906 41690 : new_list->table = t;
7907 41690 : new_list->next = NULL;
7908 41690 : if (!check_for_foreign_key_references(sql, new_list, new_list, t, cascade))
7909 2 : goto finalize;
7910 :
7911 83244 : for (struct tablelist *list_node = new_list; list_node; list_node = list_node->next) {
7912 41545 : sql_table *next = list_node->table;
7913 41545 : stmt *v = stmt_tid(be, next, 0);
7914 :
7915 : /* project all columns */
7916 41537 : if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
7917 18 : int nr = 0;
7918 18 : deleted_cols = table_update_stmts(sql, t, &nr);
7919 18 : int i = 0;
7920 50 : for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
7921 32 : sql_column *c = n->data;
7922 32 : stmt *s = stmt_col(be, c, v, v->partition);
7923 :
7924 32 : deleted_cols[i] = s;
7925 32 : list_append(l, s);
7926 : }
7927 : }
7928 :
7929 : /* before */
7930 41693 : if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
7931 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
7932 0 : ret = NULL;
7933 0 : goto finalize;
7934 : }
7935 :
7936 41461 : if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
7937 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
7938 0 : ret = NULL;
7939 0 : goto finalize;
7940 : }
7941 :
7942 41430 : other = stmt_table_clear(be, next, restart_sequences);
7943 41526 : list_append(l, other);
7944 41478 : if (next && t && next->base.id == t->base.id)
7945 41478 : ret = other;
7946 :
7947 : /* after */
7948 41478 : if (!sql_delete_triggers(be, next, v, deleted_cols, 1, 3, 4)) {
7949 0 : (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
7950 0 : ret = NULL;
7951 0 : goto finalize;
7952 : }
7953 :
7954 41544 : if (add_to_rowcount_accumulator(be, other->nr) < 0) {
7955 0 : (void) sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
7956 0 : ret = NULL;
7957 0 : goto finalize;
7958 : }
7959 41451 : if (next->s && isGlobal(next) && !isGlobalTemp(next))
7960 41583 : stmt_add_dependency_change(be, next, other);
7961 : }
7962 :
7963 41699 : finalize:
7964 41701 : sa_reset(sql->ta);
7965 41701 : return ret;
7966 : }
7967 :
7968 : #define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
7969 : #define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
7970 :
7971 : static stmt *
7972 41675 : rel2bin_truncate(backend *be, sql_rel *rel)
7973 : {
7974 41675 : mvc *sql = be->mvc;
7975 41675 : stmt *truncate = NULL;
7976 41675 : sql_rel *tr = rel->l;
7977 41675 : sql_table *t = NULL;
7978 41675 : node *n = NULL;
7979 41675 : int restart_sequences, cascade;
7980 :
7981 41675 : if (tr->op == op_basetable)
7982 41675 : t = tr->l;
7983 : else
7984 0 : assert(0/*ddl statement*/);
7985 :
7986 41675 : n = rel->exps->h;
7987 41675 : restart_sequences = E_ATOM_INT(n->data);
7988 41675 : cascade = E_ATOM_INT(n->next->data);
7989 41675 : truncate = sql_truncate(be, t, restart_sequences, cascade);
7990 41646 : if (sql->cascade_action)
7991 13 : sql->cascade_action = NULL;
7992 41646 : return truncate;
7993 : }
7994 :
7995 234 : static ValPtr take_atom_arg(node **n, int expected_type) {
7996 234 : sql_exp *e = (*n)->data;
7997 234 : atom *a = e->l;
7998 234 : assert(a->tpe.type->localtype == expected_type); (void) expected_type;
7999 234 : assert(!a->isnull);
8000 234 : *n = (*n)->next;
8001 234 : return &a->data;
8002 : }
8003 :
8004 : static stmt *
8005 74 : rel2bin_output(backend *be, sql_rel *rel, list *refs)
8006 : {
8007 74 : mvc *sql = be->mvc;
8008 74 : stmt *sub = NULL, *fns = NULL, *res = NULL;
8009 74 : list *slist = sa_list(sql->sa);
8010 :
8011 74 : if (rel->l) /* first construct the sub relation */
8012 74 : sub = subrel_bin(be, rel->l, refs);
8013 74 : sub = subrel_project(be, sub, refs, rel->l);
8014 74 : if (!sub)
8015 : return NULL;
8016 :
8017 74 : if (!rel->exps)
8018 : return sub;
8019 :
8020 74 : list *arglist = rel->exps;
8021 74 : node *argnode = arglist->h;
8022 74 : atom *a = ((sql_exp*)argnode->data)->l;
8023 74 : int tpe = a->tpe.type->localtype;
8024 :
8025 : // With regular COPY INTO <file>, the first argument is a string.
8026 : // With COPY INTO BINARY, it is an int.
8027 74 : if (tpe == TYPE_str) {
8028 32 : atom *tatom = ((sql_exp*) argnode->data)->l;
8029 32 : const char *tsep = sa_strdup(sql->sa, tatom->isnull ? "" : tatom->data.val.sval);
8030 32 : atom *ratom = ((sql_exp*) argnode->next->data)->l;
8031 32 : const char *rsep = sa_strdup(sql->sa, ratom->isnull ? "" : ratom->data.val.sval);
8032 32 : atom *satom = ((sql_exp*) argnode->next->next->data)->l;
8033 32 : const char *ssep = sa_strdup(sql->sa, satom->isnull ? "" : satom->data.val.sval);
8034 32 : atom *natom = ((sql_exp*) argnode->next->next->next->data)->l;
8035 32 : const char *ns = sa_strdup(sql->sa, natom->isnull ? "" : natom->data.val.sval);
8036 :
8037 32 : const char *fn = NULL;
8038 32 : int onclient = 0;
8039 32 : if (argnode->next->next->next->next) {
8040 23 : fn = E_ATOM_STRING(argnode->next->next->next->next->data);
8041 23 : fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
8042 23 : onclient = E_ATOM_INT(argnode->next->next->next->next->next->data);
8043 : }
8044 32 : stmt *export = stmt_export(be, sub, tsep, rsep, ssep, ns, onclient, fns);
8045 32 : list_append(slist, export);
8046 42 : } else if (tpe == TYPE_int) {
8047 42 : endianness endian = take_atom_arg(&argnode, TYPE_int)->val.ival;
8048 42 : bool do_byteswap = (endian != endian_native && endian != OUR_ENDIANNESS);
8049 42 : int on_client = take_atom_arg(&argnode, TYPE_int)->val.ival;
8050 42 : assert(sub->type == st_list);
8051 42 : list *collist = sub->op4.lval;
8052 192 : for (node *colnode = collist->h; colnode; colnode = colnode->next) {
8053 150 : stmt *colstmt = colnode->data;
8054 150 : assert(argnode != NULL);
8055 150 : const char *filename = take_atom_arg(&argnode, TYPE_str)->val.sval;
8056 150 : stmt *export = stmt_export_bin(be, colstmt, do_byteswap, filename, on_client);
8057 150 : list_append(slist, export);
8058 : }
8059 42 : assert(argnode == NULL);
8060 :
8061 : } else {
8062 0 : assert(0 && "unimplemented export statement type");
8063 : return sub;
8064 : }
8065 :
8066 74 : if (sub->type == st_list && ((stmt*)sub->op4.lval->h->data)->nrcols != 0) {
8067 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);
8068 : } else {
8069 1 : res = stmt_atom_lng(be, 1);
8070 : }
8071 74 : if (add_to_rowcount_accumulator(be, res->nr) < 0)
8072 0 : return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
8073 : return res;
8074 : }
8075 :
8076 : static list *
8077 54 : merge_stmt_join_projections(backend *be, stmt *left, stmt *right, stmt *jl, stmt *jr, stmt *diff)
8078 : {
8079 54 : mvc *sql = be->mvc;
8080 54 : list *l = sa_list(sql->sa);
8081 :
8082 54 : if (left)
8083 117 : for (node *n = left->op4.lval->h; n; n = n->next) {
8084 89 : stmt *c = n->data;
8085 89 : assert(c->type == st_alias);
8086 89 : sql_alias *rnme = table_name(sql->sa, c);
8087 89 : const char *nme = column_name(sql->sa, c);
8088 89 : stmt *s = stmt_project(be, jl ? jl : diff, column(be, c));
8089 :
8090 89 : s = stmt_alias(be, s, c->label, rnme, nme);
8091 89 : list_append(l, s);
8092 : }
8093 54 : if (right)
8094 154 : for (node *n = right->op4.lval->h; n; n = n->next) {
8095 110 : stmt *c = n->data;
8096 110 : assert(c->type == st_alias);
8097 110 : sql_alias *rnme = table_name(sql->sa, c);
8098 110 : const char *nme = column_name(sql->sa, c);
8099 170 : stmt *s = stmt_project(be, jr ? jr : diff, column(be, c));
8100 :
8101 110 : s = stmt_alias(be, s, c->label, rnme, nme);
8102 110 : list_append(l, s);
8103 : }
8104 54 : return l;
8105 : }
8106 :
8107 : static void
8108 28 : validate_merge_delete_update(backend *be, bool delete, stmt *bt_stmt, sql_rel *bt, stmt *jl, stmt *ld)
8109 : {
8110 28 : mvc *sql = be->mvc;
8111 28 : str msg;
8112 28 : sql_table *t = bt->l;
8113 28 : sql_alias *alias = rel_name(bt);
8114 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);
8115 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);
8116 28 : sql_subfunc *add = sql_bind_func(sql, "sys", "sql_add", tail_type(cnt1), tail_type(cnt2), F_FUNC, true, true);
8117 28 : stmt *s1 = stmt_binop(be, cnt1, cnt2, NULL, add);
8118 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);
8119 28 : sql_subfunc *bf = sql_bind_func(sql, "sys", ">", tail_type(s1), tail_type(cnt3), F_FUNC, true, true);
8120 28 : stmt *s2 = stmt_binop(be, s1, cnt3, NULL, bf);
8121 :
8122 28 : if (alias && a_cmp_obj_name(alias, t->base.name)) /* detect if alias is present */
8123 : alias = NULL;
8124 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'",
8125 : delete ? "DELETE" : "UPDATE",
8126 : alias ? "relation" : "table",
8127 22 : alias ? alias->name : t->s ? t->s->base.name : "", alias ? "" : ".", alias ? "" : t->base.name);
8128 28 : (void)stmt_exception(be, s2, msg, 00001);
8129 28 : }
8130 :
8131 : static stmt *
8132 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)
8133 : {
8134 54 : if (is_insert(upd->op)) {
8135 26 : if (!*rd) {
8136 26 : *rd = stmt_tdiff(be, stmt_mirror(be, bin_find_smallest_column(be, target_stmt)), jr, NULL);
8137 : }
8138 26 : stmt *s = stmt_list(be, merge_stmt_join_projections(be, NULL, target_stmt, NULL, NULL, *rd));
8139 26 : refs_update_stmt(refs, join, s); /* project the differences on the target side for inserts */
8140 :
8141 26 : return rel2bin_insert(be, upd, refs);
8142 : } else {
8143 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));
8144 28 : refs_update_stmt(refs, join, s); /* project the matched values on both sides for updates and deletes */
8145 :
8146 28 : assert(is_update(upd->op) || is_delete(upd->op));
8147 : /* the left joined values + left difference must be smaller than the table count */
8148 28 : validate_merge_delete_update(be, is_update(upd->op), bt_stmt, join->l, jl, ld);
8149 :
8150 28 : return is_update(upd->op) ? rel2bin_update(be, upd, refs) : rel2bin_delete(be, upd, refs);
8151 : }
8152 : }
8153 :
8154 : static stmt *
8155 44 : rel2bin_merge(backend *be, sql_rel *rel, list *refs)
8156 : {
8157 44 : mvc *sql = be->mvc;
8158 44 : sql_rel *join;
8159 :
8160 44 : if (is_project(((sql_rel*)rel->l)->op)) {
8161 0 : join = ((sql_rel*)rel->l)->l;
8162 : } else {
8163 : join = rel->l;
8164 : }
8165 :
8166 44 : sql_rel *r = rel->r;
8167 44 : stmt *join_st, *bt_stmt, *target_stmt, *jl, *jr, *ld, *rd = NULL, *ns;
8168 44 : list *slist = sa_list(sql->sa);
8169 :
8170 44 : assert(rel_is_ref(join) && is_left(join->op));
8171 44 : join_st = subrel_bin(be, join, refs);
8172 44 : if (!join_st)
8173 : return NULL;
8174 :
8175 : /* grab generated left join outputs and generate updates accordingly to matched and not matched values */
8176 44 : assert(join_st->type == st_list && list_length(join_st->extra) == 5);
8177 44 : bt_stmt = join_st->extra->h->data;
8178 44 : target_stmt = join_st->extra->h->next->data;
8179 44 : jl = join_st->extra->h->next->next->data;
8180 44 : jr = join_st->extra->h->next->next->next->data;
8181 44 : ld = join_st->extra->h->next->next->next->next->data;
8182 :
8183 44 : if (is_ddl(r->op)) {
8184 44 : assert(r->flag == ddl_list);
8185 44 : if (r->l) {
8186 44 : if ((ns = rel2bin_merge_apply_update(be, join, r->l, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
8187 : return NULL;
8188 44 : list_append(slist, ns);
8189 : }
8190 44 : if (r->r) {
8191 10 : if ((ns = rel2bin_merge_apply_update(be, join, r->r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
8192 : return NULL;
8193 10 : list_append(slist, ns);
8194 : }
8195 : } else {
8196 0 : if (!(ns = rel2bin_merge_apply_update(be, join, r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)))
8197 : return NULL;
8198 0 : list_append(slist, ns);
8199 : }
8200 44 : return stmt_list(be, slist);
8201 : }
8202 :
8203 : static stmt *
8204 521 : rel2bin_list(backend *be, sql_rel *rel, list *refs)
8205 : {
8206 521 : mvc *sql = be->mvc;
8207 521 : stmt *l = NULL, *r = NULL;
8208 521 : list *slist = sa_list(sql->sa);
8209 :
8210 521 : if (rel->l) /* first construct the sub relation */
8211 521 : l = subrel_bin(be, rel->l, refs);
8212 521 : if (rel->r) /* first construct the sub relation */
8213 521 : r = subrel_bin(be, rel->r, refs);
8214 521 : l = subrel_project(be, l, refs, rel->l);
8215 521 : r = subrel_project(be, r, refs, rel->r);
8216 521 : if (!l || !r)
8217 : return NULL;
8218 521 : list_append(slist, l);
8219 521 : list_append(slist, r);
8220 521 : return stmt_list(be, slist);
8221 : }
8222 :
8223 : static stmt *
8224 47751 : rel2bin_psm(backend *be, sql_rel *rel)
8225 : {
8226 47751 : mvc *sql = be->mvc;
8227 47751 : node *n;
8228 47751 : list *l = sa_list(sql->sa);
8229 47757 : stmt *sub = NULL;
8230 :
8231 91140 : for (n = rel->exps->h; n; n = n->next) {
8232 48270 : sql_exp *e = n->data;
8233 48270 : stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8234 48280 : if (!s)
8235 : return NULL;
8236 :
8237 43387 : if (s && s->type == st_table) /* relational statement */
8238 37 : sub = s->op1;
8239 : else
8240 43350 : append(l, s);
8241 : }
8242 42870 : return stmt_list(be, l);
8243 : }
8244 :
8245 : static stmt *
8246 285 : rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
8247 : {
8248 285 : stmt *l = NULL, *r = NULL;
8249 285 : node *n = NULL;
8250 285 : list *slist = sa_list(be->mvc->sa);
8251 :
8252 285 : if (rel->l) /* first construct the sub relation */
8253 0 : l = subrel_bin(be, rel->l, refs);
8254 285 : if (rel->r) /* first construct the sub relation */
8255 0 : r = subrel_bin(be, rel->r, refs);
8256 285 : l = subrel_project(be, l, refs, rel->l);
8257 285 : r = subrel_project(be, r, refs, rel->r);
8258 285 : if ((rel->l && !l) || (rel->r && !r))
8259 : return NULL;
8260 :
8261 285 : assert(rel->exps);
8262 285 : assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
8263 :
8264 285 : if (rel->exps) {
8265 2909 : for (n = rel->exps->h; n; n = n->next) {
8266 2624 : sql_exp *e = n->data;
8267 2624 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
8268 2624 : if (!s)
8269 : return NULL;
8270 2624 : append(slist, s);
8271 : }
8272 : }
8273 285 : return stmt_catalog(be, rel->flag, stmt_list(be, slist));
8274 : }
8275 :
8276 : static stmt *
8277 157 : rel2bin_exception(backend *be, sql_rel *rel, list *refs)
8278 : {
8279 157 : stmt *l = NULL, *r = NULL;
8280 157 : list *slist = sa_list(be->mvc->sa);
8281 :
8282 157 : if (rel->l) /* first construct the sub relation */
8283 0 : l = subrel_bin(be, rel->l, refs);
8284 157 : if (rel->r) /* first construct the sub relation */
8285 157 : r = subrel_bin(be, rel->r, refs);
8286 157 : l = subrel_project(be, l, refs, rel->l);
8287 157 : r = subrel_project(be, r, refs, rel->r);
8288 157 : if ((rel->l && !l) || (rel->r && !r))
8289 : return NULL;
8290 :
8291 157 : assert(rel->exps);
8292 314 : for (node *n = rel->exps->h; n; n = n->next) {
8293 157 : sql_exp *e = n->data;
8294 157 : stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
8295 157 : if (!s)
8296 : return NULL;
8297 157 : list_append(slist, s);
8298 : }
8299 157 : return stmt_list(be, slist);
8300 : }
8301 :
8302 : static stmt *
8303 363 : rel2bin_seq(backend *be, sql_rel *rel, list *refs)
8304 : {
8305 363 : mvc *sql = be->mvc;
8306 363 : node *en = rel->exps->h;
8307 363 : stmt *restart, *sname, *seq, *seqname, *sl = NULL;
8308 363 : list *l = sa_list(sql->sa);
8309 :
8310 363 : if (rel->l) { /* first construct the sub relation */
8311 0 : sl = subrel_bin(be, rel->l, refs);
8312 0 : sl = subrel_project(be, sl, refs, rel->l);
8313 0 : if (!sl)
8314 : return NULL;
8315 : }
8316 :
8317 363 : restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8318 363 : sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8319 363 : seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8320 363 : seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8321 363 : if (!restart || !sname || !seqname || !seq)
8322 : return NULL;
8323 :
8324 363 : (void)refs;
8325 363 : append(l, sname);
8326 363 : append(l, seqname);
8327 363 : append(l, seq);
8328 363 : append(l, restart);
8329 363 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
8330 : }
8331 :
8332 : static stmt *
8333 3160 : rel2bin_trans(backend *be, sql_rel *rel, list *refs)
8334 : {
8335 3160 : node *en = rel->exps->h;
8336 3160 : stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8337 3160 : stmt *name = NULL;
8338 :
8339 3160 : if (!chain)
8340 : return NULL;
8341 :
8342 3160 : (void)refs;
8343 3160 : if (en->next) {
8344 79 : name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8345 79 : if (!name)
8346 : return NULL;
8347 : }
8348 3160 : return stmt_trans(be, rel->flag, chain, name);
8349 : }
8350 :
8351 : static stmt *
8352 1293 : rel2bin_catalog_schema(backend *be, sql_rel *rel, list *refs)
8353 : {
8354 1293 : mvc *sql = be->mvc;
8355 1293 : node *en = rel->exps->h;
8356 1293 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8357 1293 : stmt *sname = NULL, *name = NULL, *ifexists = NULL;
8358 1293 : list *l = sa_list(sql->sa);
8359 :
8360 1293 : if (!action)
8361 : return NULL;
8362 :
8363 1293 : (void)refs;
8364 1293 : en = en->next;
8365 1293 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8366 1293 : if (!sname)
8367 : return NULL;
8368 1293 : append(l, sname);
8369 1293 : en = en->next;
8370 1293 : if (rel->flag == ddl_create_schema) {
8371 1100 : if (en) {
8372 38 : name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8373 38 : if (!name)
8374 : return NULL;
8375 : } else {
8376 1062 : name = stmt_atom_string_nil(be);
8377 : }
8378 1100 : append(l, name);
8379 : } else {
8380 193 : assert(rel->flag == ddl_drop_schema);
8381 193 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8382 193 : if (!ifexists)
8383 : return NULL;
8384 193 : append(l, ifexists);
8385 : }
8386 1293 : append(l, action);
8387 1293 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
8388 : }
8389 :
8390 : static stmt *
8391 38904 : rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
8392 : {
8393 38904 : mvc *sql = be->mvc;
8394 38904 : node *en = rel->exps->h;
8395 38904 : stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8396 38904 : stmt *table = NULL, *sname, *tname = NULL, *kname = NULL, *ifexists = NULL, *replace = NULL;
8397 38904 : list *l = sa_list(sql->sa);
8398 :
8399 38904 : if (!action)
8400 : return NULL;
8401 :
8402 38904 : (void)refs;
8403 38904 : en = en->next;
8404 38904 : sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8405 38904 : if (!sname)
8406 : return NULL;
8407 38904 : en = en->next;
8408 38904 : if (en) {
8409 38904 : tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8410 38904 : if (!tname)
8411 : return NULL;
8412 38904 : en = en->next;
8413 : }
8414 38904 : append(l, sname);
8415 38904 : assert(tname);
8416 38904 : append(l, tname);
8417 38904 : if (rel->flag == ddl_drop_constraint) { /* needs extra string parameter for constraint name */
8418 150 : if (en) {
8419 150 : kname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8420 150 : if (!kname)
8421 : return NULL;
8422 150 : en = en->next;
8423 : }
8424 150 : append(l, kname);
8425 : }
8426 38904 : if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
8427 34526 : if (en) {
8428 34526 : table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8429 34525 : if (!table)
8430 : return NULL;
8431 34525 : en = en->next;
8432 : }
8433 34525 : append(l, table);
8434 : } else {
8435 4378 : if (en) {
8436 4378 : ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8437 4378 : if (!ifexists)
8438 : return NULL;
8439 4378 : en = en->next;
8440 : } else {
8441 0 : ifexists = stmt_atom_int(be, 0);
8442 : }
8443 4378 : append(l, ifexists);
8444 : }
8445 38904 : append(l, action);
8446 38904 : if (rel->flag == ddl_create_view) {
8447 22911 : if (en) {
8448 22911 : replace = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8449 22911 : if (!replace)
8450 : return NULL;
8451 : } else {
8452 0 : replace = stmt_atom_int(be, 0);
8453 : }
8454 22911 : append(l, replace);
8455 15993 : } else if (rel->flag == ddl_create_table && en) {
8456 101 : stmt *name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8457 101 : if (!name)
8458 : return NULL;
8459 101 : en = en->next;
8460 101 : append(l, name);
8461 101 : if (!en)
8462 : return NULL;
8463 101 : stmt *passwd = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8464 101 : if (!passwd)
8465 : return NULL;
8466 101 : append(l, passwd);
8467 : }
8468 38904 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
8469 : }
8470 :
8471 : static stmt *
8472 250811 : rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
8473 : {
8474 250811 : mvc *sql = be->mvc;
8475 250811 : node *en;
8476 250811 : list *l = sa_list(sql->sa);
8477 :
8478 250811 : (void)refs;
8479 1515592 : for (en = rel->exps->h; en; en = en->next) {
8480 1264781 : stmt *es = NULL;
8481 :
8482 1264781 : if (en->data) {
8483 1245917 : es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
8484 1245917 : if (!es)
8485 : return NULL;
8486 : } else {
8487 18864 : es = stmt_atom_string_nil(be);
8488 : }
8489 1264781 : append(l,es);
8490 : }
8491 250811 : return stmt_catalog(be, rel->flag, stmt_list(be, l));
8492 : }
8493 :
8494 : static stmt *
8495 343318 : rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
8496 : {
8497 343318 : mvc *sql = be->mvc;
8498 343318 : stmt *s = NULL;
8499 :
8500 343318 : switch (rel->flag) {
8501 74 : case ddl_output:
8502 74 : s = rel2bin_output(be, rel, refs);
8503 74 : sql->type = Q_TABLE;
8504 74 : break;
8505 521 : case ddl_list:
8506 521 : s = rel2bin_list(be, rel, refs);
8507 521 : break;
8508 47750 : case ddl_psm:
8509 47750 : s = rel2bin_psm(be, rel);
8510 47750 : break;
8511 157 : case ddl_exception:
8512 157 : s = rel2bin_exception(be, rel, refs);
8513 157 : break;
8514 363 : case ddl_create_seq:
8515 : case ddl_alter_seq:
8516 363 : s = rel2bin_seq(be, rel, refs);
8517 363 : sql->type = Q_SCHEMA;
8518 363 : break;
8519 285 : case ddl_alter_table_add_range_partition:
8520 : case ddl_alter_table_add_list_partition:
8521 285 : s = rel2bin_partition_limits(be, rel, refs);
8522 285 : sql->type = Q_SCHEMA;
8523 285 : break;
8524 3160 : case ddl_release:
8525 : case ddl_commit:
8526 : case ddl_rollback:
8527 : case ddl_trans:
8528 3160 : s = rel2bin_trans(be, rel, refs);
8529 3160 : sql->type = Q_TRANS;
8530 3160 : break;
8531 1293 : case ddl_create_schema:
8532 : case ddl_drop_schema:
8533 1293 : s = rel2bin_catalog_schema(be, rel, refs);
8534 1293 : sql->type = Q_SCHEMA;
8535 1293 : break;
8536 38904 : case ddl_create_table:
8537 : case ddl_drop_table:
8538 : case ddl_create_view:
8539 : case ddl_drop_view:
8540 : case ddl_drop_constraint:
8541 : case ddl_alter_table:
8542 38904 : s = rel2bin_catalog_table(be, rel, refs);
8543 38904 : sql->type = Q_SCHEMA;
8544 38904 : break;
8545 250811 : case ddl_drop_seq:
8546 : case ddl_create_type:
8547 : case ddl_drop_type:
8548 : case ddl_drop_index:
8549 : case ddl_create_function:
8550 : case ddl_drop_function:
8551 : case ddl_create_trigger:
8552 : case ddl_drop_trigger:
8553 : case ddl_grant_roles:
8554 : case ddl_revoke_roles:
8555 : case ddl_grant:
8556 : case ddl_revoke:
8557 : case ddl_grant_func:
8558 : case ddl_revoke_func:
8559 : case ddl_create_user:
8560 : case ddl_drop_user:
8561 : case ddl_alter_user:
8562 : case ddl_rename_user:
8563 : case ddl_create_role:
8564 : case ddl_drop_role:
8565 : case ddl_alter_table_add_table:
8566 : case ddl_alter_table_del_table:
8567 : case ddl_alter_table_set_access:
8568 : case ddl_comment_on:
8569 : case ddl_rename_schema:
8570 : case ddl_rename_table:
8571 : case ddl_rename_column:
8572 250811 : s = rel2bin_catalog2(be, rel, refs);
8573 250811 : sql->type = Q_SCHEMA;
8574 250811 : break;
8575 : default:
8576 0 : assert(0);
8577 : }
8578 343316 : return s;
8579 : }
8580 :
8581 : static stmt *
8582 1251186 : subrel_bin(backend *be, sql_rel *rel, list *refs)
8583 : {
8584 1251186 : mvc *sql = be->mvc;
8585 1251186 : stmt *s = NULL;
8586 :
8587 1251186 : if (mvc_highwater(sql))
8588 25 : return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
8589 :
8590 1251181 : if (!rel)
8591 : return s;
8592 1251181 : if (rel_is_ref(rel)) {
8593 15606 : s = refs_find_rel(refs, rel);
8594 : /* needs a proper fix!! */
8595 15606 : if (s)
8596 : return s;
8597 : }
8598 1245043 : switch (rel->op) {
8599 149160 : case op_basetable:
8600 149160 : s = rel2bin_basetable(be, rel);
8601 149168 : sql->type = Q_TABLE;
8602 149168 : break;
8603 3185 : case op_table:
8604 3185 : s = rel2bin_table(be, rel, refs);
8605 3185 : sql->type = Q_TABLE;
8606 3185 : break;
8607 76625 : case op_join:
8608 : case op_left:
8609 : case op_right:
8610 : case op_full:
8611 76625 : s = rel2bin_join(be, rel, refs);
8612 76625 : sql->type = Q_TABLE;
8613 76625 : break;
8614 3203 : case op_semi:
8615 3203 : s = rel2bin_semijoin(be, rel, refs);
8616 3203 : sql->type = Q_TABLE;
8617 3203 : break;
8618 1531 : case op_anti:
8619 1531 : s = rel2bin_antijoin(be, rel, refs);
8620 1531 : sql->type = Q_TABLE;
8621 1531 : break;
8622 303 : case op_union:
8623 303 : s = rel2bin_union(be, rel, refs);
8624 303 : sql->type = Q_TABLE;
8625 303 : break;
8626 4319 : case op_munion:
8627 4319 : s = rel2bin_munion(be, rel, refs);
8628 4319 : sql->type = Q_TABLE;
8629 4319 : break;
8630 2025 : case op_except:
8631 2025 : s = rel2bin_except(be, rel, refs);
8632 2025 : sql->type = Q_TABLE;
8633 2025 : break;
8634 375 : case op_inter:
8635 375 : s = rel2bin_inter(be, rel, refs);
8636 375 : sql->type = Q_TABLE;
8637 375 : break;
8638 400422 : case op_project:
8639 400422 : s = rel2bin_project(be, rel, refs, NULL);
8640 400306 : sql->type = Q_TABLE;
8641 400306 : break;
8642 73580 : case op_select:
8643 73580 : s = rel2bin_select(be, rel, refs);
8644 73580 : sql->type = Q_TABLE;
8645 73580 : break;
8646 13611 : case op_groupby:
8647 13611 : s = rel2bin_groupby(be, rel, refs);
8648 13611 : sql->type = Q_TABLE;
8649 13611 : break;
8650 16977 : case op_topn:
8651 16977 : s = rel2bin_topn(be, rel, refs);
8652 16980 : sql->type = Q_TABLE;
8653 16980 : break;
8654 21 : case op_sample:
8655 21 : s = rel2bin_sample(be, rel, refs);
8656 21 : sql->type = Q_TABLE;
8657 21 : break;
8658 109786 : case op_insert:
8659 109786 : s = rel2bin_insert(be, rel, refs);
8660 109783 : if (!(rel->returning) && sql->type == Q_TABLE)
8661 104896 : sql->type = Q_UPDATE;
8662 : break;
8663 4384 : case op_update:
8664 4384 : s = rel2bin_update(be, rel, refs);
8665 4384 : if (!(rel->returning) && sql->type == Q_TABLE)
8666 4225 : sql->type = Q_UPDATE;
8667 : break;
8668 492 : case op_delete:
8669 492 : s = rel2bin_delete(be, rel, refs);
8670 492 : if (!(rel->returning) && sql->type == Q_TABLE)
8671 357 : sql->type = Q_UPDATE;
8672 : break;
8673 41673 : case op_truncate:
8674 41673 : s = rel2bin_truncate(be, rel);
8675 41635 : if (sql->type == Q_TABLE)
8676 5 : sql->type = Q_UPDATE;
8677 : break;
8678 44 : case op_merge:
8679 44 : s = rel2bin_merge(be, rel, refs);
8680 44 : if (sql->type == Q_TABLE)
8681 44 : sql->type = Q_UPDATE;
8682 : break;
8683 343327 : case op_ddl:
8684 343327 : s = rel2bin_ddl(be, rel, refs);
8685 343327 : break;
8686 : }
8687 1244879 : if (s && rel_is_ref(rel)) {
8688 9468 : list_append(refs, rel);
8689 9468 : list_append(refs, s);
8690 : }
8691 : return s;
8692 : }
8693 :
8694 : stmt *
8695 10956 : rel_bin(backend *be, sql_rel *rel)
8696 : {
8697 10956 : mvc *sql = be->mvc;
8698 10956 : list *refs = sa_list(sql->sa);
8699 10956 : mapi_query_t sqltype = sql->type;
8700 10956 : stmt *s = subrel_bin(be, rel, refs);
8701 :
8702 10955 : s = subrel_project(be, s, refs, rel);
8703 10955 : if (sqltype == Q_SCHEMA)
8704 317 : sql->type = sqltype; /* reset */
8705 :
8706 10955 : if (be->mb->errors) {
8707 0 : if (be->mvc->sa->eb.enabled)
8708 0 : eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors, 1000);
8709 : return NULL;
8710 : }
8711 : return s;
8712 : }
8713 :
8714 : stmt *
8715 616036 : output_rel_bin(backend *be, sql_rel *rel, int top)
8716 : {
8717 616036 : mvc *sql = be->mvc;
8718 616036 : list *refs = sa_list(sql->sa);
8719 616032 : mapi_query_t sqltype = sql->type;
8720 616032 : stmt *s = NULL;
8721 :
8722 616032 : be->join_idx = 0;
8723 616032 : be->rowcount = 0;
8724 616032 : be->silent = !top;
8725 :
8726 616032 : s = subrel_bin(be, rel, refs);
8727 615905 : s = subrel_project(be, s, refs, rel);
8728 :
8729 615919 : if (!s)
8730 : return NULL;
8731 615911 : if (sqltype == Q_SCHEMA)
8732 291788 : sql->type = sqltype; /* reset */
8733 :
8734 615911 : if (!be->silent) { /* don't generate outputs when we are silent */
8735 609410 : if (!is_ddl(rel->op) && sql->type == Q_TABLE && stmt_output(be, s) < 0) {
8736 : return NULL;
8737 609393 : } else if (be->rowcount > 0 && sqltype == Q_UPDATE && stmt_affected_rows(be, be->rowcount) < 0) {
8738 : /* only call stmt_affected_rows outside functions and ddl */
8739 : return NULL;
8740 : }
8741 : }
8742 : return s;
8743 : }
|