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