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 : #include "rel_rel.h"
15 : #include "rel_basetable.h"
16 : #include "rel_exp.h"
17 : #include "rel_prop.h"
18 : #include "rel_unnest.h"
19 : #include "sql_semantic.h"
20 : #include "sql_mvc.h"
21 : #include "rel_rewriter.h"
22 :
23 : void
24 193 : rel_set_exps(sql_rel *rel, list *exps)
25 : {
26 193 : rel->exps = exps;
27 193 : rel->nrcols = list_length(exps);
28 193 : }
29 :
30 : /* some projections results are order dependent (row_number etc) */
31 : int
32 1295420 : project_unsafe(sql_rel *rel, bool allow_identity)
33 : {
34 1295420 : sql_rel *sub = rel->l;
35 :
36 1295420 : if (need_distinct(rel) || rel->r /* order by */)
37 : return 1;
38 1223730 : if (list_empty(rel->exps))
39 : return 0;
40 : /* projects without sub and projects around ddl's cannot be changed */
41 1223719 : if (!sub || sub->op == op_ddl)
42 : return 1;
43 9906891 : for(node *n = rel->exps->h; n; n = n->next) {
44 8930332 : sql_exp *e = n->data, *ne;
45 :
46 : /* aggr func in project ! */
47 8930332 : if (exp_unsafe(e, allow_identity, false))
48 : return 1;
49 8884517 : if ((ne = rel_find_exp(rel, e)) && ne != e)
50 : return 1; /* no self referencing */
51 : }
52 : return 0;
53 : }
54 :
55 : /* we don't name relations directly, but sometimes we need the relation
56 : name. So we look it up in the first expression
57 :
58 : we should clean up (remove) this function.
59 : */
60 : const char *
61 239907 : rel_name( sql_rel *r )
62 : {
63 244276 : if (is_basetable(r->op))
64 197780 : return rel_base_name(r);
65 50865 : if (!is_project(r->op) && !is_base(r->op) && r->l)
66 : return rel_name(r->l);
67 42127 : if (r->exps && list_length(r->exps)) {
68 42127 : sql_exp *e = r->exps->h->data;
69 42127 : if (exp_relname(e))
70 42127 : return exp_relname(e);
71 0 : if (e->type == e_column) {
72 0 : assert(0);
73 : return e->l;
74 : }
75 : }
76 : return NULL;
77 : }
78 :
79 : sql_rel *
80 9400 : rel_distinct(sql_rel *l)
81 : {
82 9400 : set_distinct(l);
83 9400 : return l;
84 : }
85 :
86 : sql_rel *
87 770268 : rel_dup(sql_rel *r)
88 : {
89 770268 : sql_ref_inc(&r->ref);
90 770268 : return r;
91 : }
92 :
93 : static void
94 676657 : rel_destroy_(sql_rel *rel)
95 : {
96 676657 : if (!rel)
97 : return;
98 676657 : switch(rel->op){
99 : case op_basetable:
100 : break;
101 5141 : case op_table:
102 5141 : if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
103 11 : rel_destroy(rel->l);
104 : break;
105 291551 : case op_join:
106 : case op_left:
107 : case op_right:
108 : case op_full:
109 : case op_semi:
110 : case op_anti:
111 : case op_union:
112 : case op_inter:
113 : case op_except:
114 : case op_insert:
115 : case op_update:
116 : case op_delete:
117 : case op_merge:
118 291551 : if (rel->l)
119 17844 : rel_destroy(rel->l);
120 291551 : if (rel->r)
121 17852 : rel_destroy(rel->r);
122 : break;
123 41367 : case op_munion:
124 : /* the rel->l might be in purpose NULL see rel_merge_table_rewrite_() */
125 41367 : if (rel->l)
126 124182 : for (node *n = ((list*)rel->l)->h; n; n = n->next)
127 82965 : rel_destroy(n->data);
128 : break;
129 326404 : case op_project:
130 : case op_groupby:
131 : case op_select:
132 : case op_topn:
133 : case op_sample:
134 : case op_truncate:
135 326404 : if (rel->l)
136 89774 : rel_destroy(rel->l);
137 : break;
138 0 : case op_ddl:
139 0 : if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
140 0 : if (rel->l)
141 0 : rel_destroy(rel->l);
142 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
143 0 : if (rel->l)
144 0 : rel_destroy(rel->l);
145 0 : if (rel->r)
146 0 : rel_destroy(rel->r);
147 : }
148 : break;
149 : }
150 : }
151 :
152 : void
153 1387928 : rel_destroy(sql_rel *rel)
154 : {
155 1387928 : if (!rel)
156 : return;
157 1387924 : if (sql_ref_dec(&rel->ref) > 0)
158 : return;
159 636039 : rel_destroy_(rel);
160 : }
161 :
162 : sql_rel*
163 3268919 : rel_create(allocator *sa)
164 : {
165 3268919 : sql_rel *r = SA_NEW(sa, sql_rel);
166 3269125 : if(!r)
167 : return NULL;
168 :
169 3269125 : *r = (sql_rel) {
170 : .card = CARD_ATOM,
171 : };
172 3269125 : sql_ref_init(&r->ref);
173 3269125 : return r;
174 : }
175 :
176 : sql_rel *
177 181 : rel_copy(mvc *sql, sql_rel *i, int deep)
178 : {
179 181 : sql_rel *rel;
180 :
181 181 : if (mvc_highwater(sql))
182 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
183 :
184 181 : rel = rel_create(sql->sa);
185 181 : if (!rel)
186 : return NULL;
187 :
188 181 : rel->op = i->op;
189 181 : switch(i->op) {
190 55 : case op_basetable:
191 55 : rel_base_copy(sql, i, rel);
192 55 : break;
193 0 : case op_table:
194 0 : if ((IS_TABLE_PROD_FUNC(i->flag) || i->flag == TABLE_FROM_RELATION) && i->l)
195 0 : rel->l = rel_copy(sql, i->l, deep);
196 0 : rel->r = i->r;
197 0 : break;
198 80 : case op_project:
199 : case op_groupby:
200 80 : if (i->l)
201 68 : rel->l = rel_copy(sql, i->l, deep);
202 80 : if (i->r) {
203 8 : if (!deep) {
204 0 : rel->r = list_dup(i->r, (fdup) NULL);
205 : } else {
206 8 : rel->r = exps_copy(sql, i->r);
207 : }
208 : }
209 : break;
210 2 : case op_munion:
211 2 : if (i->l)
212 2 : rel->l = list_dup(i->l, (fdup) rel_dup);
213 : break;
214 0 : case op_ddl:
215 0 : if (i->flag == ddl_output || i->flag == ddl_create_seq || i->flag == ddl_alter_seq || i->flag == ddl_alter_table || i->flag == ddl_create_table || i->flag == ddl_create_view) {
216 0 : if (i->l)
217 0 : rel->l = rel_copy(sql, i->l, deep);
218 0 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
219 0 : if (i->l)
220 0 : rel->l = rel_copy(sql, i->l, deep);
221 0 : if (i->r)
222 0 : rel->r = rel_copy(sql, i->r, deep);
223 : }
224 : break;
225 23 : case op_select:
226 : case op_topn:
227 : case op_sample:
228 : case op_truncate:
229 23 : if (i->l)
230 23 : rel->l = rel_copy(sql, i->l, deep);
231 : break;
232 21 : case op_join:
233 : case op_left:
234 : case op_right:
235 : case op_full:
236 : case op_semi:
237 : case op_anti:
238 :
239 : case op_union:
240 : case op_inter:
241 : case op_except:
242 :
243 : case op_insert:
244 : case op_update:
245 : case op_delete:
246 : case op_merge:
247 21 : if (i->l)
248 21 : rel->l = rel_copy(sql, i->l, deep);
249 21 : if (i->r)
250 21 : rel->r = rel_copy(sql, i->r, deep);
251 : break;
252 : }
253 :
254 181 : rel->card = i->card;
255 181 : rel->flag = i->flag;
256 181 : rel->nrcols = i->nrcols;
257 181 : rel->grouped = i->grouped;
258 181 : rel->used = i->used;
259 :
260 181 : if (is_processed(i))
261 119 : set_processed(rel);
262 181 : if (is_dependent(i))
263 0 : set_dependent(rel);
264 181 : if (is_outer(i))
265 10 : set_outer(rel);
266 181 : if (is_single(i))
267 4 : set_single(rel);
268 181 : if (need_distinct(i))
269 4 : set_distinct(rel);
270 :
271 181 : rel->p = prop_copy(sql->sa, i->p);
272 181 : rel->exps = (!i->exps)?NULL:deep?exps_copy(sql, i->exps):list_dup(i->exps, (fdup)NULL);
273 181 : rel->attr = (!i->attr)?NULL:deep?exps_copy(sql, i->attr):list_dup(i->attr, (fdup)NULL);
274 181 : return rel;
275 : }
276 :
277 : sql_rel *
278 3939 : rel_select_copy(allocator *sa, sql_rel *l, list *exps)
279 : {
280 3939 : sql_rel *rel = rel_create(sa);
281 3939 : if(!rel)
282 : return NULL;
283 :
284 3939 : rel->l = l;
285 3939 : rel->r = NULL;
286 3939 : rel->op = op_select;
287 3939 : rel->exps = exps?list_dup(exps, (fdup)NULL):NULL;
288 3939 : rel->card = CARD_ATOM; /* no relation */
289 3939 : if (l) {
290 3939 : rel->card = l->card;
291 3939 : rel->nrcols = l->nrcols;
292 : }
293 : return rel;
294 : }
295 :
296 : sql_exp *
297 8006651 : rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int no_tname)
298 : {
299 8006651 : int ambiguous = 0, multi = 0;
300 :
301 8006651 : if (!rel)
302 : return NULL;
303 8006651 : if (mvc_highwater(sql))
304 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
305 :
306 8006651 : if ((is_project(rel->op) || is_base(rel->op))) {
307 4252661 : sql_exp *e = NULL;
308 :
309 4252661 : if (is_base(rel->op) && !rel->exps)
310 4070388 : return rel_base_bind_column(sql, rel, cname, no_tname);
311 182273 : if (!list_empty(rel->exps)) {
312 182212 : e = exps_bind_column(rel->exps, cname, &ambiguous, &multi, no_tname);
313 182211 : if (ambiguous || multi)
314 10 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
315 182201 : if (!e && is_groupby(rel->op) && rel->r) {
316 204 : sql_rel *l = rel->l;
317 204 : if (l)
318 204 : e = rel_bind_column( sql, l, cname, 0, no_tname);
319 204 : if (e) {
320 142 : e = exps_refers(e, rel->r);
321 142 : if (ambiguous || multi)
322 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
323 : return e;
324 : }
325 : }
326 : }
327 19431 : if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
328 83 : e = exps_bind_column(rel->r, cname, &ambiguous, &multi, no_tname);
329 83 : if (ambiguous || multi)
330 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
331 83 : if (e) {
332 1 : e = exp_ref(sql, e);
333 1 : e->card = rel->card;
334 1 : return e;
335 : }
336 : }
337 162690 : if (e)
338 162690 : return exp_ref(sql, e);
339 : }
340 3773420 : if (is_simple_project(rel->op) && rel->l) {
341 7104 : if (!is_processed(rel))
342 0 : return rel_bind_column(sql, rel->l, cname, f, no_tname);
343 3766316 : } else if (is_set(rel->op)) {
344 19 : assert(is_processed(rel));
345 : return NULL;
346 : } else if (is_join(rel->op)) {
347 3241503 : sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), *e2 = NULL, *res;
348 :
349 3241503 : if (e1 && (is_right(rel->op) || is_full(rel->op)))
350 6 : set_has_nil(e1);
351 1619101 : if (!e1 || !is_freevar(e1)) {
352 3241503 : e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
353 3241503 : if (e2 && (is_left(rel->op) || is_full(rel->op)))
354 57 : set_has_nil(e2);
355 3241503 : if (e1 && e2 && !is_dependent(rel))
356 23 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
357 : }
358 3241480 : if (!e1 && !e2 && !list_empty(rel->attr)) {
359 0 : e1 = exps_bind_column(rel->attr, cname, &ambiguous, &multi, no_tname);
360 0 : if (ambiguous || multi)
361 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
362 : }
363 3241480 : res = e1 ? e1 : e2;
364 1622402 : if (res)
365 1708215 : set_not_unique(res);
366 3241480 : return res;
367 : } else if (is_semi(rel->op) ||
368 : is_select(rel->op) ||
369 : is_topn(rel->op) ||
370 : is_sample(rel->op)) {
371 512487 : if (rel->l)
372 512487 : return rel_bind_column(sql, rel->l, cname, f, no_tname);
373 : }
374 : return NULL;
375 : }
376 :
377 : sql_exp *
378 4485676 : rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f)
379 : {
380 4485676 : int ambiguous = 0, multi = 0;
381 :
382 4485676 : if (!rel)
383 : return NULL;
384 4485676 : if (mvc_highwater(sql))
385 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
386 :
387 4485676 : if ((is_project(rel->op) || is_base(rel->op))) {
388 2100531 : sql_exp *e = NULL;
389 :
390 2100531 : if (is_basetable(rel->op) && !rel->exps)
391 1336777 : return rel_base_bind_column2(sql, rel, tname, cname);
392 : /* in case of orderby we should also lookup the column in group by list (and use existing references) */
393 763754 : if (!list_empty(rel->exps)) {
394 763673 : e = exps_bind_column2(rel->exps, tname, cname, &multi);
395 763674 : if (multi)
396 1 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
397 : tname, cname);
398 763673 : if (!e && is_groupby(rel->op) && rel->r) {
399 89 : sql_rel *l = rel->l;
400 89 : if (l)
401 89 : e = rel_bind_column2( sql, l, tname, cname, 0);
402 89 : if (e) {
403 76 : e = exps_refers(e, rel->r);
404 76 : if (ambiguous || multi)
405 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s%s%s' ambiguous",
406 : tname ? tname : "", tname ? "." : "", cname);
407 76 : if (e)
408 : return e;
409 : }
410 : }
411 : }
412 242200 : if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
413 105 : e = exps_bind_column2(rel->r, tname, cname, &multi);
414 105 : if (multi)
415 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
416 : tname, cname);
417 105 : if (e) {
418 10 : e = exp_ref(sql, e);
419 10 : e->card = rel->card;
420 10 : return e;
421 : }
422 : }
423 521550 : if (e)
424 521550 : return exp_ref(sql, e);
425 : }
426 2627335 : if (is_simple_project(rel->op) && rel->l) {
427 233541 : if (!is_processed(rel))
428 0 : return rel_bind_column2(sql, rel->l, tname, cname, f);
429 2393794 : } else if (is_set(rel->op)) {
430 3 : assert(is_processed(rel));
431 : return NULL;
432 : } else if (is_join(rel->op)) {
433 1922231 : sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
434 :
435 1922231 : if (e && (is_right(rel->op) || is_full(rel->op)))
436 194 : set_has_nil(e);
437 194 : if (!e) {
438 851295 : e = rel_bind_column2(sql, rel->r, tname, cname, f);
439 851295 : if (e && (is_left(rel->op) || is_full(rel->op)))
440 23087 : set_has_nil(e);
441 : }
442 404074 : if (!e && !list_empty(rel->attr)) {
443 1 : e = exps_bind_column2(rel->attr, tname, cname, &multi);
444 1 : if (multi)
445 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
446 : tname, cname);
447 : }
448 380987 : if (e)
449 1541245 : set_not_unique(e);
450 1922231 : return e;
451 : } else if (is_semi(rel->op) ||
452 : is_select(rel->op) ||
453 : is_topn(rel->op) ||
454 : is_sample(rel->op)) {
455 462914 : if (rel->l)
456 462914 : return rel_bind_column2(sql, rel->l, tname, cname, f);
457 : }
458 : return NULL;
459 : }
460 :
461 : sql_exp *
462 1246013 : rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname, int f)
463 : {
464 1246013 : if (!sname)
465 1246012 : return rel_bind_column2(sql, rel, tname, cname, f);
466 1 : if (is_basetable(rel->op) && !rel->exps) {
467 0 : return rel_base_bind_column3(sql, rel, sname, tname, cname);
468 1 : } else if (is_set(rel->op)) {
469 : return NULL;
470 1 : } else if (is_project(rel->op) && rel->l) {
471 1 : if (!is_processed(rel))
472 : return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
473 : else
474 1 : return rel_bind_column2(sql, rel->l, tname, cname, f);
475 0 : } else if (is_join(rel->op)) {
476 0 : sql_exp *e = rel_bind_column3(sql, rel->l, sname, tname, cname, f);
477 :
478 0 : if (e && (is_right(rel->op) || is_full(rel->op)))
479 0 : set_has_nil(e);
480 0 : if (!e) {
481 0 : e = rel_bind_column3(sql, rel->r, sname, tname, cname, f);
482 0 : if (e && (is_left(rel->op) || is_full(rel->op)))
483 0 : set_has_nil(e);
484 : }
485 0 : if (!e)
486 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s.%s' ambiguous", sname, tname, cname);
487 0 : if (e)
488 0 : set_not_unique(e);
489 0 : return e;
490 0 : } else if (is_semi(rel->op) ||
491 0 : is_select(rel->op) ||
492 0 : is_topn(rel->op) ||
493 : is_sample(rel->op)) {
494 0 : if (rel->l)
495 : return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
496 : }
497 : return NULL;
498 : }
499 :
500 : sql_exp *
501 0 : rel_first_column(mvc *sql, sql_rel *r)
502 : {
503 0 : if (is_simple_project(r->op))
504 0 : return r->exps->h->data;
505 :
506 0 : list *exps = rel_projections(sql, r, NULL, 1, 1);
507 :
508 0 : if (!list_empty(exps))
509 0 : return exps->h->data;
510 :
511 : return NULL;
512 : }
513 :
514 : /* rel_inplace_* used to convert a rel node into another flavor */
515 : static void
516 83795 : rel_inplace_reset_props(sql_rel *rel)
517 : {
518 83795 : rel->flag = 0;
519 83795 : rel->attr = NULL;
520 83795 : reset_dependent(rel);
521 83795 : set_processed(rel);
522 : }
523 :
524 : sql_rel *
525 113 : rel_inplace_basetable(sql_rel *rel, sql_rel *bt)
526 : {
527 113 : assert(is_basetable(bt->op));
528 :
529 113 : rel_destroy_(rel);
530 113 : rel_inplace_reset_props(rel);
531 113 : rel->l = bt->l;
532 113 : rel->r = bt->r;
533 113 : rel->op = op_basetable;
534 113 : rel->exps = bt->exps;
535 113 : rel->card = CARD_MULTI;
536 113 : rel->nrcols = bt->nrcols;
537 113 : return rel;
538 : }
539 :
540 : sql_rel *
541 19 : rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps)
542 : {
543 19 : rel_destroy_(rel);
544 19 : rel_inplace_reset_props(rel);
545 19 : rel->l = l;
546 19 : rel->r = r;
547 19 : rel->op = setop;
548 19 : rel->card = CARD_MULTI;
549 19 : rel_setop_set_exps(sql, rel, exps, false);
550 19 : return rel;
551 : }
552 :
553 : sql_rel *
554 39132 : rel_inplace_setop_n_ary(mvc *sql, sql_rel *rel, list *rl, operator_type setop, list *exps)
555 : {
556 : // TODO: for now we only deal with munion
557 39132 : assert(setop == op_munion);
558 39132 : rel_destroy_(rel);
559 39132 : rel_inplace_reset_props(rel);
560 : /* rl should be a list of relations */
561 39132 : rel->l = rl;
562 39132 : rel->r = NULL;
563 39132 : rel->op = setop;
564 39132 : rel->card = CARD_MULTI;
565 39132 : rel_setop_n_ary_set_exps(sql, rel, exps, false);
566 39132 : return rel;
567 : }
568 :
569 : sql_rel *
570 43228 : rel_inplace_project(allocator *sa, sql_rel *rel, sql_rel *l, list *e)
571 : {
572 43228 : if (!l) {
573 43177 : l = rel_create(sa);
574 43177 : if(!l)
575 : return NULL;
576 :
577 43177 : *l = *rel;
578 43177 : l->ref.refcnt = 1;
579 : } else {
580 51 : rel_destroy_(rel);
581 : }
582 43228 : rel_inplace_reset_props(rel);
583 43228 : rel->l = l;
584 43228 : rel->r = NULL;
585 43228 : rel->op = op_project;
586 43228 : rel->exps = e;
587 43228 : rel->card = CARD_MULTI;
588 43228 : if (l) {
589 43228 : rel->nrcols = l->nrcols;
590 43228 : assert (exps_card(rel->exps) <= rel->card);
591 : }
592 : return rel;
593 : }
594 :
595 : sql_rel *
596 746 : rel_inplace_select(sql_rel *rel, sql_rel *l, list *exps)
597 : {
598 746 : rel_destroy_(rel);
599 746 : rel_inplace_reset_props(rel);
600 746 : rel->l = l;
601 746 : rel->r = NULL;
602 746 : rel->op = op_select;
603 746 : rel->exps = exps;
604 746 : rel->card = CARD_ATOM; /* no relation */
605 746 : if (l) {
606 746 : rel->card = l->card;
607 746 : rel->nrcols = l->nrcols;
608 746 : if (is_single(l))
609 0 : set_single(rel);
610 : }
611 746 : return rel;
612 : }
613 :
614 : sql_rel *
615 557 : rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps )
616 : {
617 557 : rel_destroy_(rel);
618 557 : rel_inplace_reset_props(rel);
619 557 : rel->card = CARD_ATOM;
620 557 : if (groupbyexps)
621 436 : rel->card = CARD_AGGR;
622 557 : rel->l = l;
623 557 : rel->r = groupbyexps;
624 557 : rel->exps = exps;
625 557 : rel->nrcols = l->nrcols;
626 557 : rel->op = op_groupby;
627 557 : return rel;
628 : }
629 :
630 : sql_rel *
631 0 : rel_inplace_munion(sql_rel *rel, list *rels)
632 : {
633 0 : rel_destroy_(rel);
634 0 : rel_inplace_reset_props(rel);
635 : // TODO: what is the semantics of cardinality? is that right?
636 0 : rel->card = CARD_MULTI;
637 0 : rel->nrcols = 0;
638 0 : if (rels)
639 0 : rel->l = rels;
640 0 : if (rels) {
641 0 : for (node* n = rels->h; n; n = n->next) {
642 0 : sql_rel *r = n->data;
643 : // TODO: could we overflow the nrcols this way?
644 0 : rel->nrcols += r->nrcols;
645 : }
646 : }
647 0 : rel->r = NULL;
648 0 : rel->exps = NULL;
649 0 : rel->op = op_munion;
650 0 : return rel;
651 : }
652 :
653 : /* this function is to be used with the above rel_inplace_* functions */
654 : sql_rel *
655 707 : rel_dup_copy(allocator *sa, sql_rel *rel)
656 : {
657 707 : sql_rel *nrel = rel_create(sa);
658 :
659 707 : if (!nrel)
660 : return NULL;
661 707 : *nrel = *rel;
662 707 : nrel->ref.refcnt = 1;
663 707 : switch(nrel->op){
664 : case op_basetable:
665 : case op_ddl:
666 : break;
667 0 : case op_table:
668 0 : if ((IS_TABLE_PROD_FUNC(nrel->flag) || nrel->flag == TABLE_FROM_RELATION) && nrel->l)
669 0 : rel_dup(nrel->l);
670 : break;
671 697 : case op_join:
672 : case op_left:
673 : case op_right:
674 : case op_full:
675 : case op_semi:
676 : case op_anti:
677 : case op_union:
678 : case op_inter:
679 : case op_except:
680 : case op_insert:
681 : case op_update:
682 : case op_delete:
683 : case op_merge:
684 697 : if (nrel->l)
685 697 : rel_dup(nrel->l);
686 697 : if (nrel->r)
687 697 : rel_dup(nrel->r);
688 : break;
689 10 : case op_project:
690 : case op_groupby:
691 : case op_select:
692 : case op_topn:
693 : case op_sample:
694 : case op_truncate:
695 10 : if (nrel->l)
696 10 : rel_dup(nrel->l);
697 : break;
698 0 : case op_munion:
699 : // TODO: is that even right?
700 0 : if (nrel->l)
701 0 : nrel->l = list_dup(nrel->l, (fdup) rel_dup);
702 : break;
703 : }
704 : return nrel;
705 : }
706 :
707 : sql_rel *
708 2897 : rel_setop(allocator *sa, sql_rel *l, sql_rel *r, operator_type setop)
709 : {
710 2897 : sql_rel *rel = rel_create(sa);
711 2897 : if(!rel)
712 : return NULL;
713 2897 : rel->l = l;
714 2897 : rel->r = r;
715 2897 : rel->op = setop;
716 2897 : rel->exps = NULL;
717 2897 : rel->card = CARD_MULTI;
718 2897 : assert(l->nrcols == r->nrcols);
719 2897 : rel->nrcols = l->nrcols;
720 2897 : return rel;
721 : }
722 :
723 : sql_rel *
724 2481 : rel_setop_check_types(mvc *sql, sql_rel *l, sql_rel *r, list *ls, list *rs, operator_type op)
725 : {
726 2481 : list *nls = new_exp_list(sql->sa);
727 2481 : list *nrs = new_exp_list(sql->sa);
728 2481 : node *n, *m;
729 :
730 2481 : if(!nls || !nrs)
731 : return NULL;
732 :
733 5196 : for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
734 2718 : sql_exp *le = n->data;
735 2718 : sql_exp *re = m->data;
736 :
737 2718 : if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
738 3 : return NULL;
739 2715 : if (!le->alias.label && le->type == e_convert)
740 0 : exp_label(sql->sa, le, ++sql->label);
741 2715 : if (!re->alias.label && re->type == e_convert)
742 0 : exp_label(sql->sa, re, ++sql->label);
743 2715 : append(nls, le);
744 2715 : append(nrs, re);
745 : }
746 2478 : l = rel_project(sql->sa, l, nls);
747 2478 : r = rel_project(sql->sa, r, nrs);
748 2478 : set_processed(l);
749 2478 : set_processed(r);
750 2478 : return rel_setop(sql->sa, l, r, op);
751 : }
752 :
753 : void
754 2874 : rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
755 : {
756 2874 : sql_rel *l = rel->l, *r = rel->r;
757 2874 : list *lexps = l->exps, *rexps = r->exps;
758 :
759 2874 : if (!is_project(l->op))
760 19 : lexps = rel_projections(sql, l, NULL, 0, 1);
761 2874 : if (!is_project(r->op))
762 19 : rexps = rel_projections(sql, r, NULL, 0, 1);
763 :
764 2874 : assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && list_length(exps) == list_length(lexps)*/);
765 :
766 11850 : for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n = n->next, m = m->next,o = o->next) {
767 8976 : sql_exp *e = n->data, *f = m->data, *g = o->data;
768 :
769 8976 : assert(e->alias.label);
770 8976 : e->nid = 0; /* setops are positional */
771 8976 : if (is_union(rel->op)) { /* propagate set_has_no_nil only if it's applicable to both sides of the union*/
772 6038 : if (has_nil(f) || has_nil(g))
773 5142 : set_has_nil(e);
774 : else
775 896 : set_has_no_nil(e);
776 6038 : if (!keep_props) {
777 6038 : e->p = NULL; /* remove all the properties on unions on the general case */
778 6038 : set_not_unique(e);
779 : }
780 : }
781 8976 : e->card = CARD_MULTI; /* multi cardinality */
782 : }
783 2874 : rel->nrcols = l->nrcols;
784 2874 : rel->exps = exps;
785 2874 : }
786 :
787 : sql_rel *
788 62268 : rel_setop_n_ary(allocator *sa, list *rels, operator_type setop)
789 : {
790 : // TODO: for now we support only n-ary union
791 62268 : assert(setop == op_munion);
792 :
793 62268 : if (!rels)
794 : return NULL;
795 :
796 62268 : assert(list_length(rels) >= 2);
797 62268 : sql_rel *rel = rel_create(sa);
798 62268 : if(!rel)
799 : return NULL;
800 :
801 62268 : rel->l = rels;
802 62268 : rel->r = NULL;
803 62268 : rel->op = setop;
804 62268 : rel->exps = NULL;
805 62268 : rel->card = CARD_MULTI;
806 : // TODO: properly introduce the assertion over rels elements
807 : /*assert(l->nrcols == r->nrcols);*/
808 62268 : rel->nrcols = ((sql_rel*)rels->h->data)->nrcols;
809 62268 : return rel;
810 : }
811 :
812 : sql_rel *
813 58439 : rel_setop_n_ary_check_types(mvc *sql, sql_rel *l, sql_rel *r, list *ls, list *rs, operator_type op)
814 : {
815 : // TODO: for now we support only 2 relation in the list at ->l of
816 : // the n-ary operator. In the future this function should be variadic (?)
817 : // TODO: for now we support only n-ary union
818 58439 : assert(op == op_munion);
819 :
820 : /* NOTE: this is copied logic from rel_setop_check_types. A DRY-er approach
821 : * would be to call rel_setop_check_types which will return a binary
822 : * setop from which we could extract ->l and ->r and add them in a list
823 : * for the op_munion. This is kind of ugly though...
824 : */
825 58439 : list *nls = new_exp_list(sql->sa);
826 58439 : list *nrs = new_exp_list(sql->sa);
827 58439 : node *n, *m;
828 58439 : list* rels;
829 :
830 58439 : if(!nls || !nrs)
831 : return NULL;
832 :
833 457828 : for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
834 399393 : sql_exp *le = n->data;
835 399393 : sql_exp *re = m->data;
836 :
837 399393 : if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
838 4 : return NULL;
839 399389 : append(nls, le);
840 399389 : append(nrs, re);
841 : }
842 58435 : l = rel_project(sql->sa, l, nls);
843 58435 : r = rel_project(sql->sa, r, nrs);
844 58435 : set_processed(l);
845 58435 : set_processed(r);
846 :
847 : /* create a list with only 2 sql_rel entries for the n-ary set op */
848 58435 : rels = sa_list(sql->sa);
849 58435 : append(rels, l);
850 58435 : append(rels, r);
851 :
852 58435 : return rel_setop_n_ary(sql->sa, rels, op);
853 : }
854 :
855 : void
856 99869 : rel_setop_n_ary_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
857 : {
858 99869 : list *rexps;
859 99869 : sql_rel *r;
860 :
861 : /* set the exps properties first */
862 785140 : for (node *m = exps->h; m; m = m->next) {
863 : /* the nil/no_nil property will be set in the next loop where
864 : * we go through the exps of every rel of the rels. For now no_nil
865 : */
866 685271 : sql_exp *e = (sql_exp*)m->data;
867 685271 : set_has_no_nil(e);
868 : /* remove all the properties on unions on the general case */
869 685271 : if (!keep_props) {
870 684978 : e->p = NULL;
871 684978 : set_not_unique(e);
872 : }
873 : }
874 :
875 : /* for every relation in the list of relations */
876 300325 : for (node *n = ((list*)rel->l)->h; n; n = n->next) {
877 200456 : r = n->data;
878 200456 : rexps = r->exps;
879 :
880 200456 : if (!is_project(r->op))
881 13340 : rexps = rel_projections(sql, r, NULL, 0, 1);
882 :
883 : /* go through the relation's exps */
884 1574387 : for (node *m = exps->h, *o = rexps->h; m && o; m = m->next, o = o->next) {
885 1373931 : sql_exp *e = m->data, *f = o->data;
886 : /* for multi-union if any operand has nil then set the nil prop for the op exp */
887 1373931 : if (is_munion(rel->op) && has_nil(f))
888 479555 : set_has_nil(e);
889 1373931 : e->card = CARD_MULTI;
890 : }
891 : }
892 :
893 99869 : rel->exps = exps;
894 : // TODO: probably setting nrcols is redundant as we have already done
895 : // that when we create the setop_n_ary. check rel_setop_n_ary()
896 99869 : rel->nrcols = ((sql_rel*)((list*)rel->l)->h->data)->nrcols;
897 99869 : }
898 :
899 : sql_rel *
900 522384 : rel_crossproduct(allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
901 : {
902 522384 : sql_rel *rel = rel_create(sa);
903 522384 : if(!rel)
904 : return NULL;
905 :
906 522384 : rel->l = l;
907 522384 : rel->r = r;
908 522384 : rel->op = join;
909 522384 : rel->exps = NULL;
910 522384 : rel->card = CARD_MULTI;
911 522384 : rel->nrcols = l->nrcols + r->nrcols;
912 522384 : return rel;
913 : }
914 :
915 : sql_exp *
916 0 : rel_is_constant(sql_rel **R, sql_exp *e)
917 : {
918 0 : sql_rel *rel = *R;
919 :
920 0 : if (rel && rel->op == op_project && list_length(rel->exps) == 1 &&
921 0 : !rel->l && !rel->r && !rel_is_ref(rel) && e->type == e_column) {
922 0 : sql_exp *ne = rel_find_exp(rel, e);
923 0 : if (ne) {
924 0 : rel_destroy(rel);
925 0 : *R = NULL;
926 0 : return ne;
927 : }
928 : }
929 : return e;
930 : }
931 :
932 : sql_rel *
933 16825 : rel_topn(allocator *sa, sql_rel *l, list *exps )
934 : {
935 16825 : sql_rel *rel = rel_create(sa);
936 16831 : if(!rel)
937 : return NULL;
938 :
939 16831 : rel->l = l;
940 16831 : rel->r = NULL;
941 16831 : rel->op = op_topn;
942 16831 : rel->exps = exps;
943 16831 : rel->card = l->card;
944 16831 : rel->nrcols = l->nrcols;
945 16831 : return rel;
946 : }
947 :
948 : sql_rel *
949 23 : rel_sample(allocator *sa, sql_rel *l, list *exps )
950 : {
951 23 : sql_rel *rel = rel_create(sa);
952 23 : if(!rel)
953 : return NULL;
954 :
955 23 : rel->l = l;
956 23 : rel->r = NULL;
957 23 : rel->op = op_sample;
958 23 : rel->exps = exps;
959 23 : rel->card = l->card;
960 23 : rel->nrcols = l->nrcols;
961 23 : return rel;
962 : }
963 :
964 : sql_rel *
965 15216 : rel_label( mvc *sql, sql_rel *r, int all)
966 : {
967 15216 : int nr = ++sql->label;
968 15216 : char tname[16], *tnme;
969 15216 : char cname[16], *cnme = NULL;
970 :
971 15216 : tnme = sa_strdup(sql->sa, number2name(tname, sizeof(tname), nr));
972 15230 : if (!is_simple_project(r->op))
973 611 : r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 1));
974 15230 : if (!list_empty(r->exps)) {
975 15237 : list_hash_clear(r->exps);
976 59804 : for (node *ne = r->exps->h; ne; ne = ne->next) {
977 44562 : sql_exp *e = ne->data;
978 :
979 44562 : if (!is_freevar(e)) {
980 44576 : if (all) {
981 44580 : nr = ++sql->label;
982 44580 : cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
983 : }
984 44579 : exp_setname(sql, e, tnme, cnme );
985 : }
986 : }
987 : }
988 : /* op_projects can have a order by list */
989 15244 : if (!list_empty(r->r)) {
990 0 : for (node *ne = ((list*)r->r)->h; ne; ne = ne->next) {
991 0 : if (all) {
992 0 : nr = ++sql->label;
993 0 : cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
994 : }
995 0 : exp_setname(sql, ne->data, tnme, cnme );
996 : }
997 : }
998 15241 : return r;
999 : }
1000 :
1001 : sql_exp *
1002 29957 : rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e)
1003 : {
1004 29957 : assert(is_project(rel->op));
1005 :
1006 29957 : if (!e->alias.label)
1007 112 : exp_label(sql->sa, e, ++sql->label);
1008 29957 : if (is_simple_project(rel->op)) {
1009 29953 : sql_rel *l = rel->l;
1010 29953 : if (!rel->exps)
1011 24 : rel->exps = new_exp_list(sql->sa);
1012 29953 : if (l && is_groupby(l->op) && exp_card(e) <= CARD_ATOM && list_empty(l->exps))
1013 4 : e = rel_project_add_exp(sql, l, e);
1014 29953 : if (e->card > rel->card)
1015 0 : rel->card = e->card;
1016 29953 : append(rel->exps, e);
1017 29953 : rel->nrcols++;
1018 4 : } else if (is_groupby(rel->op)) {
1019 4 : return rel_groupby_add_aggr(sql, rel, e);
1020 : }
1021 29953 : e = exp_ref(sql, e);
1022 29953 : return e;
1023 : }
1024 :
1025 : sql_rel *
1026 281534 : rel_select_add_exp(allocator *sa, sql_rel *l, sql_exp *e)
1027 : {
1028 281534 : if ((l->op != op_select && !is_outerjoin(l->op)) || rel_is_ref(l))
1029 8077 : return rel_select(sa, l, e);
1030 :
1031 : /* allow during AST->relational for bool expressions as well
1032 : if (e->type != e_cmp && e->card > CARD_ATOM) {
1033 : sql_exp *t = exp_atom_bool(sa, 1);
1034 : e = exp_compare(sa, e, t, cmp_equal);
1035 : }
1036 : */
1037 273457 : if (!l->exps)
1038 3807 : l->exps = new_exp_list(sa);
1039 273457 : append(l->exps, e);
1040 273457 : return l;
1041 : }
1042 :
1043 : void
1044 484689 : rel_join_add_exp( allocator *sa, sql_rel *rel, sql_exp *e)
1045 : {
1046 484689 : assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
1047 :
1048 484689 : if (!rel->exps)
1049 439541 : rel->exps = new_exp_list(sa);
1050 484689 : append(rel->exps, e);
1051 484689 : if (e->card > rel->card)
1052 0 : rel->card = e->card;
1053 484689 : }
1054 :
1055 : sql_exp *
1056 77675 : rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
1057 : {
1058 77675 : sql_exp *m = NULL, *ne;
1059 :
1060 77675 : if (list_empty(rel->r))
1061 26090 : rel->card = e->card = CARD_ATOM;
1062 :
1063 77675 : if ((m=exps_any_match(rel->exps, e)) == NULL) {
1064 45018 : if (!exp_name(e))
1065 44994 : exp_label(sql->sa, e, ++sql->label);
1066 45018 : append(rel->exps, e);
1067 45018 : rel->nrcols++;
1068 45018 : m = e;
1069 : }
1070 77675 : ne = exp_ref(sql, m);
1071 77675 : return ne;
1072 : }
1073 :
1074 : sql_rel *
1075 264581 : rel_select(allocator *sa, sql_rel *l, sql_exp *e)
1076 : {
1077 264581 : sql_rel *rel;
1078 :
1079 264581 : if (l && is_outerjoin(l->op) && !is_processed(l)) {
1080 206 : if (e) {
1081 190 : if (!l->exps)
1082 175 : l->exps = new_exp_list(sa);
1083 190 : append(l->exps, e);
1084 : }
1085 206 : return l;
1086 : }
1087 :
1088 264375 : if (l && is_select(l->op) && !rel_is_ref(l)) { /* refine old select */
1089 16601 : if (e)
1090 9526 : rel_select_add_exp(sa, l, e);
1091 16601 : return l;
1092 : }
1093 247774 : rel = rel_create(sa);
1094 247774 : if(!rel)
1095 : return NULL;
1096 :
1097 247774 : rel->l = l;
1098 247774 : rel->r = NULL;
1099 247774 : rel->op = op_select;
1100 247774 : rel->exps = new_exp_list(sa);
1101 247774 : if (e)
1102 191942 : rel_select_add_exp(sa, rel, e);
1103 247774 : rel->card = CARD_ATOM; /* no relation */
1104 247774 : if (l) {
1105 247774 : rel->card = l->card;
1106 247774 : rel->nrcols = l->nrcols;
1107 247774 : if (is_single(l))
1108 1526 : set_single(rel);
1109 : }
1110 : return rel;
1111 : }
1112 :
1113 : sql_rel *
1114 37079 : rel_groupby(mvc *sql, sql_rel *l, list *groupbyexps )
1115 : {
1116 37079 : sql_rel *rel = rel_create(sql->sa);
1117 37079 : list *aggrs = new_exp_list(sql->sa);
1118 37079 : node *en;
1119 37079 : if(!rel || !aggrs) {
1120 0 : rel_destroy(rel);
1121 0 : return NULL;
1122 : }
1123 :
1124 37079 : rel->card = CARD_ATOM;
1125 : /* reduce duplicates in groupbyexps */
1126 37079 : if (groupbyexps && list_length(groupbyexps) > 1) {
1127 5129 : list *gexps = sa_list(sql->sa);
1128 :
1129 24699 : for (en = groupbyexps->h; en; en = en->next) {
1130 19570 : sql_exp *e = en->data, *ne = exps_find_exp(gexps, e);
1131 :
1132 19570 : if (!ne) {
1133 19467 : list_append(gexps, e);
1134 : } else {
1135 103 : const char *ername = exp_relname(e), *nername = exp_relname(ne), *ename = exp_name(e), *nename = exp_name(ne);
1136 103 : if ((ername && !nername) || (!ername && nername) ||
1137 97 : (ername && nername && strcmp(ername,nername) != 0) || strcmp(ename,nename) != 0)
1138 10 : list_append(gexps, e);
1139 : }
1140 : }
1141 : groupbyexps = gexps;
1142 : }
1143 :
1144 10441 : if (groupbyexps) {
1145 10441 : rel->card = CARD_AGGR;
1146 35088 : for (en = groupbyexps->h; en; en = en->next) {
1147 24647 : sql_exp *e = en->data, *ne;
1148 :
1149 24647 : if (exp_is_atom(e) && !e->alias.name) { /* numeric lookup done later */
1150 29 : rel->flag = 1;
1151 29 : continue;
1152 : }
1153 : /* after the group by the cardinality reduces */
1154 24618 : e->card = MIN(e->card, rel->card); /* if the column is an atom, the cardinality should not change */
1155 24618 : if (!e->alias.label)
1156 84 : exp_label(sql->sa, e, ++sql->label);
1157 24618 : ne = exp_ref(sql, e);
1158 24618 : ne = exp_propagate(sql->sa, ne, e);
1159 24618 : append(aggrs, ne);
1160 : }
1161 : }
1162 37079 : rel->l = l;
1163 37079 : rel->r = groupbyexps;
1164 37079 : rel->exps = aggrs;
1165 37079 : rel->nrcols = aggrs?list_length(aggrs):0;
1166 37078 : rel->op = op_groupby;
1167 37078 : rel->grouped = 1;
1168 37078 : return rel;
1169 : }
1170 :
1171 : sql_rel *
1172 978005 : rel_project(allocator *sa, sql_rel *l, list *e)
1173 : {
1174 978005 : sql_rel *rel = rel_create(sa);
1175 977981 : if(!rel)
1176 : return NULL;
1177 :
1178 977981 : rel->l = l;
1179 977981 : rel->r = NULL;
1180 977981 : rel->op = op_project;
1181 977981 : rel->exps = e;
1182 977981 : rel->card = exps_card(e);
1183 978300 : if (l) {
1184 795784 : rel->card = l->card;
1185 795784 : if (e)
1186 738767 : rel->nrcols = list_length(e);
1187 : else
1188 57017 : rel->nrcols = l->nrcols;
1189 795789 : rel->single = is_single(l);
1190 : }
1191 978305 : if (e && !list_empty(e)) {
1192 920581 : set_processed(rel);
1193 920581 : rel->nrcols = list_length(e);
1194 : }
1195 : return rel;
1196 : }
1197 :
1198 : sql_rel *
1199 72507 : rel_project_exp(mvc *sql, sql_exp *e)
1200 : {
1201 72507 : if (!exp_name(e))
1202 72552 : exp_label(sql->sa, e, ++sql->label);
1203 72556 : return rel_project(sql->sa, NULL, list_append(sa_list(sql->sa), e));
1204 : }
1205 :
1206 : sql_rel *
1207 118065 : rel_list(allocator *sa, sql_rel *l, sql_rel *r)
1208 : {
1209 118065 : sql_rel *rel = rel_create(sa);
1210 118065 : if (!rel)
1211 : return NULL;
1212 118065 : if (!l)
1213 : return r;
1214 565 : rel->l = l;
1215 565 : rel->r = r;
1216 565 : rel->op = op_ddl;
1217 565 : rel->flag = ddl_list;
1218 565 : return rel;
1219 : }
1220 :
1221 : sql_rel *
1222 157 : rel_exception(allocator *sa, sql_rel *l, sql_rel *r, list *exps)
1223 : {
1224 157 : sql_rel *rel = rel_create(sa);
1225 157 : if(!rel)
1226 : return NULL;
1227 157 : rel->r = r;
1228 157 : rel->exps = exps;
1229 157 : rel->op = op_ddl;
1230 157 : rel->flag = ddl_exception;
1231 157 : if (l)
1232 157 : return rel_list(sa, rel, l); /* keep base relation on the right ! */
1233 : return rel;
1234 : }
1235 :
1236 : sql_rel *
1237 313 : rel_relational_func(allocator *sa, sql_rel *l, list *exps)
1238 : {
1239 313 : sql_rel *rel = rel_create(sa);
1240 313 : if(!rel)
1241 : return NULL;
1242 :
1243 313 : rel->flag = TABLE_PROD_FUNC;
1244 313 : rel->l = l;
1245 313 : rel->op = op_table;
1246 313 : rel->exps = exps;
1247 313 : rel->card = CARD_MULTI;
1248 313 : rel->nrcols = list_length(exps);
1249 313 : return rel;
1250 : }
1251 :
1252 : sql_rel *
1253 17074 : rel_table_func(allocator *sa, sql_rel *l, sql_exp *f, list *exps, int kind)
1254 : {
1255 17074 : sql_rel *rel = rel_create(sa);
1256 17074 : if(!rel)
1257 : return NULL;
1258 :
1259 17074 : assert(kind > 0);
1260 17074 : rel->flag = kind;
1261 17074 : rel->l = l; /* relation before call */
1262 17074 : rel->r = f; /* expression (table func call) */
1263 17074 : rel->op = op_table;
1264 17074 : rel->exps = exps;
1265 17074 : rel->card = CARD_MULTI;
1266 17074 : rel->nrcols = list_length(exps);
1267 17074 : return rel;
1268 : }
1269 :
1270 : static void
1271 314592 : exps_reset_props(list *exps, bool setnil)
1272 : {
1273 314592 : if (!list_empty(exps)) {
1274 3248244 : for (node *m = exps->h; m; m = m->next) {
1275 2936531 : sql_exp *e = m->data;
1276 :
1277 2936531 : if (setnil)
1278 229461 : set_has_nil(e);
1279 2936531 : set_not_unique(e);
1280 : }
1281 : }
1282 314592 : }
1283 :
1284 : /* Return a list with all the projection expressions, that optionally
1285 : * refer to the tname relation, anywhere in the relational tree
1286 : */
1287 : list *
1288 1082504 : _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern, int basecol /* basecol only */ )
1289 : {
1290 1156667 : list *lexps, *rexps = NULL, *exps = NULL, *rels;
1291 :
1292 1156667 : if (mvc_highwater(sql))
1293 32 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1294 :
1295 1156660 : if (!rel)
1296 0 : return new_exp_list(sql->sa);
1297 :
1298 1156660 : if (!tname && is_basetable(rel->op) && !is_processed(rel))
1299 279793 : rel_base_use_all( sql, rel);
1300 :
1301 1156662 : switch(rel->op) {
1302 157296 : case op_join:
1303 : case op_left:
1304 : case op_right:
1305 : case op_full:
1306 157296 : lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1307 157296 : exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
1308 157296 : if (!rel->attr)
1309 154429 : rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
1310 157296 : exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
1311 157296 : if (rexps)
1312 154429 : lexps = list_merge(lexps, rexps, (fdup)NULL);
1313 157296 : if (rel->attr)
1314 2867 : append(lexps, exp_ref(sql, rel->attr->h->data));
1315 : return lexps;
1316 6609 : case op_groupby:
1317 6609 : if (list_empty(rel->exps) && rel->r) {
1318 0 : list *r = rel->r;
1319 :
1320 0 : exps = new_exp_list(sql->sa);
1321 0 : for (node *en = r->h; en; en = en->next) {
1322 0 : sql_exp *e = en->data;
1323 :
1324 0 : if (basecol && !is_basecol(e))
1325 0 : continue;
1326 0 : if (intern || !is_intern(e)) {
1327 0 : sql_exp *ne = exp_ref(sql, e);
1328 0 : if (settname && tname)
1329 0 : exp_setname(sql, ne, tname, exp_name(e));
1330 0 : assert(ne->alias.label);
1331 0 : e = ne;
1332 0 : append(exps, e);
1333 : }
1334 : }
1335 : return exps;
1336 : }
1337 : /* fall through */
1338 : case op_project:
1339 : case op_basetable:
1340 : case op_table:
1341 :
1342 : case op_union:
1343 : case op_except:
1344 : case op_inter:
1345 : case op_munion:
1346 925203 : if (is_basetable(rel->op) && !rel->exps)
1347 101468 : return rel_base_projection(sql, rel, intern);
1348 823735 : if (rel->exps) {
1349 762822 : exps = new_exp_list(sql->sa);
1350 6111332 : for (node *en = rel->exps->h; en; en = en->next) {
1351 5348480 : sql_exp *e = en->data;
1352 :
1353 5348480 : if (basecol && !is_basecol(e))
1354 52 : continue;
1355 5348428 : if (intern || !is_intern(e)) {
1356 5334931 : if (!e->alias.label)
1357 21448 : en->data = e = exp_label(sql->sa, e, ++sql->label);
1358 5334931 : sql_exp *ne = exp_ref(sql, e);
1359 5334922 : if (settname && tname)
1360 0 : exp_setname(sql, ne, tname, exp_name(e));
1361 5334922 : assert(ne->alias.label);
1362 5334922 : e = ne;
1363 5334922 : append(exps, e);
1364 : }
1365 : }
1366 : return exps;
1367 : }
1368 : /* differentiate for the munion set op (for now) */
1369 60913 : if (is_munion(rel->op)) {
1370 58435 : sql_rel *r = NULL;
1371 58435 : assert(rel->l);
1372 : /* get the exps from the first relation */
1373 58435 : rels = rel->l;
1374 58435 : if (rels->h)
1375 58435 : r = rels->h->data;
1376 58435 : if (r)
1377 58435 : exps = _rel_projections(sql, r, tname, settname, intern, basecol);
1378 : /* for every other relation in the list */
1379 : // TODO: do we need the assertion here? for no-assert the loop is no-op
1380 : /*
1381 : for (node *n = rels->h->next; n; n = n->next) {
1382 : rexps = _rel_projections(sql, n->data, tname, settname, intern, basecol);
1383 : assert(list_length(exps) == list_length(rexps));
1384 : }
1385 : */
1386 : /* it's a multi-union (expressions have to be the same in all the operands)
1387 : * so we are ok only with the expressions of the first operand
1388 : */
1389 58435 : if (exps) {
1390 457824 : for (node *en = exps->h; en; en = en->next) {
1391 399389 : sql_exp *e = en->data;
1392 :
1393 399389 : e->card = rel->card;
1394 399389 : if (!settname) /* noname use alias */
1395 399389 : exp_setname(sql, e, exp_relname(e), exp_name(e));
1396 : }
1397 58435 : if (!settname)
1398 58435 : list_hash_clear(rel->l);
1399 : }
1400 58435 : return exps;
1401 : }
1402 : /* I only expect set relations to hit here */
1403 2478 : assert(is_set(rel->op));
1404 2478 : lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1405 2478 : rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
1406 2478 : if (lexps && rexps) {
1407 :
1408 2478 : assert(list_length(lexps) == list_length(rexps));
1409 5193 : for (node *en = lexps->h; en; en = en->next) {
1410 2715 : sql_exp *e = en->data;
1411 :
1412 2715 : e->card = rel->card;
1413 2715 : if (!settname) /* noname use alias */
1414 2715 : exp_setname(sql, e, exp_relname(e), exp_name(e));
1415 : }
1416 2478 : if (!settname)
1417 2478 : list_hash_clear(lexps);
1418 : }
1419 : return lexps;
1420 :
1421 74163 : case op_ddl:
1422 : case op_semi:
1423 : case op_anti:
1424 :
1425 : case op_select:
1426 : case op_topn:
1427 : case op_sample:
1428 74163 : return _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1429 : default:
1430 : return NULL;
1431 : }
1432 : }
1433 :
1434 : list *
1435 665617 : rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern)
1436 : {
1437 665617 : assert(tname == NULL);
1438 665617 : return _rel_projections(sql, rel, tname, settname, intern, 0);
1439 : }
1440 :
1441 : /* find the path to the relation containing the base of the expression
1442 : (e_column), in most cases this means go down the join tree and
1443 : find the base column.
1444 : */
1445 : static int
1446 4037511 : rel_bind_path_(mvc *sql, sql_rel *rel, sql_exp *e, list *path )
1447 : {
1448 4037511 : int found = 0;
1449 :
1450 4037511 : if (mvc_highwater(sql)) {
1451 0 : sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1452 0 : return 0;
1453 : }
1454 :
1455 4037511 : switch (rel->op) {
1456 1873748 : case op_join:
1457 : case op_left:
1458 : case op_right:
1459 : case op_full:
1460 : /* first right (possible subquery) */
1461 1873748 : found = rel_bind_path_(sql, rel->r, e, path);
1462 1873748 : if (!found)
1463 1575811 : found = rel_bind_path_(sql, rel->l, e, path);
1464 1575811 : if (!found && !list_empty(rel->attr)) {
1465 0 : assert(e->nid);
1466 0 : if (exps_bind_nid(rel->attr, e->nid))
1467 : found = 1;
1468 : }
1469 : break;
1470 115106 : case op_semi:
1471 : case op_anti:
1472 : case op_select:
1473 : case op_topn:
1474 : case op_sample:
1475 115106 : found = rel_bind_path_(sql, rel->l, e, path);
1476 115106 : break;
1477 2048657 : case op_basetable:
1478 : case op_munion:
1479 : case op_union:
1480 : case op_inter:
1481 : case op_except:
1482 : case op_groupby:
1483 : case op_project:
1484 : case op_table:
1485 2048657 : if (is_basetable(rel->op) && !rel->exps) {
1486 1854619 : assert(e->nid);
1487 1854619 : if (rel_base_has_nid(rel, e->nid))
1488 : found = 1;
1489 194038 : } else if (rel->exps) {
1490 194038 : assert(e->nid);
1491 194038 : if (exps_bind_nid(rel->exps, e->nid))
1492 : found = 1;
1493 : }
1494 : break;
1495 : case op_insert:
1496 : case op_update:
1497 : case op_delete:
1498 : case op_truncate:
1499 : case op_merge:
1500 : case op_ddl:
1501 : break;
1502 : }
1503 115112 : if (found)
1504 2416797 : list_prepend(path, rel);
1505 : return found;
1506 : }
1507 :
1508 : static list *
1509 499581 : rel_bind_path(mvc *sql, sql_rel *rel, sql_exp *e, list *path)
1510 : {
1511 499581 : if (!path)
1512 : return NULL;
1513 :
1514 499581 : if (e->type == e_convert) {
1515 21091 : if (!(path = rel_bind_path(sql, rel, e->l, path)))
1516 : return NULL;
1517 478490 : } else if (e->type == e_column) {
1518 472846 : if (rel) {
1519 472846 : if (!rel_bind_path_(sql, rel, e, path)) {
1520 : /* something is wrong */
1521 : return NULL;
1522 : }
1523 : }
1524 472846 : return path;
1525 : }
1526 : /* default the top relation */
1527 26735 : append(path, rel);
1528 26735 : return path;
1529 : }
1530 :
1531 : static sql_rel *
1532 20762 : rel_select_push_exp_down(mvc *sql, sql_rel *rel, sql_exp *e)
1533 : {
1534 20762 : sql_rel *r = rel->l, *jl = r->l, *jr = r->r;
1535 20762 : int left = r->op == op_join || r->op == op_left;
1536 20762 : int right = r->op == op_join || r->op == op_right;
1537 20762 : int done = 0;
1538 :
1539 20762 : assert(is_select(rel->op));
1540 20762 : if (!is_full(r->op) && !is_single(r)) {
1541 20762 : if (left && rel_rebind_exp(sql, jl, e)) {
1542 9 : done = 1;
1543 9 : r->l = jl = rel_select_add_exp(sql->sa, jl, e);
1544 20753 : } else if (right && rel_rebind_exp(sql, jr, e)) {
1545 6 : done = 1;
1546 6 : r->r = jr = rel_select_add_exp(sql->sa, jr, e);
1547 : }
1548 : }
1549 15 : if (!done)
1550 20747 : rel_select_add_exp(sql->sa, rel, e);
1551 20762 : return rel;
1552 : }
1553 :
1554 : /* ls is the left expression of the select, e is the select expression. */
1555 : sql_rel *
1556 111618 : rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
1557 : {
1558 111618 : list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
1559 111618 : node *n;
1560 111618 : sql_rel *lrel = NULL, *p = NULL;
1561 :
1562 111618 : if (!l)
1563 : return NULL;
1564 111618 : if (is_sql_or(f)) /* expression has no clear parent relation, so filter current with it */
1565 21934 : return rel_select(sql->sa, rel, e);
1566 :
1567 255856 : for (n = l->h; n; n = n->next ) {
1568 255130 : lrel = n->data;
1569 :
1570 255130 : if (rel_is_ref(lrel))
1571 : break;
1572 :
1573 : /* push down as long as the operators allow this */
1574 254819 : if (!is_select(lrel->op) &&
1575 234412 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1576 88647 : lrel->op != op_join &&
1577 : lrel->op != op_left)
1578 : break;
1579 : /* pushing through left head of a left join is allowed */
1580 166176 : if (lrel->op == op_left && (!n->next || lrel->l != n->next->data))
1581 : break;
1582 166172 : p = lrel;
1583 : }
1584 89684 : if (!lrel)
1585 : return NULL;
1586 89684 : if (p && is_select(p->op) && !rel_is_ref(p)) { /* refine old select */
1587 17950 : p = rel_select_push_exp_down(sql, p, e);
1588 : } else {
1589 71734 : sql_rel *n = rel_select(sql->sa, lrel, e);
1590 :
1591 71734 : if (p && p != lrel) {
1592 66044 : assert(p->op == op_join || p->op == op_left || is_semi(p->op));
1593 66044 : if (p->l == lrel) {
1594 24179 : p->l = n;
1595 : } else {
1596 41865 : p->r = n;
1597 : }
1598 : } else {
1599 5690 : if (rel != lrel)
1600 0 : assert(0);
1601 : rel = n;
1602 : }
1603 : }
1604 : return rel;
1605 : }
1606 :
1607 : /* ls and rs are the left and right expression of the join, e is the
1608 : join expression.
1609 : */
1610 : sql_rel *
1611 183169 : rel_push_join(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, sql_exp *e, int f)
1612 : {
1613 183169 : list *l = NULL, *r = NULL, *r2 = NULL;
1614 183169 : node *ln, *rn;
1615 183169 : sql_rel *lrel = NULL, *rrel = NULL, *rrel2 = NULL, *p = NULL;
1616 :
1617 183169 : if (!(l = rel_bind_path(sql, rel, ls, sa_list(sql->sa))) ||
1618 183169 : !(r = rel_bind_path(sql, rel, rs, sa_list(sql->sa))) ||
1619 534 : (rs2 && !(r2 = rel_bind_path(sql, rel, rs2, sa_list(sql->sa)))))
1620 0 : return NULL;
1621 :
1622 183169 : if (is_sql_or(f))
1623 2960 : return rel_push_select(sql, rel, ls, e, f);
1624 :
1625 180209 : p = rel;
1626 180209 : if (r2) {
1627 526 : node *rn2;
1628 :
1629 1059 : for (ln = l->h, rn = r->h, rn2 = r2->h; ln && rn && rn2; ln = ln->next, rn = rn->next, rn2 = rn2->next ) {
1630 557 : lrel = ln->data;
1631 557 : rrel = rn->data;
1632 557 : rrel2 = rn2->data;
1633 :
1634 557 : if (rel_is_ref(lrel) || rel_is_ref(rrel) || rel_is_ref(rrel2) || is_processed(lrel) || is_processed(rrel))
1635 : break;
1636 :
1637 : /* push down as long as the operators allow this
1638 : and the relation is equal.
1639 : */
1640 551 : if (lrel != rrel || lrel != rrel2 ||
1641 533 : (!is_select(lrel->op) &&
1642 75 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1643 0 : lrel->op != op_join &&
1644 : lrel->op != op_left))
1645 : break;
1646 : /* pushing through left head of a left join is allowed */
1647 533 : if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
1648 : break;
1649 533 : p = lrel;
1650 : }
1651 : } else {
1652 802804 : for (ln = l->h, rn = r->h; ln && rn; ln = ln->next, rn = rn->next ) {
1653 800020 : lrel = ln->data;
1654 800020 : rrel = rn->data;
1655 :
1656 800020 : if (rel_is_ref(lrel) || rel_is_ref(rrel) || is_processed(lrel) || is_processed(rrel))
1657 : break;
1658 :
1659 : /* push down as long as the operators allow this
1660 : and the relation is equal.
1661 : */
1662 759291 : if (lrel != rrel ||
1663 624779 : (!is_select(lrel->op) &&
1664 621324 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1665 1658 : lrel->op != op_join &&
1666 : lrel->op != op_left))
1667 : break;
1668 : /* pushing through left head of a left join is allowed */
1669 623121 : if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
1670 : break;
1671 623121 : p = lrel;
1672 : }
1673 : }
1674 180209 : if (!lrel || !rrel || (r2 && !rrel2))
1675 : return NULL;
1676 :
1677 : /* filter on columns of this relation */
1678 180209 : if ((lrel == rrel && (!r2 || lrel == rrel2) && lrel->op != op_join) || rel_is_ref(p)) {
1679 2829 : if (is_select(lrel->op) && !rel_is_ref(lrel)) {
1680 1152 : lrel = rel_select_push_exp_down(sql, lrel, e);
1681 1677 : } else if (p && is_select(p->op) && !rel_is_ref(p)) {
1682 1660 : p = rel_select_push_exp_down(sql, p, e);
1683 : } else {
1684 17 : sql_rel *n = rel_select(sql->sa, lrel, e);
1685 :
1686 17 : if (p && p != lrel) {
1687 15 : if (p->l == lrel)
1688 5 : p->l = n;
1689 : else
1690 10 : p->r = n;
1691 : } else {
1692 : rel = n;
1693 : }
1694 : }
1695 2829 : return rel;
1696 : }
1697 :
1698 177380 : rel_join_add_exp( sql->sa, p, e);
1699 177380 : return rel;
1700 : }
1701 :
1702 : sql_rel *
1703 18965 : rel_or(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, list *oexps, list *lexps, list *rexps)
1704 : {
1705 18965 : sql_rel *ll = l->l, *rl = r->l;
1706 18965 : list *ls, *rs;
1707 :
1708 18965 : assert(!lexps || l == r);
1709 18965 : if (l == r && lexps) { /* merge both lists */
1710 42 : sql_exp *e = exp_or(sql->sa, lexps, rexps, 0);
1711 42 : list *nl = oexps?oexps:new_exp_list(sql->sa);
1712 :
1713 42 : rel_destroy(r);
1714 42 : append(nl, e);
1715 42 : if (is_outerjoin(l->op) && is_processed(l))
1716 0 : l = rel_select(sql->sa, l, NULL);
1717 42 : l->exps = nl;
1718 42 : return l;
1719 : }
1720 :
1721 : /* favor or expressions over union */
1722 18923 : if (l->op == r->op && is_select(l->op) &&
1723 18923 : ll == rl && ll == rel && !rel_is_ref(l) && !rel_is_ref(r)) {
1724 18923 : sql_exp *e = exp_or(sql->sa, l->exps, r->exps, 0);
1725 18923 : list *nl = new_exp_list(sql->sa);
1726 :
1727 18923 : rel_destroy(r);
1728 18923 : append(nl, e);
1729 18923 : l->exps = nl;
1730 :
1731 : /* merge and expressions */
1732 18923 : ll = l->l;
1733 21280 : while (ll && is_select(ll->op) && !rel_is_ref(ll)) {
1734 2357 : list_merge(l->exps, ll->exps, (fdup)NULL);
1735 2357 : l->l = ll->l;
1736 2357 : ll->l = NULL;
1737 2357 : rel_destroy(ll);
1738 2357 : ll = l->l;
1739 : }
1740 : return l;
1741 : }
1742 :
1743 0 : if (rel) {
1744 0 : ls = rel_projections(sql, rel, NULL, 1, 1);
1745 0 : rs = rel_projections(sql, rel, NULL, 1, 1);
1746 : } else {
1747 0 : ls = rel_projections(sql, l, NULL, 1, 1);
1748 0 : rs = rel_projections(sql, r, NULL, 1, 1);
1749 : }
1750 0 : set_processed(l);
1751 0 : set_processed(r);
1752 0 : rel = rel_setop_check_types(sql, l, r, ls, rs, op_union);
1753 0 : if (!rel)
1754 : return NULL;
1755 0 : rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 1, 1), false);
1756 0 : set_processed(rel);
1757 0 : rel->nrcols = list_length(rel->exps);
1758 0 : rel = rel_distinct(rel);
1759 0 : if (!rel)
1760 : return NULL;
1761 0 : if (exps_card(l->exps) <= CARD_AGGR &&
1762 0 : exps_card(r->exps) <= CARD_AGGR)
1763 : {
1764 0 : rel->card = exps_card(l->exps);
1765 0 : exps_fix_card( rel->exps, rel->card);
1766 : }
1767 : return rel;
1768 : }
1769 :
1770 : sql_table *
1771 4144 : rel_ddl_table_get(sql_rel *r)
1772 : {
1773 4144 : if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
1774 4144 : sql_exp *e = r->exps->t->data;
1775 4144 : atom *a = e->l;
1776 :
1777 4144 : return a->data.val.pval;
1778 : }
1779 : return NULL;
1780 : }
1781 :
1782 : sql_rel *
1783 3233 : rel_ddl_basetable_get(sql_rel *r)
1784 : {
1785 3233 : if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
1786 3233 : return r->l;
1787 : }
1788 : return NULL;
1789 : }
1790 :
1791 : static sql_exp *
1792 76 : exps_find_identity(list *exps, sql_rel *p)
1793 : {
1794 76 : node *n;
1795 :
1796 205 : for (n=exps->h; n; n = n->next) {
1797 129 : sql_exp *e = n->data;
1798 :
1799 129 : if (is_identity(e, p))
1800 0 : return e;
1801 : }
1802 : return NULL;
1803 : }
1804 :
1805 : static sql_rel *
1806 124 : _rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
1807 : {
1808 124 : list *exps = rel_projections(sql, rel, NULL, 1, 1);
1809 124 : sql_exp *e = NULL;
1810 :
1811 124 : if (list_empty(exps)) {
1812 0 : *exp = NULL;
1813 0 : return rel;
1814 : }
1815 124 : if (!is_simple_project(rel->op) || need_distinct(rel) || !list_empty(rel->r) || rel_is_ref(rel))
1816 50 : rel = rel_project(sql->sa, rel, exps);
1817 : /* filter parameters out */
1818 248 : for (node *n = rel->exps->h ; n && !e ; n = n->next) {
1819 124 : sql_exp *re = n->data;
1820 :
1821 124 : if (exp_subtype(re))
1822 124 : e = re;
1823 : }
1824 124 : if (!e)
1825 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query projection must have at least one parameter with known SQL type");
1826 :
1827 124 : sql_exp *ne = exp_column(sql->sa, exp_relname(e), exp_name(e), exp_subtype(e), rel->card, has_nil(e), is_unique(e), is_intern(e));
1828 124 : ne->nid = e->alias.label;
1829 124 : assert(ne->nid);
1830 124 : e = ne;
1831 124 : e = exp_unop(sql->sa, e, sql_bind_func(sql, "sys", "identity", exp_subtype(e), NULL, F_FUNC, true, true));
1832 124 : set_intern(e);
1833 124 : set_has_no_nil(e);
1834 124 : set_unique(e);
1835 124 : e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
1836 124 : *exp = exp_label(sql->sa, e, ++sql->label);
1837 124 : (void) rel_project_add_exp(sql, rel, e);
1838 124 : return rel;
1839 : }
1840 :
1841 : sql_rel *
1842 149 : rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
1843 : {
1844 149 : if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
1845 25 : *exp = basetable_get_tid_or_add_it(sql, rel);
1846 25 : return rel;
1847 : }
1848 124 : if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
1849 : return rel;
1850 124 : return _rel_add_identity(sql, rel, exp);
1851 : }
1852 :
1853 : sql_rel *
1854 0 : rel_add_identity2(mvc *sql, sql_rel *rel, sql_exp **exp)
1855 : {
1856 0 : sql_rel *l = rel, *p = rel;
1857 :
1858 0 : if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
1859 0 : *exp = basetable_get_tid_or_add_it(sql, rel);
1860 0 : return rel;
1861 : }
1862 0 : if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
1863 : return rel;
1864 0 : while(l && !is_set(l->op) && rel_has_freevar(sql, l) && l->l) {
1865 : p = l;
1866 : l = l->l;
1867 : }
1868 0 : if (l != p) {
1869 0 : sql_rel *o = rel;
1870 0 : sql_exp *id;
1871 :
1872 0 : if (!(p->l = _rel_add_identity(sql, l, exp)))
1873 : return NULL;
1874 0 : l = p->l;
1875 0 : id = exp_ref(sql, *exp);
1876 0 : while (o && o != l) {
1877 0 : *exp = id;
1878 0 : if (is_project(o->op))
1879 0 : rel_project_add_exp(sql, o, id);
1880 0 : o = o->l;
1881 : }
1882 : return rel;
1883 : }
1884 0 : return _rel_add_identity(sql, rel, exp);
1885 : }
1886 :
1887 : static sql_exp *
1888 1502 : rel_find_column_(mvc *sql, list *exps, const char *tname, const char *cname)
1889 : {
1890 1502 : int ambiguous = 0, multi = 0;
1891 1502 : sql_exp *e = exps_bind_column2(exps, tname, cname, &multi);
1892 1502 : if (!e && cname[0] == '%' && !tname)
1893 0 : e = exps_bind_column(exps, cname, &ambiguous, &multi, 0);
1894 1502 : if (e && !ambiguous && !multi) {
1895 1501 : return exp_ref(sql, e);
1896 : }
1897 : return NULL;
1898 : }
1899 :
1900 : sql_exp *
1901 1502 : rel_find_column(mvc *sql, sql_rel *rel, const char *tname, const char *cname )
1902 : {
1903 1798 : sql_exp *e = NULL;
1904 :
1905 1798 : if (!rel)
1906 : return NULL;
1907 1798 : if (rel->exps && (is_project(rel->op) || is_base(rel->op)) && (e = rel_find_column_(sql, rel->exps, tname, cname)))
1908 : return e;
1909 297 : if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
1910 1 : if (!is_processed(rel))
1911 : return rel_find_column(sql, rel->l, tname, cname);
1912 296 : } else if (is_set(rel->op)) {
1913 0 : assert(is_processed(rel));
1914 : return NULL;
1915 : } else if (is_join(rel->op)) {
1916 0 : e = rel_find_column(sql, rel->l, tname, cname);
1917 :
1918 0 : if (e && (is_right(rel->op) || is_full(rel->op)))
1919 0 : set_has_nil(e);
1920 0 : if (!e) {
1921 0 : e = rel_find_column(sql, rel->r, tname, cname);
1922 0 : if (e && (is_left(rel->op) || is_full(rel->op)))
1923 0 : set_has_nil(e);
1924 : }
1925 0 : if (!e && !list_empty(rel->attr))
1926 0 : e = rel_find_column_(sql, rel->attr, tname, cname);
1927 0 : if (e)
1928 0 : set_not_unique(e);
1929 0 : return e;
1930 : } else if (is_semi(rel->op) ||
1931 : is_select(rel->op) ||
1932 : is_topn(rel->op) ||
1933 : is_sample(rel->op)) {
1934 296 : if (rel->l)
1935 : return rel_find_column(sql, rel->l, tname, cname);
1936 : }
1937 : return NULL;
1938 : }
1939 :
1940 : int
1941 0 : rel_in_rel(sql_rel *super, sql_rel *sub)
1942 : {
1943 0 : if (!super)
1944 : return 0;
1945 0 : if (super == sub)
1946 : return 1;
1947 0 : if (is_join(super->op) || is_semi(super->op) || is_set(super->op) || is_modify(super->op) || is_ddl(super->op))
1948 0 : return rel_in_rel(super->l, sub) || rel_in_rel(super->r, sub);
1949 : if (is_select(super->op) || is_simple_project(super->op) || is_groupby(super->op) || is_topn(super->op) || is_sample(super->op))
1950 0 : return rel_in_rel(super->l, sub);
1951 : return 0;
1952 : }
1953 :
1954 : sql_rel*
1955 14 : rel_parent(sql_rel *rel)
1956 : {
1957 14 : if (rel->l && (is_project(rel->op) || is_topn(rel->op) || is_sample(rel->op))) {
1958 14 : sql_rel *l = rel->l;
1959 14 : if (is_project(l->op))
1960 14 : return l;
1961 : }
1962 : return rel;
1963 : }
1964 :
1965 : sql_exp *
1966 26859 : lastexp(sql_rel *rel)
1967 : {
1968 26859 : if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
1969 14 : rel = rel_parent(rel);
1970 26859 : assert(list_length(rel->exps));
1971 26859 : assert(is_project(rel->op) || rel->op == op_table);
1972 26859 : return rel->exps->t->data;
1973 : }
1974 :
1975 : sql_rel *
1976 5776 : rel_return_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
1977 : {
1978 5776 : if (ek.card < card_set && rel->card > CARD_ATOM) {
1979 4409 : list *exps = rel->exps;
1980 :
1981 4409 : assert (is_simple_project(rel->op) || is_mset(rel->op));
1982 4409 : rel = rel_groupby(sql, rel, NULL);
1983 8828 : for(node *n = exps->h; n; n=n->next) {
1984 4419 : sql_exp *e = n->data;
1985 4419 : if (!has_label(e))
1986 75 : exp_label(sql->sa, e, ++sql->label);
1987 4419 : sql_subtype *t = exp_subtype(e); /* parameters don't have a type defined, for those use 'void' one */
1988 4419 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", t ? t : sql_bind_localtype("void"), NULL, F_AGGR, true, true);
1989 :
1990 4419 : e = exp_ref(sql, e);
1991 4419 : e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
1992 4419 : (void)rel_groupby_add_aggr(sql, rel, e);
1993 : }
1994 4409 : set_processed(rel);
1995 : }
1996 5776 : return rel;
1997 : }
1998 :
1999 : sql_rel *
2000 35991 : rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
2001 : {
2002 35991 : if (is_topn(rel->op) || is_sample(rel->op))
2003 17 : rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 1, 0));
2004 35991 : if (ek.card < card_set && rel->card > CARD_ATOM) {
2005 9345 : assert (is_simple_project(rel->op) || is_mset(rel->op));
2006 :
2007 9345 : list *exps = rel->exps;
2008 18718 : for(node *n = exps->h; n; n=n->next) {
2009 9373 : sql_exp *e = n->data;
2010 9373 : if (e->alias.label == 0)
2011 12 : exp_label(sql->sa, e, ++sql->label);
2012 : }
2013 9345 : set_single(rel);
2014 : } else {
2015 26646 : sql_exp *e = lastexp(rel);
2016 26646 : if (!has_label(e))
2017 22 : exp_label(sql->sa, e, ++sql->label);
2018 : }
2019 35991 : return rel;
2020 : }
2021 :
2022 : static sql_rel *
2023 10790 : refs_find_rel(list *refs, sql_rel *rel)
2024 : {
2025 10790 : node *n;
2026 :
2027 22776 : for(n=refs->h; n; n = n->next->next) {
2028 17488 : sql_rel *ref = n->data;
2029 17488 : sql_rel *s = n->next->data;
2030 :
2031 17488 : if (rel == ref)
2032 : return s;
2033 : }
2034 : return NULL;
2035 : }
2036 :
2037 : static int exp_deps(mvc *sql, sql_exp *e, list *refs, list *l);
2038 :
2039 : static int
2040 668239 : exps_deps(mvc *sql, list *exps, list *refs, list *l)
2041 : {
2042 :
2043 2804980 : for(node *n = exps->h; n; n = n->next)
2044 2136741 : if (exp_deps(sql, n->data, refs, l) != 0)
2045 : return -1;
2046 : return 0;
2047 : }
2048 :
2049 : static int
2050 6710038 : id_cmp(sql_base *id1, sql_base *id2)
2051 : {
2052 6710038 : if (id1->id == id2->id)
2053 86233 : return 0;
2054 : return -1;
2055 : }
2056 :
2057 : static list *
2058 709498 : cond_append(list *l, sql_base *b)
2059 : {
2060 709498 : if (b->id >= FUNC_OIDS && !list_find(l, b, (fcmp) &id_cmp))
2061 356662 : list_append(l, b);
2062 709498 : return l;
2063 : }
2064 :
2065 : static int rel_deps(mvc *sql, sql_rel *r, list *refs, list *l);
2066 :
2067 : static int
2068 2323881 : exp_deps(mvc *sql, sql_exp *e, list *refs, list *l)
2069 : {
2070 2428263 : if (mvc_highwater(sql)) {
2071 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2072 0 : return -1;
2073 : }
2074 :
2075 2428263 : switch(e->type) {
2076 43987 : case e_psm:
2077 43987 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
2078 18967 : return exp_deps(sql, e->l, refs, l);
2079 25020 : } else if (e->flag & PSM_VAR) {
2080 : return 0;
2081 20338 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
2082 6204 : if (exp_deps(sql, e->l, refs, l) != 0 || exps_deps(sql, e->r, refs, l) != 0)
2083 0 : return -1;
2084 6204 : if (e->flag & PSM_IF && e->f)
2085 746 : return exps_deps(sql, e->f, refs, l);
2086 14134 : } else if (e->flag & PSM_REL) {
2087 14134 : sql_rel *rel = e->l;
2088 14134 : return rel_deps(sql, rel, refs, l);
2089 : }
2090 : break;
2091 838384 : case e_atom:
2092 838384 : if (e->f && exps_deps(sql, e->f, refs, l) != 0)
2093 : return -1;
2094 : break;
2095 : case e_column:
2096 : break;
2097 85384 : case e_convert:
2098 85384 : return exp_deps(sql, e->l, refs, l);
2099 275193 : case e_func: {
2100 275193 : sql_subfunc *f = e->f;
2101 :
2102 275193 : if (e->l && exps_deps(sql, e->l, refs, l) != 0)
2103 : return -1;
2104 275193 : cond_append(l, &f->func->base);
2105 275193 : if (e->l && list_length(e->l) == 2 && strcmp(f->func->base.name, "next_value_for") == 0) {
2106 : /* add dependency on seq nr */
2107 84 : list *nl = e->l;
2108 84 : sql_exp *schname = nl->h->data, *seqname = nl->t->data;
2109 84 : char *sch_name = is_atom(schname->type) && schname->l ? ((atom*)schname->l)->data.val.sval : NULL;
2110 84 : char *seq_name = is_atom(seqname->type) && seqname->l ? ((atom*)seqname->l)->data.val.sval : NULL;
2111 :
2112 84 : if (sch_name && seq_name) {
2113 84 : sql_schema *sche = mvc_bind_schema(sql, sch_name);
2114 84 : if (sche) {
2115 84 : sql_sequence *seq = find_sql_sequence(sql->session->tr, sche, seq_name);
2116 84 : if (seq)
2117 84 : cond_append(l, &seq->base);
2118 : }
2119 : }
2120 : }
2121 : } break;
2122 19699 : case e_aggr: {
2123 19699 : sql_subfunc *a = e->f;
2124 :
2125 19699 : if (e->l && exps_deps(sql, e->l, refs, l) != 0)
2126 : return -1;
2127 19699 : cond_append(l, &a->func->base);
2128 19699 : } break;
2129 93442 : case e_cmp: {
2130 93442 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2131 716 : if (e->flag == cmp_filter) {
2132 481 : sql_subfunc *f = e->f;
2133 481 : cond_append(l, &f->func->base);
2134 : }
2135 1432 : if (exps_deps(sql, e->l, refs, l) != 0 ||
2136 716 : exps_deps(sql, e->r, refs, l) != 0)
2137 0 : return -1;
2138 92726 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2139 9032 : if (exp_deps(sql, e->l, refs, l) != 0 ||
2140 4516 : exps_deps(sql, e->r, refs, l) != 0)
2141 0 : return -1;
2142 : } else {
2143 176420 : if (exp_deps(sql, e->l, refs, l) != 0 ||
2144 88210 : exp_deps(sql, e->r, refs, l) != 0)
2145 0 : return -1;
2146 88210 : if (e->f)
2147 : return exp_deps(sql, e->f, refs, l);
2148 : }
2149 : } break;
2150 : }
2151 : return 0;
2152 : }
2153 :
2154 : static int
2155 477637 : rel_deps(mvc *sql, sql_rel *r, list *refs, list *l)
2156 : {
2157 477637 : if (mvc_highwater(sql)) {
2158 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2159 0 : return -1;
2160 : }
2161 :
2162 477637 : if (!r)
2163 : return 0;
2164 :
2165 479826 : if (rel_is_ref(r) && refs_find_rel(refs, r)) /* already handled */
2166 : return 0;
2167 463534 : switch (r->op) {
2168 99028 : case op_basetable: {
2169 99028 : sql_table *t = r->l;
2170 :
2171 99028 : cond_append(l, &t->base);
2172 : /* find all used columns */
2173 428137 : for (node *en = r->exps->h; en; en = en->next) {
2174 329109 : sql_exp *exp = en->data;
2175 329109 : const char *oname = exp->r;
2176 :
2177 329109 : assert(!is_func(exp->type));
2178 329109 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
2179 18201 : continue;
2180 310908 : } else if (oname[0] == '%') {
2181 85 : sql_idx *i = find_sql_idx(t, oname+1);
2182 85 : if (i) {
2183 84 : cond_append(l, &i->base);
2184 84 : continue;
2185 : }
2186 : }
2187 310824 : sql_column *c = find_sql_column(t, oname);
2188 310824 : if (!c)
2189 : return -1;
2190 310824 : cond_append(l, &c->base);
2191 : }
2192 : } break;
2193 4105 : case op_table: {
2194 4105 : if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */
2195 4105 : sql_exp *op = r->r;
2196 4105 : sql_subfunc *f = op->f;
2197 4105 : cond_append(l, &f->func->base);
2198 : }
2199 : } break;
2200 68764 : case op_join:
2201 : case op_left:
2202 : case op_right:
2203 : case op_full:
2204 : case op_semi:
2205 : case op_anti:
2206 : case op_union:
2207 : case op_except:
2208 : case op_inter:
2209 :
2210 : case op_insert:
2211 : case op_update:
2212 : case op_delete:
2213 : case op_merge:
2214 137528 : if (rel_deps(sql, r->l, refs, l) != 0 ||
2215 68764 : rel_deps(sql, r->r, refs, l) != 0)
2216 0 : return -1;
2217 : break;
2218 4648 : case op_munion:
2219 19609 : for (node *n = ((list*)r->l)->h; n; n = n->next) {
2220 14961 : if (rel_deps(sql, n->data, refs, l) != 0)
2221 : return -1;
2222 : }
2223 : break;
2224 166566 : case op_project:
2225 : case op_select:
2226 : case op_groupby:
2227 : case op_topn:
2228 : case op_sample:
2229 : case op_truncate:
2230 166566 : if (rel_deps(sql, r->l, refs, l) != 0)
2231 : return -1;
2232 : break;
2233 120423 : case op_ddl:
2234 120423 : if (r->flag == ddl_output || r->flag == ddl_create_seq || r->flag == ddl_alter_seq || r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
2235 21 : if (rel_deps(sql, r->l, refs, l) != 0)
2236 : return -1;
2237 : } else if (r->flag == ddl_list || r->flag == ddl_exception) {
2238 0 : if (rel_deps(sql, r->l, refs, l) != 0 ||
2239 0 : rel_deps(sql, r->r, refs, l) != 0)
2240 0 : return -1;
2241 : }
2242 : break;
2243 : }
2244 463534 : if (!is_base(r->op) && r->exps) {
2245 348739 : if (exps_deps(sql, r->exps, refs, l) != 0)
2246 : return -1;
2247 : }
2248 463534 : if ((is_simple_project(r->op) || is_groupby(r->op)) && r->r) {
2249 18522 : if (exps_deps(sql, r->r, refs, l) != 0)
2250 : return -1;
2251 : }
2252 463534 : if (rel_is_ref(r)) {
2253 5288 : list_append(refs, r);
2254 5288 : list_append(refs, l);
2255 : }
2256 : return 0;
2257 : }
2258 :
2259 : list *
2260 144427 : rel_dependencies(mvc *sql, sql_rel *r)
2261 : {
2262 144427 : list *refs = sa_list(sql->sa);
2263 144427 : list *l = sa_list(sql->sa);
2264 :
2265 144427 : if (rel_deps(sql, r, refs, l) != 0)
2266 0 : return NULL;
2267 : return l;
2268 : }
2269 :
2270 : static list *exps_exp_visitor(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool visit_relations_once);
2271 :
2272 : static inline list *
2273 40141 : exps_exps_exp_visitor(visitor *v, sql_rel *rel, list *lists, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool visit_relations_once)
2274 : {
2275 40141 : node *n;
2276 :
2277 40141 : if (list_empty(lists))
2278 : return lists;
2279 88068 : for (n = lists->h; n; n = n->next) {
2280 47927 : if (n->data && (n->data = exps_exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2281 : return NULL;
2282 : }
2283 : return lists;
2284 : }
2285 :
2286 : static sql_rel *rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown);
2287 :
2288 : sql_exp *
2289 82042269 : exp_visitor(visitor *v, sql_rel *rel, sql_exp *e, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool visit_relations_once, bool *changed)
2290 : {
2291 82042269 : if (mvc_highwater(v->sql))
2292 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2293 :
2294 82104563 : assert(e);
2295 82104563 : if (topdown) {
2296 6768864 : int changes = v->changes;
2297 6768864 : if (!(e = exp_rewriter(v, rel, e, depth)))
2298 : return NULL;
2299 6769526 : *changed |= v->changes > changes;
2300 : }
2301 :
2302 82105225 : switch(e->type) {
2303 : case e_column:
2304 : break;
2305 1083664 : case e_convert:
2306 1083664 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2307 : return NULL;
2308 : break;
2309 4050115 : case e_aggr:
2310 : case e_func:
2311 4050115 : if (e->r) /* rewrite rank -r is list of lists */
2312 40141 : if ((e->r = exps_exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2313 : return NULL;
2314 4050115 : if (e->l)
2315 3878607 : if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2316 : return NULL;
2317 : break;
2318 3470693 : case e_cmp:
2319 3470693 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2320 192327 : if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2321 : return NULL;
2322 192327 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2323 : return NULL;
2324 3278366 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2325 224353 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2326 : return NULL;
2327 224353 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2328 : return NULL;
2329 : } else {
2330 3054013 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2331 : return NULL;
2332 3054013 : if ((e->r = exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2333 : return NULL;
2334 3054013 : if (e->f && (e->f = exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2335 : return NULL;
2336 : }
2337 : break;
2338 374604 : case e_psm:
2339 374604 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
2340 121640 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2341 : return NULL;
2342 252964 : } else if (e->flag & PSM_VAR) {
2343 : return e;
2344 223640 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
2345 39023 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once, changed)) == NULL)
2346 : return NULL;
2347 39023 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2348 : return NULL;
2349 39023 : if (e->flag == PSM_IF && e->f && (e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2350 : return NULL;
2351 184617 : } else if (e->flag & PSM_REL) {
2352 184617 : if (!visit_relations_once && (e->l = rel_exp_visitor(v, e->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2353 : return NULL;
2354 : }
2355 : break;
2356 27144799 : case e_atom:
2357 27144799 : if (e->f)
2358 908398 : if ((e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown, visit_relations_once)) == NULL)
2359 : return NULL;
2360 : break;
2361 : }
2362 82076184 : if (!topdown) {
2363 75290420 : int changes = v->changes;
2364 75290420 : if (!(e = exp_rewriter(v, rel, e, depth)))
2365 : return NULL;
2366 75308334 : *changed |= v->changes > changes;
2367 : }
2368 : return e;
2369 : }
2370 :
2371 : static list *
2372 21127598 : exps_exp_visitor(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool visit_relations_once)
2373 : {
2374 21127598 : bool changed = false;
2375 21127598 : if (list_empty(exps))
2376 : return exps;
2377 95547849 : for (node *n = exps->h; n; n = n->next)
2378 74450010 : if (n->data && (n->data = exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown, visit_relations_once, &changed)) == NULL)
2379 : return NULL;
2380 21097839 : if (changed && depth == 0) /* only level 0 exps use hash, so remove only on those */
2381 20327 : list_hash_clear(exps);
2382 : return exps;
2383 : }
2384 :
2385 : static inline sql_rel *
2386 16102491 : rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
2387 : {
2388 16102491 : if (mvc_highwater(v->sql))
2389 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2390 :
2391 16105832 : if (!rel)
2392 : return rel;
2393 :
2394 16105811 : if (relations_topdown) {
2395 5894723 : if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
2396 : return NULL;
2397 5895263 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
2398 : return NULL;
2399 : }
2400 :
2401 16106353 : switch(rel->op){
2402 : case op_basetable:
2403 : break;
2404 47207 : case op_table:
2405 47207 : if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
2406 47139 : bool changed = false;
2407 47139 : if (rel->l)
2408 962 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2409 0 : return NULL;
2410 47139 : if (rel->r)
2411 46831 : if ((rel->r = exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown, false, &changed)) == NULL)
2412 : return NULL;
2413 : }
2414 : break;
2415 2431716 : case op_ddl:
2416 2431716 : if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
2417 227474 : if (rel->l)
2418 225305 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2419 : return NULL;
2420 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
2421 2648 : if (rel->l)
2422 2334 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2423 : return NULL;
2424 2648 : if (rel->r)
2425 2381 : if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
2426 : return NULL;
2427 : }
2428 : break;
2429 2137514 : case op_insert:
2430 : case op_update:
2431 : case op_delete:
2432 : case op_merge:
2433 :
2434 : case op_join:
2435 : case op_left:
2436 : case op_right:
2437 : case op_full:
2438 : case op_semi:
2439 : case op_anti:
2440 :
2441 : case op_union:
2442 : case op_inter:
2443 : case op_except:
2444 2137514 : if (rel->l)
2445 2137525 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2446 : return NULL;
2447 2138061 : if (rel->r)
2448 2136186 : if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
2449 : return NULL;
2450 : break;
2451 493654 : case op_munion:
2452 1536044 : for (node *n = ((list*)rel->l)->h; n; n = n->next) {
2453 1042390 : if ((n->data = rel_exp_visitor(v, n->data, exp_rewriter, topdown, relations_topdown)) == NULL)
2454 : return NULL;
2455 : }
2456 : break;
2457 7171691 : case op_select:
2458 : case op_topn:
2459 : case op_sample:
2460 : case op_project:
2461 : case op_groupby:
2462 : case op_truncate:
2463 7171691 : if (rel->l)
2464 6122016 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2465 : return NULL;
2466 : break;
2467 : }
2468 :
2469 16107181 : if (!relations_topdown) {
2470 10211879 : if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
2471 : return NULL;
2472 10212429 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
2473 : return NULL;
2474 : }
2475 :
2476 : return rel;
2477 : }
2478 :
2479 : sql_rel *
2480 559993 : rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2481 : {
2482 559993 : return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
2483 : }
2484 :
2485 : sql_rel *
2486 3711806 : rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2487 : {
2488 3711806 : return rel_exp_visitor(v, rel, exp_rewriter, false, relations_topdown);
2489 : }
2490 :
2491 : static list *exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown);
2492 : static list *exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown);
2493 :
2494 : static sql_exp *
2495 342649070 : exp_rel_visitor(visitor *v, sql_exp *e, rel_rewrite_fptr rel_rewriter, bool topdown)
2496 : {
2497 342649070 : if (mvc_highwater(v->sql))
2498 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2499 :
2500 342738860 : assert(e);
2501 342738860 : switch(e->type) {
2502 : case e_column:
2503 : break;
2504 6054254 : case e_convert:
2505 6054254 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2506 : return NULL;
2507 : break;
2508 17904674 : case e_aggr:
2509 : case e_func:
2510 17904674 : if (e->r) /* rewrite rank */
2511 62863 : if ((e->r = exps_exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2512 : return NULL;
2513 17904674 : if (e->l)
2514 17346825 : if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2515 : return NULL;
2516 : break;
2517 20231885 : case e_cmp:
2518 20231885 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2519 817678 : if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2520 : return NULL;
2521 817678 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2522 : return NULL;
2523 19414207 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2524 1310213 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2525 : return NULL;
2526 1310213 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2527 : return NULL;
2528 : } else {
2529 18103994 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2530 : return NULL;
2531 18103991 : if ((e->r = exp_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2532 : return NULL;
2533 18103991 : if (e->f && (e->f = exp_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2534 : return NULL;
2535 : }
2536 : break;
2537 654360 : case e_psm:
2538 654360 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
2539 246869 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2540 : return NULL;
2541 407491 : } else if (e->flag & PSM_VAR) {
2542 : return e;
2543 348843 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
2544 78046 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2545 : return NULL;
2546 78046 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2547 : return NULL;
2548 78046 : if (e->flag == PSM_IF && e->f && (e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2549 : return NULL;
2550 270797 : } else if (e->flag & PSM_REL) {
2551 270797 : sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
2552 270797 : if ((e->l = func(v, e->l, rel_rewriter)) == NULL)
2553 : return NULL;
2554 : }
2555 : break;
2556 68281803 : case e_atom:
2557 68281803 : if (e->f)
2558 1460273 : if ((e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2559 : return NULL;
2560 : break;
2561 : }
2562 : return e;
2563 : }
2564 :
2565 : static list *
2566 90486163 : exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown)
2567 : {
2568 90486163 : if (list_empty(exps))
2569 : return exps;
2570 388957986 : for (node *n = exps->h; n; n = n->next)
2571 298718995 : if (n->data && (n->data = exp_rel_visitor(v, n->data, rel_rewriter, topdown)) == NULL)
2572 : return NULL;
2573 : return exps;
2574 : }
2575 :
2576 : static list *
2577 62863 : exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown)
2578 : {
2579 62863 : if (list_empty(lists))
2580 : return lists;
2581 125726 : for (node *n = lists->h; n; n = n->next)
2582 62863 : if (n->data && (n->data = exps_rel_visitor(v, n->data, rel_rewriter, topdown)) == NULL)
2583 : return NULL;
2584 : return lists;
2585 : }
2586 :
2587 : static inline sql_rel *
2588 69350410 : do_rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
2589 : {
2590 69350410 : if (rel->exps && (rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
2591 : return NULL;
2592 69352274 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_rel_visitor(v, rel->r, rel_rewriter, topdown)) == NULL)
2593 : return NULL;
2594 69352273 : int changes = v->changes;
2595 69352273 : rel = rel_rewriter(v, rel);
2596 69349846 : if (rel && rel->exps && v->changes > changes) {
2597 318943 : list_hash_clear(rel->exps);
2598 318938 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r)
2599 12585 : list_hash_clear(rel->r);
2600 : }
2601 : return rel;
2602 : }
2603 :
2604 : static inline sql_rel *
2605 69346440 : rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
2606 : {
2607 69346440 : sql_rel *parent = v->parent;
2608 :
2609 69346440 : if (mvc_highwater(v->sql))
2610 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2611 :
2612 69355029 : if (!rel)
2613 : return NULL;
2614 :
2615 69354970 : if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
2616 : return NULL;
2617 :
2618 69355187 : sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
2619 :
2620 69355187 : v->parent = rel;
2621 69355187 : switch(rel->op){
2622 : case op_basetable:
2623 : break;
2624 138139 : case op_table:
2625 138139 : if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
2626 137912 : if (rel->l)
2627 2814 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2628 : return NULL;
2629 : }
2630 : break;
2631 4010232 : case op_ddl:
2632 4010232 : if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
2633 417848 : if (rel->l)
2634 414190 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2635 : return NULL;
2636 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
2637 14673 : if (rel->l)
2638 10671 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2639 : return NULL;
2640 14673 : if (rel->r)
2641 13668 : if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
2642 : return NULL;
2643 : } else if (rel->flag == ddl_psm) {
2644 145042 : if ((rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
2645 : return NULL;
2646 : }
2647 : break;
2648 11317286 : case op_insert:
2649 : case op_update:
2650 : case op_delete:
2651 : case op_merge:
2652 :
2653 : case op_join:
2654 : case op_left:
2655 : case op_right:
2656 : case op_full:
2657 : case op_semi:
2658 : case op_anti:
2659 :
2660 : case op_union:
2661 : case op_inter:
2662 : case op_except:
2663 11317286 : if (rel->l)
2664 11317286 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2665 : return NULL;
2666 11317408 : if (rel->r)
2667 11313007 : if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
2668 : return NULL;
2669 : break;
2670 2282108 : case op_munion:
2671 8529994 : for (node *n = ((list*)rel->l)->h; n; n = n->next) {
2672 6247886 : if ((n->data = func(v, n->data, rel_rewriter)) == NULL)
2673 : return NULL;
2674 : }
2675 : break;
2676 33764941 : case op_select:
2677 : case op_topn:
2678 : case op_sample:
2679 : case op_project:
2680 : case op_groupby:
2681 : case op_truncate:
2682 33764941 : if (rel->l)
2683 31615899 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2684 : return NULL;
2685 : break;
2686 : }
2687 69356789 : v->parent = parent;
2688 :
2689 69356789 : if (!topdown)
2690 44010673 : rel = do_rel_visitor(v, rel, rel_rewriter, false);
2691 : return rel;
2692 : }
2693 :
2694 : sql_rel *
2695 25341089 : rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
2696 : {
2697 25341089 : v->depth++;
2698 25341089 : rel = rel_visitor(v, rel, rel_rewriter, true);
2699 25342122 : v->depth--;
2700 25342122 : return rel;
2701 : }
2702 :
2703 : sql_rel *
2704 44010206 : rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
2705 : {
2706 44010206 : v->depth++;
2707 44010206 : rel = rel_visitor(v, rel, rel_rewriter, false);
2708 44012330 : v->depth--;
2709 44012330 : return rel;
2710 : }
2711 :
2712 : list *
2713 272 : exps_exp_visitor_topdown(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2714 : {
2715 272 : return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, true, relations_topdown, false);
2716 : }
2717 :
2718 : list *
2719 586823 : exps_exp_visitor_bottomup(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2720 : {
2721 586823 : return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, false, relations_topdown, false);
2722 : }
2723 :
2724 : static bool
2725 75192 : exps_rebind_exp(mvc *sql, sql_rel *rel, list *exps)
2726 : {
2727 75192 : bool ok = true;
2728 :
2729 75192 : if (mvc_highwater(sql)) {
2730 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2731 0 : return false;
2732 : }
2733 :
2734 75192 : if (list_empty(exps))
2735 : return true;
2736 87076 : for (node *n = exps->h; n && ok; n = n->next)
2737 53346 : ok &= rel_rebind_exp(sql, rel, n->data);
2738 : return ok;
2739 : }
2740 :
2741 : bool
2742 2563924 : rel_rebind_exp(mvc *sql, sql_rel *rel, sql_exp *e)
2743 : {
2744 2587183 : if (mvc_highwater(sql)) {
2745 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2746 0 : return false;
2747 : }
2748 :
2749 2587183 : switch (e->type) {
2750 23259 : case e_convert:
2751 23259 : return rel_rebind_exp(sql, rel, e->l);
2752 14218 : case e_aggr:
2753 : case e_func:
2754 14218 : return exps_rebind_exp(sql, rel, e->l);
2755 1036296 : case e_cmp:
2756 1036296 : if (e->flag == cmp_in || e->flag == cmp_notin)
2757 8249 : return rel_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
2758 1030065 : if (e->flag == cmp_or || e->flag == cmp_filter)
2759 19707 : return exps_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
2760 2037716 : return rel_rebind_exp(sql, rel, e->l) && rel_rebind_exp(sql, rel, e->r) && (!e->f || rel_rebind_exp(sql, rel, e->f));
2761 1471933 : case e_column:
2762 1471933 : if (e->freevar)
2763 : return true;
2764 1471932 : return rel_find_exp(rel, e) != NULL;
2765 41472 : case e_atom:
2766 41472 : return exps_rebind_exp(sql, rel, e->f);
2767 : case e_psm:
2768 : return true;
2769 : }
2770 : return true;
2771 : }
2772 :
2773 : static sql_exp *
2774 388 : _exp_freevar_offset(visitor *v, sql_rel *rel, sql_exp *e, int depth)
2775 : {
2776 388 : (void)rel; (void)depth;
2777 : /* visitor will handle recursion, ie only need to check columns here */
2778 388 : int vf = is_freevar(e);
2779 388 : if (v->changes < vf)
2780 309 : v->changes=vf;
2781 388 : return e;
2782 : }
2783 :
2784 : int
2785 299 : exp_freevar_offset(mvc *sql, sql_exp *e)
2786 : {
2787 299 : bool changed = false;
2788 299 : visitor v = { .sql = sql };
2789 :
2790 299 : (void) changed;
2791 299 : exp_visitor(&v, NULL, e, 0, &_exp_freevar_offset, true, true, true, &changed);
2792 : /* freevar offset is passed via changes */
2793 299 : return (v.changes);
2794 : }
|