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 dependend (row_number etc) */
31 : int
32 1612615 : project_unsafe(sql_rel *rel, int allow_identity)
33 : {
34 1612615 : sql_rel *sub = rel->l;
35 :
36 1612615 : if (need_distinct(rel) || rel->r /* order by */)
37 : return 1;
38 1459935 : if (list_empty(rel->exps))
39 : return 0;
40 : /* projects without sub and projects around ddl's cannot be changed */
41 1459929 : if (!sub || sub->op == op_ddl)
42 : return 1;
43 9930470 : for(node *n = rel->exps->h; n; n = n->next) {
44 8896656 : sql_exp *e = n->data, *ne;
45 :
46 : /* aggr func in project ! */
47 8896656 : if (exp_unsafe(e, allow_identity))
48 : return 1;
49 8795628 : 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 127023 : rel_name( sql_rel *r )
62 : {
63 130810 : if (is_basetable(r->op))
64 126900 : return rel_base_name(r);
65 3910 : if (!is_project(r->op) && !is_base(r->op) && r->l)
66 : return rel_name(r->l);
67 123 : if (r->exps && list_length(r->exps)) {
68 123 : sql_exp *e = r->exps->h->data;
69 123 : if (exp_relname(e))
70 123 : return exp_relname(e);
71 0 : if (e->type == e_column)
72 0 : return e->l;
73 : }
74 : return NULL;
75 : }
76 :
77 : sql_rel *
78 9101 : rel_distinct(sql_rel *l)
79 : {
80 9101 : set_distinct(l);
81 9101 : return l;
82 : }
83 :
84 : sql_rel *
85 579363 : rel_dup(sql_rel *r)
86 : {
87 579363 : sql_ref_inc(&r->ref);
88 579363 : return r;
89 : }
90 :
91 : static void
92 658197 : rel_destroy_(sql_rel *rel)
93 : {
94 658197 : if (!rel)
95 : return;
96 658197 : switch(rel->op){
97 : case op_basetable:
98 : break;
99 4873 : case op_table:
100 4873 : if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
101 11 : rel_destroy(rel->l);
102 : break;
103 333147 : case op_join:
104 : case op_left:
105 : case op_right:
106 : case op_full:
107 : case op_semi:
108 : case op_anti:
109 : case op_union:
110 : case op_inter:
111 : case op_except:
112 : case op_insert:
113 : case op_update:
114 : case op_delete:
115 : case op_merge:
116 333147 : if (rel->l)
117 53451 : rel_destroy(rel->l);
118 333147 : if (rel->r)
119 57697 : rel_destroy(rel->r);
120 : break;
121 310124 : case op_project:
122 : case op_groupby:
123 : case op_select:
124 : case op_topn:
125 : case op_sample:
126 : case op_truncate:
127 310124 : if (rel->l)
128 86329 : rel_destroy(rel->l);
129 : break;
130 0 : case op_ddl:
131 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) {
132 0 : if (rel->l)
133 0 : rel_destroy(rel->l);
134 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
135 0 : if (rel->l)
136 0 : rel_destroy(rel->l);
137 0 : if (rel->r)
138 0 : rel_destroy(rel->r);
139 : }
140 : break;
141 : }
142 : }
143 :
144 : void
145 1176550 : rel_destroy(sql_rel *rel)
146 : {
147 1176550 : if (!rel)
148 : return;
149 1176546 : if (sql_ref_dec(&rel->ref) > 0)
150 : return;
151 621171 : rel_destroy_(rel);
152 : }
153 :
154 : sql_rel*
155 3197495 : rel_create(sql_allocator *sa)
156 : {
157 3197495 : sql_rel *r = SA_NEW(sa, sql_rel);
158 3197487 : if(!r)
159 : return NULL;
160 :
161 3197487 : *r = (sql_rel) {
162 : .card = CARD_ATOM,
163 : };
164 3197487 : sql_ref_init(&r->ref);
165 3197487 : return r;
166 : }
167 :
168 : sql_rel *
169 188 : rel_copy(mvc *sql, sql_rel *i, int deep)
170 : {
171 188 : sql_rel *rel;
172 :
173 188 : if (mvc_highwater(sql))
174 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
175 :
176 188 : rel = rel_create(sql->sa);
177 188 : if (!rel)
178 : return NULL;
179 :
180 188 : rel->op = i->op;
181 188 : switch(i->op) {
182 60 : case op_basetable:
183 60 : rel_base_copy(sql, i, rel);
184 60 : break;
185 0 : case op_table:
186 0 : if ((IS_TABLE_PROD_FUNC(i->flag) || i->flag == TABLE_FROM_RELATION) && i->l)
187 0 : rel->l = rel_copy(sql, i->l, deep);
188 0 : rel->r = i->r;
189 0 : break;
190 80 : case op_project:
191 : case op_groupby:
192 80 : if (i->l)
193 68 : rel->l = rel_copy(sql, i->l, deep);
194 80 : if (i->r) {
195 7 : if (!deep) {
196 0 : rel->r = list_dup(i->r, (fdup) NULL);
197 : } else {
198 7 : rel->r = exps_copy(sql, i->r);
199 : }
200 : }
201 : break;
202 0 : case op_ddl:
203 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) {
204 0 : if (i->l)
205 0 : rel->l = rel_copy(sql, i->l, deep);
206 0 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
207 0 : if (i->l)
208 0 : rel->l = rel_copy(sql, i->l, deep);
209 0 : if (i->r)
210 0 : rel->r = rel_copy(sql, i->r, deep);
211 : }
212 : break;
213 23 : case op_select:
214 : case op_topn:
215 : case op_sample:
216 : case op_truncate:
217 23 : if (i->l)
218 23 : rel->l = rel_copy(sql, i->l, deep);
219 : break;
220 25 : case op_join:
221 : case op_left:
222 : case op_right:
223 : case op_full:
224 : case op_semi:
225 : case op_anti:
226 :
227 : case op_union:
228 : case op_inter:
229 : case op_except:
230 :
231 : case op_insert:
232 : case op_update:
233 : case op_delete:
234 : case op_merge:
235 25 : if (i->l)
236 25 : rel->l = rel_copy(sql, i->l, deep);
237 25 : if (i->r)
238 25 : rel->r = rel_copy(sql, i->r, deep);
239 : break;
240 : }
241 :
242 188 : rel->card = i->card;
243 188 : rel->flag = i->flag;
244 188 : rel->nrcols = i->nrcols;
245 188 : rel->grouped = i->grouped;
246 188 : rel->used = i->used;
247 :
248 188 : if (is_processed(i))
249 120 : set_processed(rel);
250 188 : if (is_dependent(i))
251 0 : set_dependent(rel);
252 188 : if (is_outer(i))
253 9 : set_outer(rel);
254 188 : if (is_single(i))
255 4 : set_single(rel);
256 188 : if (need_distinct(i))
257 4 : set_distinct(rel);
258 :
259 188 : rel->p = prop_copy(sql->sa, i->p);
260 188 : rel->exps = (!i->exps)?NULL:deep?exps_copy(sql, i->exps):list_dup(i->exps, (fdup)NULL);
261 188 : rel->attr = (!i->attr)?NULL:deep?exps_copy(sql, i->attr):list_dup(i->attr, (fdup)NULL);
262 188 : return rel;
263 : }
264 :
265 : sql_rel *
266 4644 : rel_select_copy(sql_allocator *sa, sql_rel *l, list *exps)
267 : {
268 4644 : sql_rel *rel = rel_create(sa);
269 4644 : if(!rel)
270 : return NULL;
271 :
272 4644 : rel->l = l;
273 4644 : rel->r = NULL;
274 4644 : rel->op = op_select;
275 4644 : rel->exps = exps?list_dup(exps, (fdup)NULL):NULL;
276 4644 : rel->card = CARD_ATOM; /* no relation */
277 4644 : if (l) {
278 4644 : rel->card = l->card;
279 4644 : rel->nrcols = l->nrcols;
280 : }
281 : return rel;
282 : }
283 :
284 : sql_exp *
285 7949811 : rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int no_tname)
286 : {
287 7949811 : int ambiguous = 0, multi = 0;
288 :
289 7949811 : if (!rel)
290 : return NULL;
291 7949811 : if (mvc_highwater(sql))
292 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
293 :
294 7949811 : if ((is_project(rel->op) || is_base(rel->op))) {
295 4217460 : sql_exp *e = NULL;
296 :
297 4217460 : if (is_base(rel->op) && !rel->exps)
298 4040396 : return rel_base_bind_column(sql, rel, cname, no_tname);
299 177064 : if (!list_empty(rel->exps)) {
300 177030 : e = exps_bind_column(rel->exps, cname, &ambiguous, &multi, no_tname);
301 177030 : if (ambiguous || multi)
302 10 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
303 177020 : if (!e && is_groupby(rel->op) && rel->r) {
304 215 : e = exps_bind_alias(rel->r, NULL, cname);
305 215 : if (e) {
306 0 : e = exps_bind_column(rel->r, cname, &ambiguous, &multi, no_tname);
307 0 : if (ambiguous || multi)
308 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
309 : return e;
310 : }
311 : }
312 : }
313 19177 : if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
314 215 : e = exps_bind_column(rel->r, cname, &ambiguous, &multi, no_tname);
315 215 : if (ambiguous || multi)
316 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
317 215 : if (e) {
318 1 : e = exp_ref(sql, e);
319 1 : e->card = rel->card;
320 1 : return e;
321 : }
322 : }
323 157877 : if (e)
324 157877 : return exp_alias_or_copy(sql, exp_relname(e), cname, rel, e);
325 : }
326 3751527 : if (is_simple_project(rel->op) && rel->l) {
327 6921 : if (!is_processed(rel))
328 0 : return rel_bind_column(sql, rel->l, cname, f, no_tname);
329 3744606 : } else if (is_set(rel->op)) {
330 64 : assert(is_processed(rel));
331 : return NULL;
332 : } else if (is_join(rel->op)) {
333 3229081 : sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), *e2 = NULL, *res;
334 :
335 3229081 : if (e1 && (is_right(rel->op) || is_full(rel->op)))
336 7 : set_has_nil(e1);
337 1612962 : if (!e1 || !is_freevar(e1)) {
338 3229081 : e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
339 3229081 : if (e2 && (is_left(rel->op) || is_full(rel->op)))
340 56 : set_has_nil(e2);
341 3229081 : if (e1 && e2 && !is_dependent(rel))
342 35 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
343 : }
344 3229046 : if (!e1 && !e2 && !list_empty(rel->attr)) {
345 0 : e1 = exps_bind_column(rel->attr, cname, &ambiguous, &multi, no_tname);
346 0 : if (ambiguous || multi)
347 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
348 : }
349 3229046 : res = e1 ? e1 : e2;
350 1616119 : if (res)
351 1701886 : set_not_unique(res);
352 3229046 : return res;
353 : } else if (is_semi(rel->op) ||
354 : is_select(rel->op) ||
355 : is_topn(rel->op) ||
356 : is_sample(rel->op)) {
357 503270 : if (rel->l)
358 503270 : return rel_bind_column(sql, rel->l, cname, f, no_tname);
359 : }
360 : return NULL;
361 : }
362 :
363 : sql_exp *
364 4593581 : rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f)
365 : {
366 4593581 : int ambiguous = 0, multi = 0;
367 :
368 4593581 : if (!rel)
369 : return NULL;
370 4593110 : if (mvc_highwater(sql))
371 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
372 :
373 4593111 : if ((is_project(rel->op) || is_base(rel->op))) {
374 2198029 : sql_exp *e = NULL;
375 :
376 2198029 : if (is_basetable(rel->op) && !rel->exps)
377 1284480 : return rel_base_bind_column2(sql, rel, tname, cname);
378 : /* in case of orderby we should also lookup the column in group by list (and use existing references) */
379 913549 : if (!list_empty(rel->exps)) {
380 913469 : e = exps_bind_column2(rel->exps, tname, cname, &multi);
381 913469 : if (multi)
382 2 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
383 : tname, cname);
384 913467 : if (!e && is_groupby(rel->op) && rel->r) {
385 118 : e = exps_bind_alias(rel->r, tname, cname);
386 118 : if (e) {
387 4 : const char *rname = exp_relname(e), *nname = exp_name(e);
388 4 : if (rname)
389 0 : e = exps_bind_column2(rel->exps, rname, nname, &multi);
390 : else
391 4 : e = exps_bind_column(rel->exps, nname, &ambiguous, &multi, 0);
392 4 : if (ambiguous || multi)
393 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s%s%s' ambiguous",
394 : rname ? rname : "", rname ? "." : "", nname);
395 4 : if (e)
396 : return e;
397 : }
398 : }
399 : }
400 357100 : if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
401 133 : e = exps_bind_column2(rel->r, tname, cname, &multi);
402 133 : if (multi)
403 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
404 : tname, cname);
405 133 : if (e) {
406 10 : e = exp_ref(sql, e);
407 10 : e->card = rel->card;
408 10 : return e;
409 : }
410 : }
411 556443 : if (e)
412 556443 : return exp_alias_or_copy(sql, tname, cname, rel, e);
413 : }
414 2752172 : if (is_simple_project(rel->op) && rel->l) {
415 319285 : if (!is_processed(rel))
416 0 : return rel_bind_column2(sql, rel->l, tname, cname, f);
417 2432887 : } else if (is_set(rel->op)) {
418 4994 : assert(is_processed(rel));
419 : return NULL;
420 : } else if (is_join(rel->op)) {
421 1933391 : sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
422 :
423 1933391 : if (e && (is_right(rel->op) || is_full(rel->op)))
424 253 : set_has_nil(e);
425 253 : if (!e) {
426 849101 : e = rel_bind_column2(sql, rel->r, tname, cname, f);
427 849101 : if (e && (is_left(rel->op) || is_full(rel->op)))
428 23155 : set_has_nil(e);
429 : }
430 405621 : if (!e && !list_empty(rel->attr)) {
431 14 : e = exps_bind_column2(rel->attr, tname, cname, &multi);
432 14 : if (multi)
433 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
434 : tname, cname);
435 : }
436 382466 : if (e)
437 1550929 : set_not_unique(e);
438 1933391 : return e;
439 : } else if (is_semi(rel->op) ||
440 : is_select(rel->op) ||
441 : is_topn(rel->op) ||
442 : is_sample(rel->op)) {
443 461691 : if (rel->l)
444 461691 : return rel_bind_column2(sql, rel->l, tname, cname, f);
445 : }
446 : return NULL;
447 : }
448 :
449 : sql_exp *
450 1198239 : rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname, int f)
451 : {
452 1198239 : if (!sname)
453 1198238 : return rel_bind_column2(sql, rel, tname, cname, f);
454 1 : if (is_basetable(rel->op) && !rel->exps) {
455 0 : return rel_base_bind_column3(sql, rel, sname, tname, cname);
456 1 : } else if (is_set(rel->op)) {
457 : return NULL;
458 1 : } else if (is_project(rel->op) && rel->l) {
459 1 : if (!is_processed(rel))
460 : return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
461 : else
462 1 : return rel_bind_column2(sql, rel->l, tname, cname, f);
463 0 : } else if (is_join(rel->op)) {
464 0 : sql_exp *e = rel_bind_column3(sql, rel->l, sname, tname, cname, f);
465 :
466 0 : if (e && (is_right(rel->op) || is_full(rel->op)))
467 0 : set_has_nil(e);
468 0 : if (!e) {
469 0 : e = rel_bind_column3(sql, rel->r, sname, tname, cname, f);
470 0 : if (e && (is_left(rel->op) || is_full(rel->op)))
471 0 : set_has_nil(e);
472 : }
473 0 : if (!e)
474 0 : return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s.%s' ambiguous", sname, tname, cname);
475 0 : if (e)
476 0 : set_not_unique(e);
477 0 : return e;
478 0 : } else if (is_semi(rel->op) ||
479 0 : is_select(rel->op) ||
480 0 : is_topn(rel->op) ||
481 : is_sample(rel->op)) {
482 0 : if (rel->l)
483 : return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
484 : }
485 : return NULL;
486 : }
487 :
488 : sql_exp *
489 0 : rel_first_column(mvc *sql, sql_rel *r)
490 : {
491 0 : if (is_simple_project(r->op))
492 0 : return r->exps->h->data;
493 :
494 0 : list *exps = rel_projections(sql, r, NULL, 1, 1);
495 :
496 0 : if (!list_empty(exps))
497 0 : return exps->h->data;
498 :
499 : return NULL;
500 : }
501 :
502 : static void
503 76166 : rel_inplace_reset_props(sql_rel *rel)
504 : {
505 76166 : rel->flag = 0;
506 76166 : rel->attr = NULL;
507 76166 : reset_dependent(rel);
508 76166 : set_processed(rel);
509 : }
510 :
511 : sql_rel *
512 102 : rel_inplace_basetable(sql_rel *rel, sql_rel *bt)
513 : {
514 102 : assert(is_basetable(bt->op));
515 :
516 102 : rel_destroy_(rel);
517 102 : rel_inplace_reset_props(rel);
518 102 : rel->l = bt->l;
519 102 : rel->r = bt->r;
520 102 : rel->op = op_basetable;
521 102 : rel->exps = bt->exps;
522 102 : rel->card = CARD_MULTI;
523 102 : rel->nrcols = bt->nrcols;
524 102 : return rel;
525 : }
526 :
527 : sql_rel *
528 36307 : rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps)
529 : {
530 36307 : rel_destroy_(rel);
531 36307 : rel_inplace_reset_props(rel);
532 36307 : rel->l = l;
533 36307 : rel->r = r;
534 36307 : rel->op = setop;
535 36307 : rel->card = CARD_MULTI;
536 36307 : rel_setop_set_exps(sql, rel, exps, false);
537 36307 : return rel;
538 : }
539 :
540 : sql_rel *
541 39190 : rel_inplace_project(sql_allocator *sa, sql_rel *rel, sql_rel *l, list *e)
542 : {
543 39190 : if (!l) {
544 39140 : l = rel_create(sa);
545 39140 : if(!l)
546 : return NULL;
547 :
548 39140 : *l = *rel;
549 39140 : l->ref.refcnt = 1;
550 : } else {
551 50 : rel_destroy_(rel);
552 : }
553 39190 : rel_inplace_reset_props(rel);
554 39190 : rel->l = l;
555 39190 : rel->r = NULL;
556 39190 : rel->op = op_project;
557 39190 : rel->exps = e;
558 39190 : rel->card = CARD_MULTI;
559 39190 : if (l) {
560 39190 : rel->nrcols = l->nrcols;
561 39190 : assert (exps_card(rel->exps) <= rel->card);
562 : }
563 : return rel;
564 : }
565 :
566 : sql_rel *
567 67 : rel_inplace_select(sql_rel *rel, sql_rel *l, list *exps)
568 : {
569 67 : rel_destroy_(rel);
570 67 : rel_inplace_reset_props(rel);
571 67 : rel->l = l;
572 67 : rel->r = NULL;
573 67 : rel->op = op_select;
574 67 : rel->exps = exps;
575 67 : rel->card = CARD_ATOM; /* no relation */
576 67 : if (l) {
577 67 : rel->card = l->card;
578 67 : rel->nrcols = l->nrcols;
579 67 : if (is_single(l))
580 0 : set_single(rel);
581 : }
582 67 : return rel;
583 : }
584 :
585 : sql_rel *
586 500 : rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps )
587 : {
588 500 : rel_destroy_(rel);
589 500 : rel_inplace_reset_props(rel);
590 500 : rel->card = CARD_ATOM;
591 500 : if (groupbyexps)
592 374 : rel->card = CARD_AGGR;
593 500 : rel->l = l;
594 500 : rel->r = groupbyexps;
595 500 : rel->exps = exps;
596 500 : rel->nrcols = l->nrcols;
597 500 : rel->op = op_groupby;
598 500 : return rel;
599 : }
600 :
601 : /* this function is to be used with the above rel_inplace_* functions */
602 : sql_rel *
603 27 : rel_dup_copy(sql_allocator *sa, sql_rel *rel)
604 : {
605 27 : sql_rel *nrel = rel_create(sa);
606 :
607 27 : if (!nrel)
608 : return NULL;
609 27 : *nrel = *rel;
610 27 : nrel->ref.refcnt = 1;
611 27 : switch(nrel->op){
612 : case op_basetable:
613 : case op_ddl:
614 : break;
615 0 : case op_table:
616 0 : if ((IS_TABLE_PROD_FUNC(nrel->flag) || nrel->flag == TABLE_FROM_RELATION) && nrel->l)
617 0 : rel_dup(nrel->l);
618 : break;
619 18 : case op_join:
620 : case op_left:
621 : case op_right:
622 : case op_full:
623 : case op_semi:
624 : case op_anti:
625 : case op_union:
626 : case op_inter:
627 : case op_except:
628 : case op_insert:
629 : case op_update:
630 : case op_delete:
631 : case op_merge:
632 18 : if (nrel->l)
633 18 : rel_dup(nrel->l);
634 18 : if (nrel->r)
635 18 : rel_dup(nrel->r);
636 : break;
637 9 : case op_project:
638 : case op_groupby:
639 : case op_select:
640 : case op_topn:
641 : case op_sample:
642 : case op_truncate:
643 9 : if (nrel->l)
644 9 : rel_dup(nrel->l);
645 : break;
646 : }
647 : return nrel;
648 : }
649 :
650 : sql_rel *
651 62913 : rel_setop(sql_allocator *sa, sql_rel *l, sql_rel *r, operator_type setop)
652 : {
653 62913 : sql_rel *rel = rel_create(sa);
654 62913 : if(!rel)
655 : return NULL;
656 62913 : rel->l = l;
657 62913 : rel->r = r;
658 62913 : rel->op = setop;
659 62913 : rel->exps = NULL;
660 62913 : rel->card = CARD_MULTI;
661 62913 : assert(l->nrcols == r->nrcols);
662 62913 : rel->nrcols = l->nrcols;
663 62913 : return rel;
664 : }
665 :
666 : sql_rel *
667 58256 : rel_setop_check_types(mvc *sql, sql_rel *l, sql_rel *r, list *ls, list *rs, operator_type op)
668 : {
669 58256 : list *nls = new_exp_list(sql->sa);
670 58256 : list *nrs = new_exp_list(sql->sa);
671 58256 : node *n, *m;
672 :
673 58256 : if(!nls || !nrs)
674 : return NULL;
675 :
676 446684 : for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
677 388433 : sql_exp *le = n->data;
678 388433 : sql_exp *re = m->data;
679 :
680 388433 : if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
681 5 : return NULL;
682 388428 : append(nls, le);
683 388428 : append(nrs, re);
684 : }
685 58251 : l = rel_project(sql->sa, l, nls);
686 58251 : r = rel_project(sql->sa, r, nrs);
687 58251 : set_processed(l);
688 58251 : set_processed(r);
689 58251 : return rel_setop(sql->sa, l, r, op);
690 : }
691 :
692 : void
693 97598 : rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
694 : {
695 97598 : sql_rel *l = rel->l, *r = rel->r;
696 97598 : list *lexps = l->exps, *rexps = r->exps;
697 :
698 97598 : if (!is_project(l->op))
699 6338 : lexps = rel_projections(sql, l, NULL, 0, 1);
700 97598 : if (!is_project(r->op))
701 6406 : rexps = rel_projections(sql, r, NULL, 0, 1);
702 :
703 97598 : assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && list_length(exps) == list_length(lexps)*/);
704 :
705 757365 : for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n = n->next, m = m->next,o = o->next) {
706 659767 : sql_exp *e = n->data, *f = m->data, *g = o->data;
707 :
708 659767 : if (is_union(rel->op)) { /* propagate set_has_no_nil only if it's applicable to both sides of the union*/
709 656832 : if (has_nil(f) || has_nil(g))
710 602877 : set_has_nil(e);
711 : else
712 53955 : set_has_no_nil(e);
713 656832 : if (!keep_props) {
714 656443 : e->p = NULL; /* remove all the properties on unions on the general case */
715 656443 : set_not_unique(e);
716 : }
717 : }
718 659767 : e->card = CARD_MULTI; /* multi cardinality */
719 : }
720 97598 : rel->nrcols = l->nrcols;
721 97598 : rel->exps = exps;
722 97598 : }
723 :
724 : sql_rel *
725 514004 : rel_crossproduct(sql_allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
726 : {
727 514004 : sql_rel *rel = rel_create(sa);
728 514004 : if(!rel)
729 : return NULL;
730 :
731 514004 : rel->l = l;
732 514004 : rel->r = r;
733 514004 : rel->op = join;
734 514004 : rel->exps = NULL;
735 514004 : rel->card = CARD_MULTI;
736 514004 : rel->nrcols = l->nrcols + r->nrcols;
737 514004 : return rel;
738 : }
739 :
740 : sql_exp *
741 0 : rel_is_constant(sql_rel **R, sql_exp *e)
742 : {
743 0 : sql_rel *rel = *R;
744 :
745 0 : if (rel && rel->op == op_project && list_length(rel->exps) == 1 &&
746 0 : !rel->l && !rel->r && !rel_is_ref(rel) && e->type == e_column) {
747 0 : sql_exp *ne = rel_find_exp(rel, e);
748 0 : if (ne) {
749 0 : rel_destroy(rel);
750 0 : *R = NULL;
751 0 : return ne;
752 : }
753 : }
754 : return e;
755 : }
756 :
757 : sql_rel *
758 16980 : rel_topn(sql_allocator *sa, sql_rel *l, list *exps )
759 : {
760 16980 : sql_rel *rel = rel_create(sa);
761 16980 : if(!rel)
762 : return NULL;
763 :
764 16980 : rel->l = l;
765 16980 : rel->r = NULL;
766 16980 : rel->op = op_topn;
767 16980 : rel->exps = exps;
768 16980 : rel->card = l->card;
769 16980 : rel->nrcols = l->nrcols;
770 16980 : return rel;
771 : }
772 :
773 : sql_rel *
774 23 : rel_sample(sql_allocator *sa, sql_rel *l, list *exps )
775 : {
776 23 : sql_rel *rel = rel_create(sa);
777 23 : if(!rel)
778 : return NULL;
779 :
780 23 : rel->l = l;
781 23 : rel->r = NULL;
782 23 : rel->op = op_sample;
783 23 : rel->exps = exps;
784 23 : rel->card = l->card;
785 23 : rel->nrcols = l->nrcols;
786 23 : return rel;
787 : }
788 :
789 : sql_rel *
790 14072 : rel_label( mvc *sql, sql_rel *r, int all)
791 : {
792 14072 : int nr = ++sql->label;
793 14072 : char tname[16], *tnme;
794 14072 : char cname[16], *cnme = NULL;
795 :
796 14072 : tnme = number2name(tname, sizeof(tname), nr);
797 14072 : if (!is_simple_project(r->op))
798 603 : r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 1));
799 14072 : if (!list_empty(r->exps)) {
800 14072 : list_hash_clear(r->exps);
801 55656 : for (node *ne = r->exps->h; ne; ne = ne->next) {
802 41584 : sql_exp *e = ne->data;
803 :
804 41584 : if (!is_freevar(e)) {
805 41578 : if (all) {
806 41578 : nr = ++sql->label;
807 41578 : cnme = number2name(cname, sizeof(cname), nr);
808 : }
809 41578 : exp_setname(sql->sa, e, tnme, cnme );
810 : }
811 : }
812 : }
813 : /* op_projects can have a order by list */
814 14072 : if (!list_empty(r->r)) {
815 0 : for (node *ne = ((list*)r->r)->h; ne; ne = ne->next) {
816 0 : if (all) {
817 0 : nr = ++sql->label;
818 0 : cnme = number2name(cname, sizeof(cname), nr);
819 : }
820 0 : exp_setname(sql->sa, ne->data, tnme, cnme );
821 : }
822 : }
823 14072 : return r;
824 : }
825 :
826 : sql_exp *
827 29778 : rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e)
828 : {
829 29778 : assert(is_project(rel->op));
830 :
831 29778 : if (!exp_name(e))
832 99 : exp_label(sql->sa, e, ++sql->label);
833 29778 : if (is_simple_project(rel->op)) {
834 29774 : sql_rel *l = rel->l;
835 29774 : if (!rel->exps)
836 19 : rel->exps = new_exp_list(sql->sa);
837 29774 : if (l && is_groupby(l->op) && exp_card(e) <= CARD_ATOM && list_empty(l->exps))
838 4 : e = rel_project_add_exp(sql, l, e);
839 29774 : if (e->card > rel->card)
840 0 : rel->card = e->card;
841 29774 : append(rel->exps, e);
842 29774 : rel->nrcols++;
843 4 : } else if (is_groupby(rel->op)) {
844 4 : return rel_groupby_add_aggr(sql, rel, e);
845 : }
846 29774 : e = exp_ref(sql, e);
847 29774 : return e;
848 : }
849 :
850 : sql_rel *
851 276434 : rel_select_add_exp(sql_allocator *sa, sql_rel *l, sql_exp *e)
852 : {
853 276434 : if ((l->op != op_select && !is_outerjoin(l->op)) || rel_is_ref(l))
854 6871 : return rel_select(sa, l, e);
855 :
856 : /* allow during AST->relational for bool expresssions as well
857 : if (e->type != e_cmp && e->card > CARD_ATOM) {
858 : sql_exp *t = exp_atom_bool(sa, 1);
859 : e = exp_compare(sa, e, t, cmp_equal);
860 : }
861 : */
862 269563 : if (!l->exps)
863 4513 : l->exps = new_exp_list(sa);
864 269563 : append(l->exps, e);
865 269563 : return l;
866 : }
867 :
868 : void
869 479200 : rel_join_add_exp( sql_allocator *sa, sql_rel *rel, sql_exp *e)
870 : {
871 479200 : assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
872 :
873 479200 : if (!rel->exps)
874 435477 : rel->exps = new_exp_list(sa);
875 479200 : append(rel->exps, e);
876 479200 : if (e->card > rel->card)
877 0 : rel->card = e->card;
878 479200 : }
879 :
880 : sql_exp *
881 76182 : rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
882 : {
883 76182 : sql_exp *m = NULL, *ne;
884 :
885 76182 : if (list_empty(rel->r))
886 26463 : rel->card = e->card = CARD_ATOM;
887 :
888 76182 : if ((m=exps_any_match(rel->exps, e)) == NULL) {
889 44717 : if (!exp_name(e))
890 44693 : exp_label(sql->sa, e, ++sql->label);
891 44717 : append(rel->exps, e);
892 44717 : rel->nrcols++;
893 44717 : m = e;
894 : }
895 76182 : ne = exp_ref(sql, m);
896 76182 : return ne;
897 : }
898 :
899 : sql_rel *
900 257951 : rel_select(sql_allocator *sa, sql_rel *l, sql_exp *e)
901 : {
902 257951 : sql_rel *rel;
903 :
904 257951 : if (l && is_outerjoin(l->op) && !is_processed(l)) {
905 204 : if (e) {
906 188 : if (!l->exps)
907 173 : l->exps = new_exp_list(sa);
908 188 : append(l->exps, e);
909 : }
910 204 : return l;
911 : }
912 :
913 257747 : if (l && is_select(l->op) && !rel_is_ref(l)) { /* refine old select */
914 17541 : if (e)
915 9488 : rel_select_add_exp(sa, l, e);
916 17541 : return l;
917 : }
918 240206 : rel = rel_create(sa);
919 240206 : if(!rel)
920 : return NULL;
921 :
922 240206 : rel->l = l;
923 240206 : rel->r = NULL;
924 240206 : rel->op = op_select;
925 240206 : rel->exps = new_exp_list(sa);
926 240206 : if (e)
927 185174 : rel_select_add_exp(sa, rel, e);
928 240206 : rel->card = CARD_ATOM; /* no relation */
929 240206 : if (l) {
930 240206 : rel->card = l->card;
931 240206 : rel->nrcols = l->nrcols;
932 240206 : if (is_single(l))
933 1510 : set_single(rel);
934 : }
935 : return rel;
936 : }
937 :
938 : sql_rel *
939 36764 : rel_groupby(mvc *sql, sql_rel *l, list *groupbyexps )
940 : {
941 36764 : sql_rel *rel = rel_create(sql->sa);
942 36764 : list *aggrs = new_exp_list(sql->sa);
943 36764 : node *en;
944 36764 : if(!rel || !aggrs) {
945 0 : rel_destroy(rel);
946 0 : return NULL;
947 : }
948 :
949 36764 : rel->card = CARD_ATOM;
950 : /* reduce duplicates in groupbyexps */
951 36764 : if (groupbyexps && list_length(groupbyexps) > 1) {
952 4977 : list *gexps = sa_list(sql->sa);
953 :
954 24099 : for (en = groupbyexps->h; en; en = en->next) {
955 19122 : sql_exp *e = en->data, *ne = exps_find_exp(gexps, e);
956 :
957 19122 : if (!ne) {
958 19019 : list_append(gexps, e);
959 : } else {
960 103 : const char *ername = exp_relname(e), *nername = exp_relname(ne), *ename = exp_name(e), *nename = exp_name(ne);
961 103 : if ((ername && !nername) || (!ername && nername) ||
962 97 : (ername && nername && strcmp(ername,nername) != 0) || strcmp(ename,nename) != 0)
963 10 : list_append(gexps, e);
964 : }
965 : }
966 : groupbyexps = gexps;
967 : }
968 :
969 10031 : if (groupbyexps) {
970 10031 : rel->card = CARD_AGGR;
971 33971 : for (en = groupbyexps->h; en; en = en->next) {
972 23940 : sql_exp *e = en->data, *ne;
973 :
974 : /* after the group by the cardinality reduces */
975 23940 : e->card = MIN(e->card, rel->card); /* if the column is an atom, the cardinality should not change */
976 23940 : ne = exp_ref(sql, e);
977 23940 : ne = exp_propagate(sql->sa, ne, e);
978 23940 : append(aggrs, ne);
979 : }
980 : }
981 36764 : rel->l = l;
982 36764 : rel->r = groupbyexps;
983 36764 : rel->exps = aggrs;
984 36764 : rel->nrcols = aggrs?list_length(aggrs):0;
985 36764 : rel->op = op_groupby;
986 36764 : rel->grouped = 1;
987 36764 : return rel;
988 : }
989 :
990 : sql_rel *
991 955200 : rel_project(sql_allocator *sa, sql_rel *l, list *e)
992 : {
993 955200 : sql_rel *rel = rel_create(sa);
994 955195 : if(!rel)
995 : return NULL;
996 :
997 955195 : rel->l = l;
998 955195 : rel->r = NULL;
999 955195 : rel->op = op_project;
1000 955195 : rel->exps = e;
1001 955195 : rel->card = exps_card(e);
1002 955197 : if (l) {
1003 770132 : rel->card = l->card;
1004 770132 : if (e)
1005 717191 : rel->nrcols = list_length(e);
1006 : else
1007 52941 : rel->nrcols = l->nrcols;
1008 770128 : rel->single = is_single(l);
1009 : }
1010 955193 : if (e && !list_empty(e)) {
1011 901848 : set_processed(rel);
1012 901848 : rel->nrcols = list_length(e);
1013 : }
1014 : return rel;
1015 : }
1016 :
1017 : sql_rel *
1018 72825 : rel_project_exp(mvc *sql, sql_exp *e)
1019 : {
1020 72825 : if (!exp_name(e))
1021 72825 : exp_label(sql->sa, e, ++sql->label);
1022 72815 : return rel_project(sql->sa, NULL, list_append(sa_list(sql->sa), e));
1023 : }
1024 :
1025 : sql_rel *
1026 108342 : rel_list(sql_allocator *sa, sql_rel *l, sql_rel *r)
1027 : {
1028 108342 : sql_rel *rel = rel_create(sa);
1029 108342 : if (!rel)
1030 : return NULL;
1031 108342 : if (!l)
1032 : return r;
1033 547 : rel->l = l;
1034 547 : rel->r = r;
1035 547 : rel->op = op_ddl;
1036 547 : rel->flag = ddl_list;
1037 547 : return rel;
1038 : }
1039 :
1040 : sql_rel *
1041 149 : rel_exception(sql_allocator *sa, sql_rel *l, sql_rel *r, list *exps)
1042 : {
1043 149 : sql_rel *rel = rel_create(sa);
1044 149 : if(!rel)
1045 : return NULL;
1046 149 : rel->r = r;
1047 149 : rel->exps = exps;
1048 149 : rel->op = op_ddl;
1049 149 : rel->flag = ddl_exception;
1050 149 : if (l)
1051 149 : return rel_list(sa, rel, l); /* keep base relation on the right ! */
1052 : return rel;
1053 : }
1054 :
1055 : sql_rel *
1056 305 : rel_relational_func(sql_allocator *sa, sql_rel *l, list *exps)
1057 : {
1058 305 : sql_rel *rel = rel_create(sa);
1059 305 : if(!rel)
1060 : return NULL;
1061 :
1062 305 : rel->flag = TABLE_PROD_FUNC;
1063 305 : rel->l = l;
1064 305 : rel->op = op_table;
1065 305 : rel->exps = exps;
1066 305 : rel->card = CARD_MULTI;
1067 305 : rel->nrcols = list_length(exps);
1068 305 : return rel;
1069 : }
1070 :
1071 : sql_rel *
1072 16293 : rel_table_func(sql_allocator *sa, sql_rel *l, sql_exp *f, list *exps, int kind)
1073 : {
1074 16293 : sql_rel *rel = rel_create(sa);
1075 16293 : if(!rel)
1076 : return NULL;
1077 :
1078 16293 : assert(kind > 0);
1079 16293 : rel->flag = kind;
1080 16293 : rel->l = l; /* relation before call */
1081 16293 : rel->r = f; /* expression (table func call) */
1082 16293 : rel->op = op_table;
1083 16293 : rel->exps = exps;
1084 16293 : rel->card = CARD_MULTI;
1085 16293 : rel->nrcols = list_length(exps);
1086 16293 : return rel;
1087 : }
1088 :
1089 : static void
1090 295392 : exps_reset_props(list *exps, bool setnil)
1091 : {
1092 295392 : if (!list_empty(exps)) {
1093 2944170 : for (node *m = exps->h; m; m = m->next) {
1094 2651711 : sql_exp *e = m->data;
1095 :
1096 2651711 : if (setnil)
1097 189792 : set_has_nil(e);
1098 2651711 : set_not_unique(e);
1099 : }
1100 : }
1101 295392 : }
1102 :
1103 : list *
1104 1085692 : _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern, int basecol /* basecol only */ )
1105 : {
1106 1156206 : list *lexps, *rexps = NULL, *exps;
1107 :
1108 1156206 : if (mvc_highwater(sql))
1109 2 : return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1110 :
1111 1156204 : if (!rel)
1112 0 : return new_exp_list(sql->sa);
1113 :
1114 1156204 : if (!tname && is_basetable(rel->op) && !is_processed(rel))
1115 257106 : rel_base_use_all( sql, rel);
1116 :
1117 1156204 : switch(rel->op) {
1118 147696 : case op_join:
1119 : case op_left:
1120 : case op_right:
1121 : case op_full:
1122 147696 : lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1123 147696 : exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
1124 147696 : if (!rel->attr)
1125 144783 : rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
1126 147696 : exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
1127 147696 : if (rexps)
1128 144783 : lexps = list_merge(lexps, rexps, (fdup)NULL);
1129 147696 : if (rel->attr)
1130 2913 : append(lexps, exp_ref(sql, rel->attr->h->data));
1131 : return lexps;
1132 7017 : case op_groupby:
1133 7017 : if (list_empty(rel->exps) && rel->r) {
1134 1 : list *r = rel->r;
1135 1 : int label = 0;
1136 :
1137 1 : if (!settname)
1138 0 : label = ++sql->label;
1139 1 : exps = new_exp_list(sql->sa);
1140 2 : for (node *en = r->h; en; en = en->next) {
1141 1 : sql_exp *e = en->data;
1142 :
1143 1 : if (basecol && !is_basecol(e))
1144 0 : continue;
1145 1 : if (intern || !is_intern(e)) {
1146 1 : e = exp_alias_or_copy(sql, tname, exp_name(e), rel, e);
1147 1 : if (!settname) /* noname use alias */
1148 0 : exp_setrelname(sql->sa, e, label);
1149 1 : append(exps, e);
1150 : }
1151 : }
1152 : return exps;
1153 : }
1154 : /* fall through */
1155 : case op_project:
1156 : case op_basetable:
1157 : case op_table:
1158 :
1159 : case op_union:
1160 : case op_except:
1161 : case op_inter:
1162 937993 : if (is_basetable(rel->op) && !rel->exps)
1163 97556 : return rel_base_projection(sql, rel, intern);
1164 840437 : if (rel->exps) {
1165 782184 : int label = 0;
1166 :
1167 782184 : if (!settname)
1168 246470 : label = ++sql->label;
1169 782184 : exps = new_exp_list(sql->sa);
1170 6259035 : for (node *en = rel->exps->h; en; en = en->next) {
1171 5476852 : sql_exp *e = en->data;
1172 :
1173 5476852 : if (basecol && !is_basecol(e))
1174 44 : continue;
1175 5476808 : if (intern || !is_intern(e)) {
1176 5463425 : e = exp_alias_or_copy(sql, tname, exp_name(e), rel, e);
1177 5463426 : if (!settname) /* noname use alias */
1178 1642168 : exp_setrelname(sql->sa, e, label);
1179 5463426 : append(exps, e);
1180 : }
1181 : }
1182 : return exps;
1183 : }
1184 : /* I only expect set relations to hit here */
1185 58253 : assert(is_set(rel->op));
1186 58253 : lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1187 58253 : rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
1188 58253 : if (lexps && rexps) {
1189 58253 : int label = 0;
1190 :
1191 58253 : if (!settname)
1192 58253 : label = ++sql->label;
1193 58253 : assert(list_length(lexps) == list_length(rexps));
1194 446685 : for (node *en = lexps->h; en; en = en->next) {
1195 388432 : sql_exp *e = en->data;
1196 :
1197 388432 : e->card = rel->card;
1198 388432 : if (!settname) /* noname use alias */
1199 388432 : exp_setrelname(sql->sa, e, label);
1200 : }
1201 58253 : if (!settname)
1202 58253 : list_hash_clear(lexps);
1203 : }
1204 : return lexps;
1205 70514 : case op_ddl:
1206 : case op_semi:
1207 : case op_anti:
1208 :
1209 : case op_select:
1210 : case op_topn:
1211 : case op_sample:
1212 70514 : return _rel_projections(sql, rel->l, tname, settname, intern, basecol);
1213 : default:
1214 : return NULL;
1215 : }
1216 : }
1217 :
1218 : list *
1219 636860 : rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern)
1220 : {
1221 636860 : assert(tname == NULL);
1222 636860 : return _rel_projections(sql, rel, tname, settname, intern, 0);
1223 : }
1224 :
1225 : /* find the path to the relation containing the base of the expression
1226 : (e_column), in most cases this means go down the join tree and
1227 : find the base column.
1228 : */
1229 : static int
1230 3963147 : rel_bind_path_(mvc *sql, sql_rel *rel, sql_exp *e, list *path )
1231 : {
1232 3963147 : int found = 0;
1233 :
1234 3963147 : if (mvc_highwater(sql)) {
1235 0 : sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1236 0 : return 0;
1237 : }
1238 :
1239 3963147 : switch (rel->op) {
1240 1841785 : case op_join:
1241 : case op_left:
1242 : case op_right:
1243 : case op_full:
1244 : /* first right (possible subquery) */
1245 1841785 : found = rel_bind_path_(sql, rel->r, e, path);
1246 1841785 : if (!found)
1247 1553137 : found = rel_bind_path_(sql, rel->l, e, path);
1248 1553137 : if (!found && !list_empty(rel->attr)) {
1249 0 : if (e->l && exps_bind_column2(rel->attr, e->l, e->r, NULL))
1250 : found = 1;
1251 0 : if (!found && !e->l && exps_bind_column(rel->attr, e->r, NULL, NULL, 1))
1252 : found = 1;
1253 : }
1254 : break;
1255 112539 : case op_semi:
1256 : case op_anti:
1257 : case op_select:
1258 : case op_topn:
1259 : case op_sample:
1260 112539 : found = rel_bind_path_(sql, rel->l, e, path);
1261 112539 : break;
1262 2008823 : case op_basetable:
1263 : case op_union:
1264 : case op_inter:
1265 : case op_except:
1266 : case op_groupby:
1267 : case op_project:
1268 : case op_table:
1269 2008823 : if (is_basetable(rel->op) && !rel->exps) {
1270 1822602 : if (e->l) {
1271 1822602 : if (rel_base_bind_column2_(rel, e->l, e->r))
1272 : found = 1;
1273 0 : } else if (rel_base_bind_column_(rel, e->r))
1274 : found = 1;
1275 186221 : } else if (rel->exps) {
1276 186221 : if (!found && e->l && exps_bind_column2(rel->exps, e->l, e->r, NULL))
1277 : found = 1;
1278 94237 : if (!found && !e->l && exps_bind_column(rel->exps, e->r, NULL, NULL, 1))
1279 : found = 1;
1280 : }
1281 : break;
1282 : case op_insert:
1283 : case op_update:
1284 : case op_delete:
1285 : case op_truncate:
1286 : case op_merge:
1287 : case op_ddl:
1288 : break;
1289 : }
1290 206782 : if (found)
1291 2366242 : list_prepend(path, rel);
1292 : return found;
1293 : }
1294 :
1295 : static list *
1296 501608 : rel_bind_path(mvc *sql, sql_rel *rel, sql_exp *e, list *path)
1297 : {
1298 501608 : if (!path)
1299 : return NULL;
1300 :
1301 501608 : if (e->type == e_convert) {
1302 40337 : if (!(path = rel_bind_path(sql, rel, e->l, path)))
1303 : return NULL;
1304 461271 : } else if (e->type == e_column) {
1305 455686 : if (rel) {
1306 455686 : if (!rel_bind_path_(sql, rel, e, path)) {
1307 : /* something is wrong */
1308 : return NULL;
1309 : }
1310 : }
1311 455686 : return path;
1312 : }
1313 : /* default the top relation */
1314 45922 : append(path, rel);
1315 45922 : return path;
1316 : }
1317 :
1318 : static sql_rel *
1319 21165 : rel_select_push_exp_down(mvc *sql, sql_rel *rel, sql_exp *e)
1320 : {
1321 21165 : sql_rel *r = rel->l, *jl = r->l, *jr = r->r;
1322 21165 : int left = r->op == op_join || r->op == op_left;
1323 21165 : int right = r->op == op_join || r->op == op_right;
1324 21165 : int done = 0;
1325 :
1326 21165 : assert(is_select(rel->op));
1327 21165 : if (!is_full(r->op) && !is_single(r)) {
1328 21165 : if (left && rel_rebind_exp(sql, jl, e)) {
1329 9 : done = 1;
1330 9 : r->l = jl = rel_select_add_exp(sql->sa, jl, e);
1331 21156 : } else if (right && rel_rebind_exp(sql, jr, e)) {
1332 6 : done = 1;
1333 6 : r->r = jr = rel_select_add_exp(sql->sa, jr, e);
1334 : }
1335 : }
1336 15 : if (!done)
1337 21150 : rel_select_add_exp(sql->sa, rel, e);
1338 21165 : return rel;
1339 : }
1340 :
1341 : /* ls is the left expression of the select, e is the select expression. */
1342 : sql_rel *
1343 105951 : rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
1344 : {
1345 105951 : list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
1346 105951 : node *n;
1347 105951 : sql_rel *lrel = NULL, *p = NULL;
1348 :
1349 105951 : if (!l)
1350 : return NULL;
1351 105951 : if (is_sql_or(f)) /* expression has no clear parent relation, so filter current with it */
1352 21142 : return rel_select(sql->sa, rel, e);
1353 :
1354 246006 : for (n = l->h; n; n = n->next ) {
1355 245294 : lrel = n->data;
1356 :
1357 245294 : if (rel_is_ref(lrel))
1358 : break;
1359 :
1360 : /* push down as long as the operators allow this */
1361 245282 : if (!is_select(lrel->op) &&
1362 224741 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1363 84085 : lrel->op != op_join &&
1364 : lrel->op != op_left)
1365 : break;
1366 : /* pushing through left head of a left join is allowed */
1367 161201 : if (lrel->op == op_left && (!n->next || lrel->l != n->next->data))
1368 : break;
1369 161197 : p = lrel;
1370 : }
1371 84809 : if (!lrel)
1372 : return NULL;
1373 84809 : if (p && is_select(p->op) && !rel_is_ref(p)) { /* refine old select */
1374 18354 : p = rel_select_push_exp_down(sql, p, e);
1375 : } else {
1376 66455 : sql_rel *n = rel_select(sql->sa, lrel, e);
1377 :
1378 66455 : if (p && p != lrel) {
1379 63458 : assert(p->op == op_join || p->op == op_left || is_semi(p->op));
1380 63458 : if (p->l == lrel) {
1381 23310 : p->l = n;
1382 : } else {
1383 40148 : p->r = n;
1384 : }
1385 : } else {
1386 2997 : if (rel != lrel)
1387 0 : assert(0);
1388 : rel = n;
1389 : }
1390 : }
1391 : return rel;
1392 : }
1393 :
1394 : /* ls and rs are the left and right expression of the join, e is the
1395 : join expression.
1396 : */
1397 : sql_rel *
1398 177396 : rel_push_join(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, sql_exp *e, int f)
1399 : {
1400 177396 : list *l = NULL, *r = NULL, *r2 = NULL;
1401 177396 : node *ln, *rn;
1402 177396 : sql_rel *lrel = NULL, *rrel = NULL, *rrel2 = NULL, *p = NULL;
1403 :
1404 177396 : if (!(l = rel_bind_path(sql, rel, ls, sa_list(sql->sa))) ||
1405 177396 : !(r = rel_bind_path(sql, rel, rs, sa_list(sql->sa))) ||
1406 528 : (rs2 && !(r2 = rel_bind_path(sql, rel, rs2, sa_list(sql->sa)))))
1407 0 : return NULL;
1408 :
1409 177396 : if (is_sql_or(f))
1410 2922 : return rel_push_select(sql, rel, ls, e, f);
1411 :
1412 174474 : p = rel;
1413 174474 : if (r2) {
1414 520 : node *rn2;
1415 :
1416 1047 : for (ln = l->h, rn = r->h, rn2 = r2->h; ln && rn && rn2; ln = ln->next, rn = rn->next, rn2 = rn2->next ) {
1417 551 : lrel = ln->data;
1418 551 : rrel = rn->data;
1419 551 : rrel2 = rn2->data;
1420 :
1421 551 : if (rel_is_ref(lrel) || rel_is_ref(rrel) || rel_is_ref(rrel2) || is_processed(lrel) || is_processed(rrel))
1422 : break;
1423 :
1424 : /* push down as long as the operators allow this
1425 : and the relation is equal.
1426 : */
1427 546 : if (lrel != rrel || lrel != rrel2 ||
1428 527 : (!is_select(lrel->op) &&
1429 69 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1430 0 : lrel->op != op_join &&
1431 : lrel->op != op_left))
1432 : break;
1433 : /* pushing through left head of a left join is allowed */
1434 527 : if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
1435 : break;
1436 527 : p = lrel;
1437 : }
1438 : } else {
1439 786660 : for (ln = l->h, rn = r->h; ln && rn; ln = ln->next, rn = rn->next ) {
1440 783902 : lrel = ln->data;
1441 783902 : rrel = rn->data;
1442 :
1443 783902 : if (rel_is_ref(lrel) || rel_is_ref(rrel) || is_processed(lrel) || is_processed(rrel))
1444 : break;
1445 :
1446 : /* push down as long as the operators allow this
1447 : and the relation is equal.
1448 : */
1449 745130 : if (lrel != rrel ||
1450 614366 : (!is_select(lrel->op) &&
1451 611092 : !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
1452 1660 : lrel->op != op_join &&
1453 : lrel->op != op_left))
1454 : break;
1455 : /* pushing through left head of a left join is allowed */
1456 612706 : if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
1457 : break;
1458 612706 : p = lrel;
1459 : }
1460 : }
1461 174474 : if (!lrel || !rrel || (r2 && !rrel2))
1462 : return NULL;
1463 :
1464 : /* filter on columns of this relation */
1465 174474 : if ((lrel == rrel && (!r2 || lrel == rrel2) && lrel->op != op_join) || rel_is_ref(p)) {
1466 2832 : if (is_select(lrel->op) && !rel_is_ref(lrel)) {
1467 1152 : lrel = rel_select_push_exp_down(sql, lrel, e);
1468 1680 : } else if (p && is_select(p->op) && !rel_is_ref(p)) {
1469 1659 : p = rel_select_push_exp_down(sql, p, e);
1470 : } else {
1471 21 : sql_rel *n = rel_select(sql->sa, lrel, e);
1472 :
1473 21 : if (p && p != lrel) {
1474 21 : if (p->l == lrel)
1475 10 : p->l = n;
1476 : else
1477 11 : p->r = n;
1478 : } else {
1479 : rel = n;
1480 : }
1481 : }
1482 2832 : return rel;
1483 : }
1484 :
1485 171642 : rel_join_add_exp( sql->sa, p, e);
1486 171642 : return rel;
1487 : }
1488 :
1489 : sql_rel *
1490 18572 : rel_or(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, list *oexps, list *lexps, list *rexps)
1491 : {
1492 18572 : sql_rel *ll = l->l, *rl = r->l;
1493 18572 : list *ls, *rs;
1494 :
1495 18572 : assert(!lexps || l == r);
1496 18572 : if (l == r && lexps) { /* merge both lists */
1497 42 : sql_exp *e = exp_or(sql->sa, lexps, rexps, 0);
1498 42 : list *nl = oexps?oexps:new_exp_list(sql->sa);
1499 :
1500 42 : rel_destroy(r);
1501 42 : append(nl, e);
1502 42 : if (is_outerjoin(l->op) && is_processed(l))
1503 0 : l = rel_select(sql->sa, l, NULL);
1504 42 : l->exps = nl;
1505 42 : return l;
1506 : }
1507 :
1508 : /* favor or expressions over union */
1509 18530 : if (l->op == r->op && is_select(l->op) &&
1510 18530 : ll == rl && ll == rel && !rel_is_ref(l) && !rel_is_ref(r)) {
1511 18530 : sql_exp *e = exp_or(sql->sa, l->exps, r->exps, 0);
1512 18530 : list *nl = new_exp_list(sql->sa);
1513 :
1514 18530 : rel_destroy(r);
1515 18530 : append(nl, e);
1516 18530 : l->exps = nl;
1517 :
1518 : /* merge and expressions */
1519 18530 : ll = l->l;
1520 20874 : while (ll && is_select(ll->op) && !rel_is_ref(ll)) {
1521 2344 : list_merge(l->exps, ll->exps, (fdup)NULL);
1522 2344 : l->l = ll->l;
1523 2344 : ll->l = NULL;
1524 2344 : rel_destroy(ll);
1525 2344 : ll = l->l;
1526 : }
1527 : return l;
1528 : }
1529 :
1530 0 : if (rel) {
1531 0 : ls = rel_projections(sql, rel, NULL, 1, 1);
1532 0 : rs = rel_projections(sql, rel, NULL, 1, 1);
1533 : } else {
1534 0 : ls = rel_projections(sql, l, NULL, 1, 1);
1535 0 : rs = rel_projections(sql, r, NULL, 1, 1);
1536 : }
1537 0 : set_processed(l);
1538 0 : set_processed(r);
1539 0 : rel = rel_setop_check_types(sql, l, r, ls, rs, op_union);
1540 0 : if (!rel)
1541 : return NULL;
1542 0 : rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 1, 1), false);
1543 0 : set_processed(rel);
1544 0 : rel->nrcols = list_length(rel->exps);
1545 0 : rel = rel_distinct(rel);
1546 0 : if (!rel)
1547 : return NULL;
1548 0 : if (exps_card(l->exps) <= CARD_AGGR &&
1549 0 : exps_card(r->exps) <= CARD_AGGR)
1550 : {
1551 0 : rel->card = exps_card(l->exps);
1552 0 : exps_fix_card( rel->exps, rel->card);
1553 : }
1554 : return rel;
1555 : }
1556 :
1557 : sql_table *
1558 4059 : rel_ddl_table_get(sql_rel *r)
1559 : {
1560 4059 : if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
1561 4059 : sql_exp *e = r->exps->t->data;
1562 4059 : atom *a = e->l;
1563 :
1564 4059 : return a->data.val.pval;
1565 : }
1566 : return NULL;
1567 : }
1568 :
1569 : sql_rel *
1570 2330 : rel_ddl_basetable_get(sql_rel *r)
1571 : {
1572 2330 : if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
1573 2330 : return r->l;
1574 : }
1575 : return NULL;
1576 : }
1577 :
1578 : static sql_exp *
1579 31 : exps_find_identity(list *exps, sql_rel *p)
1580 : {
1581 31 : node *n;
1582 :
1583 113 : for (n=exps->h; n; n = n->next) {
1584 83 : sql_exp *e = n->data;
1585 :
1586 83 : if (is_identity(e, p))
1587 1 : return e;
1588 : }
1589 : return NULL;
1590 : }
1591 :
1592 : static sql_rel *
1593 82 : _rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
1594 : {
1595 82 : list *exps = rel_projections(sql, rel, NULL, 1, 1);
1596 82 : sql_exp *e = NULL;
1597 :
1598 82 : if (list_empty(exps)) {
1599 0 : *exp = NULL;
1600 0 : return rel;
1601 : }
1602 82 : if (!is_simple_project(rel->op) || need_distinct(rel) || !list_empty(rel->r) || rel_is_ref(rel))
1603 53 : rel = rel_project(sql->sa, rel, exps);
1604 : /* filter parameters out */
1605 164 : for (node *n = rel->exps->h ; n && !e ; n = n->next) {
1606 82 : sql_exp *re = n->data;
1607 :
1608 82 : if (exp_subtype(re))
1609 82 : e = re;
1610 : }
1611 82 : if (!e)
1612 0 : return sql_error(sql, 10, SQLSTATE(42000) "Query projection must have at least one parameter with known SQL type");
1613 :
1614 82 : e = exp_column(sql->sa, exp_relname(e), exp_name(e), exp_subtype(e), rel->card, has_nil(e), is_unique(e), is_intern(e));
1615 82 : e = exp_unop(sql->sa, e, sql_bind_func(sql, "sys", "identity", exp_subtype(e), NULL, F_FUNC, true));
1616 82 : set_intern(e);
1617 82 : set_has_no_nil(e);
1618 82 : set_unique(e);
1619 82 : e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
1620 82 : *exp = exp_label(sql->sa, e, ++sql->label);
1621 82 : (void) rel_project_add_exp(sql, rel, e);
1622 82 : return rel;
1623 : }
1624 :
1625 : sql_rel *
1626 98 : rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
1627 : {
1628 98 : if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
1629 15 : *exp = basetable_get_tid_or_add_it(sql, rel);
1630 15 : return rel;
1631 : }
1632 83 : if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
1633 : return rel;
1634 82 : return _rel_add_identity(sql, rel, exp);
1635 : }
1636 :
1637 : sql_rel *
1638 0 : rel_add_identity2(mvc *sql, sql_rel *rel, sql_exp **exp)
1639 : {
1640 0 : sql_rel *l = rel, *p = rel;
1641 :
1642 0 : if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
1643 0 : *exp = basetable_get_tid_or_add_it(sql, rel);
1644 0 : return rel;
1645 : }
1646 0 : if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
1647 : return rel;
1648 0 : while(l && !is_set(l->op) && rel_has_freevar(sql, l) && l->l) {
1649 : p = l;
1650 : l = l->l;
1651 : }
1652 0 : if (l != p) {
1653 0 : sql_rel *o = rel;
1654 0 : sql_exp *id;
1655 :
1656 0 : if (!(p->l = _rel_add_identity(sql, l, exp)))
1657 : return NULL;
1658 0 : l = p->l;
1659 0 : id = exp_ref(sql, *exp);
1660 0 : while (o && o != l) {
1661 0 : *exp = id;
1662 0 : if (is_project(o->op))
1663 0 : rel_project_add_exp(sql, o, id);
1664 0 : o = o->l;
1665 : }
1666 : return rel;
1667 : }
1668 0 : return _rel_add_identity(sql, rel, exp);
1669 : }
1670 :
1671 : static sql_exp *
1672 1482 : rel_find_column_(sql_allocator *sa, list *exps, const char *tname, const char *cname)
1673 : {
1674 1482 : int ambiguous = 0, multi = 0;
1675 1482 : sql_exp *e = exps_bind_column2(exps, tname, cname, &multi);
1676 1482 : if (!e && cname[0] == '%' && !tname)
1677 0 : e = exps_bind_column(exps, cname, &ambiguous, &multi, 0);
1678 1482 : if (e && !ambiguous && !multi)
1679 1481 : return exp_alias(sa, exp_relname(e), exp_name(e), exp_relname(e), cname, exp_subtype(e), e->card, has_nil(e), is_unique(e), is_intern(e));
1680 : return NULL;
1681 : }
1682 :
1683 : sql_exp *
1684 1482 : rel_find_column(sql_allocator *sa, sql_rel *rel, const char *tname, const char *cname )
1685 : {
1686 1771 : sql_exp *e = NULL;
1687 :
1688 1771 : if (!rel)
1689 : return NULL;
1690 1771 : if (rel->exps && (is_project(rel->op) || is_base(rel->op)) && (e = rel_find_column_(sa, rel->exps, tname, cname)))
1691 : return e;
1692 290 : if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
1693 1 : if (!is_processed(rel))
1694 : return rel_find_column(sa, rel->l, tname, cname);
1695 289 : } else if (is_set(rel->op)) {
1696 0 : assert(is_processed(rel));
1697 : return NULL;
1698 : } else if (is_join(rel->op)) {
1699 0 : e = rel_find_column(sa, rel->l, tname, cname);
1700 :
1701 0 : if (e && (is_right(rel->op) || is_full(rel->op)))
1702 0 : set_has_nil(e);
1703 0 : if (!e) {
1704 0 : e = rel_find_column(sa, rel->r, tname, cname);
1705 0 : if (e && (is_left(rel->op) || is_full(rel->op)))
1706 0 : set_has_nil(e);
1707 : }
1708 0 : if (!e && !list_empty(rel->attr))
1709 0 : e = rel_find_column_(sa, rel->attr, tname, cname);
1710 0 : if (e)
1711 0 : set_not_unique(e);
1712 0 : return e;
1713 : } else if (is_semi(rel->op) ||
1714 : is_select(rel->op) ||
1715 : is_topn(rel->op) ||
1716 : is_sample(rel->op)) {
1717 289 : if (rel->l)
1718 : return rel_find_column(sa, rel->l, tname, cname);
1719 : }
1720 : return NULL;
1721 : }
1722 :
1723 : int
1724 0 : rel_in_rel(sql_rel *super, sql_rel *sub)
1725 : {
1726 0 : if (!super)
1727 : return 0;
1728 0 : if (super == sub)
1729 : return 1;
1730 0 : if (is_join(super->op) || is_semi(super->op) || is_set(super->op) || is_modify(super->op) || is_ddl(super->op))
1731 0 : return rel_in_rel(super->l, sub) || rel_in_rel(super->r, sub);
1732 : if (is_select(super->op) || is_simple_project(super->op) || is_groupby(super->op) || is_topn(super->op) || is_sample(super->op))
1733 0 : return rel_in_rel(super->l, sub);
1734 : return 0;
1735 : }
1736 :
1737 : sql_rel*
1738 12 : rel_parent(sql_rel *rel)
1739 : {
1740 12 : if (rel->l && (is_project(rel->op) || is_topn(rel->op) || is_sample(rel->op))) {
1741 12 : sql_rel *l = rel->l;
1742 12 : if (is_project(l->op))
1743 12 : return l;
1744 : }
1745 : return rel;
1746 : }
1747 :
1748 : sql_exp *
1749 26602 : lastexp(sql_rel *rel)
1750 : {
1751 26602 : if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
1752 12 : rel = rel_parent(rel);
1753 26602 : assert(list_length(rel->exps));
1754 26602 : assert(is_project(rel->op) || rel->op == op_table);
1755 26602 : return rel->exps->t->data;
1756 : }
1757 :
1758 : sql_rel *
1759 5723 : rel_return_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
1760 : {
1761 5723 : if (ek.card < card_set && rel->card > CARD_ATOM) {
1762 4368 : list *exps = rel->exps;
1763 :
1764 4368 : assert (is_simple_project(rel->op) || is_set(rel->op));
1765 4368 : rel = rel_groupby(sql, rel, NULL);
1766 8746 : for(node *n = exps->h; n; n=n->next) {
1767 4378 : sql_exp *e = n->data;
1768 4378 : if (!has_label(e))
1769 49 : exp_label(sql->sa, e, ++sql->label);
1770 4378 : sql_subtype *t = exp_subtype(e); /* parameters don't have a type defined, for those use 'void' one */
1771 4378 : sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", t ? t : sql_bind_localtype("void"), NULL, F_AGGR, true);
1772 :
1773 4378 : e = exp_ref(sql, e);
1774 4378 : e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
1775 4378 : (void)rel_groupby_add_aggr(sql, rel, e);
1776 : }
1777 4368 : set_processed(rel);
1778 : }
1779 5723 : return rel;
1780 : }
1781 :
1782 : sql_rel *
1783 35454 : rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
1784 : {
1785 35454 : if (is_topn(rel->op) || is_sample(rel->op))
1786 17 : rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 1, 0));
1787 35454 : if (ek.card < card_set && rel->card > CARD_ATOM) {
1788 9039 : assert (is_simple_project(rel->op) || is_set(rel->op));
1789 :
1790 9039 : list *exps = rel->exps;
1791 18106 : for(node *n = exps->h; n; n=n->next) {
1792 9067 : sql_exp *e = n->data;
1793 9067 : if (!has_label(e))
1794 9028 : exp_label(sql->sa, e, ++sql->label);
1795 : }
1796 9039 : set_single(rel);
1797 : } else {
1798 26415 : sql_exp *e = lastexp(rel);
1799 26415 : if (!has_label(e))
1800 12668 : exp_label(sql->sa, e, ++sql->label);
1801 : }
1802 35454 : return rel;
1803 : }
1804 :
1805 : static sql_rel *
1806 8898 : refs_find_rel(list *refs, sql_rel *rel)
1807 : {
1808 8898 : node *n;
1809 :
1810 20117 : for(n=refs->h; n; n = n->next->next) {
1811 15778 : sql_rel *ref = n->data;
1812 15778 : sql_rel *s = n->next->data;
1813 :
1814 15778 : if (rel == ref)
1815 : return s;
1816 : }
1817 : return NULL;
1818 : }
1819 :
1820 : static int exp_deps(mvc *sql, sql_exp *e, list *refs, list *l);
1821 :
1822 : static int
1823 700824 : exps_deps(mvc *sql, list *exps, list *refs, list *l)
1824 : {
1825 :
1826 2941152 : for(node *n = exps->h; n; n = n->next)
1827 2240328 : if (exp_deps(sql, n->data, refs, l) != 0)
1828 : return -1;
1829 : return 0;
1830 : }
1831 :
1832 : static int
1833 6822594 : id_cmp(sql_base *id1, sql_base *id2)
1834 : {
1835 6822594 : if (id1->id == id2->id)
1836 85707 : return 0;
1837 : return -1;
1838 : }
1839 :
1840 : static list *
1841 744584 : cond_append(list *l, sql_base *b)
1842 : {
1843 744584 : if (b->id >= FUNC_OIDS && !list_find(l, b, (fcmp) &id_cmp))
1844 351934 : list_append(l, b);
1845 744584 : return l;
1846 : }
1847 :
1848 : static int rel_deps(mvc *sql, sql_rel *r, list *refs, list *l);
1849 :
1850 : static int
1851 2425726 : exp_deps(mvc *sql, sql_exp *e, list *refs, list *l)
1852 : {
1853 2573830 : if (mvc_highwater(sql)) {
1854 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1855 0 : return -1;
1856 : }
1857 :
1858 2573830 : switch(e->type) {
1859 43819 : case e_psm:
1860 43819 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
1861 18801 : return exp_deps(sql, e->l, refs, l);
1862 25018 : } else if (e->flag & PSM_VAR) {
1863 : return 0;
1864 20372 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
1865 6152 : if (exp_deps(sql, e->l, refs, l) != 0 || exps_deps(sql, e->r, refs, l) != 0)
1866 0 : return -1;
1867 6152 : if (e->flag & PSM_IF && e->f)
1868 740 : return exps_deps(sql, e->f, refs, l);
1869 14220 : } else if (e->flag & PSM_REL) {
1870 14220 : sql_rel *rel = e->l;
1871 14220 : return rel_deps(sql, rel, refs, l);
1872 : }
1873 : break;
1874 878168 : case e_atom:
1875 878168 : if (e->f && exps_deps(sql, e->f, refs, l) != 0)
1876 : return -1;
1877 : break;
1878 : case e_column:
1879 : break;
1880 129272 : case e_convert:
1881 129272 : return exp_deps(sql, e->l, refs, l);
1882 314878 : case e_func: {
1883 314878 : sql_subfunc *f = e->f;
1884 :
1885 314878 : if (e->l && exps_deps(sql, e->l, refs, l) != 0)
1886 : return -1;
1887 314878 : cond_append(l, &f->func->base);
1888 314878 : if (e->l && list_length(e->l) == 2 && strcmp(f->func->base.name, "next_value_for") == 0) {
1889 : /* add dependency on seq nr */
1890 82 : list *nl = e->l;
1891 82 : sql_exp *schname = nl->h->data, *seqname = nl->t->data;
1892 82 : char *sch_name = is_atom(schname->type) && schname->l ? ((atom*)schname->l)->data.val.sval : NULL;
1893 82 : char *seq_name = is_atom(seqname->type) && seqname->l ? ((atom*)seqname->l)->data.val.sval : NULL;
1894 :
1895 82 : if (sch_name && seq_name) {
1896 82 : sql_schema *sche = mvc_bind_schema(sql, sch_name);
1897 82 : if (sche) {
1898 82 : sql_sequence *seq = find_sql_sequence(sql->session->tr, sche, seq_name);
1899 82 : if (seq)
1900 82 : cond_append(l, &seq->base);
1901 : }
1902 : }
1903 : }
1904 : } break;
1905 19739 : case e_aggr: {
1906 19739 : sql_subfunc *a = e->f;
1907 :
1908 19739 : if (e->l && exps_deps(sql, e->l, refs, l) != 0)
1909 : return -1;
1910 19739 : cond_append(l, &a->func->base);
1911 19739 : } break;
1912 91896 : case e_cmp: {
1913 91896 : if (e->flag == cmp_or || e->flag == cmp_filter) {
1914 250 : if (e->flag == cmp_filter) {
1915 17 : sql_subfunc *f = e->f;
1916 17 : cond_append(l, &f->func->base);
1917 : }
1918 500 : if (exps_deps(sql, e->l, refs, l) != 0 ||
1919 250 : exps_deps(sql, e->r, refs, l) != 0)
1920 0 : return -1;
1921 91646 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
1922 8092 : if (exp_deps(sql, e->l, refs, l) != 0 ||
1923 4046 : exps_deps(sql, e->r, refs, l) != 0)
1924 0 : return -1;
1925 : } else {
1926 175200 : if (exp_deps(sql, e->l, refs, l) != 0 ||
1927 87600 : exp_deps(sql, e->r, refs, l) != 0)
1928 0 : return -1;
1929 87600 : if (e->f)
1930 : return exp_deps(sql, e->f, refs, l);
1931 : }
1932 : } break;
1933 : }
1934 : return 0;
1935 : }
1936 :
1937 : static int
1938 470323 : rel_deps(mvc *sql, sql_rel *r, list *refs, list *l)
1939 : {
1940 470323 : if (mvc_highwater(sql)) {
1941 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
1942 0 : return -1;
1943 : }
1944 :
1945 470323 : if (!r)
1946 : return 0;
1947 :
1948 470457 : if (rel_is_ref(r) && refs_find_rel(refs, r)) /* already handled */
1949 : return 0;
1950 457000 : switch (r->op) {
1951 97697 : case op_basetable: {
1952 97697 : sql_table *t = r->l;
1953 :
1954 97697 : cond_append(l, &t->base);
1955 : /* find all used columns */
1956 439056 : for (node *en = r->exps->h; en; en = en->next) {
1957 341359 : sql_exp *exp = en->data;
1958 341359 : const char *oname = exp->r;
1959 :
1960 341359 : assert(!is_func(exp->type));
1961 341359 : if (oname[0] == '%' && strcmp(oname, TID) == 0) {
1962 33255 : continue;
1963 308104 : } else if (oname[0] == '%') {
1964 212 : sql_idx *i = find_sql_idx(t, oname+1);
1965 212 : if (i) {
1966 211 : cond_append(l, &i->base);
1967 211 : continue;
1968 : }
1969 : }
1970 307893 : sql_column *c = find_sql_column(t, oname);
1971 307893 : if (!c)
1972 : return -1;
1973 307893 : cond_append(l, &c->base);
1974 : }
1975 : } break;
1976 4067 : case op_table: {
1977 4067 : if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */
1978 4067 : sql_exp *op = r->r;
1979 4067 : sql_subfunc *f = op->f;
1980 4067 : cond_append(l, &f->func->base);
1981 : }
1982 : } break;
1983 77050 : case op_join:
1984 : case op_left:
1985 : case op_right:
1986 : case op_full:
1987 : case op_semi:
1988 : case op_anti:
1989 : case op_union:
1990 : case op_except:
1991 : case op_inter:
1992 :
1993 : case op_insert:
1994 : case op_update:
1995 : case op_delete:
1996 : case op_merge:
1997 154100 : if (rel_deps(sql, r->l, refs, l) != 0 ||
1998 77050 : rel_deps(sql, r->r, refs, l) != 0)
1999 0 : return -1;
2000 : break;
2001 163660 : case op_project:
2002 : case op_select:
2003 : case op_groupby:
2004 : case op_topn:
2005 : case op_sample:
2006 : case op_truncate:
2007 163660 : if (rel_deps(sql, r->l, refs, l) != 0)
2008 : return -1;
2009 : break;
2010 114526 : case op_ddl:
2011 114526 : 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) {
2012 21 : if (rel_deps(sql, r->l, refs, l) != 0)
2013 : return -1;
2014 : } else if (r->flag == ddl_list || r->flag == ddl_exception) {
2015 0 : if (rel_deps(sql, r->l, refs, l) != 0 ||
2016 0 : rel_deps(sql, r->r, refs, l) != 0)
2017 0 : return -1;
2018 : }
2019 : break;
2020 : }
2021 457000 : if (!is_base(r->op) && r->exps) {
2022 343622 : if (exps_deps(sql, r->exps, refs, l) != 0)
2023 : return -1;
2024 : }
2025 457000 : if ((is_simple_project(r->op) || is_groupby(r->op)) && r->r) {
2026 18122 : if (exps_deps(sql, r->r, refs, l) != 0)
2027 : return -1;
2028 : }
2029 457000 : if (rel_is_ref(r)) {
2030 4339 : list_append(refs, r);
2031 4339 : list_append(refs, l);
2032 : }
2033 : return 0;
2034 : }
2035 :
2036 : list *
2037 138322 : rel_dependencies(mvc *sql, sql_rel *r)
2038 : {
2039 138322 : list *refs = sa_list(sql->sa);
2040 138322 : list *l = sa_list(sql->sa);
2041 :
2042 138322 : if (rel_deps(sql, r, refs, l) != 0)
2043 0 : return NULL;
2044 : return l;
2045 : }
2046 :
2047 : static list *exps_exp_visitor(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown);
2048 :
2049 : static inline list *
2050 39483 : exps_exps_exp_visitor(visitor *v, sql_rel *rel, list *lists, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
2051 : {
2052 39483 : node *n;
2053 :
2054 39483 : if (list_empty(lists))
2055 : return lists;
2056 86628 : for (n = lists->h; n; n = n->next) {
2057 47145 : if (n->data && (n->data = exps_exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown)) == NULL)
2058 : return NULL;
2059 : }
2060 : return lists;
2061 : }
2062 :
2063 : static sql_rel *rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown);
2064 :
2065 : static sql_exp *
2066 76162847 : exp_visitor(visitor *v, sql_rel *rel, sql_exp *e, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool *changed)
2067 : {
2068 76162847 : if (mvc_highwater(v->sql))
2069 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2070 :
2071 76170826 : assert(e);
2072 76170826 : if (topdown) {
2073 874 : int changes = v->changes;
2074 874 : if (!(e = exp_rewriter(v, rel, e, depth)))
2075 : return NULL;
2076 874 : *changed |= v->changes > changes;
2077 : }
2078 :
2079 76170826 : switch(e->type) {
2080 : case e_column:
2081 : break;
2082 2205827 : case e_convert:
2083 2205827 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2084 : return NULL;
2085 : break;
2086 3961593 : case e_aggr:
2087 : case e_func:
2088 3961593 : if (e->r) /* rewrite rank -r is list of lists */
2089 39483 : if ((e->r = exps_exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2090 : return NULL;
2091 3961593 : if (e->l)
2092 3831716 : if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2093 : return NULL;
2094 : break;
2095 3211879 : case e_cmp:
2096 3211879 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2097 167425 : if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2098 : return NULL;
2099 167425 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2100 : return NULL;
2101 3044454 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2102 195173 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2103 : return NULL;
2104 195173 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2105 : return NULL;
2106 : } else {
2107 2849281 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2108 : return NULL;
2109 2849281 : if ((e->r = exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2110 : return NULL;
2111 2849281 : if (e->f && (e->f = exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2112 : return NULL;
2113 : }
2114 : break;
2115 369545 : case e_psm:
2116 369545 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
2117 114208 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2118 : return NULL;
2119 255337 : } else if (e->flag & PSM_VAR) {
2120 : return e;
2121 225471 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
2122 35134 : if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
2123 : return NULL;
2124 35134 : if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2125 : return NULL;
2126 35134 : if (e->flag == PSM_IF && e->f && (e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2127 : return NULL;
2128 190337 : } else if (e->flag & PSM_REL) {
2129 190337 : if ((e->l = rel_exp_visitor(v, e->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2130 : return NULL;
2131 : }
2132 : break;
2133 24136160 : case e_atom:
2134 24136160 : if (e->f)
2135 790447 : if ((e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
2136 : return NULL;
2137 : break;
2138 : }
2139 76140940 : if (!topdown) {
2140 76132013 : int changes = v->changes;
2141 76132013 : if (!(e = exp_rewriter(v, rel, e, depth)))
2142 : return NULL;
2143 76133151 : *changed |= v->changes > changes;
2144 : }
2145 : return e;
2146 : }
2147 :
2148 : static list *
2149 19349378 : exps_exp_visitor(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
2150 : {
2151 19349378 : bool changed = false;
2152 19349378 : if (list_empty(exps))
2153 : return exps;
2154 87287537 : for (node *n = exps->h; n; n = n->next)
2155 67969580 : if (n->data && (n->data = exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown, &changed)) == NULL)
2156 : return NULL;
2157 19317957 : if (changed && depth == 0) /* only level 0 exps use hash, so remove only on those */
2158 17864 : list_hash_clear(exps);
2159 : return exps;
2160 : }
2161 :
2162 : static inline sql_rel *
2163 14546404 : rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
2164 : {
2165 14546404 : if (mvc_highwater(v->sql))
2166 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2167 :
2168 14546826 : if (!rel)
2169 : return rel;
2170 :
2171 14546805 : if (relations_topdown) {
2172 4427665 : if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
2173 : return NULL;
2174 4427662 : 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)) == NULL)
2175 : return NULL;
2176 : }
2177 :
2178 14546802 : switch(rel->op){
2179 : case op_basetable:
2180 : break;
2181 46399 : case op_table:
2182 46399 : if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
2183 46306 : if (rel->l)
2184 567 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2185 : return NULL;
2186 : }
2187 : break;
2188 2025932 : case op_ddl:
2189 2025932 : 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) {
2190 186617 : if (rel->l)
2191 184848 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2192 : return NULL;
2193 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
2194 1892 : if (rel->l)
2195 1743 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2196 : return NULL;
2197 1892 : if (rel->r)
2198 1659 : if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
2199 : return NULL;
2200 : }
2201 : break;
2202 2507146 : case op_insert:
2203 : case op_update:
2204 : case op_delete:
2205 : case op_merge:
2206 :
2207 : case op_join:
2208 : case op_left:
2209 : case op_right:
2210 : case op_full:
2211 : case op_semi:
2212 : case op_anti:
2213 :
2214 : case op_union:
2215 : case op_inter:
2216 : case op_except:
2217 2507146 : if (rel->l)
2218 2507146 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2219 : return NULL;
2220 2507143 : if (rel->r)
2221 2505016 : if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
2222 : return NULL;
2223 : break;
2224 6530863 : case op_select:
2225 : case op_topn:
2226 : case op_sample:
2227 : case op_project:
2228 : case op_groupby:
2229 : case op_truncate:
2230 6530863 : if (rel->l)
2231 5568856 : if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
2232 : return NULL;
2233 : break;
2234 : }
2235 :
2236 14546764 : if (!relations_topdown) {
2237 10119019 : if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
2238 : return NULL;
2239 10119036 : 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)) == NULL)
2240 : return NULL;
2241 : }
2242 :
2243 : return rel;
2244 : }
2245 :
2246 : sql_rel *
2247 0 : rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2248 : {
2249 0 : return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
2250 : }
2251 :
2252 : sql_rel *
2253 3586720 : rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2254 : {
2255 3586720 : return rel_exp_visitor(v, rel, exp_rewriter, false, relations_topdown);
2256 : }
2257 :
2258 : static list *exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown);
2259 : static list *exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown);
2260 :
2261 : static sql_exp *
2262 380768818 : exp_rel_visitor(visitor *v, sql_exp *e, rel_rewrite_fptr rel_rewriter, bool topdown)
2263 : {
2264 380768818 : if (mvc_highwater(v->sql))
2265 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2266 :
2267 380792721 : assert(e);
2268 380792721 : switch(e->type) {
2269 : case e_column:
2270 : break;
2271 12721074 : case e_convert:
2272 12721074 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2273 : return NULL;
2274 : break;
2275 22328403 : case e_aggr:
2276 : case e_func:
2277 22328403 : if (e->r) /* rewrite rank */
2278 62012 : if ((e->r = exps_exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2279 : return NULL;
2280 22328403 : if (e->l)
2281 21500178 : if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2282 : return NULL;
2283 : break;
2284 23002653 : case e_cmp:
2285 23002653 : if (e->flag == cmp_or || e->flag == cmp_filter) {
2286 781675 : if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2287 : return NULL;
2288 781675 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2289 : return NULL;
2290 22220978 : } else if (e->flag == cmp_in || e->flag == cmp_notin) {
2291 1470599 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2292 : return NULL;
2293 1470599 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2294 : return NULL;
2295 : } else {
2296 20750379 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2297 : return NULL;
2298 20750380 : if ((e->r = exp_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2299 : return NULL;
2300 20750380 : if (e->f && (e->f = exp_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2301 : return NULL;
2302 : }
2303 : break;
2304 1914586 : case e_psm:
2305 1914586 : if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
2306 630720 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2307 : return NULL;
2308 1283866 : } else if (e->flag & PSM_VAR) {
2309 : return e;
2310 1092384 : } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
2311 170120 : if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
2312 : return NULL;
2313 170120 : if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
2314 : return NULL;
2315 170120 : if (e->flag == PSM_IF && e->f && (e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2316 : return NULL;
2317 922264 : } else if (e->flag & PSM_REL) {
2318 922264 : sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
2319 922264 : if ((e->l = func(v, e->l, rel_rewriter)) == NULL)
2320 : return NULL;
2321 : }
2322 : break;
2323 72190254 : case e_atom:
2324 72190254 : if (e->f)
2325 1532878 : if ((e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
2326 : return NULL;
2327 : break;
2328 : }
2329 : return e;
2330 : }
2331 :
2332 : static list *
2333 102024984 : exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown)
2334 : {
2335 102024984 : if (list_empty(exps))
2336 : return exps;
2337 425906593 : for (node *n = exps->h; n; n = n->next)
2338 324248940 : if (n->data && (n->data = exp_rel_visitor(v, n->data, rel_rewriter, topdown)) == NULL)
2339 : return NULL;
2340 : return exps;
2341 : }
2342 :
2343 : static list *
2344 62012 : exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown)
2345 : {
2346 62012 : if (list_empty(lists))
2347 : return lists;
2348 124024 : for (node *n = lists->h; n; n = n->next)
2349 62012 : if (n->data && (n->data = exps_rel_visitor(v, n->data, rel_rewriter, topdown)) == NULL)
2350 : return NULL;
2351 : return lists;
2352 : }
2353 :
2354 : static inline sql_rel *
2355 75688190 : do_rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
2356 : {
2357 75688190 : if (rel->exps && (rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
2358 : return NULL;
2359 75686805 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_rel_visitor(v, rel->r, rel_rewriter, topdown)) == NULL)
2360 : return NULL;
2361 75686805 : int changes = v->changes;
2362 75686805 : rel = rel_rewriter(v, rel);
2363 75688877 : if (rel && rel->exps && v->changes > changes) {
2364 296290 : list_hash_clear(rel->exps);
2365 296290 : if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r)
2366 12203 : list_hash_clear(rel->r);
2367 : }
2368 : return rel;
2369 : }
2370 :
2371 : static inline sql_rel *
2372 75689044 : rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
2373 : {
2374 75689044 : sql_rel *parent = v->parent;
2375 :
2376 75689044 : if (mvc_highwater(v->sql))
2377 0 : return sql_error(v->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2378 :
2379 75690854 : if (!rel)
2380 : return NULL;
2381 :
2382 75690795 : if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
2383 : return NULL;
2384 :
2385 75690748 : sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
2386 :
2387 75690748 : v->parent = rel;
2388 75690748 : switch(rel->op){
2389 : case op_basetable:
2390 : break;
2391 150535 : case op_table:
2392 150535 : if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
2393 150102 : if (rel->l)
2394 2921 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2395 : return NULL;
2396 : }
2397 : break;
2398 3928207 : case op_ddl:
2399 3928207 : 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) {
2400 414138 : if (rel->l)
2401 410560 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2402 : return NULL;
2403 : } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
2404 13766 : if (rel->l)
2405 10090 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2406 : return NULL;
2407 13766 : if (rel->r)
2408 12751 : if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
2409 : return NULL;
2410 : } else if (rel->flag == ddl_psm) {
2411 278322 : if ((rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
2412 : return NULL;
2413 : }
2414 : break;
2415 16656585 : case op_insert:
2416 : case op_update:
2417 : case op_delete:
2418 : case op_merge:
2419 :
2420 : case op_join:
2421 : case op_left:
2422 : case op_right:
2423 : case op_full:
2424 : case op_semi:
2425 : case op_anti:
2426 :
2427 : case op_union:
2428 : case op_inter:
2429 : case op_except:
2430 16656585 : if (rel->l)
2431 16656585 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2432 : return NULL;
2433 16656546 : if (rel->r)
2434 16642238 : if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
2435 : return NULL;
2436 : break;
2437 35732514 : case op_select:
2438 : case op_topn:
2439 : case op_sample:
2440 : case op_project:
2441 : case op_groupby:
2442 : case op_truncate:
2443 35732514 : if (rel->l)
2444 33266016 : if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
2445 : return NULL;
2446 : break;
2447 : }
2448 75690579 : v->parent = parent;
2449 :
2450 75690579 : if (!topdown)
2451 47084708 : rel = do_rel_visitor(v, rel, rel_rewriter, false);
2452 : return rel;
2453 : }
2454 :
2455 : sql_rel *
2456 28604674 : rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
2457 : {
2458 28604674 : v->depth++;
2459 28604674 : rel = rel_visitor(v, rel, rel_rewriter, true);
2460 28604653 : v->depth--;
2461 28604653 : return rel;
2462 : }
2463 :
2464 : sql_rel *
2465 47085766 : rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
2466 : {
2467 47085766 : v->depth++;
2468 47085766 : rel = rel_visitor(v, rel, rel_rewriter, false);
2469 47085390 : v->depth--;
2470 47085390 : return rel;
2471 : }
2472 :
2473 : list *
2474 276 : exps_exp_visitor_topdown(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2475 : {
2476 276 : return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, true, relations_topdown);
2477 : }
2478 :
2479 : list *
2480 553691 : exps_exp_visitor_bottomup(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
2481 : {
2482 553691 : return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, false, relations_topdown);
2483 : }
2484 :
2485 : static bool
2486 99396 : exps_rebind_exp(mvc *sql, sql_rel *rel, list *exps)
2487 : {
2488 99396 : bool ok = true;
2489 :
2490 99396 : if (mvc_highwater(sql)) {
2491 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2492 0 : return false;
2493 : }
2494 :
2495 99396 : if (list_empty(exps))
2496 : return true;
2497 124406 : for (node *n = exps->h; n && ok; n = n->next)
2498 78162 : ok &= rel_rebind_exp(sql, rel, n->data);
2499 : return ok;
2500 : }
2501 :
2502 : bool
2503 6285690 : rel_rebind_exp(mvc *sql, sql_rel *rel, sql_exp *e)
2504 : {
2505 6344942 : if (mvc_highwater(sql)) {
2506 0 : (void) sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
2507 0 : return false;
2508 : }
2509 :
2510 6344942 : switch (e->type) {
2511 59252 : case e_convert:
2512 59252 : return rel_rebind_exp(sql, rel, e->l);
2513 27726 : case e_aggr:
2514 : case e_func:
2515 27726 : return exps_rebind_exp(sql, rel, e->l);
2516 2721637 : case e_cmp:
2517 2721637 : if (e->flag == cmp_in || e->flag == cmp_notin)
2518 8211 : return rel_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
2519 2715489 : if (e->flag == cmp_or || e->flag == cmp_filter)
2520 18866 : return exps_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
2521 5409812 : return rel_rebind_exp(sql, rel, e->l) && rel_rebind_exp(sql, rel, e->r) && (!e->f || rel_rebind_exp(sql, rel, e->f));
2522 3483161 : case e_column:
2523 3483161 : if (e->freevar)
2524 : return true;
2525 3483147 : return rel_find_exp(rel, e) != NULL;
2526 53161 : case e_atom:
2527 53161 : return exps_rebind_exp(sql, rel, e->f);
2528 : case e_psm:
2529 : return true;
2530 : }
2531 : return true;
2532 : }
2533 :
2534 : static sql_exp *
2535 456 : _exp_freevar_offset(visitor *v, sql_rel *rel, sql_exp *e, int depth)
2536 : {
2537 456 : (void)rel; (void)depth;
2538 : /* visitor will handle recursion, ie only need to check columns here */
2539 456 : int vf = is_freevar(e);
2540 456 : if (v->changes < vf)
2541 316 : v->changes=vf;
2542 456 : return e;
2543 : }
2544 :
2545 : int
2546 306 : exp_freevar_offset(mvc *sql, sql_exp *e)
2547 : {
2548 306 : bool changed = false;
2549 306 : visitor v = { .sql = sql };
2550 :
2551 306 : (void) changed;
2552 306 : exp_visitor(&v, NULL, e, 0, &_exp_freevar_offset, true, true, &changed);
2553 : /* freevar offset is passed via changes */
2554 306 : return (v.changes);
2555 : }
|