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