LCOV - code coverage report
Current view: top level - sql/server - rel_rel.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1298 1509 86.0 %
Date: 2024-12-20 21:24:02 Functions: 87 92 94.6 %

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

Generated by: LCOV version 1.14