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