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