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