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