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