LCOV - code coverage report
Current view: top level - sql/server - rel_rel.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1296 1507 86.0 %
Date: 2024-12-19 20:05:57 Functions: 87 92 94.6 %

          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     1296094 : project_unsafe(sql_rel *rel, bool allow_identity)
      33             : {
      34     1296094 :         sql_rel *sub = rel->l;
      35             : 
      36     1296094 :         if (need_distinct(rel) || rel->r /* order by */)
      37             :                 return 1;
      38     1224390 :         if (list_empty(rel->exps))
      39             :                 return 0;
      40             :         /* projects without sub and projects around ddl's cannot be changed */
      41     1224379 :         if (!sub || sub->op == op_ddl)
      42             :                 return 1;
      43     9912823 :         for(node *n = rel->exps->h; n; n = n->next) {
      44     8935616 :                 sql_exp *e = n->data, *ne;
      45             : 
      46             :                 /* aggr func in project ! */
      47     8935616 :                 if (exp_unsafe(e, allow_identity, false))
      48             :                         return 1;
      49     8889795 :                 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      240345 : rel_name( sql_rel *r )
      62             : {
      63      244718 :         if (is_basetable(r->op))
      64      198218 :                 return rel_base_name(r);
      65       50873 :         if (!is_project(r->op) && !is_base(r->op) && r->l)
      66             :                 return rel_name(r->l);
      67       42127 :         if (r->exps && list_length(r->exps)) {
      68       42127 :                 sql_exp *e = r->exps->h->data;
      69       42127 :                 if (exp_relname(e))
      70       42127 :                         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        9400 : rel_distinct(sql_rel *l)
      81             : {
      82        9400 :         set_distinct(l);
      83        9400 :         return l;
      84             : }
      85             : 
      86             : sql_rel *
      87      770745 : rel_dup(sql_rel *r)
      88             : {
      89      770745 :         sql_ref_inc(&r->ref);
      90      770745 :         return r;
      91             : }
      92             : 
      93             : static void
      94      677304 : rel_destroy_(sql_rel *rel)
      95             : {
      96      677304 :         if (!rel)
      97             :                 return;
      98      677304 :         switch(rel->op){
      99             :         case op_basetable:
     100             :                 break;
     101        5141 :         case op_table:
     102        5141 :                 if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
     103          11 :                         rel_destroy(rel->l);
     104             :                 break;
     105      291696 :         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      291696 :                 if (rel->l)
     119       17868 :                         rel_destroy(rel->l);
     120      291696 :                 if (rel->r)
     121       17876 :                         rel_destroy(rel->r);
     122             :                 break;
     123       41419 :         case op_munion:
     124             :                 /* the rel->l might be in purpose NULL see rel_merge_table_rewrite_() */
     125       41419 :                 if (rel->l)
     126      124338 :                         for (node *n = ((list*)rel->l)->h; n; n = n->next)
     127       83069 :                                 rel_destroy(n->data);
     128             :                 break;
     129      326846 :         case op_project:
     130             :         case op_groupby:
     131             :         case op_select:
     132             :         case op_topn:
     133             :         case op_sample:
     134             :         case op_truncate:
     135      326846 :                 if (rel->l)
     136       89896 :                         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     1388999 : rel_destroy(sql_rel *rel)
     154             : {
     155     1388999 :         if (!rel)
     156             :                 return;
     157     1388995 :         if (sql_ref_dec(&rel->ref) > 0)
     158             :                 return;
     159      636639 :         rel_destroy_(rel);
     160             : }
     161             : 
     162             : sql_rel*
     163     3272477 : rel_create(allocator *sa)
     164             : {
     165     3272477 :         sql_rel *r = SA_NEW(sa, sql_rel);
     166     3272476 :         if(!r)
     167             :                 return NULL;
     168             : 
     169     3272476 :         *r = (sql_rel) {
     170             :                 .card = CARD_ATOM,
     171             :         };
     172     3272476 :         sql_ref_init(&r->ref);
     173     3272476 :         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        3951 : rel_select_copy(allocator *sa, sql_rel *l, list *exps)
     279             : {
     280        3951 :         sql_rel *rel = rel_create(sa);
     281        3951 :         if(!rel)
     282             :                 return NULL;
     283             : 
     284        3951 :         rel->l = l;
     285        3951 :         rel->r = NULL;
     286        3951 :         rel->op = op_select;
     287        3951 :         rel->exps = exps?list_dup(exps, (fdup)NULL):NULL;
     288        3951 :         rel->card = CARD_ATOM; /* no relation */
     289        3951 :         if (l) {
     290        3951 :                 rel->card = l->card;
     291        3951 :                 rel->nrcols = l->nrcols;
     292             :         }
     293             :         return rel;
     294             : }
     295             : 
     296             : sql_exp *
     297     8008329 : rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int no_tname)
     298             : {
     299     8008329 :         int ambiguous = 0, multi = 0;
     300             : 
     301     8008329 :         if (!rel)
     302             :                 return NULL;
     303     8008329 :         if (mvc_highwater(sql))
     304           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     305             : 
     306     8008329 :         if ((is_project(rel->op) || is_base(rel->op))) {
     307     4253895 :                 sql_exp *e = NULL;
     308             : 
     309     4253895 :                 if (is_base(rel->op) && !rel->exps)
     310     4071537 :                         return rel_base_bind_column(sql, rel, cname, no_tname);
     311      182358 :                 if (!list_empty(rel->exps)) {
     312      182296 :                         e = exps_bind_column(rel->exps, cname, &ambiguous, &multi, no_tname);
     313      182296 :                         if (ambiguous || multi)
     314          10 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     315      182286 :                         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       19435 :                 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      162771 :                 if (e)
     338      162771 :                         return exp_ref(sql, e);
     339             :         }
     340     3773868 :         if (is_simple_project(rel->op) && rel->l) {
     341        7106 :                 if (!is_processed(rel))
     342           0 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     343     3766762 :         } else if (is_set(rel->op)) {
     344          19 :                 assert(is_processed(rel));
     345             :                 return NULL;
     346             :         } else if (is_join(rel->op)) {
     347     3241503 :                 sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), *e2 = NULL, *res;
     348             : 
     349     3241503 :                 if (e1 && (is_right(rel->op) || is_full(rel->op)))
     350           6 :                         set_has_nil(e1);
     351     1619101 :                 if (!e1 || !is_freevar(e1)) {
     352     3241503 :                         e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
     353     3241503 :                         if (e2 && (is_left(rel->op) || is_full(rel->op)))
     354          57 :                                 set_has_nil(e2);
     355     3241503 :                         if (e1 && e2 && !is_dependent(rel))
     356          23 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     357             :                 }
     358     3241480 :                 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     3241480 :                 res = e1 ? e1 : e2;
     364     1622402 :                 if (res)
     365     1708215 :                         set_not_unique(res);
     366     3241480 :                 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      512931 :                 if (rel->l)
     372      512931 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     373             :         }
     374             :         return NULL;
     375             : }
     376             : 
     377             : sql_exp *
     378     4487560 : rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f)
     379             : {
     380     4487560 :         int ambiguous = 0, multi = 0;
     381             : 
     382     4487560 :         if (!rel)
     383             :                 return NULL;
     384     4487560 :         if (mvc_highwater(sql))
     385           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     386             : 
     387     4487560 :         if ((is_project(rel->op) || is_base(rel->op))) {
     388     2101290 :                 sql_exp *e = NULL;
     389             : 
     390     2101290 :                 if (is_basetable(rel->op) && !rel->exps)
     391     1337441 :                         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      763849 :                 if (!list_empty(rel->exps)) {
     394      763769 :                         e = exps_bind_column2(rel->exps, tname, cname, &multi);
     395      763769 :                         if (multi)
     396           1 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     397             :                                                                  tname, cname);
     398      763768 :                         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      242224 :                 if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
     413         105 :                         e = exps_bind_column2(rel->r, tname, cname, &multi);
     414         105 :                         if (multi)
     415           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     416             :                                                                  tname, cname);
     417         105 :                         if (e) {
     418          10 :                                 e = exp_ref(sql, e);
     419          10 :                                 e->card = rel->card;
     420          10 :                                 return e;
     421             :                         }
     422             :                 }
     423      521621 :                 if (e)
     424      521621 :                         return exp_ref(sql, e);
     425             :         }
     426     2628484 :         if (is_simple_project(rel->op) && rel->l) {
     427      233565 :                 if (!is_processed(rel))
     428           0 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     429     2394919 :         } else if (is_set(rel->op)) {
     430           3 :                 assert(is_processed(rel));
     431             :                 return NULL;
     432             :         } else if (is_join(rel->op)) {
     433     1923094 :                 sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
     434             : 
     435     1923094 :                 if (e && (is_right(rel->op) || is_full(rel->op)))
     436         194 :                         set_has_nil(e);
     437         194 :                 if (!e) {
     438      851644 :                         e = rel_bind_column2(sql, rel->r, tname, cname, f);
     439      851644 :                         if (e && (is_left(rel->op) || is_full(rel->op)))
     440       23087 :                                 set_has_nil(e);
     441             :                 }
     442      404230 :                 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      381143 :                 if (e)
     449     1541952 :                         set_not_unique(e);
     450     1923094 :                 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      463176 :                 if (rel->l)
     456      463176 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     457             :         }
     458             :         return NULL;
     459             : }
     460             : 
     461             : sql_exp *
     462     1246423 : rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname, int f)
     463             : {
     464     1246423 :         if (!sname)
     465     1246422 :                 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       83913 : rel_inplace_reset_props(sql_rel *rel)
     517             : {
     518       83913 :         rel->flag = 0;
     519       83913 :         rel->attr = NULL;
     520       83913 :         reset_dependent(rel);
     521       83913 :         set_processed(rel);
     522             : }
     523             : 
     524             : sql_rel *
     525         108 : rel_inplace_basetable(sql_rel *rel, sql_rel *bt)
     526             : {
     527         108 :         assert(is_basetable(bt->op));
     528             : 
     529         108 :         rel_destroy_(rel);
     530         108 :         rel_inplace_reset_props(rel);
     531         108 :         rel->l = bt->l;
     532         108 :         rel->r = bt->r;
     533         108 :         rel->op = op_basetable;
     534         108 :         rel->exps = bt->exps;
     535         108 :         rel->card = CARD_MULTI;
     536         108 :         rel->nrcols = bt->nrcols;
     537         108 :         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       39184 : 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       39184 :         assert(setop == op_munion);
     558       39184 :         rel_destroy_(rel);
     559       39184 :         rel_inplace_reset_props(rel);
     560             :         /* rl should be a list of relations */
     561       39184 :         rel->l = rl;
     562       39184 :         rel->r = NULL;
     563       39184 :         rel->op = setop;
     564       39184 :         rel->card = CARD_MULTI;
     565       39184 :         rel_setop_n_ary_set_exps(sql, rel, exps, false);
     566       39184 :         return rel;
     567             : }
     568             : 
     569             : sql_rel *
     570       43299 : rel_inplace_project(allocator *sa, sql_rel *rel, sql_rel *l, list *e)
     571             : {
     572       43299 :         if (!l) {
     573       43248 :                 l = rel_create(sa);
     574       43248 :                 if(!l)
     575             :                         return NULL;
     576             : 
     577       43248 :                 *l = *rel;
     578       43248 :                 l->ref.refcnt = 1;
     579             :         } else {
     580          51 :                 rel_destroy_(rel);
     581             :         }
     582       43299 :         rel_inplace_reset_props(rel);
     583       43299 :         rel->l = l;
     584       43299 :         rel->r = NULL;
     585       43299 :         rel->op = op_project;
     586       43299 :         rel->exps = e;
     587       43299 :         rel->card = CARD_MULTI;
     588       43299 :         if (l) {
     589       43299 :                 rel->nrcols = l->nrcols;
     590       43299 :                 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         557 : rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps )
     616             : {
     617         557 :         rel_destroy_(rel);
     618         557 :         rel_inplace_reset_props(rel);
     619         557 :         rel->card = CARD_ATOM;
     620         557 :         if (groupbyexps)
     621         436 :                 rel->card = CARD_AGGR;
     622         557 :         rel->l = l;
     623         557 :         rel->r = groupbyexps;
     624         557 :         rel->exps = exps;
     625         557 :         rel->nrcols = l->nrcols;
     626         557 :         rel->op = op_groupby;
     627         557 :         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        2900 : rel_setop(allocator *sa, sql_rel *l, sql_rel *r, operator_type setop)
     709             : {
     710        2900 :         sql_rel *rel = rel_create(sa);
     711        2900 :         if(!rel)
     712             :                 return NULL;
     713        2900 :         rel->l = l;
     714        2900 :         rel->r = r;
     715        2900 :         rel->op = setop;
     716        2900 :         rel->exps = NULL;
     717        2900 :         rel->card = CARD_MULTI;
     718        2900 :         assert(l->nrcols == r->nrcols);
     719        2900 :         rel->nrcols = l->nrcols;
     720        2900 :         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        2878 : rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     755             : {
     756        2878 :         sql_rel *l = rel->l, *r = rel->r;
     757        2878 :         list *lexps = l->exps, *rexps = r->exps;
     758             : 
     759        2878 :         if (!is_project(l->op))
     760          22 :                 lexps = rel_projections(sql, l, NULL, 0, 1);
     761        2878 :         if (!is_project(r->op))
     762          23 :                 rexps = rel_projections(sql, r, NULL, 0, 1);
     763             : 
     764        2878 :         assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && list_length(exps) == list_length(lexps)*/);
     765             : 
     766       11862 :         for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n = n->next, m = m->next,o = o->next) {
     767        8984 :                 sql_exp *e = n->data, *f = m->data, *g = o->data;
     768             : 
     769        8984 :                 assert(e->alias.label);
     770        8984 :                 e->nid = 0; /* setops are positional */
     771        8984 :                 if (is_union(rel->op)) { /* propagate set_has_no_nil only if it's applicable to both sides of the union*/
     772        6046 :                         if (has_nil(f) || has_nil(g))
     773        5150 :                                 set_has_nil(e);
     774             :                         else
     775         896 :                                 set_has_no_nil(e);
     776        6046 :                         if (!keep_props) {
     777        6046 :                                 e->p = NULL; /* remove all the properties on unions on the general case */
     778        6046 :                                 set_not_unique(e);
     779             :                         }
     780             :                 }
     781        8984 :                 e->card = CARD_MULTI; /* multi cardinality */
     782             :         }
     783        2878 :         rel->nrcols = l->nrcols;
     784        2878 :         rel->exps = exps;
     785        2878 : }
     786             : 
     787             : sql_rel *
     788       62288 : rel_setop_n_ary(allocator *sa, list *rels, operator_type setop)
     789             : {
     790             :         // TODO: for now we support only n-ary union
     791       62288 :         assert(setop == op_munion);
     792             : 
     793       62288 :         if (!rels)
     794             :                 return NULL;
     795             : 
     796       62288 :         assert(list_length(rels) >= 2);
     797       62288 :         sql_rel *rel = rel_create(sa);
     798       62288 :         if(!rel)
     799             :                 return NULL;
     800             : 
     801       62288 :         rel->l = rels;
     802       62288 :         rel->r = NULL;
     803       62288 :         rel->op = setop;
     804       62288 :         rel->exps = NULL;
     805       62288 :         rel->card = CARD_MULTI;
     806             :         // TODO: properly introduce the assertion over rels elements
     807             :         /*assert(l->nrcols == r->nrcols);*/
     808       62288 :         rel->nrcols = ((sql_rel*)rels->h->data)->nrcols;
     809       62288 :         return rel;
     810             : }
     811             : 
     812             : sql_rel *
     813       58459 : 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       58459 :         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       58459 :         list *nls = new_exp_list(sql->sa);
     826       58459 :         list *nrs = new_exp_list(sql->sa);
     827       58459 :         node *n, *m;
     828       58459 :         list* rels;
     829             : 
     830       58459 :         if(!nls || !nrs)
     831             :                 return NULL;
     832             : 
     833      458028 :         for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
     834      399573 :                 sql_exp *le = n->data;
     835      399573 :                 sql_exp *re = m->data;
     836             : 
     837      399573 :                 if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
     838           4 :                         return NULL;
     839      399569 :                 append(nls, le);
     840      399569 :                 append(nrs, re);
     841             :         }
     842       58455 :         l = rel_project(sql->sa, l, nls);
     843       58455 :         r = rel_project(sql->sa, r, nrs);
     844       58455 :         set_processed(l);
     845       58455 :         set_processed(r);
     846             : 
     847             :         /* create a list with only 2 sql_rel entries for the n-ary set op */
     848       58455 :         rels = sa_list(sql->sa);
     849       58455 :         append(rels, l);
     850       58455 :         append(rels, r);
     851             : 
     852       58455 :         return rel_setop_n_ary(sql->sa, rels, op);
     853             : }
     854             : 
     855             : void
     856       99941 : rel_setop_n_ary_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     857             : {
     858       99941 :         list *rexps;
     859       99941 :         sql_rel *r;
     860             : 
     861             :         /* set the exps properties first */
     862      785792 :         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      685851 :                 sql_exp *e = (sql_exp*)m->data;
     867      685851 :                 set_has_no_nil(e);
     868             :                 /* remove all the properties on unions on the general case */
     869      685851 :                 if (!keep_props) {
     870      685558 :                         e->p = NULL;
     871      685558 :                         set_not_unique(e);
     872             :                 }
     873             :         }
     874             : 
     875             :         /* for every relation in the list of relations */
     876      300541 :         for (node *n = ((list*)rel->l)->h; n; n = n->next) {
     877      200600 :                 r = n->data;
     878      200600 :                 rexps = r->exps;
     879             : 
     880      200600 :                 if (!is_project(r->op))
     881       13380 :                         rexps = rel_projections(sql, r, NULL, 0, 1);
     882             : 
     883             :                 /* go through the relation's exps */
     884     1575691 :                 for (node *m = exps->h, *o = rexps->h; m && o; m = m->next, o = o->next) {
     885     1375091 :                         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     1375091 :                         if (is_munion(rel->op) && has_nil(f))
     888      479759 :                                 set_has_nil(e);
     889     1375091 :                         e->card = CARD_MULTI;
     890             :                 }
     891             :         }
     892             : 
     893       99941 :         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       99941 :         rel->nrcols = ((sql_rel*)((list*)rel->l)->h->data)->nrcols;
     897       99941 : }
     898             : 
     899             : sql_rel *
     900      522650 : rel_crossproduct(allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
     901             : {
     902      522650 :         sql_rel *rel = rel_create(sa);
     903      522650 :         if(!rel)
     904             :                 return NULL;
     905             : 
     906      522650 :         rel->l = l;
     907      522650 :         rel->r = r;
     908      522650 :         rel->op = join;
     909      522650 :         rel->exps = NULL;
     910      522650 :         rel->card = CARD_MULTI;
     911      522650 :         rel->nrcols = l->nrcols + r->nrcols;
     912      522650 :         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       16840 : rel_topn(allocator *sa, sql_rel *l, list *exps )
     934             : {
     935       16840 :         sql_rel *rel = rel_create(sa);
     936       16840 :         if(!rel)
     937             :                 return NULL;
     938             : 
     939       16840 :         rel->l = l;
     940       16840 :         rel->r = NULL;
     941       16840 :         rel->op = op_topn;
     942       16840 :         rel->exps = exps;
     943       16840 :         rel->card = l->card;
     944       16840 :         rel->nrcols = l->nrcols;
     945       16840 :         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       15250 : rel_label( mvc *sql, sql_rel *r, int all)
     966             : {
     967       15250 :         int nr = ++sql->label;
     968       15250 :         char tname[16], *tnme;
     969       15250 :         char cname[16], *cnme = NULL;
     970             : 
     971       15250 :         tnme = sa_strdup(sql->sa, number2name(tname, sizeof(tname), nr));
     972       15250 :         if (!is_simple_project(r->op))
     973         611 :                 r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 1));
     974       15250 :         if (!list_empty(r->exps)) {
     975       15250 :                 list_hash_clear(r->exps);
     976       59863 :                 for (node *ne = r->exps->h; ne; ne = ne->next) {
     977       44613 :                         sql_exp *e = ne->data;
     978             : 
     979       44613 :                         if (!is_freevar(e)) {
     980       44608 :                                 if (all) {
     981       44608 :                                         nr = ++sql->label;
     982       44608 :                                         cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
     983             :                                 }
     984       44608 :                                 exp_setname(sql, e, tnme, cnme );
     985             :                         }
     986             :                 }
     987             :         }
     988             :         /* op_projects can have a order by list */
     989       15250 :         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       15250 :         return r;
     999             : }
    1000             : 
    1001             : sql_exp *
    1002       29965 : rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e)
    1003             : {
    1004       29965 :         assert(is_project(rel->op));
    1005             : 
    1006       29965 :         if (!e->alias.label)
    1007         112 :                 exp_label(sql->sa, e, ++sql->label);
    1008       29965 :         if (is_simple_project(rel->op)) {
    1009       29961 :                 sql_rel *l = rel->l;
    1010       29961 :                 if (!rel->exps)
    1011          24 :                         rel->exps = new_exp_list(sql->sa);
    1012       29961 :                 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       29961 :                 if (e->card > rel->card)
    1015           0 :                         rel->card = e->card;
    1016       29961 :                 append(rel->exps, e);
    1017       29961 :                 rel->nrcols++;
    1018           4 :         } else if (is_groupby(rel->op)) {
    1019           4 :                 return rel_groupby_add_aggr(sql, rel, e);
    1020             :         }
    1021       29961 :         e = exp_ref(sql, e);
    1022       29961 :         return e;
    1023             : }
    1024             : 
    1025             : sql_rel *
    1026      282222 : rel_select_add_exp(allocator *sa, sql_rel *l, sql_exp *e)
    1027             : {
    1028      282222 :         if ((l->op != op_select && !is_outerjoin(l->op)) || rel_is_ref(l))
    1029        8138 :                 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      274084 :         if (!l->exps)
    1038        3819 :                 l->exps = new_exp_list(sa);
    1039      274084 :         append(l->exps, e);
    1040      274084 :         return l;
    1041             : }
    1042             : 
    1043             : void
    1044      484853 : rel_join_add_exp( allocator *sa, sql_rel *rel, sql_exp *e)
    1045             : {
    1046      484853 :         assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
    1047             : 
    1048      484853 :         if (!rel->exps)
    1049      439699 :                 rel->exps = new_exp_list(sa);
    1050      484853 :         append(rel->exps, e);
    1051      484853 :         if (e->card > rel->card)
    1052           0 :                 rel->card = e->card;
    1053      484853 : }
    1054             : 
    1055             : sql_exp *
    1056       77680 : rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
    1057             : {
    1058       77680 :         sql_exp *m = NULL, *ne;
    1059             : 
    1060       77680 :         if (list_empty(rel->r))
    1061       26090 :                 rel->card = e->card = CARD_ATOM;
    1062             : 
    1063       77680 :         if ((m=exps_any_match(rel->exps, e)) == NULL) {
    1064       45019 :                 if (!exp_name(e))
    1065       44995 :                         exp_label(sql->sa, e, ++sql->label);
    1066       45019 :                 append(rel->exps, e);
    1067       45019 :                 rel->nrcols++;
    1068       45019 :                 m = e;
    1069             :         }
    1070       77680 :         ne = exp_ref(sql, m);
    1071       77680 :         return ne;
    1072             : }
    1073             : 
    1074             : sql_rel *
    1075      265129 : rel_select(allocator *sa, sql_rel *l, sql_exp *e)
    1076             : {
    1077      265129 :         sql_rel *rel;
    1078             : 
    1079      265129 :         if (l && is_outerjoin(l->op) && !is_processed(l)) {
    1080         211 :                 if (e) {
    1081         195 :                         if (!l->exps)
    1082         180 :                                 l->exps = new_exp_list(sa);
    1083         195 :                         append(l->exps, e);
    1084             :                 }
    1085         211 :                 return l;
    1086             :         }
    1087             : 
    1088      264918 :         if (l && is_select(l->op) && !rel_is_ref(l)) { /* refine old select */
    1089       16673 :                 if (e)
    1090        9530 :                         rel_select_add_exp(sa, l, e);
    1091       16673 :                 return l;
    1092             :         }
    1093      248245 :         rel = rel_create(sa);
    1094      248245 :         if(!rel)
    1095             :                 return NULL;
    1096             : 
    1097      248245 :         rel->l = l;
    1098      248245 :         rel->r = NULL;
    1099      248245 :         rel->op = op_select;
    1100      248245 :         rel->exps = new_exp_list(sa);
    1101      248245 :         if (e)
    1102      192310 :                 rel_select_add_exp(sa, rel, e);
    1103      248245 :         rel->card = CARD_ATOM; /* no relation */
    1104      248245 :         if (l) {
    1105      248245 :                 rel->card = l->card;
    1106      248245 :                 rel->nrcols = l->nrcols;
    1107      248245 :                 if (is_single(l))
    1108        1526 :                         set_single(rel);
    1109             :         }
    1110             :         return rel;
    1111             : }
    1112             : 
    1113             : sql_rel *
    1114       37080 : rel_groupby(mvc *sql, sql_rel *l, list *groupbyexps )
    1115             : {
    1116       37080 :         sql_rel *rel = rel_create(sql->sa);
    1117       37080 :         list *aggrs = new_exp_list(sql->sa);
    1118       37080 :         node *en;
    1119       37080 :         if(!rel || !aggrs) {
    1120           0 :                 rel_destroy(rel);
    1121           0 :                 return NULL;
    1122             :         }
    1123             : 
    1124       37080 :         rel->card = CARD_ATOM;
    1125             :         /* reduce duplicates in groupbyexps */
    1126       37080 :         if (groupbyexps && list_length(groupbyexps) > 1) {
    1127        5129 :                 list *gexps = sa_list(sql->sa);
    1128             : 
    1129       24699 :                 for (en = groupbyexps->h; en; en = en->next) {
    1130       19570 :                         sql_exp *e = en->data, *ne = exps_find_exp(gexps, e);
    1131             : 
    1132       19570 :                         if (!ne) {
    1133       19467 :                                 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       10442 :         if (groupbyexps) {
    1145       10442 :                 rel->card = CARD_AGGR;
    1146       35090 :                 for (en = groupbyexps->h; en; en = en->next) {
    1147       24648 :                         sql_exp *e = en->data, *ne;
    1148             : 
    1149       24648 :                         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       24619 :                         e->card = MIN(e->card, rel->card); /* if the column is an atom, the cardinality should not change */
    1155       24619 :                         if (!e->alias.label)
    1156          84 :                                 exp_label(sql->sa, e, ++sql->label);
    1157       24619 :                         ne = exp_ref(sql, e);
    1158       24619 :                         ne = exp_propagate(sql->sa, ne, e);
    1159       24619 :                         append(aggrs, ne);
    1160             :                 }
    1161             :         }
    1162       37080 :         rel->l = l;
    1163       37080 :         rel->r = groupbyexps;
    1164       37080 :         rel->exps = aggrs;
    1165       37080 :         rel->nrcols = aggrs?list_length(aggrs):0;
    1166       37080 :         rel->op = op_groupby;
    1167       37080 :         rel->grouped = 1;
    1168       37080 :         return rel;
    1169             : }
    1170             : 
    1171             : sql_rel *
    1172      978982 : rel_project(allocator *sa, sql_rel *l, list *e)
    1173             : {
    1174      978982 :         sql_rel *rel = rel_create(sa);
    1175      978984 :         if(!rel)
    1176             :                 return NULL;
    1177             : 
    1178      978984 :         rel->l = l;
    1179      978984 :         rel->r = NULL;
    1180      978984 :         rel->op = op_project;
    1181      978984 :         rel->exps = e;
    1182      978984 :         rel->card = exps_card(e);
    1183      978984 :         if (l) {
    1184      796378 :                 rel->card = l->card;
    1185      796378 :                 if (e)
    1186      739321 :                         rel->nrcols = list_length(e);
    1187             :                 else
    1188       57057 :                         rel->nrcols = l->nrcols;
    1189      796378 :                 rel->single = is_single(l);
    1190             :         }
    1191      978984 :         if (e && !list_empty(e)) {
    1192      921308 :                 set_processed(rel);
    1193      921308 :                 rel->nrcols = list_length(e);
    1194             :         }
    1195             :         return rel;
    1196             : }
    1197             : 
    1198             : sql_rel *
    1199       72632 : rel_project_exp(mvc *sql, sql_exp *e)
    1200             : {
    1201       72632 :         if (!exp_name(e))
    1202       72632 :                 exp_label(sql->sa, e, ++sql->label);
    1203       72630 :         return rel_project(sql->sa, NULL, list_append(sa_list(sql->sa), e));
    1204             : }
    1205             : 
    1206             : sql_rel *
    1207      118068 : rel_list(allocator *sa, sql_rel *l, sql_rel *r)
    1208             : {
    1209      118068 :         sql_rel *rel = rel_create(sa);
    1210      118068 :         if (!rel)
    1211             :                 return NULL;
    1212      118068 :         if (!l)
    1213             :                 return r;
    1214         568 :         rel->l = l;
    1215         568 :         rel->r = r;
    1216         568 :         rel->op = op_ddl;
    1217         568 :         rel->flag = ddl_list;
    1218         568 :         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       17084 : rel_table_func(allocator *sa, sql_rel *l, sql_exp *f, list *exps, int kind)
    1254             : {
    1255       17084 :         sql_rel *rel = rel_create(sa);
    1256       17084 :         if(!rel)
    1257             :                 return NULL;
    1258             : 
    1259       17084 :         assert(kind > 0);
    1260       17084 :         rel->flag = kind;
    1261       17084 :         rel->l = l; /* relation before call */
    1262       17084 :         rel->r = f; /* expression (table func call) */
    1263       17084 :         rel->op = op_table;
    1264       17084 :         rel->exps = exps;
    1265       17084 :         rel->card = CARD_MULTI;
    1266       17084 :         rel->nrcols = list_length(exps);
    1267       17084 :         return rel;
    1268             : }
    1269             : 
    1270             : static void
    1271      314698 : exps_reset_props(list *exps, bool setnil)
    1272             : {
    1273      314698 :         if (!list_empty(exps)) {
    1274     3248939 :                 for (node *m = exps->h; m; m = m->next) {
    1275     2937120 :                         sql_exp *e = m->data;
    1276             : 
    1277     2937120 :                         if (setnil)
    1278      229461 :                                 set_has_nil(e);
    1279     2937120 :                         set_not_unique(e);
    1280             :                 }
    1281             :         }
    1282      314698 : }
    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     1083151 : _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern, int basecol /* basecol only */ )
    1289             : {
    1290     1157407 :         list *lexps, *rexps = NULL, *exps = NULL, *rels;
    1291             : 
    1292     1157407 :         if (mvc_highwater(sql))
    1293           1 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1294             : 
    1295     1157406 :         if (!rel)
    1296           0 :                 return new_exp_list(sql->sa);
    1297             : 
    1298     1157406 :         if (!tname && is_basetable(rel->op) && !is_processed(rel))
    1299      280002 :                 rel_base_use_all( sql, rel);
    1300             : 
    1301     1157406 :         switch(rel->op) {
    1302      157349 :         case op_join:
    1303             :         case op_left:
    1304             :         case op_right:
    1305             :         case op_full:
    1306      157349 :                 lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1307      157349 :                 exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
    1308      157349 :                 if (!rel->attr)
    1309      154482 :                         rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
    1310      157349 :                 exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
    1311      157349 :                 if (rexps)
    1312      154482 :                         lexps = list_merge(lexps, rexps, (fdup)NULL);
    1313      157349 :                 if (rel->attr)
    1314        2867 :                         append(lexps, exp_ref(sql, rel->attr->h->data));
    1315             :                 return lexps;
    1316        6609 :         case op_groupby:
    1317        6609 :                 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      925801 :                 if (is_basetable(rel->op) && !rel->exps)
    1347      101625 :                         return rel_base_projection(sql, rel, intern);
    1348      824176 :                 if (rel->exps) {
    1349      763239 :                         exps = new_exp_list(sql->sa);
    1350     6114143 :                         for (node *en = rel->exps->h; en; en = en->next) {
    1351     5350904 :                                 sql_exp *e = en->data;
    1352             : 
    1353     5350904 :                                 if (basecol && !is_basecol(e))
    1354          52 :                                         continue;
    1355     5350852 :                                 if (intern || !is_intern(e)) {
    1356     5337348 :                                         if (!e->alias.label)
    1357       21451 :                                                 en->data = e = exp_label(sql->sa, e, ++sql->label);
    1358     5337348 :                                         sql_exp *ne = exp_ref(sql, e);
    1359     5337348 :                                         if (settname && tname)
    1360           0 :                                                 exp_setname(sql, ne, tname, exp_name(e));
    1361     5337348 :                                         assert(ne->alias.label);
    1362     5337348 :                                         e = ne;
    1363     5337348 :                                         append(exps, e);
    1364             :                                 }
    1365             :                         }
    1366             :                         return exps;
    1367             :                 }
    1368             :                 /* differentiate for the munion set op (for now) */
    1369       60937 :                 if (is_munion(rel->op)) {
    1370       58455 :                         sql_rel *r = NULL;
    1371       58455 :                         assert(rel->l);
    1372             :                         /* get the exps from the first relation */
    1373       58455 :                         rels = rel->l;
    1374       58455 :                         if (rels->h)
    1375       58455 :                                 r = rels->h->data;
    1376       58455 :                         if (r)
    1377       58455 :                                 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       58455 :                         if (exps) {
    1390      458024 :                                 for (node *en = exps->h; en; en = en->next) {
    1391      399569 :                                         sql_exp *e = en->data;
    1392             : 
    1393      399569 :                                         e->card = rel->card;
    1394      399569 :                                         if (!settname) /* noname use alias */
    1395      399569 :                                                 exp_setname(sql, e, exp_relname(e), exp_name(e));
    1396             :                                 }
    1397       58455 :                                 if (!settname)
    1398       58455 :                                         list_hash_clear(rel->l);
    1399             :                         }
    1400       58455 :                         return exps;
    1401             :                 }
    1402             :                 /* I only expect set relations to hit here */
    1403        2482 :                 assert(is_set(rel->op));
    1404        2482 :                 lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1405        2482 :                 rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
    1406        2482 :                 if (lexps && rexps) {
    1407             : 
    1408        2482 :                         assert(list_length(lexps) == list_length(rexps));
    1409        5205 :                         for (node *en = lexps->h; en; en = en->next) {
    1410        2723 :                                 sql_exp *e = en->data;
    1411             : 
    1412        2723 :                                 e->card = rel->card;
    1413        2723 :                                 if (!settname) /* noname use alias */
    1414        2723 :                                         exp_setname(sql, e, exp_relname(e), exp_name(e));
    1415             :                         }
    1416        2482 :                         if (!settname)
    1417        2482 :                                 list_hash_clear(lexps);
    1418             :                 }
    1419             :                 return lexps;
    1420             : 
    1421       74256 :         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       74256 :                 return _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1429             :         default:
    1430             :                 return NULL;
    1431             :         }
    1432             : }
    1433             : 
    1434             : list *
    1435      665987 : rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern)
    1436             : {
    1437      665987 :         assert(tname == NULL);
    1438      665987 :         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     4038538 : rel_bind_path_(mvc *sql, sql_rel *rel, sql_exp *e, list *path )
    1447             : {
    1448     4038538 :         int found = 0;
    1449             : 
    1450     4038538 :         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     4038538 :         switch (rel->op) {
    1456     1874133 :         case op_join:
    1457             :         case op_left:
    1458             :         case op_right:
    1459             :         case op_full:
    1460             :                 /* first right (possible subquery) */
    1461     1874133 :                 found = rel_bind_path_(sql, rel->r, e, path);
    1462     1874133 :                 if (!found)
    1463     1576131 :                         found = rel_bind_path_(sql, rel->l, e, path);
    1464     1576131 :                 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      115227 :         case op_semi:
    1471             :         case op_anti:
    1472             :         case op_select:
    1473             :         case op_topn:
    1474             :         case op_sample:
    1475      115227 :                 found = rel_bind_path_(sql, rel->l, e, path);
    1476      115227 :                 break;
    1477     2049178 :         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     2049178 :                 if (is_basetable(rel->op) && !rel->exps) {
    1486     1855139 :                         assert(e->nid);
    1487     1855139 :                         if (rel_base_has_nid(rel, e->nid))
    1488             :                                 found = 1;
    1489      194039 :                 } else if (rel->exps) {
    1490      194039 :                         assert(e->nid);
    1491      194039 :                         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      115233 :         if (found)
    1504     2417504 :                 list_prepend(path, rel);
    1505             :         return found;
    1506             : }
    1507             : 
    1508             : static list *
    1509      499758 : rel_bind_path(mvc *sql, sql_rel *rel, sql_exp *e, list *path)
    1510             : {
    1511      499758 :         if (!path)
    1512             :                 return NULL;
    1513             : 
    1514      499758 :         if (e->type == e_convert) {
    1515       21081 :                 if (!(path = rel_bind_path(sql, rel, e->l, path)))
    1516             :                         return NULL;
    1517      478677 :         } else if (e->type == e_column) {
    1518      473047 :                 if (rel) {
    1519      473047 :                         if (!rel_bind_path_(sql, rel, e, path)) {
    1520             :                                 /* something is wrong */
    1521             :                                 return NULL;
    1522             :                         }
    1523             :                 }
    1524      473047 :                 return path;
    1525             :         }
    1526             :         /* default the top relation */
    1527       26711 :         append(path, rel);
    1528       26711 :         return path;
    1529             : }
    1530             : 
    1531             : static sql_rel *
    1532       20850 : rel_select_push_exp_down(mvc *sql, sql_rel *rel, sql_exp *e)
    1533             : {
    1534       20850 :         sql_rel *r = rel->l, *jl = r->l, *jr = r->r;
    1535       20850 :         int left = r->op == op_join || r->op == op_left;
    1536       20850 :         int right = r->op == op_join || r->op == op_right;
    1537       20850 :         int done = 0;
    1538             : 
    1539       20850 :         assert(is_select(rel->op));
    1540       20850 :         if (!is_full(r->op) && !is_single(r)) {
    1541       20850 :                 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       20841 :                 } 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       20835 :                 rel_select_add_exp(sql->sa, rel, e);
    1551       20850 :         return rel;
    1552             : }
    1553             : 
    1554             : /* ls is the left expression of the select, e is the select expression.  */
    1555             : sql_rel *
    1556      111765 : rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
    1557             : {
    1558      111765 :         list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
    1559      111765 :         node *n;
    1560      111765 :         sql_rel *lrel = NULL, *p = NULL;
    1561             : 
    1562      111765 :         if (!l)
    1563             :                 return NULL;
    1564      111765 :         if (is_sql_or(f)) /* expression has no clear parent relation, so filter current with it */
    1565       21934 :                 return rel_select(sql->sa, rel, e);
    1566             : 
    1567      256207 :         for (n = l->h; n; n = n->next ) {
    1568      255481 :                 lrel = n->data;
    1569             : 
    1570      255481 :                 if (rel_is_ref(lrel))
    1571             :                         break;
    1572             : 
    1573             :                 /* push down as long as the operators allow this */
    1574      255170 :                 if (!is_select(lrel->op) &&
    1575      234675 :                     !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1576       88794 :                     lrel->op != op_join &&
    1577             :                     lrel->op != op_left)
    1578             :                         break;
    1579             :                 /* pushing through left head of a left join is allowed */
    1580      166380 :                 if (lrel->op == op_left && (!n->next || lrel->l != n->next->data))
    1581             :                         break;
    1582      166376 :                 p = lrel;
    1583             :         }
    1584       89831 :         if (!lrel)
    1585             :                 return NULL;
    1586       89831 :         if (p && is_select(p->op) && !rel_is_ref(p)) { /* refine old select */
    1587       18038 :                 p = rel_select_push_exp_down(sql, p, e);
    1588             :         } else {
    1589       71793 :                 sql_rel *n = rel_select(sql->sa, lrel, e);
    1590             : 
    1591       71793 :                 if (p && p != lrel) {
    1592       66088 :                         assert(p->op == op_join || p->op == op_left || is_semi(p->op));
    1593       66088 :                         if (p->l == lrel) {
    1594       24211 :                                 p->l = n;
    1595             :                         } else {
    1596       41877 :                                 p->r = n;
    1597             :                         }
    1598             :                 } else {
    1599        5705 :                         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      183189 : rel_push_join(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, sql_exp *e, int f)
    1612             : {
    1613      183189 :         list *l = NULL, *r = NULL, *r2 = NULL;
    1614      183189 :         node *ln, *rn;
    1615      183189 :         sql_rel *lrel = NULL, *rrel = NULL, *rrel2 = NULL, *p = NULL;
    1616             : 
    1617      183189 :         if (!(l = rel_bind_path(sql, rel, ls, sa_list(sql->sa))) ||
    1618      183189 :                 !(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      183189 :         if (is_sql_or(f))
    1623        2960 :                 return rel_push_select(sql, rel, ls, e, f);
    1624             : 
    1625      180229 :         p = rel;
    1626      180229 :         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      802917 :                 for (ln = l->h, rn = r->h; ln && rn; ln = ln->next, rn = rn->next ) {
    1653      800137 :                         lrel = ln->data;
    1654      800137 :                         rrel = rn->data;
    1655             : 
    1656      800137 :                         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      759426 :                         if (lrel != rrel ||
    1663      624870 :                                 (!is_select(lrel->op) &&
    1664      621415 :                                  !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1665        1656 :                                  lrel->op != op_join &&
    1666             :                                  lrel->op != op_left))
    1667             :                                 break;
    1668             :                         /* pushing through left head of a left join is allowed */
    1669      623214 :                         if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
    1670             :                                 break;
    1671      623214 :                         p = lrel;
    1672             :                 }
    1673             :         }
    1674      180229 :         if (!lrel || !rrel || (r2 && !rrel2))
    1675             :                 return NULL;
    1676             : 
    1677             :         /* filter on columns of this relation */
    1678      180229 :         if ((lrel == rrel && (!r2 || lrel == rrel2) && lrel->op != op_join) || rel_is_ref(p)) {
    1679        2826 :                 if (is_select(lrel->op) && !rel_is_ref(lrel)) {
    1680        1152 :                         lrel = rel_select_push_exp_down(sql, lrel, e);
    1681        1674 :                 } 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          14 :                         sql_rel *n = rel_select(sql->sa, lrel, e);
    1685             : 
    1686          14 :                         if (p && p != lrel) {
    1687          14 :                                 if (p->l == lrel)
    1688           5 :                                         p->l = n;
    1689             :                                 else
    1690           9 :                                         p->r = n;
    1691             :                         } else {
    1692             :                                 rel = n;
    1693             :                         }
    1694             :                 }
    1695        2826 :                 return rel;
    1696             :         }
    1697             : 
    1698      177403 :         rel_join_add_exp( sql->sa, p, e);
    1699      177403 :         return rel;
    1700             : }
    1701             : 
    1702             : sql_rel *
    1703       18968 : rel_or(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, list *oexps, list *lexps, list *rexps)
    1704             : {
    1705       18968 :         sql_rel *ll = l->l, *rl = r->l;
    1706       18968 :         list *ls, *rs;
    1707             : 
    1708       18968 :         assert(!lexps || l == r);
    1709       18968 :         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       18926 :         if (l->op == r->op && is_select(l->op) &&
    1723       18926 :             ll == rl && ll == rel && !rel_is_ref(l) && !rel_is_ref(r)) {
    1724       18926 :                 sql_exp *e = exp_or(sql->sa, l->exps, r->exps, 0);
    1725       18926 :                 list *nl = new_exp_list(sql->sa);
    1726             : 
    1727       18926 :                 rel_destroy(r);
    1728       18926 :                 append(nl, e);
    1729       18926 :                 l->exps = nl;
    1730             : 
    1731             :                 /* merge and expressions */
    1732       18926 :                 ll = l->l;
    1733       21283 :                 while (ll && is_select(ll->op) && !rel_is_ref(ll)) {
    1734        2357 :                         list_merge(l->exps, ll->exps, (fdup)NULL);
    1735        2357 :                         l->l = ll->l;
    1736        2357 :                         ll->l = NULL;
    1737        2357 :                         rel_destroy(ll);
    1738        2357 :                         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        4153 : rel_ddl_table_get(sql_rel *r)
    1772             : {
    1773        4153 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1774        4153 :                 sql_exp *e = r->exps->t->data;
    1775        4153 :                 atom *a = e->l;
    1776             : 
    1777        4153 :                 return a->data.val.pval;
    1778             :         }
    1779             :         return NULL;
    1780             : }
    1781             : 
    1782             : sql_rel *
    1783        3240 : rel_ddl_basetable_get(sql_rel *r)
    1784             : {
    1785        3240 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1786        3240 :                 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       26871 : lastexp(sql_rel *rel)
    1967             : {
    1968       26871 :         if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
    1969          14 :                 rel = rel_parent(rel);
    1970       26871 :         assert(list_length(rel->exps));
    1971       26871 :         assert(is_project(rel->op) || rel->op == op_table);
    1972       26871 :         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       36011 : rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
    2001             : {
    2002       36011 :         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       36011 :         if (ek.card < card_set && rel->card > CARD_ATOM) {
    2005        9353 :                 assert (is_simple_project(rel->op) || is_mset(rel->op));
    2006             : 
    2007        9353 :                 list *exps = rel->exps;
    2008       18734 :                 for(node *n = exps->h; n; n=n->next) {
    2009        9381 :                         sql_exp *e = n->data;
    2010        9381 :                         if (e->alias.label == 0)
    2011          12 :                                 exp_label(sql->sa, e, ++sql->label);
    2012             :                 }
    2013        9353 :                 set_single(rel);
    2014             :         } else {
    2015       26658 :                 sql_exp *e = lastexp(rel);
    2016       26658 :                 if (!has_label(e))
    2017          22 :                         exp_label(sql->sa, e, ++sql->label);
    2018             :         }
    2019       36011 :         return rel;
    2020             : }
    2021             : 
    2022             : static sql_rel *
    2023       10790 : refs_find_rel(list *refs, sql_rel *rel)
    2024             : {
    2025       10790 :         node *n;
    2026             : 
    2027       22776 :         for(n=refs->h; n; n = n->next->next) {
    2028       17488 :                 sql_rel *ref = n->data;
    2029       17488 :                 sql_rel *s = n->next->data;
    2030             : 
    2031       17488 :                 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      668242 : exps_deps(mvc *sql, list *exps, list *refs, list *l)
    2041             : {
    2042             : 
    2043     2804987 :         for(node *n = exps->h; n; n = n->next)
    2044     2136745 :                 if (exp_deps(sql, n->data, refs, l) != 0)
    2045             :                         return -1;
    2046             :         return 0;
    2047             : }
    2048             : 
    2049             : static int
    2050     6710038 : id_cmp(sql_base *id1, sql_base *id2)
    2051             : {
    2052     6710038 :         if (id1->id == id2->id)
    2053       86233 :                 return 0;
    2054             :         return -1;
    2055             : }
    2056             : 
    2057             : static list *
    2058      709500 : cond_append(list *l, sql_base *b)
    2059             : {
    2060      709500 :         if (b->id >= FUNC_OIDS && !list_find(l, b, (fcmp) &id_cmp))
    2061      356663 :                 list_append(l, b);
    2062      709500 :         return l;
    2063             : }
    2064             : 
    2065             : static int rel_deps(mvc *sql, sql_rel *r, list *refs, list *l);
    2066             : 
    2067             : static int
    2068     2323885 : exp_deps(mvc *sql, sql_exp *e, list *refs, list *l)
    2069             : {
    2070     2428203 :         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     2428203 :         switch(e->type) {
    2076       43987 :         case e_psm:
    2077       43987 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2078       18967 :                         return exp_deps(sql, e->l, refs, l);
    2079       25020 :                 } else if (e->flag & PSM_VAR) {
    2080             :                         return 0;
    2081       20338 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2082        6204 :                         if (exp_deps(sql, e->l, refs, l) != 0 || exps_deps(sql, e->r, refs, l) != 0)
    2083           0 :                                 return -1;
    2084        6204 :                         if (e->flag & PSM_IF && e->f)
    2085         746 :                                 return exps_deps(sql, e->f, refs, l);
    2086       14134 :                 } else if (e->flag & PSM_REL) {
    2087       14134 :                         sql_rel *rel = e->l;
    2088       14134 :                         return rel_deps(sql, rel, refs, l);
    2089             :                 }
    2090             :                 break;
    2091      838387 :         case e_atom:
    2092      838387 :                 if (e->f && exps_deps(sql, e->f, refs, l) != 0)
    2093             :                         return -1;
    2094             :                 break;
    2095             :         case e_column:
    2096             :                 break;
    2097       85320 :         case e_convert:
    2098       85320 :                 return exp_deps(sql, e->l, refs, l);
    2099      275194 :         case e_func: {
    2100      275194 :                 sql_subfunc *f = e->f;
    2101             : 
    2102      275194 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2103             :                         return -1;
    2104      275194 :                 cond_append(l, &f->func->base);
    2105      275194 :                 if (e->l && list_length(e->l) == 2 && strcmp(f->func->base.name, "next_value_for") == 0) {
    2106             :                         /* add dependency on seq nr */
    2107          85 :                         list *nl = e->l;
    2108          85 :                         sql_exp *schname = nl->h->data, *seqname = nl->t->data;
    2109          85 :                         char *sch_name = is_atom(schname->type) && schname->l ? ((atom*)schname->l)->data.val.sval : NULL;
    2110          85 :                         char *seq_name = is_atom(seqname->type) && seqname->l ? ((atom*)seqname->l)->data.val.sval : NULL;
    2111             : 
    2112          85 :                         if (sch_name && seq_name) {
    2113          85 :                                 sql_schema *sche = mvc_bind_schema(sql, sch_name);
    2114          85 :                                 if (sche) {
    2115          85 :                                         sql_sequence *seq = find_sql_sequence(sql->session->tr, sche, seq_name);
    2116          85 :                                         if (seq)
    2117          85 :                                                 cond_append(l, &seq->base);
    2118             :                                 }
    2119             :                         }
    2120             :                 }
    2121             :         } break;
    2122       19699 :         case e_aggr: {
    2123       19699 :                 sql_subfunc *a = e->f;
    2124             : 
    2125       19699 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2126             :                         return -1;
    2127       19699 :                 cond_append(l, &a->func->base);
    2128       19699 :         } break;
    2129       93442 :         case e_cmp: {
    2130       93442 :                 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       92726 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2139        9032 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2140        4516 :                                 exps_deps(sql, e->r, refs, l) != 0)
    2141           0 :                                 return -1;
    2142             :                 } else {
    2143      176420 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2144       88210 :                                 exp_deps(sql, e->r, refs, l) != 0)
    2145           0 :                                 return -1;
    2146       88210 :                         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      477640 : rel_deps(mvc *sql, sql_rel *r, list *refs, list *l)
    2156             : {
    2157      477640 :         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      477640 :         if (!r)
    2163             :                 return 0;
    2164             : 
    2165      479828 :         if (rel_is_ref(r) && refs_find_rel(refs, r)) /* already handled */
    2166             :                 return 0;
    2167      463536 :         switch (r->op) {
    2168       99028 :         case op_basetable: {
    2169       99028 :                 sql_table *t = r->l;
    2170             : 
    2171       99028 :                 cond_append(l, &t->base);
    2172             :                 /* find all used columns */
    2173      428137 :                 for (node *en = r->exps->h; en; en = en->next) {
    2174      329109 :                         sql_exp *exp = en->data;
    2175      329109 :                         const char *oname = exp->r;
    2176             : 
    2177      329109 :                         assert(!is_func(exp->type));
    2178      329109 :                         if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    2179       18201 :                                 continue;
    2180      310908 :                         } 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      310824 :                         sql_column *c = find_sql_column(t, oname);
    2188      310824 :                         if (!c)
    2189             :                                 return -1;
    2190      310824 :                         cond_append(l, &c->base);
    2191             :                 }
    2192             :         } break;
    2193        4105 :         case op_table: {
    2194        4105 :                 if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */
    2195        4105 :                         sql_exp *op = r->r;
    2196        4105 :                         sql_subfunc *f = op->f;
    2197        4105 :                         cond_append(l, &f->func->base);
    2198             :                 }
    2199             :         } break;
    2200       68764 :         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      137528 :                 if (rel_deps(sql, r->l, refs, l) != 0 ||
    2215       68764 :                         rel_deps(sql, r->r, refs, l) != 0)
    2216           0 :                         return -1;
    2217             :                 break;
    2218        4648 :         case op_munion:
    2219       19609 :                 for (node *n = ((list*)r->l)->h; n; n = n->next) {
    2220       14961 :                         if (rel_deps(sql, n->data, refs, l) != 0)
    2221             :                                 return -1;
    2222             :                 }
    2223             :                 break;
    2224      166568 :         case op_project:
    2225             :         case op_select:
    2226             :         case op_groupby:
    2227             :         case op_topn:
    2228             :         case op_sample:
    2229             :         case op_truncate:
    2230      166568 :                 if (rel_deps(sql, r->l, refs, l) != 0)
    2231             :                         return -1;
    2232             :                 break;
    2233      120423 :         case op_ddl:
    2234      120423 :                 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      463536 :         if (!is_base(r->op) && r->exps) {
    2245      348741 :                 if (exps_deps(sql, r->exps, refs, l) != 0)
    2246             :                         return -1;
    2247             :         }
    2248      463536 :         if ((is_simple_project(r->op) || is_groupby(r->op)) && r->r) {
    2249       18522 :                 if (exps_deps(sql, r->r, refs, l) != 0)
    2250             :                         return -1;
    2251             :         }
    2252      463536 :         if (rel_is_ref(r)) {
    2253        5288 :                 list_append(refs, r);
    2254        5288 :                 list_append(refs, l);
    2255             :         }
    2256             :         return 0;
    2257             : }
    2258             : 
    2259             : list *
    2260      144428 : rel_dependencies(mvc *sql, sql_rel *r)
    2261             : {
    2262      144428 :         list *refs = sa_list(sql->sa);
    2263      144428 :         list *l = sa_list(sql->sa);
    2264             : 
    2265      144428 :         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       40141 : 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       40141 :         node *n;
    2276             : 
    2277       40141 :         if (list_empty(lists))
    2278             :                 return lists;
    2279       88068 :         for (n = lists->h; n; n = n->next) {
    2280       47927 :                 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    82197262 : 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    82197262 :         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    82209178 :         assert(e);
    2295    82209178 :         if (topdown) {
    2296     6778966 :                 int changes = v->changes;
    2297     6778966 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2298             :                         return NULL;
    2299     6778999 :                 *changed |= v->changes > changes;
    2300             :         }
    2301             : 
    2302    82209211 :         switch(e->type) {
    2303             :         case e_column:
    2304             :                 break;
    2305     1081982 :         case e_convert:
    2306     1081982 :                 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     4055121 :         case e_aggr:
    2310             :         case e_func:
    2311     4055121 :                 if (e->r) /* rewrite rank -r is list of lists */
    2312       40141 :                         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     4055121 :                 if (e->l)
    2315     3883602 :                         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     3475236 :         case e_cmp:
    2319     3475236 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2320      192709 :                         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      192709 :                         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     3282527 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2325      224640 :                         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      224640 :                         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     3057887 :                         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     3057887 :                         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     3057887 :                         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      374682 :         case e_psm:
    2339      374682 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2340      121654 :                         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      253028 :                 } else if (e->flag & PSM_VAR) {
    2343             :                         return e;
    2344      223704 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2345       39023 :                         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       39023 :                         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       39023 :                         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      184681 :                 } else if (e->flag & PSM_REL) {
    2352      184681 :                         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    27182440 :         case e_atom:
    2357    27182440 :                 if (e->f)
    2358      910137 :                         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    82179919 :         if (!topdown) {
    2363    75401008 :                 int changes = v->changes;
    2364    75401008 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2365             :                         return NULL;
    2366    75404021 :                 *changed |= v->changes > changes;
    2367             :         }
    2368             :         return e;
    2369             : }
    2370             : 
    2371             : static list *
    2372    21155757 : 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    21155757 :         bool changed = false;
    2375    21155757 :         if (list_empty(exps))
    2376             :                 return exps;
    2377    95720331 :         for (node *n = exps->h; n; n = n->next)
    2378    74597777 :                 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    21122554 :         if (changed && depth == 0) /* only level 0 exps use hash, so remove only on those */
    2381       20344 :                 list_hash_clear(exps);
    2382             :         return exps;
    2383             : }
    2384             : 
    2385             : static inline sql_rel *
    2386    16120943 : rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
    2387             : {
    2388    16120943 :         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    16121654 :         if (!rel)
    2392             :                 return rel;
    2393             : 
    2394    16121633 :         if (relations_topdown) {
    2395     5900815 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
    2396             :                         return NULL;
    2397     5900848 :                 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    16121666 :         switch(rel->op){
    2402             :         case op_basetable:
    2403             :                 break;
    2404       47275 :         case op_table:
    2405       47275 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2406       47207 :                         bool changed = false;
    2407       47207 :                         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       47207 :                         if (rel->r)
    2411       46899 :                                 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     2432876 :         case op_ddl:
    2416     2432876 :                 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      227606 :                         if (rel->l)
    2418      225417 :                                 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        2668 :                         if (rel->l)
    2422        2354 :                                 if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2423             :                                         return NULL;
    2424        2668 :                         if (rel->r)
    2425        2401 :                                 if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2426             :                                         return NULL;
    2427             :                 }
    2428             :                 break;
    2429     2139083 :         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     2139083 :                 if (rel->l)
    2445     2139083 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2446             :                                 return NULL;
    2447     2139085 :                 if (rel->r)
    2448     2137210 :                         if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2449             :                                 return NULL;
    2450             :                 break;
    2451      493794 :         case op_munion:
    2452     1536464 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2453     1042670 :                         if ((n->data = rel_exp_visitor(v, n->data, exp_rewriter, topdown, relations_topdown)) == NULL)
    2454             :                                 return NULL;
    2455             :                 }
    2456             :                 break;
    2457     7179607 :         case op_select:
    2458             :         case op_topn:
    2459             :         case op_sample:
    2460             :         case op_project:
    2461             :         case op_groupby:
    2462             :         case op_truncate:
    2463     7179607 :                 if (rel->l)
    2464     6129479 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2465             :                                 return NULL;
    2466             :                 break;
    2467             :         }
    2468             : 
    2469    16121697 :         if (!relations_topdown) {
    2470    10220772 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
    2471             :                         return NULL;
    2472    10220885 :                 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      560832 : rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2481             : {
    2482      560832 :         return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
    2483             : }
    2484             : 
    2485             : sql_rel *
    2486     3716124 : rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2487             : {
    2488     3716124 :         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   343003338 : exp_rel_visitor(visitor *v, sql_exp *e, rel_rewrite_fptr rel_rewriter, bool topdown)
    2496             : {
    2497   343003338 :         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   343024868 :         assert(e);
    2501   343024868 :         switch(e->type) {
    2502             :         case e_column:
    2503             :                 break;
    2504     6049164 :         case e_convert:
    2505     6049164 :                 if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2506             :                         return NULL;
    2507             :                 break;
    2508    17918933 :         case e_aggr:
    2509             :         case e_func:
    2510    17918933 :                 if (e->r) /* rewrite rank */
    2511       62863 :                         if ((e->r = exps_exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2512             :                                 return NULL;
    2513    17918933 :                 if (e->l)
    2514    17361032 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2515             :                                 return NULL;
    2516             :                 break;
    2517    20246769 :         case e_cmp:
    2518    20246769 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2519      819376 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2520             :                                 return NULL;
    2521      819376 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2522             :                                 return NULL;
    2523    19427393 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2524     1311383 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2525             :                                 return NULL;
    2526     1311383 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2527             :                                 return NULL;
    2528             :                 } else {
    2529    18116010 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2530             :                                 return NULL;
    2531    18116011 :                         if ((e->r = exp_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2532             :                                 return NULL;
    2533    18116011 :                         if (e->f && (e->f = exp_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2534             :                                 return NULL;
    2535             :                 }
    2536             :                 break;
    2537      654421 :         case e_psm:
    2538      654421 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2539      246898 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2540             :                                 return NULL;
    2541      407523 :                 } else if (e->flag & PSM_VAR) {
    2542             :                         return e;
    2543      348875 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2544       78046 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2545             :                                 return NULL;
    2546       78046 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2547             :                                 return NULL;
    2548       78046 :                         if (e->flag == PSM_IF && e->f && (e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2549             :                                 return NULL;
    2550      270829 :                 } else if (e->flag & PSM_REL) {
    2551      270829 :                         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2552      270829 :                         if ((e->l = func(v, e->l, rel_rewriter)) == NULL)
    2553             :                                 return NULL;
    2554             :                 }
    2555             :                 break;
    2556    68359826 :         case e_atom:
    2557    68359826 :                 if (e->f)
    2558     1465462 :                         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    90565826 : exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown)
    2567             : {
    2568    90565826 :         if (list_empty(exps))
    2569             :                 return exps;
    2570   389369667 :         for (node *n = exps->h; n; n = n->next)
    2571   299056132 :                 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       62863 : exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown)
    2578             : {
    2579       62863 :         if (list_empty(lists))
    2580             :                 return lists;
    2581      125726 :         for (node *n = lists->h; n; n = n->next)
    2582       62863 :                 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    69399296 : do_rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2589             : {
    2590    69399296 :         if (rel->exps && (rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2591             :                 return NULL;
    2592    69397627 :         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    69397627 :         int changes = v->changes;
    2595    69397627 :         rel = rel_rewriter(v, rel);
    2596    69399433 :         if (rel && rel->exps && v->changes > changes) {
    2597      319361 :                 list_hash_clear(rel->exps);
    2598      319362 :                 if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r)
    2599       12588 :                         list_hash_clear(rel->r);
    2600             :         }
    2601             :         return rel;
    2602             : }
    2603             : 
    2604             : static inline sql_rel *
    2605    69399849 : rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2606             : {
    2607    69399849 :         sql_rel *parent = v->parent;
    2608             : 
    2609    69399849 :         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    69401562 :         if (!rel)
    2613             :                 return NULL;
    2614             : 
    2615    69401503 :         if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
    2616             :                 return NULL;
    2617             : 
    2618    69401414 :         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2619             : 
    2620    69401414 :         v->parent = rel;
    2621    69401414 :         switch(rel->op){
    2622             :         case op_basetable:
    2623             :                 break;
    2624      138298 :         case op_table:
    2625      138298 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2626      138071 :                         if (rel->l)
    2627        2814 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2628             :                                         return NULL;
    2629             :                 }
    2630             :                 break;
    2631     4011715 :         case op_ddl:
    2632     4011715 :                 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      418090 :                         if (rel->l)
    2634      414394 :                                 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       14711 :                         if (rel->l)
    2638       10709 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2639             :                                         return NULL;
    2640       14711 :                         if (rel->r)
    2641       13706 :                                 if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2642             :                                         return NULL;
    2643             :                 } else if (rel->flag == ddl_psm) {
    2644      146155 :                         if ((rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2645             :                                 return NULL;
    2646             :                 }
    2647             :                 break;
    2648    11322084 :         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    11322084 :                 if (rel->l)
    2664    11322084 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2665             :                                 return NULL;
    2666    11322024 :                 if (rel->r)
    2667    11317623 :                         if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2668             :                                 return NULL;
    2669             :                 break;
    2670     2282816 :         case op_munion:
    2671     8532118 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2672     6249302 :                         if ((n->data = func(v, n->data, rel_rewriter)) == NULL)
    2673             :                                 return NULL;
    2674             :                 }
    2675             :                 break;
    2676    33790363 :         case op_select:
    2677             :         case op_topn:
    2678             :         case op_sample:
    2679             :         case op_project:
    2680             :         case op_groupby:
    2681             :         case op_truncate:
    2682    33790363 :                 if (rel->l)
    2683    31640495 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2684             :                                 return NULL;
    2685             :                 break;
    2686             :         }
    2687    69401194 :         v->parent = parent;
    2688             : 
    2689    69401194 :         if (!topdown)
    2690    44045069 :                 rel = do_rel_visitor(v, rel, rel_rewriter, false);
    2691             :         return rel;
    2692             : }
    2693             : 
    2694             : sql_rel *
    2695    25355189 : rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2696             : {
    2697    25355189 :         v->depth++;
    2698    25355189 :         rel = rel_visitor(v, rel, rel_rewriter, true);
    2699    25355097 :         v->depth--;
    2700    25355097 :         return rel;
    2701             : }
    2702             : 
    2703             : sql_rel *
    2704    44045888 : rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2705             : {
    2706    44045888 :         v->depth++;
    2707    44045888 :         rel = rel_visitor(v, rel, rel_rewriter, false);
    2708    44045403 :         v->depth--;
    2709    44045403 :         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      587707 : exps_exp_visitor_bottomup(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2720             : {
    2721      587707 :         return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, false, relations_topdown, false);
    2722             : }
    2723             : 
    2724             : static bool
    2725       75189 : exps_rebind_exp(mvc *sql, sql_rel *rel, list *exps)
    2726             : {
    2727       75189 :         bool ok = true;
    2728             : 
    2729       75189 :         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       75189 :         if (list_empty(exps))
    2735             :                 return true;
    2736       87065 :         for (node *n = exps->h; n && ok; n = n->next)
    2737       53331 :                 ok &= rel_rebind_exp(sql, rel, n->data);
    2738             :         return ok;
    2739             : }
    2740             : 
    2741             : bool
    2742     2564808 : rel_rebind_exp(mvc *sql, sql_rel *rel, sql_exp *e)
    2743             : {
    2744     2587900 :         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     2587900 :         switch (e->type) {
    2750       23092 :         case e_convert:
    2751       23092 :                 return rel_rebind_exp(sql, rel, e->l);
    2752       14173 :         case e_aggr:
    2753             :         case e_func:
    2754       14173 :                 return exps_rebind_exp(sql, rel, e->l);
    2755     1036663 :         case e_cmp:
    2756     1036663 :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    2757        8263 :                         return rel_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2758     1030422 :                 if (e->flag == cmp_or || e->flag == cmp_filter)
    2759       19776 :                         return exps_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2760     2038368 :                 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     1472502 :         case e_column:
    2762     1472502 :                 if (e->freevar)
    2763             :                         return true;
    2764     1472501 :                 return rel_find_exp(rel, e) != NULL;
    2765       41465 :         case e_atom:
    2766       41465 :                 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             : }

Generated by: LCOV version 1.14