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

Generated by: LCOV version 1.14