LCOV - code coverage report
Current view: top level - sql/server - rel_rel.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1309 1516 86.3 %
Date: 2024-04-26 00:35:57 Functions: 89 94 94.7 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "rel_rel.h"
      15             : #include "rel_basetable.h"
      16             : #include "rel_exp.h"
      17             : #include "rel_prop.h"
      18             : #include "rel_unnest.h"
      19             : #include "sql_semantic.h"
      20             : #include "sql_mvc.h"
      21             : #include "rel_rewriter.h"
      22             : 
      23             : void
      24         193 : rel_set_exps(sql_rel *rel, list *exps)
      25             : {
      26         193 :         rel->exps = exps;
      27         193 :         rel->nrcols = list_length(exps);
      28         193 : }
      29             : 
      30             : /* some projections results are order dependend (row_number etc) */
      31             : int
      32      796321 : project_unsafe(sql_rel *rel, int allow_identity)
      33             : {
      34      796321 :         sql_rel *sub = rel->l;
      35             : 
      36      796321 :         if (need_distinct(rel) || rel->r /* order by */)
      37             :                 return 1;
      38      723494 :         if (list_empty(rel->exps))
      39             :                 return 0;
      40             :         /* projects without sub and projects around ddl's cannot be changed */
      41      723495 :         if (!sub || sub->op == op_ddl)
      42             :                 return 1;
      43     4895732 :         for(node *n = rel->exps->h; n; n = n->next) {
      44     4533236 :                 sql_exp *e = n->data, *ne;
      45             : 
      46             :                 /* aggr func in project ! */
      47     4533236 :                 if (exp_unsafe(e, allow_identity))
      48             :                         return 1;
      49     4429383 :                 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      132437 : rel_name( sql_rel *r )
      62             : {
      63      136430 :         if (is_basetable(r->op))
      64      132310 :                 return rel_base_name(r);
      65        8113 :         if (!is_project(r->op) && !is_base(r->op) && r->l)
      66             :                 return rel_name(r->l);
      67         127 :         if (r->exps && list_length(r->exps)) {
      68         127 :                 sql_exp *e = r->exps->h->data;
      69         127 :                 if (exp_relname(e))
      70         127 :                         return exp_relname(e);
      71           0 :                 if (e->type == e_column)
      72           0 :                         return e->l;
      73             :         }
      74             :         return NULL;
      75             : }
      76             : 
      77             : sql_rel *
      78        9294 : rel_distinct(sql_rel *l)
      79             : {
      80        9294 :         set_distinct(l);
      81        9294 :         return l;
      82             : }
      83             : 
      84             : sql_rel *
      85      434602 : rel_dup(sql_rel *r)
      86             : {
      87      434602 :         sql_ref_inc(&r->ref);
      88      434602 :         return r;
      89             : }
      90             : 
      91             : static void
      92      535186 : rel_destroy_(sql_rel *rel)
      93             : {
      94      535186 :         if (!rel)
      95             :                 return;
      96      535186 :         switch(rel->op){
      97             :         case op_basetable:
      98             :                 break;
      99        4938 :         case op_table:
     100        4938 :                 if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
     101          11 :                         rel_destroy(rel->l);
     102             :                 break;
     103      255009 :         case op_join:
     104             :         case op_left:
     105             :         case op_right:
     106             :         case op_full:
     107             :         case op_semi:
     108             :         case op_anti:
     109             :         case op_union:
     110             :         case op_inter:
     111             :         case op_except:
     112             :         case op_insert:
     113             :         case op_update:
     114             :         case op_delete:
     115             :         case op_merge:
     116      255009 :                 if (rel->l)
     117       12289 :                         rel_destroy(rel->l);
     118      255009 :                 if (rel->r)
     119       12253 :                         rel_destroy(rel->r);
     120             :                 break;
     121        4258 :         case op_munion:
     122             :                 /* the rel->l might be in purpose NULL see rel_merge_table_rewrite_() */
     123        4258 :                 if (rel->l)
     124       12774 :                         for (node *n = ((list*)rel->l)->h; n; n = n->next)
     125        8516 :                                 rel_destroy(n->data);
     126             :                 break;
     127      260342 :         case op_project:
     128             :         case op_groupby:
     129             :         case op_select:
     130             :         case op_topn:
     131             :         case op_sample:
     132             :         case op_truncate:
     133      260342 :                 if (rel->l)
     134       58691 :                         rel_destroy(rel->l);
     135             :                 break;
     136           0 :         case op_ddl:
     137           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) {
     138           0 :                         if (rel->l)
     139           0 :                                 rel_destroy(rel->l);
     140             :                 } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
     141           0 :                         if (rel->l)
     142           0 :                                 rel_destroy(rel->l);
     143           0 :                         if (rel->r)
     144           0 :                                 rel_destroy(rel->r);
     145             :                 }
     146             :                 break;
     147             :         }
     148             : }
     149             : 
     150             : void
     151      951613 : rel_destroy(sql_rel *rel)
     152             : {
     153      951613 :         if (!rel)
     154             :                 return;
     155      951178 :         if (sql_ref_dec(&rel->ref) > 0)
     156             :                 return;
     157      527745 :         rel_destroy_(rel);
     158             : }
     159             : 
     160             : sql_rel*
     161     3116584 : rel_create(allocator *sa)
     162             : {
     163     3116584 :         sql_rel *r = SA_NEW(sa, sql_rel);
     164     3116810 :         if(!r)
     165             :                 return NULL;
     166             : 
     167     3116810 :         *r = (sql_rel) {
     168             :                 .card = CARD_ATOM,
     169             :         };
     170     3116810 :         sql_ref_init(&r->ref);
     171     3116810 :         return r;
     172             : }
     173             : 
     174             : sql_rel *
     175         173 : rel_copy(mvc *sql, sql_rel *i, int deep)
     176             : {
     177         173 :         sql_rel *rel;
     178             : 
     179         173 :         if (mvc_highwater(sql))
     180           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     181             : 
     182         173 :         rel = rel_create(sql->sa);
     183         173 :         if (!rel)
     184             :                 return NULL;
     185             : 
     186         173 :         rel->op = i->op;
     187         173 :         switch(i->op) {
     188          57 :         case op_basetable:
     189          57 :                 rel_base_copy(sql, i, rel);
     190          57 :                 break;
     191           0 :         case op_table:
     192           0 :                 if ((IS_TABLE_PROD_FUNC(i->flag) || i->flag == TABLE_FROM_RELATION) && i->l)
     193           0 :                         rel->l = rel_copy(sql, i->l, deep);
     194           0 :                 rel->r = i->r;
     195           0 :                 break;
     196          73 :         case op_project:
     197             :         case op_groupby:
     198          73 :                 if (i->l)
     199          63 :                         rel->l = rel_copy(sql, i->l, deep);
     200          73 :                 if (i->r) {
     201           8 :                         if (!deep) {
     202           0 :                                 rel->r = list_dup(i->r, (fdup) NULL);
     203             :                         } else {
     204           8 :                                 rel->r = exps_copy(sql, i->r);
     205             :                         }
     206             :                 }
     207             :                 break;
     208           0 :         case op_munion:
     209           0 :                 if (i->l)
     210           0 :                         rel->l = list_dup(i->l, (fdup) rel_dup);
     211             :                 break;
     212           0 :         case op_ddl:
     213           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) {
     214           0 :                         if (i->l)
     215           0 :                                 rel->l = rel_copy(sql, i->l, deep);
     216           0 :                 } else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
     217           0 :                         if (i->l)
     218           0 :                                 rel->l = rel_copy(sql, i->l, deep);
     219           0 :                         if (i->r)
     220           0 :                                 rel->r = rel_copy(sql, i->r, deep);
     221             :                 }
     222             :                 break;
     223          22 :         case op_select:
     224             :         case op_topn:
     225             :         case op_sample:
     226             :         case op_truncate:
     227          22 :                 if (i->l)
     228          22 :                         rel->l = rel_copy(sql, i->l, deep);
     229             :                 break;
     230          21 :         case op_join:
     231             :         case op_left:
     232             :         case op_right:
     233             :         case op_full:
     234             :         case op_semi:
     235             :         case op_anti:
     236             : 
     237             :         case op_union:
     238             :         case op_inter:
     239             :         case op_except:
     240             : 
     241             :         case op_insert:
     242             :         case op_update:
     243             :         case op_delete:
     244             :         case op_merge:
     245          21 :                 if (i->l)
     246          21 :                         rel->l = rel_copy(sql, i->l, deep);
     247          21 :                 if (i->r)
     248          21 :                         rel->r = rel_copy(sql, i->r, deep);
     249             :                 break;
     250             :         }
     251             : 
     252         173 :         rel->card = i->card;
     253         173 :         rel->flag = i->flag;
     254         173 :         rel->nrcols = i->nrcols;
     255         173 :         rel->grouped = i->grouped;
     256         173 :         rel->used = i->used;
     257             : 
     258         173 :         if (is_processed(i))
     259         110 :                 set_processed(rel);
     260         173 :         if (is_dependent(i))
     261           0 :                 set_dependent(rel);
     262         173 :         if (is_outer(i))
     263          10 :                 set_outer(rel);
     264         173 :         if (is_single(i))
     265           4 :                 set_single(rel);
     266         173 :         if (need_distinct(i))
     267           2 :                 set_distinct(rel);
     268             : 
     269         173 :         rel->p = prop_copy(sql->sa, i->p);
     270         173 :         rel->exps = (!i->exps)?NULL:deep?exps_copy(sql, i->exps):list_dup(i->exps, (fdup)NULL);
     271         173 :         rel->attr = (!i->attr)?NULL:deep?exps_copy(sql, i->attr):list_dup(i->attr, (fdup)NULL);
     272         173 :         return rel;
     273             : }
     274             : 
     275             : sql_rel *
     276        4700 : rel_select_copy(allocator *sa, sql_rel *l, list *exps)
     277             : {
     278        4700 :         sql_rel *rel = rel_create(sa);
     279        4700 :         if(!rel)
     280             :                 return NULL;
     281             : 
     282        4700 :         rel->l = l;
     283        4700 :         rel->r = NULL;
     284        4700 :         rel->op = op_select;
     285        4700 :         rel->exps = exps?list_dup(exps, (fdup)NULL):NULL;
     286        4700 :         rel->card = CARD_ATOM; /* no relation */
     287        4700 :         if (l) {
     288        4700 :                 rel->card = l->card;
     289        4700 :                 rel->nrcols = l->nrcols;
     290             :         }
     291             :         return rel;
     292             : }
     293             : 
     294             : sql_exp *
     295     7935982 : rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int no_tname)
     296             : {
     297     7935982 :         int ambiguous = 0, multi = 0;
     298             : 
     299     7935982 :         if (!rel)
     300             :                 return NULL;
     301     7935982 :         if (mvc_highwater(sql))
     302           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     303             : 
     304     7935982 :         if ((is_project(rel->op) || is_base(rel->op))) {
     305     4208018 :                 sql_exp *e = NULL;
     306             : 
     307     4208018 :                 if (is_base(rel->op) && !rel->exps)
     308     4030557 :                         return rel_base_bind_column(sql, rel, cname, no_tname);
     309      177461 :                 if (!list_empty(rel->exps)) {
     310      177427 :                         e = exps_bind_column(rel->exps, cname, &ambiguous, &multi, no_tname);
     311      177427 :                         if (ambiguous || multi)
     312          10 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     313      177417 :                         if (!e && is_groupby(rel->op) && rel->r) {
     314         197 :                                 e = exps_bind_alias(rel->r, NULL, cname);
     315         197 :                                 if (e) {
     316           0 :                                         e = exps_bind_column(rel->r, cname, &ambiguous, &multi, no_tname);
     317           0 :                                         if (ambiguous || multi)
     318           0 :                                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     319             :                                         return e;
     320             :                                 }
     321             :                         }
     322             :                 }
     323       19080 :                 if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
     324         197 :                         e = exps_bind_column(rel->r, cname, &ambiguous, &multi, no_tname);
     325         197 :                         if (ambiguous || multi)
     326           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     327         197 :                         if (e) {
     328           1 :                                 e = exp_ref(sql, e);
     329           1 :                                 e->card = rel->card;
     330           1 :                                 return e;
     331             :                         }
     332             :                 }
     333      158371 :                 if (e)
     334      158371 :                         return exp_alias_or_copy(sql, exp_relname(e), cname, rel, e);
     335             :         }
     336     3747043 :         if (is_simple_project(rel->op) && rel->l) {
     337        6996 :                 if (!is_processed(rel))
     338           0 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     339     3740047 :         } else if (is_set(rel->op)) {
     340          22 :                 assert(is_processed(rel));
     341             :                 return NULL;
     342             :         } else if (is_join(rel->op)) {
     343     3224988 :                 sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), *e2 = NULL, *res;
     344             : 
     345     3224988 :                 if (e1 && (is_right(rel->op) || is_full(rel->op)))
     346           6 :                         set_has_nil(e1);
     347     1610902 :                 if (!e1 || !is_freevar(e1)) {
     348     3224988 :                         e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
     349     3224988 :                         if (e2 && (is_left(rel->op) || is_full(rel->op)))
     350          56 :                                 set_has_nil(e2);
     351     3224988 :                         if (e1 && e2 && !is_dependent(rel))
     352          23 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     353             :                 }
     354     3224965 :                 if (!e1 && !e2 && !list_empty(rel->attr)) {
     355           0 :                         e1 = exps_bind_column(rel->attr, cname, &ambiguous, &multi, no_tname);
     356           0 :                         if (ambiguous || multi)
     357           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     358             :                 }
     359     3224965 :                 res = e1 ? e1 : e2;
     360     1614086 :                 if (res)
     361     1699326 :                         set_not_unique(res);
     362     3224965 :                 return res;
     363             :         } else if (is_semi(rel->op) ||
     364             :                    is_select(rel->op) ||
     365             :                    is_topn(rel->op) ||
     366             :                    is_sample(rel->op)) {
     367      502976 :                 if (rel->l)
     368      502976 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     369             :         }
     370             :         return NULL;
     371             : }
     372             : 
     373             : sql_exp *
     374     4624626 : rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f)
     375             : {
     376     4624626 :         int ambiguous = 0, multi = 0;
     377             : 
     378     4624626 :         if (!rel)
     379             :                 return NULL;
     380     4624159 :         if (mvc_highwater(sql))
     381           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     382             : 
     383     4624159 :         if ((is_project(rel->op) || is_base(rel->op))) {
     384     2182961 :                 sql_exp *e = NULL;
     385             : 
     386     2182961 :                 if (is_basetable(rel->op) && !rel->exps)
     387     1308114 :                         return rel_base_bind_column2(sql, rel, tname, cname);
     388             :                 /* in case of orderby we should also lookup the column in group by list (and use existing references) */
     389      874847 :                 if (!list_empty(rel->exps)) {
     390      874768 :                         e = exps_bind_column2(rel->exps, tname, cname, &multi);
     391      874768 :                         if (multi)
     392           2 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     393             :                                                                  tname, cname);
     394      874766 :                         if (!e && is_groupby(rel->op) && rel->r) {
     395         135 :                                 e = exps_bind_alias(rel->r, tname, cname);
     396         135 :                                 if (e) {
     397           4 :                                         const char *rname = exp_relname(e), *nname = exp_name(e);
     398           4 :                                         if (rname)
     399           0 :                                                 e = exps_bind_column2(rel->exps, rname, nname, &multi);
     400             :                                         else
     401           4 :                                                 e = exps_bind_column(rel->exps, nname, &ambiguous, &multi, 0);
     402           4 :                                         if (ambiguous || multi)
     403           0 :                                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s%s%s' ambiguous",
     404             :                                                                                  rname ? rname : "", rname ? "." : "", nname);
     405           4 :                                         if (e)
     406             :                                                 return e;
     407             :                                 }
     408             :                         }
     409             :                 }
     410      314669 :                 if (!e && (is_sql_sel(f) || is_sql_having(f) || !f) && is_groupby(rel->op) && rel->r) {
     411         150 :                         e = exps_bind_column2(rel->r, tname, cname, &multi);
     412         150 :                         if (multi)
     413           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     414             :                                                                  tname, cname);
     415         150 :                         if (e) {
     416          10 :                                 e = exp_ref(sql, e);
     417          10 :                                 e->card = rel->card;
     418          10 :                                 return e;
     419             :                         }
     420             :                 }
     421      560173 :                 if (e)
     422      560173 :                         return exp_alias_or_copy(sql, tname, cname, rel, e);
     423             :         }
     424     2755857 :         if (is_simple_project(rel->op) && rel->l) {
     425      278285 :                 if (!is_processed(rel))
     426           0 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     427     2477572 :         } else if (is_set(rel->op)) {
     428         228 :                 assert(is_processed(rel));
     429             :                 return NULL;
     430             :         } else if (is_join(rel->op)) {
     431     1971386 :                 sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
     432             : 
     433     1971386 :                 if (e && (is_right(rel->op) || is_full(rel->op)))
     434         243 :                         set_has_nil(e);
     435         243 :                 if (!e) {
     436      866086 :                         e = rel_bind_column2(sql, rel->r, tname, cname, f);
     437      866086 :                         if (e && (is_left(rel->op) || is_full(rel->op)))
     438       23597 :                                 set_has_nil(e);
     439             :                 }
     440      415427 :                 if (!e && !list_empty(rel->attr)) {
     441          14 :                         e = exps_bind_column2(rel->attr, tname, cname, &multi);
     442          14 :                         if (multi)
     443           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     444             :                                                                  tname, cname);
     445             :                 }
     446      391830 :                 if (e)
     447     1579560 :                         set_not_unique(e);
     448     1971386 :                 return e;
     449             :         } else if (is_semi(rel->op) ||
     450             :                    is_select(rel->op) ||
     451             :                    is_topn(rel->op) ||
     452             :                    is_sample(rel->op)) {
     453      469813 :                 if (rel->l)
     454      469813 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     455             :         }
     456             :         return NULL;
     457             : }
     458             : 
     459             : sql_exp *
     460     1210041 : rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname, int f)
     461             : {
     462     1210041 :         if (!sname)
     463     1210040 :                 return rel_bind_column2(sql, rel, tname, cname, f);
     464           1 :         if (is_basetable(rel->op) && !rel->exps) {
     465           0 :                 return rel_base_bind_column3(sql, rel, sname, tname, cname);
     466           1 :         } else if (is_set(rel->op)) {
     467             :                 return NULL;
     468           1 :         } else if (is_project(rel->op) && rel->l) {
     469           1 :                 if (!is_processed(rel))
     470             :                         return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
     471             :                 else
     472           1 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     473           0 :         } else if (is_join(rel->op)) {
     474           0 :                 sql_exp *e = rel_bind_column3(sql, rel->l, sname, tname, cname, f);
     475             : 
     476           0 :                 if (e && (is_right(rel->op) || is_full(rel->op)))
     477           0 :                         set_has_nil(e);
     478           0 :                 if (!e) {
     479           0 :                         e = rel_bind_column3(sql, rel->r, sname, tname, cname, f);
     480           0 :                         if (e && (is_left(rel->op) || is_full(rel->op)))
     481           0 :                                 set_has_nil(e);
     482             :                 }
     483           0 :                 if (!e)
     484           0 :                         return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s.%s' ambiguous", sname, tname, cname);
     485           0 :                 if (e)
     486           0 :                         set_not_unique(e);
     487           0 :                 return e;
     488           0 :         } else if (is_semi(rel->op) ||
     489           0 :                    is_select(rel->op) ||
     490           0 :                    is_topn(rel->op) ||
     491             :                    is_sample(rel->op)) {
     492           0 :                 if (rel->l)
     493             :                         return rel_bind_column3(sql, rel->l, sname, tname, cname, f);
     494             :         }
     495             :         return NULL;
     496             : }
     497             : 
     498             : sql_exp *
     499           0 : rel_first_column(mvc *sql, sql_rel *r)
     500             : {
     501           0 :         if (is_simple_project(r->op))
     502           0 :                 return r->exps->h->data;
     503             : 
     504           0 :         list *exps = rel_projections(sql, r, NULL, 1, 1);
     505             : 
     506           0 :         if (!list_empty(exps))
     507           0 :                 return exps->h->data;
     508             : 
     509             :         return NULL;
     510             : }
     511             : 
     512             : /* rel_inplace_* used to convert a rel node into another flavor */
     513             : static void
     514       46372 : rel_inplace_reset_props(sql_rel *rel)
     515             : {
     516       46372 :         rel->flag = 0;
     517       46372 :         rel->attr = NULL;
     518       46372 :         reset_dependent(rel);
     519       46372 :         set_processed(rel);
     520             : }
     521             : 
     522             : sql_rel *
     523         103 : rel_inplace_basetable(sql_rel *rel, sql_rel *bt)
     524             : {
     525         103 :         assert(is_basetable(bt->op));
     526             : 
     527         103 :         rel_destroy_(rel);
     528         103 :         rel_inplace_reset_props(rel);
     529         103 :         rel->l = bt->l;
     530         103 :         rel->r = bt->r;
     531         103 :         rel->op = op_basetable;
     532         103 :         rel->exps = bt->exps;
     533         103 :         rel->card = CARD_MULTI;
     534         103 :         rel->nrcols = bt->nrcols;
     535         103 :         return rel;
     536             : }
     537             : 
     538             : sql_rel *
     539        2344 : rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps)
     540             : {
     541        2344 :         rel_destroy_(rel);
     542        2344 :         rel_inplace_reset_props(rel);
     543        2344 :         rel->l = l;
     544        2344 :         rel->r = r;
     545        2344 :         rel->op = setop;
     546        2344 :         rel->card = CARD_MULTI;
     547        2344 :         rel_setop_set_exps(sql, rel, exps, false);
     548        2344 :         return rel;
     549             : }
     550             : 
     551             : sql_rel *
     552        3938 : rel_inplace_setop_n_ary(mvc *sql, sql_rel *rel, list *rl, operator_type setop, list *exps)
     553             : {
     554             :         // TODO: for now we only deal with munion
     555        3938 :         assert(setop == op_munion);
     556        3938 :         rel_destroy_(rel);
     557        3938 :         rel_inplace_reset_props(rel);
     558             :         /* rl should be a list of relations */
     559        3938 :         rel->l = rl;
     560        3938 :         rel->op = setop;
     561        3938 :         rel->card = CARD_MULTI;
     562        3938 :         rel_setop_n_ary_set_exps(sql, rel, exps, false);
     563        3938 :         return rel;
     564             : }
     565             : 
     566             : sql_rel *
     567       38973 : rel_inplace_project(allocator *sa, sql_rel *rel, sql_rel *l, list *e)
     568             : {
     569       38973 :         if (!l) {
     570       38930 :                 l = rel_create(sa);
     571       38930 :                 if(!l)
     572             :                         return NULL;
     573             : 
     574       38930 :                 *l = *rel;
     575       38930 :                 l->ref.refcnt = 1;
     576             :         } else {
     577          43 :                 rel_destroy_(rel);
     578             :         }
     579       38973 :         rel_inplace_reset_props(rel);
     580       38973 :         rel->l = l;
     581       38973 :         rel->r = NULL;
     582       38973 :         rel->op = op_project;
     583       38973 :         rel->exps = e;
     584       38973 :         rel->card = CARD_MULTI;
     585       38973 :         if (l) {
     586       38973 :                 rel->nrcols = l->nrcols;
     587       38973 :                 assert (exps_card(rel->exps) <= rel->card);
     588             :         }
     589             :         return rel;
     590             : }
     591             : 
     592             : sql_rel *
     593         724 : rel_inplace_select(sql_rel *rel, sql_rel *l, list *exps)
     594             : {
     595         724 :         rel_destroy_(rel);
     596         724 :         rel_inplace_reset_props(rel);
     597         724 :         rel->l = l;
     598         724 :         rel->r = NULL;
     599         724 :         rel->op = op_select;
     600         724 :         rel->exps = exps;
     601         724 :         rel->card = CARD_ATOM; /* no relation */
     602         724 :         if (l) {
     603         724 :                 rel->card = l->card;
     604         724 :                 rel->nrcols = l->nrcols;
     605         724 :                 if (is_single(l))
     606           0 :                         set_single(rel);
     607             :         }
     608         724 :         return rel;
     609             : }
     610             : 
     611             : sql_rel *
     612         290 : rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps )
     613             : {
     614         290 :         rel_destroy_(rel);
     615         290 :         rel_inplace_reset_props(rel);
     616         290 :         rel->card = CARD_ATOM;
     617         290 :         if (groupbyexps)
     618         217 :                 rel->card = CARD_AGGR;
     619         290 :         rel->l = l;
     620         290 :         rel->r = groupbyexps;
     621         290 :         rel->exps = exps;
     622         290 :         rel->nrcols = l->nrcols;
     623         290 :         rel->op = op_groupby;
     624         290 :         return rel;
     625             : }
     626             : 
     627             : sql_rel *
     628           0 : rel_inplace_munion(sql_rel *rel, list *rels)
     629             : {
     630           0 :         rel_destroy_(rel);
     631           0 :         rel_inplace_reset_props(rel);
     632             :         // TODO: what is the semantics of cardinality? is that right?
     633           0 :         rel->card = CARD_MULTI;
     634           0 :         rel->nrcols = 0;
     635           0 :         if (rels)
     636           0 :                 rel->l = rels;
     637           0 :         if (rels) {
     638           0 :                 for (node* n = rels->h; n; n = n->next) {
     639           0 :                         sql_rel *r = n->data;
     640             :                         // TODO: could we overflow the nrcols this way?
     641           0 :                         rel->nrcols += r->nrcols;
     642             :                 }
     643             :         }
     644           0 :         rel->r = NULL;
     645           0 :         rel->exps = NULL;
     646           0 :         rel->op = op_munion;
     647           0 :         return rel;
     648             : }
     649             : 
     650             : /* this function is to be used with the above rel_inplace_* functions */
     651             : sql_rel *
     652         694 : rel_dup_copy(allocator *sa, sql_rel *rel)
     653             : {
     654         694 :         sql_rel *nrel = rel_create(sa);
     655             : 
     656         694 :         if (!nrel)
     657             :                 return NULL;
     658         694 :         *nrel = *rel;
     659         694 :         nrel->ref.refcnt = 1;
     660         694 :         switch(nrel->op){
     661             :         case op_basetable:
     662             :         case op_ddl:
     663             :                 break;
     664           0 :         case op_table:
     665           0 :                 if ((IS_TABLE_PROD_FUNC(nrel->flag) || nrel->flag == TABLE_FROM_RELATION) && nrel->l)
     666           0 :                         rel_dup(nrel->l);
     667             :                 break;
     668         689 :         case op_join:
     669             :         case op_left:
     670             :         case op_right:
     671             :         case op_full:
     672             :         case op_semi:
     673             :         case op_anti:
     674             :         case op_union:
     675             :         case op_inter:
     676             :         case op_except:
     677             :         case op_insert:
     678             :         case op_update:
     679             :         case op_delete:
     680             :         case op_merge:
     681         689 :                 if (nrel->l)
     682         689 :                         rel_dup(nrel->l);
     683         689 :                 if (nrel->r)
     684         689 :                         rel_dup(nrel->r);
     685             :                 break;
     686           5 :         case op_project:
     687             :         case op_groupby:
     688             :         case op_select:
     689             :         case op_topn:
     690             :         case op_sample:
     691             :         case op_truncate:
     692           5 :                 if (nrel->l)
     693           5 :                         rel_dup(nrel->l);
     694             :                 break;
     695           0 :         case op_munion:
     696             :                 // TODO: is that even right?
     697           0 :                 if (nrel->l)
     698           0 :                         nrel->l = list_dup(nrel->l, (fdup) rel_dup);
     699             :                 break;
     700             :         }
     701             :         return nrel;
     702             : }
     703             : 
     704             : sql_rel *
     705        6523 : rel_setop(allocator *sa, sql_rel *l, sql_rel *r, operator_type setop)
     706             : {
     707        6523 :         sql_rel *rel = rel_create(sa);
     708        6523 :         if(!rel)
     709             :                 return NULL;
     710        6523 :         rel->l = l;
     711        6523 :         rel->r = r;
     712        6523 :         rel->op = setop;
     713        6523 :         rel->exps = NULL;
     714        6523 :         rel->card = CARD_MULTI;
     715        6523 :         assert(l->nrcols == r->nrcols);
     716        6523 :         rel->nrcols = l->nrcols;
     717        6523 :         return rel;
     718             : }
     719             : 
     720             : sql_rel *
     721        2419 : rel_setop_check_types(mvc *sql, sql_rel *l, sql_rel *r, list *ls, list *rs, operator_type op)
     722             : {
     723        2419 :         list *nls = new_exp_list(sql->sa);
     724        2419 :         list *nrs = new_exp_list(sql->sa);
     725        2419 :         node *n, *m;
     726             : 
     727        2419 :         if(!nls || !nrs)
     728             :                 return NULL;
     729             : 
     730        4952 :         for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
     731        2536 :                 sql_exp *le = n->data;
     732        2536 :                 sql_exp *re = m->data;
     733             : 
     734        2536 :                 if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
     735           3 :                         return NULL;
     736        2533 :                 append(nls, le);
     737        2533 :                 append(nrs, re);
     738             :         }
     739        2416 :         l = rel_project(sql->sa, l, nls);
     740        2416 :         r = rel_project(sql->sa, r, nrs);
     741        2416 :         set_processed(l);
     742        2416 :         set_processed(r);
     743        2416 :         return rel_setop(sql->sa, l, r, op);
     744             : }
     745             : 
     746             : void
     747        7321 : rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     748             : {
     749        7321 :         sql_rel *l = rel->l, *r = rel->r;
     750        7321 :         list *lexps = l->exps, *rexps = r->exps;
     751             : 
     752        7321 :         if (!is_project(l->op))
     753        1885 :                 lexps = rel_projections(sql, l, NULL, 0, 1);
     754        7321 :         if (!is_project(r->op))
     755        1941 :                 rexps = rel_projections(sql, r, NULL, 0, 1);
     756             : 
     757        7321 :         assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && list_length(exps) == list_length(lexps)*/);
     758             : 
     759       29349 :         for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n = n->next, m = m->next,o = o->next) {
     760       22028 :                 sql_exp *e = n->data, *f = m->data, *g = o->data;
     761             : 
     762       22028 :                 if (is_union(rel->op)) { /* propagate set_has_no_nil only if it's applicable to both sides of the union*/
     763       19290 :                         if (has_nil(f) || has_nil(g))
     764       16448 :                                 set_has_nil(e);
     765             :                         else
     766        2842 :                                 set_has_no_nil(e);
     767       19290 :                         if (!keep_props) {
     768       18993 :                                 e->p = NULL; /* remove all the properties on unions on the general case */
     769       18993 :                                 set_not_unique(e);
     770             :                         }
     771             :                 }
     772       22028 :                 e->card = CARD_MULTI; /* multi cardinality */
     773             :         }
     774        7321 :         rel->nrcols = l->nrcols;
     775        7321 :         rel->exps = exps;
     776        7321 : }
     777             : 
     778             : sql_rel *
     779       56013 : rel_setop_n_ary(allocator *sa, list *rels, operator_type setop)
     780             : {
     781             :         // TODO: for now we support only n-ary union
     782       56013 :         assert(setop == op_munion);
     783             : 
     784       56013 :         if (!rels)
     785             :                 return NULL;
     786             : 
     787       56013 :         assert(list_length(rels) >= 2);
     788       56013 :         sql_rel *rel = rel_create(sa);
     789       56013 :         if(!rel)
     790             :                 return NULL;
     791             : 
     792       56013 :         rel->l = rels;
     793       56013 :         rel->r = NULL;
     794       56013 :         rel->op = setop;
     795       56013 :         rel->exps = NULL;
     796       56013 :         rel->card = CARD_MULTI;
     797             :         // TODO: properly introduce the assertion over rels elements
     798             :         /*assert(l->nrcols == r->nrcols);*/
     799       56013 :         rel->nrcols = ((sql_rel*)rels->h->data)->nrcols;
     800       56013 :         return rel;
     801             : }
     802             : 
     803             : sql_rel *
     804       55770 : rel_setop_n_ary_check_types(mvc *sql, sql_rel *l, sql_rel *r, list *ls, list *rs, operator_type op)
     805             : {
     806             :         // TODO: for now we support only 2 relation in the list at ->l of
     807             :         // the n-ary operator. In the future this function should be variadic (?)
     808             :         // TODO: for now we support only n-ary union
     809       55770 :         assert(op == op_munion);
     810             : 
     811             :         /* NOTE: this is copied logic from rel_setop_check_types. A DRY-er approach
     812             :          * would be to call rel_setop_check_types which will return a binary
     813             :          * setop from which we could extract ->l and ->r and add them in a list
     814             :          * for the op_munion. This is kind of ugly though...
     815             :          */
     816       55770 :         list *nls = new_exp_list(sql->sa);
     817       55770 :         list *nrs = new_exp_list(sql->sa);
     818       55770 :         node *n, *m;
     819       55770 :         list* rels;
     820             : 
     821       55770 :         if(!nls || !nrs)
     822             :                 return NULL;
     823             : 
     824      440513 :         for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
     825      384747 :                 sql_exp *le = n->data;
     826      384747 :                 sql_exp *re = m->data;
     827             : 
     828      384747 :                 if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
     829           4 :                         return NULL;
     830      384743 :                 append(nls, le);
     831      384743 :                 append(nrs, re);
     832             :         }
     833       55766 :         l = rel_project(sql->sa, l, nls);
     834       55766 :         r = rel_project(sql->sa, r, nrs);
     835       55766 :         set_processed(l);
     836       55766 :         set_processed(r);
     837             : 
     838             :         /* create a list with only 2 sql_rel entries for the n-ary set op */
     839       55766 :         rels = sa_list(sql->sa);
     840       55766 :         append(rels, l);
     841       55766 :         append(rels, r);
     842             : 
     843       55766 :         return rel_setop_n_ary(sql->sa, rels, op);
     844             : }
     845             : 
     846             : void
     847       59920 : rel_setop_n_ary_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     848             : {
     849       59920 :         list *rexps;
     850       59920 :         sql_rel *r;
     851             : 
     852             :         /* set the exps properties first */
     853      479380 :         for (node *m = exps->h; m; m = m->next) {
     854             :                 /* the nil/no_nil property will be set in the next loop where
     855             :                  * we go through the exps of every rel of the rels. For now no_nil
     856             :                  */
     857      419460 :                 sql_exp *e = (sql_exp*)m->data;
     858      419460 :                 set_has_no_nil(e);
     859             :                 /* remove all the properties on unions on the general case */
     860      419460 :                 if (!keep_props) {
     861      419460 :                         e->p = NULL;
     862      419460 :                         set_not_unique(e);
     863             :                 }
     864             :         }
     865             : 
     866             :         /* for every relation in the list of relations */
     867      179760 :         for (node *n = ((list*)rel->l)->h; n; n = n->next) {
     868      119840 :                 r = n->data;
     869      119840 :                 rexps = r->exps;
     870             : 
     871      119840 :                 if (!is_project(r->op))
     872        7816 :                         rexps = rel_projections(sql, r, NULL, 0, 1);
     873             : 
     874             :                 /* go through the relation's exps */
     875      958760 :                 for (node *m = exps->h, *o = rexps->h; m && o; m = m->next, o = o->next) {
     876      838920 :                         sql_exp *e = m->data, *f = o->data;
     877             :                         /* for multi-union if any operand has nil then set the nil prop for the op exp */
     878      838920 :                         if (is_munion(rel->op) && has_nil(f))
     879      479909 :                                 set_has_nil(e);
     880      838920 :                         e->card = CARD_MULTI;
     881             :                 }
     882             :         }
     883             : 
     884       59920 :         rel->exps = exps;
     885             :         // TODO: probably setting nrcols is redundant as we have allready done
     886             :         // that when we create the setop_n_ary. check rel_setop_n_ary()
     887       59920 :         rel->nrcols = ((sql_rel*)((list*)rel->l)->h->data)->nrcols;
     888       59920 : }
     889             : 
     890             : sql_rel *
     891      473994 : rel_crossproduct(allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
     892             : {
     893      473994 :         sql_rel *rel = rel_create(sa);
     894      473994 :         if(!rel)
     895             :                 return NULL;
     896             : 
     897      473994 :         rel->l = l;
     898      473994 :         rel->r = r;
     899      473994 :         rel->op = join;
     900      473994 :         rel->exps = NULL;
     901      473994 :         rel->card = CARD_MULTI;
     902      473994 :         rel->nrcols = l->nrcols + r->nrcols;
     903      473994 :         return rel;
     904             : }
     905             : 
     906             : sql_exp *
     907           0 : rel_is_constant(sql_rel **R, sql_exp *e)
     908             : {
     909           0 :         sql_rel *rel = *R;
     910             : 
     911           0 :         if (rel && rel->op == op_project && list_length(rel->exps) == 1 &&
     912           0 :             !rel->l && !rel->r && !rel_is_ref(rel) && e->type == e_column) {
     913           0 :                 sql_exp *ne = rel_find_exp(rel, e);
     914           0 :                 if (ne) {
     915           0 :                         rel_destroy(rel);
     916           0 :                         *R = NULL;
     917           0 :                         return ne;
     918             :                 }
     919             :         }
     920             :         return e;
     921             : }
     922             : 
     923             : sql_rel *
     924       16907 : rel_topn(allocator *sa, sql_rel *l, list *exps )
     925             : {
     926       16907 :         sql_rel *rel = rel_create(sa);
     927       16912 :         if(!rel)
     928             :                 return NULL;
     929             : 
     930       16912 :         rel->l = l;
     931       16912 :         rel->r = NULL;
     932       16912 :         rel->op = op_topn;
     933       16912 :         rel->exps = exps;
     934       16912 :         rel->card = l->card;
     935       16912 :         rel->nrcols = l->nrcols;
     936       16912 :         return rel;
     937             : }
     938             : 
     939             : sql_rel *
     940          23 : rel_sample(allocator *sa, sql_rel *l, list *exps )
     941             : {
     942          23 :         sql_rel *rel = rel_create(sa);
     943          23 :         if(!rel)
     944             :                 return NULL;
     945             : 
     946          23 :         rel->l = l;
     947          23 :         rel->r = NULL;
     948          23 :         rel->op = op_sample;
     949          23 :         rel->exps = exps;
     950          23 :         rel->card = l->card;
     951          23 :         rel->nrcols = l->nrcols;
     952          23 :         return rel;
     953             : }
     954             : 
     955             : sql_rel *
     956       14057 : rel_label( mvc *sql, sql_rel *r, int all)
     957             : {
     958       14057 :         int nr = ++sql->label;
     959       14057 :         char tname[16], *tnme;
     960       14057 :         char cname[16], *cnme = NULL;
     961             : 
     962       14057 :         tnme = sa_strdup(sql->sa, number2name(tname, sizeof(tname), nr));
     963       14061 :         if (!is_simple_project(r->op))
     964         597 :                 r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 1));
     965       14061 :         if (!list_empty(r->exps)) {
     966       14060 :                 list_hash_clear(r->exps);
     967       55506 :                 for (node *ne = r->exps->h; ne; ne = ne->next) {
     968       41445 :                         sql_exp *e = ne->data;
     969             : 
     970       41445 :                         if (!is_freevar(e)) {
     971       41437 :                                 if (all) {
     972       41437 :                                         nr = ++sql->label;
     973       41437 :                                         cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
     974             :                                 }
     975       41444 :                                 exp_setname(sql->sa, e, tnme, cnme );
     976             :                         }
     977             :                 }
     978             :         }
     979             :         /* op_projects can have a order by list */
     980       14062 :         if (!list_empty(r->r)) {
     981           0 :                 for (node *ne = ((list*)r->r)->h; ne; ne = ne->next) {
     982           0 :                         if (all) {
     983           0 :                                 nr = ++sql->label;
     984           0 :                                 cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
     985             :                         }
     986           0 :                         exp_setname(sql->sa, ne->data, tnme, cnme );
     987             :                 }
     988             :         }
     989       14061 :         return r;
     990             : }
     991             : 
     992             : sql_exp *
     993       30087 : rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e)
     994             : {
     995       30087 :         assert(is_project(rel->op));
     996             : 
     997       30087 :         if (!exp_name(e))
     998          90 :                 exp_label(sql->sa, e, ++sql->label);
     999       30087 :         if (is_simple_project(rel->op)) {
    1000       30087 :                 sql_rel *l = rel->l;
    1001       30087 :                 if (!rel->exps)
    1002          19 :                         rel->exps = new_exp_list(sql->sa);
    1003       30087 :                 if (l && is_groupby(l->op) && exp_card(e) <= CARD_ATOM && list_empty(l->exps))
    1004           0 :                         e = rel_project_add_exp(sql, l, e);
    1005       30087 :                 if (e->card > rel->card)
    1006           0 :                         rel->card = e->card;
    1007       30087 :                 append(rel->exps, e);
    1008       30087 :                 rel->nrcols++;
    1009           0 :         } else if (is_groupby(rel->op)) {
    1010           0 :                 return rel_groupby_add_aggr(sql, rel, e);
    1011             :         }
    1012       30087 :         e = exp_ref(sql, e);
    1013       30087 :         return e;
    1014             : }
    1015             : 
    1016             : sql_rel *
    1017      278003 : rel_select_add_exp(allocator *sa, sql_rel *l, sql_exp *e)
    1018             : {
    1019      278003 :         if ((l->op != op_select && !is_outerjoin(l->op)) || rel_is_ref(l))
    1020        6851 :                 return rel_select(sa, l, e);
    1021             : 
    1022             : /*      allow during AST->relational for bool expresssions as well
    1023             :         if (e->type != e_cmp && e->card > CARD_ATOM) {
    1024             :                 sql_exp *t = exp_atom_bool(sa, 1);
    1025             :                 e = exp_compare(sa, e, t, cmp_equal);
    1026             :         }
    1027             : */
    1028      271152 :         if (!l->exps)
    1029        4581 :                 l->exps = new_exp_list(sa);
    1030      271152 :         append(l->exps, e);
    1031      271152 :         return l;
    1032             : }
    1033             : 
    1034             : void
    1035      448779 : rel_join_add_exp( allocator *sa, sql_rel *rel, sql_exp *e)
    1036             : {
    1037      448779 :         assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
    1038             : 
    1039      448779 :         if (!rel->exps)
    1040      404480 :                 rel->exps = new_exp_list(sa);
    1041      448779 :         append(rel->exps, e);
    1042      448779 :         if (e->card > rel->card)
    1043           0 :                 rel->card = e->card;
    1044      448779 : }
    1045             : 
    1046             : sql_exp *
    1047       76444 : rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
    1048             : {
    1049       76444 :         sql_exp *m = NULL, *ne;
    1050             : 
    1051       76444 :         if (list_empty(rel->r))
    1052       26492 :                 rel->card = e->card = CARD_ATOM;
    1053             : 
    1054       76444 :         if ((m=exps_any_match(rel->exps, e)) == NULL) {
    1055       44704 :                 if (!exp_name(e))
    1056       44666 :                         exp_label(sql->sa, e, ++sql->label);
    1057       44704 :                 append(rel->exps, e);
    1058       44704 :                 rel->nrcols++;
    1059       44704 :                 m = e;
    1060             :         }
    1061       76444 :         ne = exp_ref(sql, m);
    1062       76444 :         return ne;
    1063             : }
    1064             : 
    1065             : sql_rel *
    1066      256697 : rel_select(allocator *sa, sql_rel *l, sql_exp *e)
    1067             : {
    1068      256697 :         sql_rel *rel;
    1069             : 
    1070      256697 :         if (l && is_outerjoin(l->op) && !is_processed(l)) {
    1071         188 :                 if (e) {
    1072         172 :                         if (!l->exps)
    1073         157 :                                 l->exps = new_exp_list(sa);
    1074         172 :                         append(l->exps, e);
    1075             :                 }
    1076         188 :                 return l;
    1077             :         }
    1078             : 
    1079      256509 :         if (l && is_select(l->op) && !rel_is_ref(l)) { /* refine old select */
    1080       17576 :                 if (e)
    1081        9706 :                         rel_select_add_exp(sa, l, e);
    1082       17576 :                 return l;
    1083             :         }
    1084      238933 :         rel = rel_create(sa);
    1085      238933 :         if(!rel)
    1086             :                 return NULL;
    1087             : 
    1088      238933 :         rel->l = l;
    1089      238933 :         rel->r = NULL;
    1090      238933 :         rel->op = op_select;
    1091      238933 :         rel->exps = new_exp_list(sa);
    1092      238933 :         if (e)
    1093      186213 :                 rel_select_add_exp(sa, rel, e);
    1094      238933 :         rel->card = CARD_ATOM; /* no relation */
    1095      238933 :         if (l) {
    1096      238933 :                 rel->card = l->card;
    1097      238933 :                 rel->nrcols = l->nrcols;
    1098      238933 :                 if (is_single(l))
    1099        1487 :                         set_single(rel);
    1100             :         }
    1101             :         return rel;
    1102             : }
    1103             : 
    1104             : sql_rel *
    1105       36379 : rel_groupby(mvc *sql, sql_rel *l, list *groupbyexps )
    1106             : {
    1107       36379 :         sql_rel *rel = rel_create(sql->sa);
    1108       36379 :         list *aggrs = new_exp_list(sql->sa);
    1109       36379 :         node *en;
    1110       36379 :         if(!rel || !aggrs) {
    1111           0 :                 rel_destroy(rel);
    1112           0 :                 return NULL;
    1113             :         }
    1114             : 
    1115       36379 :         rel->card = CARD_ATOM;
    1116             :         /* reduce duplicates in groupbyexps */
    1117       36379 :         if (groupbyexps && list_length(groupbyexps) > 1) {
    1118        4969 :                 list *gexps = sa_list(sql->sa);
    1119             : 
    1120       24204 :                 for (en = groupbyexps->h; en; en = en->next) {
    1121       19235 :                         sql_exp *e = en->data, *ne = exps_find_exp(gexps, e);
    1122             : 
    1123       19235 :                         if (!ne) {
    1124       19132 :                                 list_append(gexps, e);
    1125             :                         } else {
    1126         103 :                                 const char *ername = exp_relname(e), *nername = exp_relname(ne), *ename = exp_name(e), *nename = exp_name(ne);
    1127         103 :                                 if ((ername && !nername) || (!ername && nername) ||
    1128          97 :                                         (ername && nername && strcmp(ername,nername) != 0) || strcmp(ename,nename) != 0)
    1129          10 :                                         list_append(gexps, e);
    1130             :                         }
    1131             :                 }
    1132             :                 groupbyexps = gexps;
    1133             :         }
    1134             : 
    1135        9994 :         if (groupbyexps) {
    1136        9994 :                 rel->card = CARD_AGGR;
    1137       34024 :                 for (en = groupbyexps->h; en; en = en->next) {
    1138       24030 :                         sql_exp *e = en->data, *ne;
    1139             : 
    1140             :                         /* after the group by the cardinality reduces */
    1141       24030 :                         e->card = MIN(e->card, rel->card); /* if the column is an atom, the cardinality should not change */
    1142       24030 :                         ne = exp_ref(sql, e);
    1143       24030 :                         ne = exp_propagate(sql->sa, ne, e);
    1144       24030 :                         append(aggrs, ne);
    1145             :                 }
    1146             :         }
    1147       36379 :         rel->l = l;
    1148       36379 :         rel->r = groupbyexps;
    1149       36379 :         rel->exps = aggrs;
    1150       36379 :         rel->nrcols = aggrs?list_length(aggrs):0;
    1151       36379 :         rel->op = op_groupby;
    1152       36379 :         rel->grouped = 1;
    1153       36379 :         return rel;
    1154             : }
    1155             : 
    1156             : sql_rel *
    1157      901301 : rel_project(allocator *sa, sql_rel *l, list *e)
    1158             : {
    1159      901301 :         sql_rel *rel = rel_create(sa);
    1160      901203 :         if(!rel)
    1161             :                 return NULL;
    1162             : 
    1163      901203 :         rel->l = l;
    1164      901203 :         rel->r = NULL;
    1165      901203 :         rel->op = op_project;
    1166      901203 :         rel->exps = e;
    1167      901203 :         rel->card = exps_card(e);
    1168      901620 :         if (l) {
    1169      710301 :                 rel->card = l->card;
    1170      710301 :                 if (e)
    1171      706037 :                         rel->nrcols = list_length(e);
    1172             :                 else
    1173        4264 :                         rel->nrcols = l->nrcols;
    1174      710308 :                 rel->single = is_single(l);
    1175             :         }
    1176      901627 :         if (e && !list_empty(e)) {
    1177      896635 :                 set_processed(rel);
    1178      896635 :                 rel->nrcols = list_length(e);
    1179             :         }
    1180             :         return rel;
    1181             : }
    1182             : 
    1183             : sql_rel *
    1184       72254 : rel_project_exp(mvc *sql, sql_exp *e)
    1185             : {
    1186       72254 :         if (!exp_name(e))
    1187       72308 :                 exp_label(sql->sa, e, ++sql->label);
    1188       72251 :         return rel_project(sql->sa, NULL, list_append(sa_list(sql->sa), e));
    1189             : }
    1190             : 
    1191             : sql_rel *
    1192      111563 : rel_list(allocator *sa, sql_rel *l, sql_rel *r)
    1193             : {
    1194      111563 :         sql_rel *rel = rel_create(sa);
    1195      111563 :         if (!rel)
    1196             :                 return NULL;
    1197      111563 :         if (!l)
    1198             :                 return r;
    1199         556 :         rel->l = l;
    1200         556 :         rel->r = r;
    1201         556 :         rel->op = op_ddl;
    1202         556 :         rel->flag = ddl_list;
    1203         556 :         return rel;
    1204             : }
    1205             : 
    1206             : sql_rel *
    1207         157 : rel_exception(allocator *sa, sql_rel *l, sql_rel *r, list *exps)
    1208             : {
    1209         157 :         sql_rel *rel = rel_create(sa);
    1210         157 :         if(!rel)
    1211             :                 return NULL;
    1212         157 :         rel->r = r;
    1213         157 :         rel->exps = exps;
    1214         157 :         rel->op = op_ddl;
    1215         157 :         rel->flag = ddl_exception;
    1216         157 :         if (l)
    1217         157 :                 return rel_list(sa, rel, l); /* keep base relation on the right ! */
    1218             :         return rel;
    1219             : }
    1220             : 
    1221             : sql_rel *
    1222         300 : rel_relational_func(allocator *sa, sql_rel *l, list *exps)
    1223             : {
    1224         300 :         sql_rel *rel = rel_create(sa);
    1225         300 :         if(!rel)
    1226             :                 return NULL;
    1227             : 
    1228         300 :         rel->flag = TABLE_PROD_FUNC;
    1229         300 :         rel->l = l;
    1230         300 :         rel->op = op_table;
    1231         300 :         rel->exps = exps;
    1232         300 :         rel->card = CARD_MULTI;
    1233         300 :         rel->nrcols = list_length(exps);
    1234         300 :         return rel;
    1235             : }
    1236             : 
    1237             : sql_rel *
    1238       16351 : rel_table_func(allocator *sa, sql_rel *l, sql_exp *f, list *exps, int kind)
    1239             : {
    1240       16351 :         sql_rel *rel = rel_create(sa);
    1241       16351 :         if(!rel)
    1242             :                 return NULL;
    1243             : 
    1244       16351 :         assert(kind > 0);
    1245       16351 :         rel->flag = kind;
    1246       16351 :         rel->l = l; /* relation before call */
    1247       16351 :         rel->r = f; /* expression (table func call) */
    1248       16351 :         rel->op = op_table;
    1249       16351 :         rel->exps = exps;
    1250       16351 :         rel->card = CARD_MULTI;
    1251       16351 :         rel->nrcols = list_length(exps);
    1252       16351 :         return rel;
    1253             : }
    1254             : 
    1255             : static void
    1256      260932 : exps_reset_props(list *exps, bool setnil)
    1257             : {
    1258      260932 :         if (!list_empty(exps)) {
    1259     2686767 :                 for (node *m = exps->h; m; m = m->next) {
    1260     2428724 :                         sql_exp *e = m->data;
    1261             : 
    1262     2428724 :                         if (setnil)
    1263      194153 :                                 set_has_nil(e);
    1264     2428724 :                         set_not_unique(e);
    1265             :                 }
    1266             :         }
    1267      260932 : }
    1268             : 
    1269             : /* Return a list with all the projection expressions, that optionaly
    1270             :  * refer to the tname relation, anywhere in the relational tree
    1271             :  */
    1272             : list *
    1273      953263 : _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern, int basecol /* basecol only */ )
    1274             : {
    1275     1021622 :         list *lexps, *rexps = NULL, *exps = NULL, *rels;
    1276     1021622 :         sql_rel *r = NULL;
    1277             : 
    1278     1021622 :         if (mvc_highwater(sql))
    1279           4 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1280             : 
    1281     1021621 :         if (!rel)
    1282           0 :                 return new_exp_list(sql->sa);
    1283             : 
    1284     1021621 :         if (!tname && is_basetable(rel->op) && !is_processed(rel))
    1285      258886 :                 rel_base_use_all( sql, rel);
    1286             : 
    1287     1021619 :         switch(rel->op) {
    1288      130466 :         case op_join:
    1289             :         case op_left:
    1290             :         case op_right:
    1291             :         case op_full:
    1292      130466 :                 lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1293      130466 :                 exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
    1294      130466 :                 if (!rel->attr)
    1295      127594 :                         rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
    1296      130466 :                 exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
    1297      130466 :                 if (rexps)
    1298      127594 :                         lexps = list_merge(lexps, rexps, (fdup)NULL);
    1299      130466 :                 if (rel->attr)
    1300        2872 :                         append(lexps, exp_ref(sql, rel->attr->h->data));
    1301             :                 return lexps;
    1302        6579 :         case op_groupby:
    1303        6579 :                 if (list_empty(rel->exps) && rel->r) {
    1304           1 :                         list *r = rel->r;
    1305           1 :                         int label = 0;
    1306             : 
    1307           1 :                         if (!settname)
    1308           0 :                                 label = ++sql->label;
    1309           1 :                         exps = new_exp_list(sql->sa);
    1310           2 :                         for (node *en = r->h; en; en = en->next) {
    1311           1 :                                 sql_exp *e = en->data;
    1312             : 
    1313           1 :                                 if (basecol && !is_basecol(e))
    1314           0 :                                         continue;
    1315           1 :                                 if (intern || !is_intern(e)) {
    1316           1 :                                         e = exp_alias_or_copy(sql, tname, exp_name(e), rel, e);
    1317           1 :                                         if (!settname) /* noname use alias */
    1318           0 :                                                 exp_setrelname(sql->sa, e, label);
    1319           1 :                                         append(exps, e);
    1320             :                                 }
    1321             :                         }
    1322             :                         return exps;
    1323             :                 }
    1324             :                 /* fall through */
    1325             :         case op_project:
    1326             :         case op_basetable:
    1327             :         case op_table:
    1328             : 
    1329             :         case op_union:
    1330             :         case op_except:
    1331             :         case op_inter:
    1332             :         case op_munion:
    1333      822793 :                 if (is_basetable(rel->op) && !rel->exps)
    1334       98147 :                         return rel_base_projection(sql, rel, intern);
    1335      724646 :                 if (rel->exps) {
    1336      666464 :                         int label = 0;
    1337             : 
    1338      666464 :                         if (!settname)
    1339      186169 :                                 label = ++sql->label;
    1340      666464 :                         exps = new_exp_list(sql->sa);
    1341     5401931 :                         for (node *en = rel->exps->h; en; en = en->next) {
    1342     4735463 :                                 sql_exp *e = en->data;
    1343             : 
    1344     4735463 :                                 if (basecol && !is_basecol(e))
    1345          40 :                                         continue;
    1346     4735423 :                                 if (intern || !is_intern(e)) {
    1347     4722225 :                                         e = exp_alias_or_copy(sql, tname, exp_name(e), rel, e);
    1348     4722225 :                                         if (!settname) /* noname use alias */
    1349     1236214 :                                                 exp_setrelname(sql->sa, e, label);
    1350     4722225 :                                         append(exps, e);
    1351             :                                 }
    1352             :                         }
    1353             :                         return exps;
    1354             :                 }
    1355             :                 /* differentiate for the munion set op (for now) */
    1356       58182 :                 if (is_munion(rel->op)) {
    1357       55766 :                         assert(rel->l);
    1358             :                         /* get the exps from the first relation */
    1359       55766 :                         rels = rel->l;
    1360       55766 :                         if (rels->h)
    1361       55766 :                                 r = rels->h->data;
    1362       55766 :                         if (r)
    1363       55766 :                                 exps = _rel_projections(sql, r, tname, settname, intern, basecol);
    1364             :                         /* for every other relation in the list */
    1365             :                         // TODO: do we need the assertion here? for no-assert the loop is no-op
    1366             :                         /*
    1367             :                         for (node *n = rels->h->next; n; n = n->next) {
    1368             :                                 rexps = _rel_projections(sql, n->data, tname, settname, intern, basecol);
    1369             :                                 assert(list_length(exps) == list_length(rexps));
    1370             :                         }
    1371             :                         */
    1372             :                         /* it's a multi-union (expressions have to be the same in all the operands)
    1373             :                          * so we are ok only with the expressions of the first operand
    1374             :                          */
    1375       55766 :                         if (exps) {
    1376       55766 :                                 int label = 0;
    1377       55766 :                                 if (!settname)
    1378       55766 :                                         label = ++sql->label;
    1379      440509 :                                 for (node *en = exps->h; en; en = en->next) {
    1380      384743 :                                         sql_exp *e = en->data;
    1381             : 
    1382      384743 :                                         e->card = rel->card;
    1383      384743 :                                         if (!settname) /* noname use alias */
    1384      384743 :                                                 exp_setrelname(sql->sa, e, label);
    1385             :                                 }
    1386       55766 :                                 if (!settname)
    1387       55766 :                                         list_hash_clear(rel->l);
    1388             :                         }
    1389       55766 :                         return exps;
    1390             :                 }
    1391             :                 /* I only expect set relations to hit here */
    1392        2416 :                 assert(is_set(rel->op));
    1393        2416 :                 lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1394             :                 //rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
    1395        2416 :                 if (lexps/* && rexps*/) {
    1396        2416 :                         int label = 0;
    1397             : 
    1398        2416 :                         if (!settname)
    1399        2416 :                                 label = ++sql->label;
    1400             :                         //assert(list_length(lexps) == list_length(rexps));
    1401        4949 :                         for (node *en = lexps->h; en; en = en->next) {
    1402        2533 :                                 sql_exp *e = en->data;
    1403             : 
    1404        2533 :                                 e->card = rel->card;
    1405        2533 :                                 if (!settname) /* noname use alias */
    1406        2533 :                                         exp_setrelname(sql->sa, e, label);
    1407             :                         }
    1408        2416 :                         if (!settname)
    1409        2416 :                                 list_hash_clear(lexps);
    1410             :                 }
    1411             :                 return lexps;
    1412             : 
    1413       68359 :         case op_ddl:
    1414             :         case op_semi:
    1415             :         case op_anti:
    1416             : 
    1417             :         case op_select:
    1418             :         case op_topn:
    1419             :         case op_sample:
    1420       68359 :                 return _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1421             :         default:
    1422             :                 return NULL;
    1423             :         }
    1424             : }
    1425             : 
    1426             : list *
    1427      597457 : rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern)
    1428             : {
    1429      597457 :         assert(tname == NULL);
    1430      597457 :         return _rel_projections(sql, rel, tname, settname, intern, 0);
    1431             : }
    1432             : 
    1433             : /* find the path to the relation containing the base of the expression
    1434             :         (e_column), in most cases this means go down the join tree and
    1435             :         find the base column.
    1436             :  */
    1437             : static int
    1438     3999169 : rel_bind_path_(mvc *sql, sql_rel *rel, sql_exp *e, list *path )
    1439             : {
    1440     3999169 :         int found = 0;
    1441     3999169 :         list *rels;
    1442             : 
    1443     3999169 :         if (mvc_highwater(sql)) {
    1444           0 :                 sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1445           0 :                 return 0;
    1446             :         }
    1447             : 
    1448     3999169 :         switch (rel->op) {
    1449     1856472 :         case op_join:
    1450             :         case op_left:
    1451             :         case op_right:
    1452             :         case op_full:
    1453             :                 /* first right (possible subquery) */
    1454     1856472 :                 found = rel_bind_path_(sql, rel->r, e, path);
    1455     1856472 :                 if (!found)
    1456     1563538 :                         found = rel_bind_path_(sql, rel->l, e, path);
    1457     1563538 :                 if (!found && !list_empty(rel->attr)) {
    1458           0 :                         if (e->l && exps_bind_column2(rel->attr, e->l, e->r, NULL))
    1459             :                                 found = 1;
    1460           0 :                         if (!found && !e->l && exps_bind_column(rel->attr, e->r, NULL, NULL, 1))
    1461             :                                 found = 1;
    1462             :                 }
    1463             :                 break;
    1464      115084 :         case op_semi:
    1465             :         case op_anti:
    1466             :         case op_select:
    1467             :         case op_topn:
    1468             :         case op_sample:
    1469      115084 :                 found = rel_bind_path_(sql, rel->l, e, path);
    1470      115084 :                 break;
    1471     2024346 :         case op_basetable:
    1472             :         case op_union:
    1473             :         case op_inter:
    1474             :         case op_except:
    1475             :         case op_groupby:
    1476             :         case op_project:
    1477             :         case op_table:
    1478     2024346 :                 if (is_basetable(rel->op) && !rel->exps) {
    1479     1836980 :                         if (e->l) {
    1480     1836980 :                                 if (rel_base_bind_column2_(rel, e->l, e->r))
    1481             :                                         found = 1;
    1482           0 :                         } else if (rel_base_bind_column_(rel, e->r))
    1483             :                                 found = 1;
    1484      187366 :                 } else if (rel->exps) {
    1485      187366 :                         if (!found && e->l && exps_bind_column2(rel->exps, e->l, e->r, NULL))
    1486             :                                 found = 1;
    1487       96578 :                         if (!found && !e->l && exps_bind_column(rel->exps, e->r, NULL, NULL, 1))
    1488             :                                 found = 1;
    1489             :                 }
    1490             :                 break;
    1491        3267 :         case op_munion:
    1492        3267 :                 assert(rel->l);
    1493        3267 :                 rels = rel->l;
    1494        7036 :                 for (node *n = rels->h; n && !found; n = n->next) {
    1495        3769 :                         if (!found && e->l && exps_bind_column2(rel->exps, e->l, e->r, NULL))
    1496             :                                 found = 1;
    1497        1004 :                         if (!found && !e->l && exps_bind_column(rel->exps, e->r, NULL, NULL, 1))
    1498        2765 :                                 found = 1;
    1499             :                 }
    1500             :                 break;
    1501             :         case op_insert:
    1502             :         case op_update:
    1503             :         case op_delete:
    1504             :         case op_truncate:
    1505             :         case op_merge:
    1506             :         case op_ddl:
    1507             :                 break;
    1508             :         }
    1509      214936 :         if (found)
    1510     2391091 :                 list_prepend(path, rel);
    1511             :         return found;
    1512             : }
    1513             : 
    1514             : static list *
    1515      490677 : rel_bind_path(mvc *sql, sql_rel *rel, sql_exp *e, list *path)
    1516             : {
    1517      490677 :         if (!path)
    1518             :                 return NULL;
    1519             : 
    1520      490677 :         if (e->type == e_convert) {
    1521       21033 :                 if (!(path = rel_bind_path(sql, rel, e->l, path)))
    1522             :                         return NULL;
    1523      469644 :         } else if (e->type == e_column) {
    1524      464075 :                 if (rel) {
    1525      464075 :                         if (!rel_bind_path_(sql, rel, e, path)) {
    1526             :                                 /* something is wrong */
    1527             :                                 return NULL;
    1528             :                         }
    1529             :                 }
    1530      464075 :                 return path;
    1531             :         }
    1532             :         /* default the top relation */
    1533       26602 :         append(path, rel);
    1534       26602 :         return path;
    1535             : }
    1536             : 
    1537             : static sql_rel *
    1538       21989 : rel_select_push_exp_down(mvc *sql, sql_rel *rel, sql_exp *e)
    1539             : {
    1540       21989 :         sql_rel *r = rel->l, *jl = r->l, *jr = r->r;
    1541       21989 :         int left = r->op == op_join || r->op == op_left;
    1542       21989 :         int right = r->op == op_join || r->op == op_right;
    1543       21989 :         int done = 0;
    1544             : 
    1545       21989 :         assert(is_select(rel->op));
    1546       21989 :         if (!is_full(r->op) && !is_single(r)) {
    1547       21989 :                 if (left && rel_rebind_exp(sql, jl, e)) {
    1548           9 :                         done = 1;
    1549           9 :                         r->l = jl = rel_select_add_exp(sql->sa, jl, e);
    1550       21980 :                 } else if (right && rel_rebind_exp(sql, jr, e)) {
    1551           6 :                         done = 1;
    1552           6 :                         r->r = jr = rel_select_add_exp(sql->sa, jr, e);
    1553             :                 }
    1554             :         }
    1555          15 :         if (!done)
    1556       21974 :                 rel_select_add_exp(sql->sa, rel, e);
    1557       21989 :         return rel;
    1558             : }
    1559             : 
    1560             : /* ls is the left expression of the select, e is the select expression.  */
    1561             : sql_rel *
    1562      110641 : rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
    1563             : {
    1564      110641 :         list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
    1565      110641 :         node *n;
    1566      110641 :         sql_rel *lrel = NULL, *p = NULL;
    1567             : 
    1568      110641 :         if (!l)
    1569             :                 return NULL;
    1570      110641 :         if (is_sql_or(f)) /* expression has no clear parent relation, so filter current with it */
    1571       21517 :                 return rel_select(sql->sa, rel, e);
    1572             : 
    1573      254206 :         for (n = l->h; n; n = n->next ) {
    1574      253499 :                 lrel = n->data;
    1575             : 
    1576      253499 :                 if (rel_is_ref(lrel))
    1577             :                         break;
    1578             : 
    1579             :                 /* push down as long as the operators allow this */
    1580      253491 :                 if (!is_select(lrel->op) &&
    1581      231930 :                     !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1582       88409 :                     lrel->op != op_join &&
    1583             :                     lrel->op != op_left)
    1584             :                         break;
    1585             :                 /* pushing through left head of a left join is allowed */
    1586      165086 :                 if (lrel->op == op_left && (!n->next || lrel->l != n->next->data))
    1587             :                         break;
    1588      165082 :                 p = lrel;
    1589             :         }
    1590       89124 :         if (!lrel)
    1591             :                 return NULL;
    1592       89124 :         if (p && is_select(p->op) && !rel_is_ref(p)) { /* refine old select */
    1593       19190 :                 p = rel_select_push_exp_down(sql, p, e);
    1594             :         } else {
    1595       69934 :                 sql_rel *n = rel_select(sql->sa, lrel, e);
    1596             : 
    1597       69934 :                 if (p && p != lrel) {
    1598       64665 :                         assert(p->op == op_join || p->op == op_left || is_semi(p->op));
    1599       64665 :                         if (p->l == lrel) {
    1600       23355 :                                 p->l = n;
    1601             :                         } else {
    1602       41310 :                                 p->r = n;
    1603             :                         }
    1604             :                 } else {
    1605        5269 :                         if (rel != lrel)
    1606           0 :                                 assert(0);
    1607             :                         rel = n;
    1608             :                 }
    1609             :         }
    1610             :         return rel;
    1611             : }
    1612             : 
    1613             : /* ls and rs are the left and right expression of the join, e is the
    1614             :    join expression.
    1615             :  */
    1616             : sql_rel *
    1617      179243 : rel_push_join(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, sql_exp *e, int f)
    1618             : {
    1619      179243 :         list *l = NULL, *r = NULL, *r2 = NULL;
    1620      179243 :         node *ln, *rn;
    1621      179243 :         sql_rel *lrel = NULL, *rrel = NULL, *rrel2 = NULL, *p = NULL;
    1622             : 
    1623      179243 :         if (!(l = rel_bind_path(sql, rel, ls, sa_list(sql->sa))) ||
    1624      179243 :                 !(r = rel_bind_path(sql, rel, rs, sa_list(sql->sa))) ||
    1625         517 :                 (rs2 && !(r2 = rel_bind_path(sql, rel, rs2, sa_list(sql->sa)))))
    1626           0 :                 return NULL;
    1627             : 
    1628      179243 :         if (is_sql_or(f))
    1629        2989 :                 return rel_push_select(sql, rel, ls, e, f);
    1630             : 
    1631      176254 :         p = rel;
    1632      176254 :         if (r2) {
    1633         509 :                 node *rn2;
    1634             : 
    1635        1025 :                 for (ln = l->h, rn = r->h, rn2 = r2->h; ln && rn && rn2; ln = ln->next, rn = rn->next, rn2 = rn2->next ) {
    1636         533 :                         lrel = ln->data;
    1637         533 :                         rrel = rn->data;
    1638         533 :                         rrel2 = rn2->data;
    1639             : 
    1640         533 :                         if (rel_is_ref(lrel) || rel_is_ref(rrel) || rel_is_ref(rrel2) || is_processed(lrel) || is_processed(rrel))
    1641             :                                 break;
    1642             : 
    1643             :                         /* push down as long as the operators allow this
    1644             :                                 and the relation is equal.
    1645             :                         */
    1646         528 :                         if (lrel != rrel || lrel != rrel2 ||
    1647         516 :                                 (!is_select(lrel->op) &&
    1648          61 :                                  !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1649           0 :                                  lrel->op != op_join &&
    1650             :                                  lrel->op != op_left))
    1651             :                                 break;
    1652             :                         /* pushing through left head of a left join is allowed */
    1653         516 :                         if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
    1654             :                                 break;
    1655         516 :                         p = lrel;
    1656             :                 }
    1657             :         } else {
    1658      792997 :                 for (ln = l->h, rn = r->h; ln && rn; ln = ln->next, rn = rn->next ) {
    1659      790248 :                         lrel = ln->data;
    1660      790248 :                         rrel = rn->data;
    1661             : 
    1662      790248 :                         if (rel_is_ref(lrel) || rel_is_ref(rrel) || is_processed(lrel) || is_processed(rrel))
    1663             :                                 break;
    1664             : 
    1665             :                         /* push down as long as the operators allow this
    1666             :                                 and the relation is equal.
    1667             :                         */
    1668      750832 :                         if (lrel != rrel ||
    1669      618909 :                                 (!is_select(lrel->op) &&
    1670      615522 :                                  !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1671        1657 :                                  lrel->op != op_join &&
    1672             :                                  lrel->op != op_left))
    1673             :                                 break;
    1674             :                         /* pushing through left head of a left join is allowed */
    1675      617252 :                         if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
    1676             :                                 break;
    1677      617252 :                         p = lrel;
    1678             :                 }
    1679             :         }
    1680      176254 :         if (!lrel || !rrel || (r2 && !rrel2))
    1681             :                 return NULL;
    1682             : 
    1683             :         /* filter on columns of this relation */
    1684      176254 :         if ((lrel == rrel && (!r2 || lrel == rrel2) && lrel->op != op_join) || rel_is_ref(p)) {
    1685        2813 :                 if (is_select(lrel->op) && !rel_is_ref(lrel)) {
    1686        1145 :                         lrel = rel_select_push_exp_down(sql, lrel, e);
    1687        1668 :                 } else if (p && is_select(p->op) && !rel_is_ref(p)) {
    1688        1654 :                         p = rel_select_push_exp_down(sql, p, e);
    1689             :                 } else {
    1690          14 :                         sql_rel *n = rel_select(sql->sa, lrel, e);
    1691             : 
    1692          14 :                         if (p && p != lrel) {
    1693          12 :                                 if (p->l == lrel)
    1694           1 :                                         p->l = n;
    1695             :                                 else
    1696          11 :                                         p->r = n;
    1697             :                         } else {
    1698             :                                 rel = n;
    1699             :                         }
    1700             :                 }
    1701        2813 :                 return rel;
    1702             :         }
    1703             : 
    1704      173441 :         rel_join_add_exp( sql->sa, p, e);
    1705      173441 :         return rel;
    1706             : }
    1707             : 
    1708             : sql_rel *
    1709       18666 : rel_or(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, list *oexps, list *lexps, list *rexps)
    1710             : {
    1711       18666 :         sql_rel *ll = l->l, *rl = r->l;
    1712       18666 :         list *ls, *rs;
    1713             : 
    1714       18666 :         assert(!lexps || l == r);
    1715       18666 :         if (l == r && lexps) { /* merge both lists */
    1716          36 :                 sql_exp *e = exp_or(sql->sa, lexps, rexps, 0);
    1717          36 :                 list *nl = oexps?oexps:new_exp_list(sql->sa);
    1718             : 
    1719          36 :                 rel_destroy(r);
    1720          36 :                 append(nl, e);
    1721          36 :                 if (is_outerjoin(l->op) && is_processed(l))
    1722           0 :                         l = rel_select(sql->sa, l, NULL);
    1723          36 :                 l->exps = nl;
    1724          36 :                 return l;
    1725             :         }
    1726             : 
    1727             :         /* favor or expressions over union */
    1728       18630 :         if (l->op == r->op && is_select(l->op) &&
    1729       18630 :             ll == rl && ll == rel && !rel_is_ref(l) && !rel_is_ref(r)) {
    1730       18630 :                 sql_exp *e = exp_or(sql->sa, l->exps, r->exps, 0);
    1731       18630 :                 list *nl = new_exp_list(sql->sa);
    1732             : 
    1733       18630 :                 rel_destroy(r);
    1734       18630 :                 append(nl, e);
    1735       18630 :                 l->exps = nl;
    1736             : 
    1737             :                 /* merge and expressions */
    1738       18630 :                 ll = l->l;
    1739       20968 :                 while (ll && is_select(ll->op) && !rel_is_ref(ll)) {
    1740        2338 :                         list_merge(l->exps, ll->exps, (fdup)NULL);
    1741        2338 :                         l->l = ll->l;
    1742        2338 :                         ll->l = NULL;
    1743        2338 :                         rel_destroy(ll);
    1744        2338 :                         ll = l->l;
    1745             :                 }
    1746             :                 return l;
    1747             :         }
    1748             : 
    1749           0 :         if (rel) {
    1750           0 :                 ls = rel_projections(sql, rel, NULL, 1, 1);
    1751           0 :                 rs = rel_projections(sql, rel, NULL, 1, 1);
    1752             :         } else {
    1753           0 :                 ls = rel_projections(sql, l, NULL, 1, 1);
    1754           0 :                 rs = rel_projections(sql, r, NULL, 1, 1);
    1755             :         }
    1756           0 :         set_processed(l);
    1757           0 :         set_processed(r);
    1758           0 :         rel = rel_setop_check_types(sql, l, r, ls, rs, op_union);
    1759           0 :         if (!rel)
    1760             :                 return NULL;
    1761           0 :         rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 1, 1), false);
    1762           0 :         set_processed(rel);
    1763           0 :         rel->nrcols = list_length(rel->exps);
    1764           0 :         rel = rel_distinct(rel);
    1765           0 :         if (!rel)
    1766             :                 return NULL;
    1767           0 :         if (exps_card(l->exps) <= CARD_AGGR &&
    1768           0 :             exps_card(r->exps) <= CARD_AGGR)
    1769             :         {
    1770           0 :                 rel->card = exps_card(l->exps);
    1771           0 :                 exps_fix_card( rel->exps, rel->card);
    1772             :         }
    1773             :         return rel;
    1774             : }
    1775             : 
    1776             : sql_table *
    1777        4002 : rel_ddl_table_get(sql_rel *r)
    1778             : {
    1779        4002 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1780        4002 :                 sql_exp *e = r->exps->t->data;
    1781        4002 :                 atom *a = e->l;
    1782             : 
    1783        4002 :                 return a->data.val.pval;
    1784             :         }
    1785             :         return NULL;
    1786             : }
    1787             : 
    1788             : sql_rel *
    1789        2285 : rel_ddl_basetable_get(sql_rel *r)
    1790             : {
    1791        2285 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1792        2285 :                 return r->l;
    1793             :         }
    1794             :         return NULL;
    1795             : }
    1796             : 
    1797             : static sql_exp *
    1798          26 : exps_find_identity(list *exps, sql_rel *p)
    1799             : {
    1800          26 :         node *n;
    1801             : 
    1802         102 :         for (n=exps->h; n; n = n->next) {
    1803          77 :                 sql_exp *e = n->data;
    1804             : 
    1805          77 :                 if (is_identity(e, p))
    1806           1 :                         return e;
    1807             :         }
    1808             :         return NULL;
    1809             : }
    1810             : 
    1811             : static sql_rel *
    1812          76 : _rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
    1813             : {
    1814          76 :         list *exps = rel_projections(sql, rel, NULL, 1, 1);
    1815          76 :         sql_exp *e = NULL;
    1816             : 
    1817          76 :         if (list_empty(exps)) {
    1818           0 :                 *exp = NULL;
    1819           0 :                 return rel;
    1820             :         }
    1821          76 :         if (!is_simple_project(rel->op) || need_distinct(rel) || !list_empty(rel->r) || rel_is_ref(rel))
    1822          52 :                 rel = rel_project(sql->sa, rel, exps);
    1823             :         /* filter parameters out */
    1824         152 :         for (node *n = rel->exps->h ; n && !e ; n = n->next) {
    1825          76 :                 sql_exp *re = n->data;
    1826             : 
    1827          76 :                 if (exp_subtype(re))
    1828          76 :                         e = re;
    1829             :         }
    1830          76 :         if (!e)
    1831           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query projection must have at least one parameter with known SQL type");
    1832             : 
    1833          76 :         e = exp_column(sql->sa, exp_relname(e), exp_name(e), exp_subtype(e), rel->card, has_nil(e), is_unique(e), is_intern(e));
    1834          76 :         e = exp_unop(sql->sa, e, sql_bind_func(sql, "sys", "identity", exp_subtype(e), NULL, F_FUNC, true, true));
    1835          76 :         set_intern(e);
    1836          76 :         set_has_no_nil(e);
    1837          76 :         set_unique(e);
    1838          76 :         e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
    1839          76 :         *exp = exp_label(sql->sa, e, ++sql->label);
    1840          76 :         (void) rel_project_add_exp(sql, rel, e);
    1841          76 :         return rel;
    1842             : }
    1843             : 
    1844             : sql_rel *
    1845          92 : rel_add_identity(mvc *sql, sql_rel *rel, sql_exp **exp)
    1846             : {
    1847          92 :         if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
    1848          15 :                 *exp = basetable_get_tid_or_add_it(sql, rel);
    1849          15 :                 return rel;
    1850             :         }
    1851          77 :         if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
    1852             :                 return rel;
    1853          76 :         return _rel_add_identity(sql, rel, exp);
    1854             : }
    1855             : 
    1856             : sql_rel *
    1857           0 : rel_add_identity2(mvc *sql, sql_rel *rel, sql_exp **exp)
    1858             : {
    1859           0 :         sql_rel *l = rel, *p = rel;
    1860             : 
    1861           0 :         if (rel && is_basetable(rel->op)) { /* for base table relations just use TID column as identity */
    1862           0 :                 *exp = basetable_get_tid_or_add_it(sql, rel);
    1863           0 :                 return rel;
    1864             :         }
    1865           0 :         if (rel && is_simple_project(rel->op) && !need_distinct(rel) && (*exp = exps_find_identity(rel->exps, rel->l)) != NULL)
    1866             :                 return rel;
    1867           0 :         while(l && !is_set(l->op) && rel_has_freevar(sql, l) && l->l) {
    1868             :                 p = l;
    1869             :                 l = l->l;
    1870             :         }
    1871           0 :         if (l != p) {
    1872           0 :                 sql_rel *o = rel;
    1873           0 :                 sql_exp *id;
    1874             : 
    1875           0 :                 if (!(p->l = _rel_add_identity(sql, l, exp)))
    1876             :                         return NULL;
    1877           0 :                 l = p->l;
    1878           0 :                 id = exp_ref(sql, *exp);
    1879           0 :                 while (o && o != l) {
    1880           0 :                         *exp = id;
    1881           0 :                         if (is_project(o->op))
    1882           0 :                                 rel_project_add_exp(sql, o, id);
    1883           0 :                         o = o->l;
    1884             :                 }
    1885             :                 return rel;
    1886             :         }
    1887           0 :         return _rel_add_identity(sql, rel, exp);
    1888             : }
    1889             : 
    1890             : static sql_exp *
    1891        1474 : rel_find_column_(allocator *sa, list *exps, const char *tname, const char *cname)
    1892             : {
    1893        1474 :         int ambiguous = 0, multi = 0;
    1894        1474 :         sql_exp *e = exps_bind_column2(exps, tname, cname, &multi);
    1895        1474 :         if (!e && cname[0] == '%' && !tname)
    1896           0 :                 e = exps_bind_column(exps, cname, &ambiguous, &multi, 0);
    1897        1474 :         if (e && !ambiguous && !multi)
    1898        1473 :                 return exp_alias(sa, exp_relname(e), exp_name(e), exp_relname(e), cname, exp_subtype(e), e->card, has_nil(e), is_unique(e), is_intern(e));
    1899             :         return NULL;
    1900             : }
    1901             : 
    1902             : sql_exp *
    1903        1474 : rel_find_column(allocator *sa, sql_rel *rel, const char *tname, const char *cname )
    1904             : {
    1905        1761 :         sql_exp *e = NULL;
    1906             : 
    1907        1761 :         if (!rel)
    1908             :                 return NULL;
    1909        1761 :         if (rel->exps && (is_project(rel->op) || is_base(rel->op)) && (e = rel_find_column_(sa, rel->exps, tname, cname)))
    1910             :                 return e;
    1911         288 :         if ((is_simple_project(rel->op) || is_groupby(rel->op)) && rel->l) {
    1912           1 :                 if (!is_processed(rel))
    1913             :                         return rel_find_column(sa, rel->l, tname, cname);
    1914         287 :         } 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(sa, 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(sa, 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_(sa, 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         287 :                 if (rel->l)
    1937             :                         return rel_find_column(sa, 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           6 : rel_parent(sql_rel *rel)
    1958             : {
    1959           6 :         if (rel->l && (is_project(rel->op) || is_topn(rel->op) || is_sample(rel->op))) {
    1960           6 :                 sql_rel *l = rel->l;
    1961           6 :                 if (is_project(l->op))
    1962           6 :                         return l;
    1963             :         }
    1964             :         return rel;
    1965             : }
    1966             : 
    1967             : sql_exp *
    1968       26632 : lastexp(sql_rel *rel)
    1969             : {
    1970       26632 :         if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
    1971           6 :                 rel = rel_parent(rel);
    1972       26632 :         assert(list_length(rel->exps));
    1973       26632 :         assert(is_project(rel->op) || rel->op == op_table);
    1974       26632 :         return rel->exps->t->data;
    1975             : }
    1976             : 
    1977             : sql_rel *
    1978        5676 : rel_return_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
    1979             : {
    1980        5676 :         if (ek.card < card_set && rel->card > CARD_ATOM) {
    1981        4333 :                 list *exps = rel->exps;
    1982             : 
    1983        4333 :                 assert (is_simple_project(rel->op) || is_mset(rel->op));
    1984        4333 :                 rel = rel_groupby(sql, rel, NULL);
    1985        8676 :                 for(node *n = exps->h; n; n=n->next) {
    1986        4343 :                         sql_exp *e = n->data;
    1987        4343 :                         if (!has_label(e))
    1988          49 :                                 exp_label(sql->sa, e, ++sql->label);
    1989        4343 :                         sql_subtype *t = exp_subtype(e); /* parameters don't have a type defined, for those use 'void' one */
    1990        4343 :                         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        4343 :                         e = exp_ref(sql, e);
    1993        4343 :                         e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
    1994        4343 :                         (void)rel_groupby_add_aggr(sql, rel, e);
    1995             :                 }
    1996        4333 :                 set_processed(rel);
    1997             :         }
    1998        5676 :         return rel;
    1999             : }
    2000             : 
    2001             : sql_rel *
    2002       35870 : rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
    2003             : {
    2004       35870 :         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       35870 :         if (ek.card < card_set && rel->card > CARD_ATOM) {
    2007        9433 :                 assert (is_simple_project(rel->op) || is_mset(rel->op));
    2008             : 
    2009        9433 :                 list *exps = rel->exps;
    2010       18887 :                 for(node *n = exps->h; n; n=n->next) {
    2011        9454 :                         sql_exp *e = n->data;
    2012        9454 :                         if (!has_label(e))
    2013        9417 :                                 exp_label(sql->sa, e, ++sql->label);
    2014             :                 }
    2015        9433 :                 set_single(rel);
    2016             :         } else {
    2017       26437 :                 sql_exp *e = lastexp(rel);
    2018       26437 :                 if (!has_label(e))
    2019       12135 :                         exp_label(sql->sa, e, ++sql->label);
    2020             :         }
    2021       35870 :         return rel;
    2022             : }
    2023             : 
    2024             : static sql_rel *
    2025        6528 : refs_find_rel(list *refs, sql_rel *rel)
    2026             : {
    2027        6528 :         node *n;
    2028             : 
    2029       16952 :         for(n=refs->h; n; n = n->next->next) {
    2030       13796 :                 sql_rel *ref = n->data;
    2031       13796 :                 sql_rel *s = n->next->data;
    2032             : 
    2033       13796 :                 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      667045 : exps_deps(mvc *sql, list *exps, list *refs, list *l)
    2043             : {
    2044             : 
    2045     2757069 :         for(node *n = exps->h; n; n = n->next)
    2046     2090024 :                 if (exp_deps(sql, n->data, refs, l) != 0)
    2047             :                         return -1;
    2048             :         return 0;
    2049             : }
    2050             : 
    2051             : static int
    2052     6863266 : id_cmp(sql_base *id1, sql_base *id2)
    2053             : {
    2054     6863266 :         if (id1->id == id2->id)
    2055       87374 :                 return 0;
    2056             :         return -1;
    2057             : }
    2058             : 
    2059             : static list *
    2060      718086 : cond_append(list *l, sql_base *b)
    2061             : {
    2062      718086 :         if (b->id >= FUNC_OIDS && !list_find(l, b, (fcmp) &id_cmp))
    2063      352794 :                 list_append(l, b);
    2064      718086 :         return l;
    2065             : }
    2066             : 
    2067             : static int rel_deps(mvc *sql, sql_rel *r, list *refs, list *l);
    2068             : 
    2069             : static int
    2070     2271169 : exp_deps(mvc *sql, sql_exp *e, list *refs, list *l)
    2071             : {
    2072     2367707 :         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     2367707 :         switch(e->type) {
    2078       43702 :         case e_psm:
    2079       43702 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2080       18706 :                         return exp_deps(sql, e->l, refs, l);
    2081       24996 :                 } else if (e->flag & PSM_VAR) {
    2082             :                         return 0;
    2083       20388 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2084        6113 :                         if (exp_deps(sql, e->l, refs, l) != 0 || exps_deps(sql, e->r, refs, l) != 0)
    2085           0 :                                 return -1;
    2086        6113 :                         if (e->flag & PSM_IF && e->f)
    2087         732 :                                 return exps_deps(sql, e->f, refs, l);
    2088       14275 :                 } else if (e->flag & PSM_REL) {
    2089       14275 :                         sql_rel *rel = e->l;
    2090       14275 :                         return rel_deps(sql, rel, refs, l);
    2091             :                 }
    2092             :                 break;
    2093      832958 :         case e_atom:
    2094      832958 :                 if (e->f && exps_deps(sql, e->f, refs, l) != 0)
    2095             :                         return -1;
    2096             :                 break;
    2097             :         case e_column:
    2098             :                 break;
    2099       77808 :         case e_convert:
    2100       77808 :                 return exp_deps(sql, e->l, refs, l);
    2101      286195 :         case e_func: {
    2102      286195 :                 sql_subfunc *f = e->f;
    2103             : 
    2104      286195 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2105             :                         return -1;
    2106      286195 :                 cond_append(l, &f->func->base);
    2107      286195 :                 if (e->l && list_length(e->l) == 2 && strcmp(f->func->base.name, "next_value_for") == 0) {
    2108             :                         /* add dependency on seq nr */
    2109          81 :                         list *nl = e->l;
    2110          81 :                         sql_exp *schname = nl->h->data, *seqname = nl->t->data;
    2111          81 :                         char *sch_name = is_atom(schname->type) && schname->l ? ((atom*)schname->l)->data.val.sval : NULL;
    2112          81 :                         char *seq_name = is_atom(seqname->type) && seqname->l ? ((atom*)seqname->l)->data.val.sval : NULL;
    2113             : 
    2114          81 :                         if (sch_name && seq_name) {
    2115          81 :                                 sql_schema *sche = mvc_bind_schema(sql, sch_name);
    2116          81 :                                 if (sche) {
    2117          81 :                                         sql_sequence *seq = find_sql_sequence(sql->session->tr, sche, seq_name);
    2118          81 :                                         if (seq)
    2119          81 :                                                 cond_append(l, &seq->base);
    2120             :                                 }
    2121             :                         }
    2122             :                 }
    2123             :         } break;
    2124       19690 :         case e_aggr: {
    2125       19690 :                 sql_subfunc *a = e->f;
    2126             : 
    2127       19690 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2128             :                         return -1;
    2129       19690 :                 cond_append(l, &a->func->base);
    2130       19690 :         } break;
    2131       90468 :         case e_cmp: {
    2132       90468 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2133         718 :                         if (e->flag == cmp_filter) {
    2134         488 :                                 sql_subfunc *f = e->f;
    2135         488 :                                 cond_append(l, &f->func->base);
    2136             :                         }
    2137        1436 :                         if (exps_deps(sql, e->l, refs, l) != 0 ||
    2138         718 :                                 exps_deps(sql, e->r, refs, l) != 0)
    2139           0 :                                 return -1;
    2140       89750 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2141        8936 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2142        4468 :                                 exps_deps(sql, e->r, refs, l) != 0)
    2143           0 :                                 return -1;
    2144             :                 } else {
    2145      170564 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2146       85282 :                                 exp_deps(sql, e->r, refs, l) != 0)
    2147           0 :                                 return -1;
    2148       85282 :                         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      464568 : rel_deps(mvc *sql, sql_rel *r, list *refs, list *l)
    2158             : {
    2159      464568 :         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      464568 :         if (!r)
    2165             :                 return 0;
    2166             : 
    2167      462375 :         if (rel_is_ref(r) && refs_find_rel(refs, r)) /* already handled */
    2168             :                 return 0;
    2169      452475 :         switch (r->op) {
    2170       98505 :         case op_basetable: {
    2171       98505 :                 sql_table *t = r->l;
    2172             : 
    2173       98505 :                 cond_append(l, &t->base);
    2174             :                 /* find all used columns */
    2175      440384 :                 for (node *en = r->exps->h; en; en = en->next) {
    2176      341879 :                         sql_exp *exp = en->data;
    2177      341879 :                         const char *oname = exp->r;
    2178             : 
    2179      341879 :                         assert(!is_func(exp->type));
    2180      341879 :                         if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    2181       32783 :                                 continue;
    2182      309096 :                         } else if (oname[0] == '%') {
    2183         216 :                                 sql_idx *i = find_sql_idx(t, oname+1);
    2184         216 :                                 if (i) {
    2185         215 :                                         cond_append(l, &i->base);
    2186         215 :                                         continue;
    2187             :                                 }
    2188             :                         }
    2189      308881 :                         sql_column *c = find_sql_column(t, oname);
    2190      308881 :                         if (!c)
    2191             :                                 return -1;
    2192      308881 :                         cond_append(l, &c->base);
    2193             :                 }
    2194             :         } break;
    2195        4031 :         case op_table: {
    2196        4031 :                 if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */
    2197        4031 :                         sql_exp *op = r->r;
    2198        4031 :                         sql_subfunc *f = op->f;
    2199        4031 :                         cond_append(l, &f->func->base);
    2200             :                 }
    2201             :         } break;
    2202       68170 :         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      136340 :                 if (rel_deps(sql, r->l, refs, l) != 0 ||
    2217       68170 :                         rel_deps(sql, r->r, refs, l) != 0)
    2218           0 :                         return -1;
    2219             :                 break;
    2220        8468 :         case op_munion:
    2221       25404 :                 for (node *n = ((list*)r->l)->h; n; n = n->next) {
    2222       16936 :                         if (rel_deps(sql, n->data, refs, l) != 0)
    2223             :                                 return -1;
    2224             :                 }
    2225             :                 break;
    2226      155624 :         case op_project:
    2227             :         case op_select:
    2228             :         case op_groupby:
    2229             :         case op_topn:
    2230             :         case op_sample:
    2231             :         case op_truncate:
    2232      155624 :                 if (rel_deps(sql, r->l, refs, l) != 0)
    2233             :                         return -1;
    2234             :                 break;
    2235      117677 :         case op_ddl:
    2236      117677 :                 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      452475 :         if (!is_base(r->op) && r->exps) {
    2247      337571 :                 if (exps_deps(sql, r->exps, refs, l) != 0)
    2248             :                         return -1;
    2249             :         }
    2250      452475 :         if ((is_simple_project(r->op) || is_groupby(r->op)) && r->r) {
    2251       18170 :                 if (exps_deps(sql, r->r, refs, l) != 0)
    2252             :                         return -1;
    2253             :         }
    2254      452475 :         if (rel_is_ref(r)) {
    2255        3156 :                 list_append(refs, r);
    2256        3156 :                 list_append(refs, l);
    2257             :         }
    2258             :         return 0;
    2259             : }
    2260             : 
    2261             : list *
    2262      141372 : rel_dependencies(mvc *sql, sql_rel *r)
    2263             : {
    2264      141372 :         list *refs = sa_list(sql->sa);
    2265      141372 :         list *l = sa_list(sql->sa);
    2266             : 
    2267      141372 :         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);
    2273             : 
    2274             : static inline list *
    2275       41273 : exps_exps_exp_visitor(visitor *v, sql_rel *rel, list *lists, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
    2276             : {
    2277       41273 :         node *n;
    2278             : 
    2279       41273 :         if (list_empty(lists))
    2280             :                 return lists;
    2281       90559 :         for (n = lists->h; n; n = n->next) {
    2282       49286 :                 if (n->data && (n->data = exps_exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown)) == 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             : static sql_exp *
    2291    78983111 : exp_visitor(visitor *v, sql_rel *rel, sql_exp *e, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown, bool *changed)
    2292             : {
    2293    78983111 :         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    79043411 :         assert(e);
    2297    79043411 :         if (topdown) {
    2298     6395729 :                 int changes = v->changes;
    2299     6395729 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2300             :                         return NULL;
    2301     6397133 :                 *changed |= v->changes > changes;
    2302             :         }
    2303             : 
    2304    79044815 :         switch(e->type) {
    2305             :         case e_column:
    2306             :                 break;
    2307     1062790 :         case e_convert:
    2308     1062790 :                 if  ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2309             :                         return NULL;
    2310             :                 break;
    2311     3982277 :         case e_aggr:
    2312             :         case e_func:
    2313     3982277 :                 if (e->r) /* rewrite rank -r is list of lists */
    2314       41273 :                         if ((e->r = exps_exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2315             :                                 return NULL;
    2316     3982277 :                 if (e->l)
    2317     3813872 :                         if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2318             :                                 return NULL;
    2319             :                 break;
    2320     3338071 :         case e_cmp:
    2321     3338071 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2322      191261 :                         if ((e->l = exps_exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2323             :                                 return NULL;
    2324      191261 :                         if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2325             :                                 return NULL;
    2326     3146810 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2327      209437 :                         if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2328             :                                 return NULL;
    2329      209437 :                         if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2330             :                                 return NULL;
    2331             :                 } else {
    2332     2937373 :                         if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2333             :                                 return NULL;
    2334     2937373 :                         if ((e->r = exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2335             :                                 return NULL;
    2336     2937373 :                         if (e->f && (e->f = exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2337             :                                 return NULL;
    2338             :                 }
    2339             :                 break;
    2340      371877 :         case e_psm:
    2341      371877 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2342      114194 :                         if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2343             :                                 return NULL;
    2344      257683 :                 } else if (e->flag & PSM_VAR) {
    2345             :                         return e;
    2346      227885 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2347       35117 :                         if ((e->l = exp_visitor(v, rel, e->l, depth+1, exp_rewriter, topdown, relations_topdown, changed)) == NULL)
    2348             :                                 return NULL;
    2349       35117 :                         if ((e->r = exps_exp_visitor(v, rel, e->r, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2350             :                                 return NULL;
    2351       35117 :                         if (e->flag == PSM_IF && e->f && (e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2352             :                                 return NULL;
    2353      192768 :                 } else if (e->flag & PSM_REL) {
    2354      192768 :                         if ((e->l = rel_exp_visitor(v, e->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2355             :                                 return NULL;
    2356             :                 }
    2357             :                 break;
    2358    25627920 :         case e_atom:
    2359    25627920 :                 if (e->f)
    2360      902212 :                         if ((e->f = exps_exp_visitor(v, rel, e->f, depth+1, exp_rewriter, topdown, relations_topdown)) == NULL)
    2361             :                                 return NULL;
    2362             :                 break;
    2363             :         }
    2364    79015991 :         if (!topdown) {
    2365    72595308 :                 int changes = v->changes;
    2366    72595308 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2367             :                         return NULL;
    2368    72601325 :                 *changed |= v->changes > changes;
    2369             :         }
    2370             :         return e;
    2371             : }
    2372             : 
    2373             : static list *
    2374    20736235 : exps_exp_visitor(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
    2375             : {
    2376    20736235 :         bool changed = false;
    2377    20736235 :         if (list_empty(exps))
    2378             :                 return exps;
    2379    92233697 :         for (node *n = exps->h; n; n = n->next)
    2380    71525679 :                 if (n->data && (n->data = exp_visitor(v, rel, n->data, depth, exp_rewriter, topdown, relations_topdown, &changed)) == NULL)
    2381             :                         return NULL;
    2382    20708018 :         if (changed && depth == 0) /* only level 0 exps use hash, so remove only on those */
    2383       19161 :                 list_hash_clear(exps);
    2384             :         return exps;
    2385             : }
    2386             : 
    2387             : static inline sql_rel *
    2388    15930542 : rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
    2389             : {
    2390    15930542 :         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    15934623 :         if (!rel)
    2394             :                 return rel;
    2395             : 
    2396    15934602 :         if (relations_topdown) {
    2397     5795562 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
    2398             :                         return NULL;
    2399     5795983 :                 if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
    2400             :                         return NULL;
    2401             :         }
    2402             : 
    2403    15935023 :         switch(rel->op){
    2404             :         case op_basetable:
    2405             :                 break;
    2406       44128 :         case op_table:
    2407       44128 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2408       44067 :                         bool changed = false;
    2409       44067 :                         if (rel->l)
    2410         921 :                                 if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2411           0 :                                         return NULL;
    2412       44067 :                         if (rel->r)
    2413       43772 :                                 if ((rel->r = exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown, &changed)) == NULL)
    2414             :                                         return NULL;
    2415             :                 }
    2416             :                 break;
    2417     2357859 :         case op_ddl:
    2418     2357859 :                 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      220253 :                         if (rel->l)
    2420      218120 :                                 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        2589 :                         if (rel->l)
    2424        2275 :                                 if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2425             :                                         return NULL;
    2426        2589 :                         if (rel->r)
    2427        2345 :                                 if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2428             :                                         return NULL;
    2429             :                 }
    2430             :                 break;
    2431     2184906 :         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     2184906 :                 if (rel->l)
    2447     2184867 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2448             :                                 return NULL;
    2449     2185518 :                 if (rel->r)
    2450     2183221 :                         if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2451             :                                 return NULL;
    2452             :                 break;
    2453      490751 :         case op_munion:
    2454     1472253 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2455      981502 :                         if ((n->data = rel_exp_visitor(v, n->data, exp_rewriter, topdown, relations_topdown)) == NULL)
    2456             :                                 return NULL;
    2457             :                 }
    2458             :                 break;
    2459     7066354 :         case op_select:
    2460             :         case op_topn:
    2461             :         case op_sample:
    2462             :         case op_project:
    2463             :         case op_groupby:
    2464             :         case op_truncate:
    2465     7066354 :                 if (rel->l)
    2466     5964304 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2467             :                                 return NULL;
    2468             :                 break;
    2469             :         }
    2470             : 
    2471    15935947 :         if (!relations_topdown) {
    2472    10139731 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
    2473             :                         return NULL;
    2474    10140472 :                 if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r && (rel->r = exps_exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, relations_topdown)) == NULL)
    2475             :                         return NULL;
    2476             :         }
    2477             : 
    2478             :         return rel;
    2479             : }
    2480             : 
    2481             : sql_rel *
    2482      553618 : rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2483             : {
    2484      553618 :         return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
    2485             : }
    2486             : 
    2487             : sql_rel *
    2488     3650689 : rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2489             : {
    2490     3650689 :         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   325312808 : exp_rel_visitor(visitor *v, sql_exp *e, rel_rewrite_fptr rel_rewriter, bool topdown)
    2498             : {
    2499   325312808 :         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   325413968 :         assert(e);
    2503   325413968 :         switch(e->type) {
    2504             :         case e_column:
    2505             :                 break;
    2506     4884699 :         case e_convert:
    2507     4884699 :                 if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2508             :                         return NULL;
    2509             :                 break;
    2510    19635311 :         case e_aggr:
    2511             :         case e_func:
    2512    19635311 :                 if (e->r) /* rewrite rank */
    2513       65150 :                         if ((e->r = exps_exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2514             :                                 return NULL;
    2515    19635311 :                 if (e->l)
    2516    18823444 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2517             :                                 return NULL;
    2518             :                 break;
    2519    20173774 :         case e_cmp:
    2520    20173774 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2521      744448 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2522             :                                 return NULL;
    2523      744448 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2524             :                                 return NULL;
    2525    19429326 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2526     1380927 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2527             :                                 return NULL;
    2528     1380927 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2529             :                                 return NULL;
    2530             :                 } else {
    2531    18048399 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2532             :                                 return NULL;
    2533    18048399 :                         if ((e->r = exp_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2534             :                                 return NULL;
    2535    18048399 :                         if (e->f && (e->f = exp_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2536             :                                 return NULL;
    2537             :                 }
    2538             :                 break;
    2539     1885190 :         case e_psm:
    2540     1885190 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2541      619578 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2542             :                                 return NULL;
    2543     1265612 :                 } else if (e->flag & PSM_VAR) {
    2544             :                         return e;
    2545     1075812 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2546      168672 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2547             :                                 return NULL;
    2548      168672 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2549             :                                 return NULL;
    2550      168672 :                         if (e->flag == PSM_IF && e->f && (e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2551             :                                 return NULL;
    2552      907140 :                 } else if (e->flag & PSM_REL) {
    2553      907140 :                         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2554      907140 :                         if ((e->l = func(v, e->l, rel_rewriter)) == NULL)
    2555             :                                 return NULL;
    2556             :                 }
    2557             :                 break;
    2558    64427264 :         case e_atom:
    2559    64427264 :                 if (e->f)
    2560     1480294 :                         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    91963226 : exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown)
    2569             : {
    2570    91963226 :         if (list_empty(exps))
    2571             :                 return exps;
    2572   373762595 :         for (node *n = exps->h; n; n = n->next)
    2573   282132043 :                 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       65150 : exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown)
    2580             : {
    2581       65150 :         if (list_empty(lists))
    2582             :                 return lists;
    2583      130300 :         for (node *n = lists->h; n; n = n->next)
    2584       65150 :                 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    69376628 : do_rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2591             : {
    2592    69376628 :         if (rel->exps && (rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2593             :                 return NULL;
    2594    69379318 :         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    69379317 :         int changes = v->changes;
    2597    69379317 :         rel = rel_rewriter(v, rel);
    2598    69377249 :         if (rel && rel->exps && v->changes > changes) {
    2599      273253 :                 list_hash_clear(rel->exps);
    2600      273246 :                 if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r)
    2601       12326 :                         list_hash_clear(rel->r);
    2602             :         }
    2603             :         return rel;
    2604             : }
    2605             : 
    2606             : static inline sql_rel *
    2607    69373003 : rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2608             : {
    2609    69373003 :         sql_rel *parent = v->parent;
    2610             : 
    2611    69373003 :         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    69382784 :         if (!rel)
    2615             :                 return NULL;
    2616             : 
    2617    69382733 :         if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
    2618             :                 return NULL;
    2619             : 
    2620    69383441 :         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2621             : 
    2622    69383441 :         v->parent = rel;
    2623    69383441 :         switch(rel->op){
    2624             :         case op_basetable:
    2625             :                 break;
    2626      131565 :         case op_table:
    2627      131565 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2628      131289 :                         if (rel->l)
    2629        2891 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2630             :                                         return NULL;
    2631             :                 }
    2632             :                 break;
    2633     4005592 :         case op_ddl:
    2634     4005592 :                 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      407492 :                         if (rel->l)
    2636      403897 :                                 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       14206 :                         if (rel->l)
    2640       10339 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2641             :                                         return NULL;
    2642       14206 :                         if (rel->r)
    2643       13290 :                                 if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2644             :                                         return NULL;
    2645             :                 } else if (rel->flag == ddl_psm) {
    2646      272684 :                         if ((rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2647             :                                 return NULL;
    2648             :                 }
    2649             :                 break;
    2650    12696306 :         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    12696306 :                 if (rel->l)
    2666    12696306 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2667             :                                 return NULL;
    2668    12696665 :                 if (rel->r)
    2669    12682441 :                         if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2670             :                                 return NULL;
    2671             :                 break;
    2672     2262107 :         case op_munion:
    2673     6786321 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2674     4524214 :                         if ((n->data = func(v, n->data, rel_rewriter)) == NULL)
    2675             :                                 return NULL;
    2676             :                 }
    2677             :                 break;
    2678    32706104 :         case op_select:
    2679             :         case op_topn:
    2680             :         case op_sample:
    2681             :         case op_project:
    2682             :         case op_groupby:
    2683             :         case op_truncate:
    2684    32706104 :                 if (rel->l)
    2685    30330227 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2686             :                                 return NULL;
    2687             :                 break;
    2688             :         }
    2689    69385154 :         v->parent = parent;
    2690             : 
    2691    69385154 :         if (!topdown)
    2692    43576402 :                 rel = do_rel_visitor(v, rel, rel_rewriter, false);
    2693             :         return rel;
    2694             : }
    2695             : 
    2696             : sql_rel *
    2697    25802100 : rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2698             : {
    2699    25802100 :         v->depth++;
    2700    25802100 :         rel = rel_visitor(v, rel, rel_rewriter, true);
    2701    25803657 :         v->depth--;
    2702    25803657 :         return rel;
    2703             : }
    2704             : 
    2705             : sql_rel *
    2706    43576491 : rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2707             : {
    2708    43576491 :         v->depth++;
    2709    43576491 :         rel = rel_visitor(v, rel, rel_rewriter, false);
    2710    43579325 :         v->depth--;
    2711    43579325 :         return rel;
    2712             : }
    2713             : 
    2714             : list *
    2715         276 : exps_exp_visitor_topdown(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2716             : {
    2717         276 :         return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, true, relations_topdown);
    2718             : }
    2719             : 
    2720             : list *
    2721      531358 : exps_exp_visitor_bottomup(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2722             : {
    2723      531358 :         return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, false, relations_topdown);
    2724             : }
    2725             : 
    2726             : static bool
    2727       74128 : exps_rebind_exp(mvc *sql, sql_rel *rel, list *exps)
    2728             : {
    2729       74128 :         bool ok = true;
    2730             : 
    2731       74128 :         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       74128 :         if (list_empty(exps))
    2737             :                 return true;
    2738       84639 :         for (node *n = exps->h; n && ok; n = n->next)
    2739       52128 :                 ok &= rel_rebind_exp(sql, rel, n->data);
    2740             :         return ok;
    2741             : }
    2742             : 
    2743             : bool
    2744     2825077 : rel_rebind_exp(mvc *sql, sql_rel *rel, sql_exp *e)
    2745             : {
    2746     2848546 :         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     2848546 :         switch (e->type) {
    2752       23469 :         case e_convert:
    2753       23469 :                 return rel_rebind_exp(sql, rel, e->l);
    2754       13205 :         case e_aggr:
    2755             :         case e_func:
    2756       13205 :                 return exps_rebind_exp(sql, rel, e->l);
    2757     1147050 :         case e_cmp:
    2758     1147050 :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    2759        8261 :                         return rel_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2760     1140822 :                 if (e->flag == cmp_or || e->flag == cmp_filter)
    2761       19388 :                         return exps_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2762     2259586 :                 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     1623191 :         case e_column:
    2764     1623191 :                 if (e->freevar)
    2765             :                         return true;
    2766     1623177 :                 return rel_find_exp(rel, e) != NULL;
    2767       41626 :         case e_atom:
    2768       41626 :                 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         409 : _exp_freevar_offset(visitor *v, sql_rel *rel, sql_exp *e, int depth)
    2777             : {
    2778         409 :         (void)rel; (void)depth;
    2779             :         /* visitor will handle recursion, ie only need to check columns here */
    2780         409 :         int vf = is_freevar(e);
    2781         409 :         if (v->changes < vf)
    2782         316 :                 v->changes=vf;
    2783         409 :         return e;
    2784             : }
    2785             : 
    2786             : int
    2787         306 : exp_freevar_offset(mvc *sql, sql_exp *e)
    2788             : {
    2789         306 :         bool changed = false;
    2790         306 :         visitor v = { .sql = sql };
    2791             : 
    2792         306 :         (void) changed;
    2793         306 :         exp_visitor(&v, NULL, e, 0, &_exp_freevar_offset, true, true, &changed);
    2794             :         /* freevar offset is passed via changes */
    2795         306 :         return (v.changes);
    2796             : }
    2797             : 
    2798             : static sql_exp *
    2799      296161 : _exp_has_selfref(visitor *v, sql_rel *rel, sql_exp *e, int depth)
    2800             : {
    2801      296161 :         (void)rel; (void)depth;
    2802      296161 :         int vf = is_selfref(e);
    2803      296161 :         if (v->changes < vf)
    2804         871 :                 v->changes=vf;
    2805      296161 :         return e;
    2806             : }
    2807             : 
    2808             : int
    2809      184614 : exp_has_selfref(mvc *sql, sql_exp *e)
    2810             : {
    2811      184614 :         bool changed = false;
    2812      184614 :         visitor v = { .sql = sql };
    2813             : 
    2814      184614 :         (void) changed;
    2815      184614 :         exp_visitor(&v, NULL, e, 0, &_exp_has_selfref, true, true, &changed);
    2816             :         /* freevar offset is passed via changes */
    2817      184614 :         return (v.changes);
    2818             : }

Generated by: LCOV version 1.14