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: 2025-03-26 20:06:40 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, 2025 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     1334136 : project_unsafe(sql_rel *rel, bool allow_identity)
      34             : {
      35     1334136 :         sql_rel *sub = rel->l;
      36             : 
      37     1334136 :         if (need_distinct(rel) || rel->r /* order by */)
      38             :                 return 1;
      39     1266166 :         if (list_empty(rel->exps))
      40             :                 return 0;
      41             :         /* projects without sub and projects around ddl's cannot be changed */
      42     1266155 :         if (!sub || sub->op == op_ddl)
      43             :                 return 1;
      44    10212376 :         for(node *n = rel->exps->h; n; n = n->next) {
      45     9194876 :                 sql_exp *e = n->data, *ne;
      46             : 
      47             :                 /* aggr func in project ! */
      48     9194876 :                 if (exp_unsafe(e, allow_identity, false))
      49             :                         return 1;
      50     9152404 :                 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      254877 : rel_name( sql_rel *r )
      63             : {
      64      259541 :         if (is_basetable(r->op))
      65      213900 :                 return rel_base_name(r);
      66       50305 :         if (!is_project(r->op) && !is_base(r->op) && r->l)
      67             :                 return rel_name(r->l);
      68       40977 :         if (r->exps && list_length(r->exps)) {
      69       40977 :                 sql_exp *e = r->exps->h->data;
      70       40977 :                 if (exp_relname(e))
      71       40977 :                         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       13912 : rel_distinct(sql_rel *l)
      82             : {
      83       13912 :         set_distinct(l);
      84       13912 :         return l;
      85             : }
      86             : 
      87             : sql_rel *
      88      783729 : rel_dup(sql_rel *r)
      89             : {
      90      783729 :         sql_ref_inc(&r->ref);
      91      783729 :         return r;
      92             : }
      93             : 
      94             : static void
      95      705227 : rel_destroy_(sql_rel *rel)
      96             : {
      97      705227 :         if (!rel)
      98             :                 return;
      99      705227 :         switch(rel->op){
     100             :         case op_basetable:
     101             :                 break;
     102        4946 :         case op_table:
     103        4946 :                 if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
     104          11 :                         rel_destroy(rel->l);
     105             :                 break;
     106      297909 :         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      297909 :                 if (rel->l)
     120       17868 :                         rel_destroy(rel->l);
     121      297909 :                 if (rel->r)
     122       17876 :                         rel_destroy(rel->r);
     123             :                 break;
     124       42927 :         case op_munion:
     125             :                 /* the rel->l might be in purpose NULL see rel_merge_table_rewrite_() */
     126       42927 :                 if (rel->l)
     127      128826 :                         for (node *n = ((list*)rel->l)->h; n; n = n->next)
     128       86049 :                                 rel_destroy(n->data);
     129             :                 break;
     130      347173 :         case op_project:
     131             :         case op_groupby:
     132             :         case op_select:
     133             :         case op_topn:
     134             :         case op_sample:
     135             :         case op_truncate:
     136      347173 :                 if (rel->l)
     137       87353 :                         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     1429192 : rel_destroy(sql_rel *rel)
     155             : {
     156     1429192 :         if (!rel)
     157             :                 return;
     158     1429188 :         if (sql_ref_dec(&rel->ref) > 0)
     159             :                 return;
     160      663077 :         rel_destroy_(rel);
     161             : }
     162             : 
     163             : sql_rel*
     164     3438377 : rel_create(allocator *sa)
     165             : {
     166     3438377 :         sql_rel *r = SA_NEW(sa, sql_rel);
     167     3438374 :         if(!r)
     168             :                 return NULL;
     169             : 
     170     3438374 :         *r = (sql_rel) {
     171             :                 .card = CARD_ATOM,
     172             :         };
     173     3438374 :         sql_ref_init(&r->ref);
     174     3438374 :         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        3976 : rel_select_copy(allocator *sa, sql_rel *l, list *exps)
     280             : {
     281        3976 :         sql_rel *rel = rel_create(sa);
     282        3976 :         if(!rel)
     283             :                 return NULL;
     284             : 
     285        3976 :         rel->l = l;
     286        3976 :         rel->r = NULL;
     287        3976 :         rel->op = op_select;
     288        3976 :         rel->exps = exps?list_dup(exps, (fdup)NULL):NULL;
     289        3976 :         rel->card = CARD_ATOM; /* no relation */
     290        3976 :         if (l) {
     291        3976 :                 rel->card = l->card;
     292        3976 :                 rel->nrcols = l->nrcols;
     293             :         }
     294             :         return rel;
     295             : }
     296             : 
     297             : sql_exp *
     298     8000502 : rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, int f, int no_tname)
     299             : {
     300     8000502 :         int ambiguous = 0, multi = 0;
     301             : 
     302     8000502 :         if (!rel)
     303             :                 return NULL;
     304     8000502 :         if (mvc_highwater(sql))
     305           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     306             : 
     307     8000502 :         if (is_insert(rel->op))
     308           0 :                 rel = rel->r;
     309     8000502 :         if ((is_project(rel->op) || is_base(rel->op))) {
     310     4259071 :                 sql_exp *e = NULL;
     311             : 
     312     4259071 :                 if (is_base(rel->op) && !rel->exps)
     313     4081142 :                         return rel_base_bind_column(sql, rel, cname, no_tname);
     314      177929 :                 if (!list_empty(rel->exps)) {
     315      177867 :                         e = exps_bind_column(rel->exps, cname, &ambiguous, &multi, no_tname);
     316      177867 :                         if (ambiguous || multi)
     317          10 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     318      177857 :                         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       19882 :                 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      157897 :                 if (e)
     341      157897 :                         return exp_ref(sql, e);
     342             :         }
     343     3761312 :         if (is_simple_project(rel->op) && rel->l) {
     344        7341 :                 if (!is_processed(rel))
     345           0 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     346     3753971 :         } else if (is_set(rel->op)) {
     347          19 :                 assert(is_processed(rel));
     348             :                 return NULL;
     349             :         } else if (is_join(rel->op)) {
     350     3241788 :                 sql_exp *e1 = rel_bind_column(sql, rel->l, cname, f, no_tname), *e2 = NULL, *res;
     351             : 
     352     3241788 :                 if (e1 && (is_right(rel->op) || is_full(rel->op)))
     353           8 :                         set_has_nil(e1);
     354     1619214 :                 if (!e1 || !is_freevar(e1)) {
     355     3241788 :                         e2 = rel_bind_column(sql, rel->r, cname, f, no_tname);
     356     3241788 :                         if (e2 && (is_left(rel->op) || is_full(rel->op)))
     357          57 :                                 set_has_nil(e2);
     358     3241788 :                         if (e1 && e2 && !is_dependent(rel))
     359          21 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", cname);
     360             :                 }
     361     3241767 :                 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     3241767 :                 res = e1 ? e1 : e2;
     367     1622574 :                 if (res)
     368     1708363 :                         set_not_unique(res);
     369     3241767 :                 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      499643 :                 if (rel->l)
     375      499643 :                         return rel_bind_column(sql, rel->l, cname, f, no_tname);
     376             :         }
     377             :         return NULL;
     378             : }
     379             : 
     380             : sql_exp *
     381     4659730 : rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f)
     382             : {
     383     4659730 :         int ambiguous = 0, multi = 0;
     384             : 
     385     4659730 :         if (!rel)
     386             :                 return NULL;
     387     4659730 :         if (mvc_highwater(sql))
     388           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
     389             : 
     390     4659730 :         if ((is_project(rel->op) || is_base(rel->op))) {
     391     2184739 :                 sql_exp *e = NULL;
     392             : 
     393     2184739 :                 if (is_basetable(rel->op) && !rel->exps)
     394     1402528 :                         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      782211 :                 if (!list_empty(rel->exps)) {
     397      782115 :                         e = exps_bind_column2(rel->exps, tname, cname, &multi);
     398      782113 :                         if (multi)
     399           1 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous",
     400             :                                                                  tname, cname);
     401      782112 :                         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      245146 :                 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      537058 :                 if (e)
     427      537058 :                         return exp_ref(sql, e);
     428             :         }
     429     2720127 :         if (is_simple_project(rel->op) && rel->l) {
     430      236281 :                 if (!is_processed(rel))
     431           9 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     432     2483846 :         } else if (is_set(rel->op)) {
     433           3 :                 assert(is_processed(rel));
     434             :                 return NULL;
     435             :         } else if (is_join(rel->op)) {
     436     1991157 :                 sql_exp *e = rel_bind_column2(sql, rel->l, tname, cname, f);
     437             : 
     438     1991157 :                 if (e && (is_right(rel->op) || is_full(rel->op)))
     439         195 :                         set_has_nil(e);
     440         195 :                 if (!e) {
     441      882226 :                         e = rel_bind_column2(sql, rel->r, tname, cname, f);
     442      882226 :                         if (e && (is_left(rel->op) || is_full(rel->op)))
     443       22525 :                                 set_has_nil(e);
     444             :                 }
     445      418220 :                 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      395695 :                 if (e)
     452     1595463 :                         set_not_unique(e);
     453     1991157 :                 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      483834 :                 if (rel->l)
     459      483834 :                         return rel_bind_column2(sql, rel->l, tname, cname, f);
     460             :         }
     461             :         return NULL;
     462             : }
     463             : 
     464             : sql_exp *
     465     1299196 : rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname, int f)
     466             : {
     467     1299196 :         if (!sname)
     468     1299195 :                 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       85510 : rel_inplace_reset_props(sql_rel *rel)
     520             : {
     521       85510 :         rel->flag = 0;
     522       85510 :         rel->attr = NULL;
     523       85510 :         reset_dependent(rel);
     524       85510 :         set_processed(rel);
     525             : }
     526             : 
     527             : sql_rel *
     528         112 : rel_inplace_basetable(sql_rel *rel, sql_rel *bt)
     529             : {
     530         112 :         assert(is_basetable(bt->op));
     531             : 
     532         112 :         rel_destroy_(rel);
     533         112 :         rel_inplace_reset_props(rel);
     534         112 :         rel->l = bt->l;
     535         112 :         rel->r = bt->r;
     536         112 :         rel->op = op_basetable;
     537         112 :         rel->exps = bt->exps;
     538         112 :         rel->card = CARD_MULTI;
     539         112 :         rel->nrcols = bt->nrcols;
     540         112 :         return rel;
     541             : }
     542             : 
     543             : sql_rel *
     544          20 : rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps)
     545             : {
     546          20 :         rel_destroy_(rel);
     547          20 :         rel_inplace_reset_props(rel);
     548          20 :         rel->l = l;
     549          20 :         rel->r = r;
     550          20 :         rel->op = setop;
     551          20 :         rel->card = CARD_MULTI;
     552          20 :         rel_setop_set_exps(sql, rel, exps, false);
     553          20 :         return rel;
     554             : }
     555             : 
     556             : sql_rel *
     557       40680 : 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       40680 :         assert(setop == op_munion);
     561       40680 :         rel_destroy_(rel);
     562       40680 :         rel_inplace_reset_props(rel);
     563             :         /* rl should be a list of relations */
     564       40680 :         rel->l = rl;
     565       40680 :         rel->r = NULL;
     566       40680 :         rel->op = setop;
     567       40680 :         rel->card = CARD_MULTI;
     568       40680 :         rel_setop_n_ary_set_exps(sql, rel, exps, false);
     569       40680 :         return rel;
     570             : }
     571             : 
     572             : sql_rel *
     573       43413 : rel_inplace_project(allocator *sa, sql_rel *rel, sql_rel *l, list *e)
     574             : {
     575       43413 :         if (!l) {
     576       43360 :                 l = rel_create(sa);
     577       43360 :                 if(!l)
     578             :                         return NULL;
     579             : 
     580       43360 :                 *l = *rel;
     581       43360 :                 l->ref.refcnt = 1;
     582             :         } else {
     583          53 :                 rel_destroy_(rel);
     584             :         }
     585       43413 :         rel_inplace_reset_props(rel);
     586       43413 :         rel->l = l;
     587       43413 :         rel->r = NULL;
     588       43413 :         rel->op = op_project;
     589       43413 :         rel->exps = e;
     590       43413 :         rel->card = CARD_MULTI;
     591       43413 :         if (l) {
     592       43413 :                 rel->nrcols = l->nrcols;
     593       43413 :                 assert (exps_card(rel->exps) <= rel->card);
     594             :         }
     595             :         return rel;
     596             : }
     597             : 
     598             : sql_rel *
     599         758 : rel_inplace_select(sql_rel *rel, sql_rel *l, list *exps)
     600             : {
     601         758 :         rel_destroy_(rel);
     602         758 :         rel_inplace_reset_props(rel);
     603         758 :         rel->l = l;
     604         758 :         rel->r = NULL;
     605         758 :         rel->op = op_select;
     606         758 :         rel->exps = exps;
     607         758 :         rel->card = CARD_ATOM; /* no relation */
     608         758 :         if (l) {
     609         758 :                 rel->card = l->card;
     610         758 :                 rel->nrcols = l->nrcols;
     611         758 :                 if (is_single(l))
     612           0 :                         set_single(rel);
     613             :         }
     614         758 :         return rel;
     615             : }
     616             : 
     617             : sql_rel *
     618         527 : rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps )
     619             : {
     620         527 :         rel_destroy_(rel);
     621         527 :         rel_inplace_reset_props(rel);
     622         527 :         rel->card = CARD_ATOM;
     623         527 :         if (groupbyexps)
     624         422 :                 rel->card = CARD_AGGR;
     625         527 :         rel->l = l;
     626         527 :         rel->r = groupbyexps;
     627         527 :         rel->exps = exps;
     628         527 :         rel->nrcols = l->nrcols;
     629         527 :         rel->op = op_groupby;
     630         527 :         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         719 : rel_dup_copy(allocator *sa, sql_rel *rel)
     659             : {
     660         719 :         sql_rel *nrel = rel_create(sa);
     661             : 
     662         719 :         if (!nrel)
     663             :                 return NULL;
     664         719 :         *nrel = *rel;
     665         719 :         nrel->ref.refcnt = 1;
     666         719 :         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         709 :         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         709 :                 if (nrel->l)
     688         709 :                         rel_dup(nrel->l);
     689         709 :                 if (nrel->r)
     690         709 :                         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        2882 : rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     758             : {
     759        2882 :         sql_rel *l = rel->l, *r = rel->r;
     760        2882 :         list *lexps = l->exps, *rexps = r->exps;
     761             : 
     762        2882 :         if (!is_project(l->op))
     763          23 :                 lexps = rel_projections(sql, l, NULL, 0, 1);
     764        2882 :         if (!is_project(r->op))
     765          24 :                 rexps = rel_projections(sql, r, NULL, 0, 1);
     766             : 
     767        2882 :         assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && list_length(exps) == list_length(lexps)*/);
     768             : 
     769       11870 :         for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n = n->next, m = m->next,o = o->next) {
     770        8988 :                 sql_exp *e = n->data, *f = m->data, *g = o->data;
     771             : 
     772        8988 :                 assert(e->alias.label);
     773        8988 :                 e->nid = 0; /* setops are positional */
     774        8988 :                 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        8988 :                 e->card = CARD_MULTI; /* multi cardinality */
     785             :         }
     786        2882 :         rel->nrcols = l->nrcols;
     787        2882 :         rel->exps = exps;
     788        2882 : }
     789             : 
     790             : sql_rel *
     791       66513 : rel_setop_n_ary(allocator *sa, list *rels, operator_type setop)
     792             : {
     793             :         // TODO: for now we support only n-ary union
     794       66513 :         assert(setop == op_munion);
     795             : 
     796       66513 :         if (!rels)
     797             :                 return NULL;
     798             : 
     799       66513 :         assert(list_length(rels) >= 2);
     800       66513 :         sql_rel *rel = rel_create(sa);
     801       66513 :         if(!rel)
     802             :                 return NULL;
     803             : 
     804       66513 :         rel->l = rels;
     805       66513 :         rel->r = NULL;
     806       66513 :         rel->op = setop;
     807       66513 :         rel->exps = NULL;
     808       66513 :         rel->card = CARD_MULTI;
     809             :         // TODO: properly introduce the assertion over rels elements
     810             :         /*assert(l->nrcols == r->nrcols);*/
     811       66513 :         rel->nrcols = ((sql_rel*)rels->h->data)->nrcols;
     812       66513 :         return rel;
     813             : }
     814             : 
     815             : sql_rel *
     816       62570 : 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       62570 :         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       62570 :         list *nls = new_exp_list(sql->sa);
     829       62570 :         list *nrs = new_exp_list(sql->sa);
     830       62570 :         node *n, *m;
     831       62570 :         list* rels;
     832             : 
     833       62570 :         if(!nls || !nrs)
     834             :                 return NULL;
     835             : 
     836      484924 :         for (n = ls->h, m = rs->h; n && m; n = n->next, m = m->next) {
     837      422358 :                 sql_exp *le = n->data;
     838      422358 :                 sql_exp *re = m->data;
     839             : 
     840      422358 :                 if (rel_convert_types(sql, l, r, &le, &re, 1, type_set) < 0)
     841           4 :                         return NULL;
     842      422354 :                 append(nls, le);
     843      422354 :                 append(nrs, re);
     844             :         }
     845       62566 :         l = rel_project(sql->sa, l, nls);
     846       62566 :         r = rel_project(sql->sa, r, nrs);
     847       62566 :         set_processed(l);
     848       62566 :         set_processed(r);
     849             : 
     850             :         /* create a list with only 2 sql_rel entries for the n-ary set op */
     851       62566 :         rels = sa_list(sql->sa);
     852       62566 :         append(rels, l);
     853       62566 :         append(rels, r);
     854             : 
     855       62566 :         return rel_setop_n_ary(sql->sa, rels, op);
     856             : }
     857             : 
     858             : void
     859      105619 : rel_setop_n_ary_set_exps(mvc *sql, sql_rel *rel, list *exps, bool keep_props)
     860             : {
     861      105619 :         list *rexps;
     862      105619 :         sql_rel *r;
     863             : 
     864             :         /* set the exps properties first */
     865      824727 :         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      719108 :                 sql_exp *e = (sql_exp*)m->data;
     870      719108 :                 set_has_no_nil(e);
     871             :                 /* remove all the properties on unions on the general case */
     872      719108 :                 if (!keep_props) {
     873      718815 :                         e->p = NULL;
     874      718815 :                         set_not_unique(e);
     875             :                 }
     876             :         }
     877             : 
     878             :         /* for every relation in the list of relations */
     879      317539 :         for (node *n = ((list*)rel->l)->h; n; n = n->next) {
     880      211920 :                 r = n->data;
     881      211920 :                 rexps = r->exps;
     882             : 
     883      211920 :                 if (!is_project(r->op))
     884       13600 :                         rexps = rel_projections(sql, r, NULL, 0, 1);
     885             : 
     886             :                 /* go through the relation's exps */
     887     1653197 :                 for (node *m = exps->h, *o = rexps->h; m && o; m = m->next, o = o->next) {
     888     1441277 :                         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     1441277 :                         if (is_munion(rel->op) && has_nil(f))
     891      513505 :                                 set_has_nil(e);
     892     1441277 :                         e->card = CARD_MULTI;
     893             :                 }
     894             :         }
     895             : 
     896      105619 :         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      105619 :         rel->nrcols = ((sql_rel*)((list*)rel->l)->h->data)->nrcols;
     900      105619 : }
     901             : 
     902             : sql_rel *
     903      537914 : rel_crossproduct(allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
     904             : {
     905      537914 :         sql_rel *rel = rel_create(sa);
     906      537914 :         if(!rel)
     907             :                 return NULL;
     908             : 
     909      537914 :         rel->l = l;
     910      537914 :         rel->r = r;
     911      537914 :         rel->op = join;
     912      537914 :         rel->exps = NULL;
     913      537914 :         rel->card = CARD_MULTI;
     914      537914 :         rel->nrcols = l->nrcols + r->nrcols;
     915      537914 :         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       17066 : rel_topn(allocator *sa, sql_rel *l, list *exps )
     937             : {
     938       17066 :         sql_rel *rel = rel_create(sa);
     939       17066 :         if(!rel)
     940             :                 return NULL;
     941             : 
     942       17066 :         rel->l = l;
     943       17066 :         rel->r = NULL;
     944       17066 :         rel->op = op_topn;
     945       17066 :         rel->exps = exps;
     946       17066 :         rel->card = l->card;
     947       17066 :         rel->nrcols = l->nrcols;
     948       17066 :         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       15332 : rel_label( mvc *sql, sql_rel *r, int all)
     969             : {
     970       15332 :         int nr = ++sql->label;
     971       15332 :         char tname[16], *tnme;
     972       15332 :         char cname[16], *cnme = NULL;
     973             : 
     974       15332 :         tnme = sa_strdup(sql->sa, number2name(tname, sizeof(tname), nr));
     975       15332 :         if (!is_simple_project(r->op))
     976         616 :                 r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 1));
     977       15332 :         if (!list_empty(r->exps)) {
     978       15332 :                 list_hash_clear(r->exps);
     979       60235 :                 for (node *ne = r->exps->h; ne; ne = ne->next) {
     980       44903 :                         sql_exp *e = ne->data;
     981             : 
     982       44903 :                         if (!is_freevar(e)) {
     983       44897 :                                 if (all) {
     984       44897 :                                         nr = ++sql->label;
     985       44897 :                                         cnme = sa_strdup(sql->sa, number2name(cname, sizeof(cname), nr));
     986             :                                 }
     987       44897 :                                 exp_setname(sql, e, tnme, cnme );
     988             :                         }
     989             :                 }
     990             :         }
     991             :         /* op_projects can have a order by list */
     992       15332 :         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       15332 :         return r;
    1002             : }
    1003             : 
    1004             : sql_exp *
    1005       30509 : rel_project_add_exp( mvc *sql, sql_rel *rel, sql_exp *e)
    1006             : {
    1007       30509 :         assert(is_project(rel->op));
    1008             : 
    1009       30509 :         if (!e->alias.label)
    1010         111 :                 exp_label(sql->sa, e, ++sql->label);
    1011       30509 :         if (is_simple_project(rel->op)) {
    1012       30505 :                 sql_rel *l = rel->l;
    1013       30505 :                 if (!rel->exps)
    1014          24 :                         rel->exps = new_exp_list(sql->sa);
    1015       30505 :                 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       30505 :                 if (e->card > rel->card)
    1018           0 :                         rel->card = e->card;
    1019       30505 :                 append(rel->exps, e);
    1020       30505 :                 rel->nrcols++;
    1021           4 :         } else if (is_groupby(rel->op)) {
    1022           4 :                 return rel_groupby_add_aggr(sql, rel, e);
    1023             :         }
    1024       30505 :         e = exp_ref(sql, e);
    1025       30505 :         return e;
    1026             : }
    1027             : 
    1028             : sql_rel *
    1029      288628 : rel_select_add_exp(allocator *sa, sql_rel *l, sql_exp *e)
    1030             : {
    1031      288628 :         if ((l->op != op_select && !is_outerjoin(l->op)) || rel_is_ref(l))
    1032        8299 :                 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      280329 :         if (!l->exps)
    1041        3840 :                 l->exps = new_exp_list(sa);
    1042      280329 :         append(l->exps, e);
    1043      280329 :         return l;
    1044             : }
    1045             : 
    1046             : void
    1047      498628 : rel_join_add_exp( allocator *sa, sql_rel *rel, sql_exp *e)
    1048             : {
    1049      498628 :         assert(is_join(rel->op) || is_semi(rel->op) || is_select(rel->op));
    1050             : 
    1051      498628 :         if (!rel->exps)
    1052      451708 :                 rel->exps = new_exp_list(sa);
    1053      498628 :         append(rel->exps, e);
    1054      498628 :         if (e->card > rel->card)
    1055           0 :                 rel->card = e->card;
    1056      498628 : }
    1057             : 
    1058             : sql_exp *
    1059       95682 : rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
    1060             : {
    1061       95682 :         sql_exp *m = NULL, *ne;
    1062             : 
    1063       95682 :         if (list_empty(rel->r))
    1064       27163 :                 rel->card = e->card = CARD_ATOM;
    1065             : 
    1066       95682 :         if ((m=exps_any_match(rel->exps, e)) == NULL) {
    1067       49546 :                 if (!exp_name(e))
    1068       49522 :                         exp_label(sql->sa, e, ++sql->label);
    1069       49546 :                 append(rel->exps, e);
    1070       49546 :                 rel->nrcols++;
    1071       49546 :                 m = e;
    1072             :         }
    1073       95682 :         ne = exp_ref(sql, m);
    1074       95682 :         return ne;
    1075             : }
    1076             : 
    1077             : sql_rel *
    1078      272926 : rel_select(allocator *sa, sql_rel *l, sql_exp *e)
    1079             : {
    1080      272926 :         sql_rel *rel;
    1081             : 
    1082      272926 :         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      272715 :         if (l && is_select(l->op) && !rel_is_ref(l)) { /* refine old select */
    1092       16931 :                 if (e)
    1093        8280 :                         rel_select_add_exp(sa, l, e);
    1094       16931 :                 return l;
    1095             :         }
    1096      255784 :         rel = rel_create(sa);
    1097      255784 :         if(!rel)
    1098             :                 return NULL;
    1099             : 
    1100      255784 :         rel->l = l;
    1101      255784 :         rel->r = NULL;
    1102      255784 :         rel->op = op_select;
    1103      255784 :         rel->exps = new_exp_list(sa);
    1104      255784 :         if (e)
    1105      187471 :                 rel_select_add_exp(sa, rel, e);
    1106      255784 :         rel->card = CARD_ATOM; /* no relation */
    1107      255784 :         if (l) {
    1108      255784 :                 rel->card = l->card;
    1109      255784 :                 rel->nrcols = l->nrcols;
    1110      255784 :                 if (is_single(l))
    1111        1550 :                         set_single(rel);
    1112             :         }
    1113             :         return rel;
    1114             : }
    1115             : 
    1116             : sql_rel *
    1117       41831 : rel_groupby(mvc *sql, sql_rel *l, list *groupbyexps )
    1118             : {
    1119       41831 :         sql_rel *rel = rel_create(sql->sa);
    1120       41831 :         list *aggrs = new_exp_list(sql->sa);
    1121       41831 :         node *en;
    1122       41831 :         if(!rel || !aggrs) {
    1123           0 :                 rel_destroy(rel);
    1124           0 :                 return NULL;
    1125             :         }
    1126             : 
    1127       41831 :         rel->card = CARD_ATOM;
    1128             :         /* reduce duplicates in groupbyexps */
    1129       41831 :         if (groupbyexps && list_length(groupbyexps) > 1) {
    1130        8235 :                 list *gexps = sa_list(sql->sa);
    1131             : 
    1132       40309 :                 for (en = groupbyexps->h; en; en = en->next) {
    1133       32074 :                         sql_exp *e = en->data, *ne = exps_find_exp(gexps, e);
    1134             : 
    1135       32074 :                         if (!ne) {
    1136       31971 :                                 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       14226 :         if (groupbyexps) {
    1148       14226 :                 rel->card = CARD_AGGR;
    1149       52053 :                 for (en = groupbyexps->h; en; en = en->next) {
    1150       37827 :                         sql_exp *e = en->data, *ne;
    1151             : 
    1152       37827 :                         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       37798 :                         e->card = MIN(e->card, rel->card); /* if the column is an atom, the cardinality should not change */
    1158       37798 :                         if (!e->alias.label)
    1159          86 :                                 exp_label(sql->sa, e, ++sql->label);
    1160       37798 :                         ne = exp_ref(sql, e);
    1161       37798 :                         ne = exp_propagate(sql->sa, ne, e);
    1162       37798 :                         append(aggrs, ne);
    1163             :                 }
    1164             :         }
    1165       41831 :         rel->l = l;
    1166       41831 :         rel->r = groupbyexps;
    1167       41831 :         rel->exps = aggrs;
    1168       41831 :         rel->nrcols = aggrs?list_length(aggrs):0;
    1169       41831 :         rel->op = op_groupby;
    1170       41831 :         rel->grouped = 1;
    1171       41831 :         return rel;
    1172             : }
    1173             : 
    1174             : sql_rel *
    1175     1022148 : rel_project(allocator *sa, sql_rel *l, list *e)
    1176             : {
    1177     1022148 :         sql_rel *rel = rel_create(sa);
    1178     1022148 :         if(!rel)
    1179             :                 return NULL;
    1180             : 
    1181     1022148 :         rel->l = l;
    1182     1022148 :         rel->r = NULL;
    1183     1022148 :         rel->op = op_project;
    1184     1022148 :         rel->exps = e;
    1185     1022148 :         rel->card = exps_card(e);
    1186     1022150 :         if (l) {
    1187      828422 :                 rel->card = l->card;
    1188      828422 :                 if (e)
    1189      768770 :                         rel->nrcols = list_length(e);
    1190             :                 else
    1191       59652 :                         rel->nrcols = l->nrcols;
    1192      828422 :                 rel->single = is_single(l);
    1193             :         }
    1194     1022150 :         if (e && !list_empty(e)) {
    1195      961871 :                 set_processed(rel);
    1196      961871 :                 rel->nrcols = list_length(e);
    1197             :         }
    1198             :         return rel;
    1199             : }
    1200             : 
    1201             : sql_rel *
    1202       72995 : rel_project_exp(mvc *sql, sql_exp *e)
    1203             : {
    1204       72995 :         if (!exp_name(e))
    1205       72995 :                 exp_label(sql->sa, e, ++sql->label);
    1206       72995 :         return rel_project(sql->sa, NULL, list_append(sa_list(sql->sa), e));
    1207             : }
    1208             : 
    1209             : sql_rel *
    1210      121029 : rel_list(allocator *sa, sql_rel *l, sql_rel *r)
    1211             : {
    1212      121029 :         sql_rel *rel = rel_create(sa);
    1213      121029 :         if (!rel)
    1214             :                 return NULL;
    1215      121029 :         if (!l)
    1216             :                 return r;
    1217         568 :         rel->l = l;
    1218         568 :         rel->r = r;
    1219         568 :         rel->op = op_ddl;
    1220         568 :         rel->flag = ddl_list;
    1221         568 :         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       17200 : rel_table_func(allocator *sa, sql_rel *l, sql_exp *f, list *exps, int kind)
    1257             : {
    1258       17200 :         sql_rel *rel = rel_create(sa);
    1259       17200 :         if(!rel)
    1260             :                 return NULL;
    1261             : 
    1262       17200 :         assert(kind > 0);
    1263       17200 :         rel->flag = kind;
    1264       17200 :         rel->l = l; /* relation before call */
    1265       17200 :         rel->r = f; /* expression (table func call) */
    1266       17200 :         rel->op = op_table;
    1267       17200 :         rel->exps = exps;
    1268       17200 :         rel->card = CARD_MULTI;
    1269       17200 :         rel->nrcols = list_length(exps);
    1270       17200 :         return rel;
    1271             : }
    1272             : 
    1273             : static void
    1274      318884 : exps_reset_props(list *exps, bool setnil)
    1275             : {
    1276      318884 :         if (!list_empty(exps)) {
    1277     3284831 :                 for (node *m = exps->h; m; m = m->next) {
    1278     2968857 :                         sql_exp *e = m->data;
    1279             : 
    1280     2968857 :                         if (setnil)
    1281      201997 :                                 set_has_nil(e);
    1282     2968857 :                         set_not_unique(e);
    1283             :                 }
    1284             :         }
    1285      318884 : }
    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     1092494 : _rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern, int basecol /* basecol only */ )
    1292             : {
    1293     1160864 :         list *lexps, *rexps = NULL, *exps = NULL, *rels;
    1294             : 
    1295     1160864 :         if (mvc_highwater(sql))
    1296           1 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1297             : 
    1298     1160863 :         if (!rel)
    1299           0 :                 return new_exp_list(sql->sa);
    1300             : 
    1301     1160863 :         if (!tname && is_basetable(rel->op) && !is_processed(rel))
    1302      266462 :                 rel_base_use_all( sql, rel);
    1303             : 
    1304     1160863 :         switch(rel->op) {
    1305      159442 :         case op_join:
    1306             :         case op_left:
    1307             :         case op_right:
    1308             :         case op_full:
    1309      159442 :                 lexps = _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1310      159442 :                 exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
    1311      159442 :                 if (!rel->attr)
    1312      156544 :                         rexps = _rel_projections(sql, rel->r, tname, settname, intern, basecol);
    1313      159442 :                 exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
    1314      159442 :                 if (rexps)
    1315      156544 :                         lexps = list_merge(lexps, rexps, (fdup)NULL);
    1316      159442 :                 if (rel->attr)
    1317        2898 :                         append(lexps, exp_ref(sql, rel->attr->h->data));
    1318             :                 return lexps;
    1319        7925 :         case op_groupby:
    1320        7925 :                 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      933051 :                 if (is_basetable(rel->op) && !rel->exps)
    1350      104942 :                         return rel_base_projection(sql, rel, intern);
    1351      828109 :                 if (rel->exps) {
    1352      762983 :                         exps = new_exp_list(sql->sa);
    1353     6103312 :                         for (node *en = rel->exps->h; en; en = en->next) {
    1354     5340330 :                                 sql_exp *e = en->data;
    1355             : 
    1356     5340330 :                                 if (basecol && !is_basecol(e))
    1357          52 :                                         continue;
    1358     5340278 :                                 if (intern || !is_intern(e)) {
    1359     5326607 :                                         if (!e->alias.label)
    1360       22296 :                                                 en->data = e = exp_label(sql->sa, e, ++sql->label);
    1361     5326607 :                                         sql_exp *ne = exp_ref(sql, e);
    1362     5326607 :                                         if (settname && tname)
    1363           0 :                                                 exp_setname(sql, ne, tname, exp_name(e));
    1364     5326607 :                                         assert(ne->alias.label);
    1365     5326607 :                                         e = ne;
    1366     5326607 :                                         append(exps, e);
    1367             :                                 }
    1368             :                         }
    1369             :                         return exps;
    1370             :                 }
    1371             :                 /* differentiate for the munion set op (for now) */
    1372       65126 :                 if (is_munion(rel->op)) {
    1373       62641 :                         sql_rel *r = NULL;
    1374       62641 :                         assert(rel->l);
    1375             :                         /* get the exps from the first relation */
    1376       62641 :                         rels = rel->l;
    1377       62641 :                         if (rels->h)
    1378       62641 :                                 r = rels->h->data;
    1379       62641 :                         if (r)
    1380       62641 :                                 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       62641 :                         if (exps) {
    1393      485094 :                                 for (node *en = exps->h; en; en = en->next) {
    1394      422453 :                                         sql_exp *e = en->data;
    1395             : 
    1396      422453 :                                         e->card = rel->card;
    1397      422453 :                                         if (!settname) /* noname use alias */
    1398      422453 :                                                 exp_setname(sql, e, exp_relname(e), exp_name(e));
    1399             :                                 }
    1400       62641 :                                 if (!settname)
    1401       62641 :                                         list_hash_clear(rel->l);
    1402             :                         }
    1403       62641 :                         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       68370 :         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       68370 :                 return _rel_projections(sql, rel->l, tname, settname, intern, basecol);
    1432             :         default:
    1433             :                 return NULL;
    1434             :         }
    1435             : }
    1436             : 
    1437             : list *
    1438      665953 : rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int intern)
    1439             : {
    1440      665953 :         assert(tname == NULL);
    1441      665953 :         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     4087923 : rel_bind_path_(mvc *sql, sql_rel *rel, sql_exp *e, list *path )
    1450             : {
    1451     4087923 :         int found = 0;
    1452             : 
    1453     4087923 :         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     4087923 :         switch (rel->op) {
    1459     1901972 :         case op_join:
    1460             :         case op_left:
    1461             :         case op_right:
    1462             :         case op_full:
    1463             :                 /* first right (possible subquery) */
    1464     1901972 :                 found = rel_bind_path_(sql, rel->r, e, path);
    1465     1901972 :                 if (!found)
    1466     1594073 :                         found = rel_bind_path_(sql, rel->l, e, path);
    1467     1594073 :                 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      111788 :         case op_semi:
    1474             :         case op_anti:
    1475             :         case op_select:
    1476             :         case op_topn:
    1477             :         case op_sample:
    1478      111788 :                 found = rel_bind_path_(sql, rel->l, e, path);
    1479      111788 :                 break;
    1480     2074163 :         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     2074163 :                 if (is_basetable(rel->op) && !rel->exps) {
    1489     1889258 :                         assert(e->nid);
    1490     1889258 :                         if (rel_base_has_nid(rel, e->nid))
    1491             :                                 found = 1;
    1492      184905 :                 } else if (rel->exps) {
    1493      184905 :                         assert(e->nid);
    1494      184905 :                         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      111792 :         if (found)
    1507     2448349 :                 list_prepend(path, rel);
    1508             :         return found;
    1509             : }
    1510             : 
    1511             : static list *
    1512      509116 : rel_bind_path(mvc *sql, sql_rel *rel, sql_exp *e, list *path)
    1513             : {
    1514      509116 :         if (!path)
    1515             :                 return NULL;
    1516             : 
    1517      509116 :         if (e->type == e_convert) {
    1518       23325 :                 if (!(path = rel_bind_path(sql, rel, e->l, path)))
    1519             :                         return NULL;
    1520      485791 :         } else if (e->type == e_column) {
    1521      480090 :                 if (rel) {
    1522      480090 :                         if (!rel_bind_path_(sql, rel, e, path)) {
    1523             :                                 /* something is wrong */
    1524             :                                 return NULL;
    1525             :                         }
    1526             :                 }
    1527      480090 :                 return path;
    1528             :         }
    1529             :         /* default the top relation */
    1530       29026 :         append(path, rel);
    1531       29026 :         return path;
    1532             : }
    1533             : 
    1534             : static sql_rel *
    1535       19288 : rel_select_push_exp_down(mvc *sql, sql_rel *rel, sql_exp *e)
    1536             : {
    1537       19288 :         sql_rel *r = rel->l, *jl = r->l, *jr = r->r;
    1538       19288 :         int left = r->op == op_join || r->op == op_left;
    1539       19288 :         int right = r->op == op_join || r->op == op_right;
    1540       19288 :         int done = 0;
    1541             : 
    1542       19288 :         assert(is_select(rel->op));
    1543       19288 :         if (!is_full(r->op) && !is_single(r)) {
    1544       19288 :                 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       19279 :                 } 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       19273 :                 rel_select_add_exp(sql->sa, rel, e);
    1554       19288 :         return rel;
    1555             : }
    1556             : 
    1557             : /* ls is the left expression of the select, e is the select expression.  */
    1558             : sql_rel *
    1559      104630 : rel_push_select(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *e, int f)
    1560             : {
    1561      104630 :         list *l = rel_bind_path(sql, rel, ls, sa_list(sql->sa));
    1562      104630 :         node *n;
    1563      104630 :         sql_rel *lrel = NULL, *p = NULL;
    1564             : 
    1565      104630 :         if (!l)
    1566             :                 return NULL;
    1567      104630 :         if (is_sql_or(f)) /* expression has no clear parent relation, so filter current with it */
    1568       15799 :                 return rel_select(sql->sa, rel, e);
    1569             : 
    1570      257142 :         for (n = l->h; n; n = n->next ) {
    1571      256402 :                 lrel = n->data;
    1572             : 
    1573      256402 :                 if (rel_is_ref(lrel))
    1574             :                         break;
    1575             : 
    1576             :                 /* push down as long as the operators allow this */
    1577      255720 :                 if (!is_select(lrel->op) &&
    1578      236782 :                     !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
    1579       87409 :                     lrel->op != op_join &&
    1580             :                     lrel->op != op_left)
    1581             :                         break;
    1582             :                 /* pushing through left head of a left join is allowed */
    1583      168315 :                 if (lrel->op == op_left && (!n->next || lrel->l != n->next->data))
    1584             :                         break;
    1585      168311 :                 p = lrel;
    1586             :         }
    1587       88831 :         if (!lrel)
    1588             :                 return NULL;
    1589       88831 :         if (p && is_select(p->op) && !rel_is_ref(p)) { /* refine old select */
    1590       16481 :                 p = rel_select_push_exp_down(sql, p, e);
    1591             :         } else {
    1592       72350 :                 sql_rel *n = rel_select(sql->sa, lrel, e);
    1593             : 
    1594       72350 :                 if (p && p != lrel) {
    1595       67581 :                         assert(p->op == op_join || p->op == op_left || is_semi(p->op));
    1596       67581 :                         if (p->l == lrel) {
    1597       24767 :                                 p->l = n;
    1598             :                         } else {
    1599       42814 :                                 p->r = n;
    1600             :                         }
    1601             :                 } else {
    1602        4769 :                         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      190318 : rel_push_join(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, sql_exp *e, int f)
    1615             : {
    1616      190318 :         list *l = NULL, *r = NULL, *r2 = NULL;
    1617      190318 :         node *ln, *rn;
    1618      190318 :         sql_rel *lrel = NULL, *rrel = NULL, *rrel2 = NULL, *p = NULL;
    1619             : 
    1620      190318 :         if (!(l = rel_bind_path(sql, rel, ls, sa_list(sql->sa))) ||
    1621      190318 :                 !(r = rel_bind_path(sql, rel, rs, sa_list(sql->sa))) ||
    1622         525 :                 (rs2 && !(r2 = rel_bind_path(sql, rel, rs2, sa_list(sql->sa)))))
    1623           0 :                 return NULL;
    1624             : 
    1625      190318 :         if (is_sql_or(f))
    1626        1591 :                 return rel_push_select(sql, rel, ls, e, f);
    1627             : 
    1628      188727 :         p = rel;
    1629      188727 :         if (r2) {
    1630         518 :                 node *rn2;
    1631             : 
    1632        1043 :                 for (ln = l->h, rn = r->h, rn2 = r2->h; ln && rn && rn2; ln = ln->next, rn = rn->next, rn2 = rn2->next ) {
    1633         549 :                         lrel = ln->data;
    1634         549 :                         rrel = rn->data;
    1635         549 :                         rrel2 = rn2->data;
    1636             : 
    1637         549 :                         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         543 :                         if (lrel != rrel || lrel != rrel2 ||
    1644         525 :                                 (!is_select(lrel->op) &&
    1645          71 :                                  !(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         525 :                         if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
    1651             :                                 break;
    1652         525 :                         p = lrel;
    1653             :                 }
    1654             :         } else {
    1655      823730 :                 for (ln = l->h, rn = r->h; ln && rn; ln = ln->next, rn = rn->next ) {
    1656      820880 :                         lrel = ln->data;
    1657      820880 :                         rrel = rn->data;
    1658             : 
    1659      820880 :                         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      780005 :                         if (lrel != rrel ||
    1666      637177 :                                 (!is_select(lrel->op) &&
    1667      633721 :                                  !(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      635521 :                         if (lrel->op == op_left && (!ln->next || lrel->l != ln->next->data))
    1673             :                                 break;
    1674      635521 :                         p = lrel;
    1675             :                 }
    1676             :         }
    1677      188727 :         if (!lrel || !rrel || (r2 && !rrel2))
    1678             :                 return NULL;
    1679             : 
    1680             :         /* filter on columns of this relation */
    1681      188727 :         if ((lrel == rrel && (!r2 || lrel == rrel2) && lrel->op != op_join) || rel_is_ref(p)) {
    1682        2821 :                 if (is_select(lrel->op) && !rel_is_ref(lrel)) {
    1683        1148 :                         lrel = rel_select_push_exp_down(sql, lrel, e);
    1684        1673 :                 } else if (p && is_select(p->op) && !rel_is_ref(p)) {
    1685        1659 :                         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        2821 :                 return rel;
    1699             :         }
    1700             : 
    1701      185906 :         rel_join_add_exp( sql->sa, p, e);
    1702      185906 :         return rel;
    1703             : }
    1704             : 
    1705             : sql_rel *
    1706       14555 : rel_or(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, list *oexps, list *lexps, list *rexps)
    1707             : {
    1708       14555 :         sql_rel *ll = l->l, *rl = r->l;
    1709       14555 :         list *ls, *rs;
    1710             : 
    1711       14555 :         assert(!lexps || l == r);
    1712       14555 :         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       14513 :         if (l->op == r->op && is_select(l->op) &&
    1726       14513 :             ll == rl && ll == rel && !rel_is_ref(l) && !rel_is_ref(r)) {
    1727       14513 :                 sql_exp *e = exp_or(sql->sa, l->exps, r->exps, 0);
    1728       14513 :                 list *nl = new_exp_list(sql->sa);
    1729             : 
    1730       14513 :                 rel_destroy(r);
    1731       14513 :                 append(nl, e);
    1732       14513 :                 l->exps = nl;
    1733             : 
    1734             :                 /* merge and expressions */
    1735       14513 :                 ll = l->l;
    1736       16296 :                 while (ll && is_select(ll->op) && !rel_is_ref(ll)) {
    1737        1783 :                         list_merge(l->exps, ll->exps, (fdup)NULL);
    1738        1783 :                         l->l = ll->l;
    1739        1783 :                         ll->l = NULL;
    1740        1783 :                         rel_destroy(ll);
    1741        1783 :                         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        4167 : rel_ddl_table_get(sql_rel *r)
    1775             : {
    1776        4167 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1777        4167 :                 sql_exp *e = r->exps->t->data;
    1778        4167 :                 atom *a = e->l;
    1779             : 
    1780        4167 :                 return a->data.val.pval;
    1781             :         }
    1782             :         return NULL;
    1783             : }
    1784             : 
    1785             : sql_rel *
    1786        3240 : rel_ddl_basetable_get(sql_rel *r)
    1787             : {
    1788        3240 :         if (r->flag == ddl_alter_table || r->flag == ddl_create_table || r->flag == ddl_create_view) {
    1789        3240 :                 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       29490 : lastexp(sql_rel *rel)
    1970             : {
    1971       29490 :         if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
    1972          14 :                 rel = rel_parent(rel);
    1973       29490 :         assert(list_length(rel->exps));
    1974       29490 :         assert(is_project(rel->op) || rel->op == op_table);
    1975       29490 :         return rel->exps->t->data;
    1976             : }
    1977             : 
    1978             : sql_rel *
    1979        5872 : rel_return_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
    1980             : {
    1981        5872 :         if (ek.card < card_set && rel->card > CARD_ATOM) {
    1982        4481 :                 list *exps = rel->exps;
    1983             : 
    1984        4481 :                 assert (is_simple_project(rel->op) || is_mset(rel->op));
    1985        4481 :                 rel = rel_groupby(sql, rel, NULL);
    1986        8972 :                 for(node *n = exps->h; n; n=n->next) {
    1987        4491 :                         sql_exp *e = n->data;
    1988        4491 :                         if (!has_label(e))
    1989          75 :                                 exp_label(sql->sa, e, ++sql->label);
    1990        4491 :                         sql_subtype *t = exp_subtype(e); /* parameters don't have a type defined, for those use 'void' one */
    1991        4491 :                         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        4491 :                         e = exp_ref(sql, e);
    1994        4491 :                         e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
    1995        4491 :                         (void)rel_groupby_add_aggr(sql, rel, e);
    1996             :                 }
    1997        4481 :                 set_processed(rel);
    1998             :         }
    1999        5872 :         return rel;
    2000             : }
    2001             : 
    2002             : sql_rel *
    2003       38832 : rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
    2004             : {
    2005       38832 :         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       38832 :         if (ek.card < card_set && rel->card > CARD_ATOM) {
    2008        9555 :                 assert (is_simple_project(rel->op) || is_mset(rel->op));
    2009             : 
    2010        9555 :                 list *exps = rel->exps;
    2011       19138 :                 for(node *n = exps->h; n; n=n->next) {
    2012        9583 :                         sql_exp *e = n->data;
    2013        9583 :                         if (e->alias.label == 0)
    2014          12 :                                 exp_label(sql->sa, e, ++sql->label);
    2015             :                 }
    2016        9555 :                 set_single(rel);
    2017             :         } else {
    2018       29277 :                 sql_exp *e = lastexp(rel);
    2019       29277 :                 if (!has_label(e))
    2020          26 :                         exp_label(sql->sa, e, ++sql->label);
    2021             :         }
    2022       38832 :         return rel;
    2023             : }
    2024             : 
    2025             : static sql_rel *
    2026       10588 : refs_find_rel(list *refs, sql_rel *rel)
    2027             : {
    2028       10588 :         node *n;
    2029             : 
    2030       22786 :         for(n=refs->h; n; n = n->next->next) {
    2031       17601 :                 sql_rel *ref = n->data;
    2032       17601 :                 sql_rel *s = n->next->data;
    2033             : 
    2034       17601 :                 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      685425 : exps_deps(mvc *sql, list *exps, list *refs, list *l)
    2044             : {
    2045             : 
    2046     2850016 :         for(node *n = exps->h; n; n = n->next)
    2047     2164591 :                 if (exp_deps(sql, n->data, refs, l) != 0)
    2048             :                         return -1;
    2049             :         return 0;
    2050             : }
    2051             : 
    2052             : static int
    2053     6822452 : id_cmp(sql_base *id1, sql_base *id2)
    2054             : {
    2055     6822452 :         if (id1->id == id2->id)
    2056       93738 :                 return 0;
    2057             :         return -1;
    2058             : }
    2059             : 
    2060             : static list *
    2061      728806 : cond_append(list *l, sql_base *b)
    2062             : {
    2063      728806 :         if (b->id >= FUNC_OIDS && !list_find(l, b, (fcmp) &id_cmp))
    2064      363445 :                 list_append(l, b);
    2065      728806 :         return l;
    2066             : }
    2067             : 
    2068             : static int rel_deps(mvc *sql, sql_rel *r, list *refs, list *l);
    2069             : 
    2070             : static int
    2071     2356484 : exp_deps(mvc *sql, sql_exp *e, list *refs, list *l)
    2072             : {
    2073     2466371 :         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     2466371 :         switch(e->type) {
    2079       45629 :         case e_psm:
    2080       45629 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2081       19797 :                         return exp_deps(sql, e->l, refs, l);
    2082       25832 :                 } else if (e->flag & PSM_VAR) {
    2083             :                         return 0;
    2084       21078 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2085        6324 :                         if (exp_deps(sql, e->l, refs, l) != 0 || exps_deps(sql, e->r, refs, l) != 0)
    2086           0 :                                 return -1;
    2087        6324 :                         if (e->flag & PSM_IF && e->f)
    2088         758 :                                 return exps_deps(sql, e->f, refs, l);
    2089       14754 :                 } else if (e->flag & PSM_REL) {
    2090       14754 :                         sql_rel *rel = e->l;
    2091       14754 :                         return rel_deps(sql, rel, refs, l);
    2092             :                 }
    2093             :                 break;
    2094      858029 :         case e_atom:
    2095      858029 :                 if (e->f && exps_deps(sql, e->f, refs, l) != 0)
    2096             :                         return -1;
    2097             :                 break;
    2098             :         case e_column:
    2099             :                 break;
    2100       90059 :         case e_convert:
    2101       90059 :                 return exp_deps(sql, e->l, refs, l);
    2102      279957 :         case e_func: {
    2103      279957 :                 sql_subfunc *f = e->f;
    2104             : 
    2105      279957 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2106             :                         return -1;
    2107      279957 :                 cond_append(l, &f->func->base);
    2108      279957 :                 if (e->l && list_length(e->l) == 2 && strcmp(f->func->base.name, "next_value_for") == 0) {
    2109             :                         /* add dependency on seq nr */
    2110          85 :                         list *nl = e->l;
    2111          85 :                         sql_exp *schname = nl->h->data, *seqname = nl->t->data;
    2112          85 :                         char *sch_name = is_atom(schname->type) && schname->l ? ((atom*)schname->l)->data.val.sval : NULL;
    2113          85 :                         char *seq_name = is_atom(seqname->type) && seqname->l ? ((atom*)seqname->l)->data.val.sval : NULL;
    2114             : 
    2115          85 :                         if (sch_name && seq_name) {
    2116          85 :                                 sql_schema *sche = mvc_bind_schema(sql, sch_name);
    2117          85 :                                 if (sche) {
    2118          85 :                                         sql_sequence *seq = find_sql_sequence(sql->session->tr, sche, seq_name);
    2119          85 :                                         if (seq)
    2120          85 :                                                 cond_append(l, &seq->base);
    2121             :                                 }
    2122             :                         }
    2123             :                 }
    2124             :         } break;
    2125       21128 :         case e_aggr: {
    2126       21128 :                 sql_subfunc *a = e->f;
    2127             : 
    2128       21128 :                 if (e->l && exps_deps(sql, e->l, refs, l) != 0)
    2129             :                         return -1;
    2130       21128 :                 cond_append(l, &a->func->base);
    2131       21128 :         } break;
    2132       95706 :         case e_cmp: {
    2133       95706 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2134         729 :                         if (e->flag == cmp_filter) {
    2135         490 :                                 sql_subfunc *f = e->f;
    2136         490 :                                 cond_append(l, &f->func->base);
    2137             :                         }
    2138        1458 :                         if (exps_deps(sql, e->l, refs, l) != 0 ||
    2139         729 :                                 exps_deps(sql, e->r, refs, l) != 0)
    2140           0 :                                 return -1;
    2141       94977 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2142        8770 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2143        4385 :                                 exps_deps(sql, e->r, refs, l) != 0)
    2144           0 :                                 return -1;
    2145             :                 } else {
    2146      181184 :                         if (exp_deps(sql, e->l, refs, l) != 0 ||
    2147       90592 :                                 exp_deps(sql, e->r, refs, l) != 0)
    2148           0 :                                 return -1;
    2149       90592 :                         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      494388 : rel_deps(mvc *sql, sql_rel *r, list *refs, list *l)
    2159             : {
    2160      494388 :         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      494388 :         if (!r)
    2166             :                 return 0;
    2167             : 
    2168      496191 :         if (rel_is_ref(r) && refs_find_rel(refs, r)) /* already handled */
    2169             :                 return 0;
    2170      480200 :         switch (r->op) {
    2171      104088 :         case op_basetable: {
    2172      104088 :                 sql_table *t = r->l;
    2173             : 
    2174      104088 :                 cond_append(l, &t->base);
    2175             :                 /* find all used columns */
    2176      441299 :                 for (node *en = r->exps->h; en; en = en->next) {
    2177      337211 :                         sql_exp *exp = en->data;
    2178      337211 :                         const char *oname = exp->r;
    2179             : 
    2180      337211 :                         assert(!is_func(exp->type));
    2181      337211 :                         if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    2182       18330 :                                 continue;
    2183      318881 :                         } else if (oname[0] == '%') {
    2184          90 :                                 sql_idx *i = find_sql_idx(t, oname+1);
    2185          90 :                                 if (i) {
    2186          89 :                                         cond_append(l, &i->base);
    2187          89 :                                         continue;
    2188             :                                 }
    2189             :                         }
    2190      318792 :                         sql_column *c = find_sql_column(t, oname);
    2191      318792 :                         if (!c)
    2192             :                                 return -1;
    2193      318792 :                         cond_append(l, &c->base);
    2194             :                 }
    2195             :         } break;
    2196        4177 :         case op_table: {
    2197        4177 :                 if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */
    2198        4177 :                         sql_exp *op = r->r;
    2199        4177 :                         sql_subfunc *f = op->f;
    2200        4177 :                         cond_append(l, &f->func->base);
    2201             :                 }
    2202             :         } break;
    2203       71963 :         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      143926 :                 if (rel_deps(sql, r->l, refs, l) != 0 ||
    2218       71963 :                         rel_deps(sql, r->r, refs, l) != 0)
    2219           0 :                         return -1;
    2220             :                 break;
    2221        5072 :         case op_munion:
    2222       21269 :                 for (node *n = ((list*)r->l)->h; n; n = n->next) {
    2223       16197 :                         if (rel_deps(sql, n->data, refs, l) != 0)
    2224             :                                 return -1;
    2225             :                 }
    2226             :                 break;
    2227      170846 :         case op_project:
    2228             :         case op_select:
    2229             :         case op_groupby:
    2230             :         case op_topn:
    2231             :         case op_sample:
    2232             :         case op_truncate:
    2233      170846 :                 if (rel_deps(sql, r->l, refs, l) != 0)
    2234             :                         return -1;
    2235             :                 break;
    2236      124054 :         case op_ddl:
    2237      124054 :                 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      480200 :         if (!is_base(r->op) && r->exps) {
    2248      359388 :                 if (exps_deps(sql, r->exps, refs, l) != 0)
    2249             :                         return -1;
    2250             :         }
    2251      480200 :         if ((is_simple_project(r->op) || is_groupby(r->op)) && r->r) {
    2252       18810 :                 if (exps_deps(sql, r->r, refs, l) != 0)
    2253             :                         return -1;
    2254             :         }
    2255      480200 :         if (rel_is_ref(r)) {
    2256        5185 :                 list_append(refs, r);
    2257        5185 :                 list_append(refs, l);
    2258             :         }
    2259             :         return 0;
    2260             : }
    2261             : 
    2262             : list *
    2263      148644 : rel_dependencies(mvc *sql, sql_rel *r)
    2264             : {
    2265      148644 :         list *refs = sa_list(sql->sa);
    2266      148644 :         list *l = sa_list(sql->sa);
    2267             : 
    2268      148644 :         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       42232 : 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       42232 :         node *n;
    2279             : 
    2280       42232 :         if (list_empty(lists))
    2281             :                 return lists;
    2282       91226 :         for (n = lists->h; n; n = n->next) {
    2283       48994 :                 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    84948260 : 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    84948260 :         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    84960588 :         assert(e);
    2298    84960588 :         if (topdown) {
    2299     7254519 :                 int changes = v->changes;
    2300     7254519 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2301             :                         return NULL;
    2302     7254537 :                 *changed |= v->changes > changes;
    2303             :         }
    2304             : 
    2305    84960606 :         switch(e->type) {
    2306             :         case e_column:
    2307             :                 break;
    2308     1119856 :         case e_convert:
    2309     1119856 :                 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     4595644 :         case e_aggr:
    2313             :         case e_func:
    2314     4595644 :                 if (e->r) /* rewrite rank -r is list of lists */
    2315       42232 :                         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     4595644 :                 if (e->l)
    2318     4425534 :                         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     3425514 :         case e_cmp:
    2322     3425514 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2323      164100 :                         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      164100 :                         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     3261414 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2328      215130 :                         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      215130 :                         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     3046284 :                         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     3046284 :                         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     3046283 :                         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      386251 :         case e_psm:
    2342      386251 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2343      126683 :                         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      259568 :                 } else if (e->flag & PSM_VAR) {
    2346             :                         return e;
    2347      229812 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2348       39743 :                         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       39743 :                         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       39743 :                         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      190069 :                 } else if (e->flag & PSM_REL) {
    2355      190069 :                         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    28504887 :         case e_atom:
    2360    28504887 :                 if (e->f)
    2361      928406 :                         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    84930923 :         if (!topdown) {
    2366    77676817 :                 int changes = v->changes;
    2367    77676817 :                 if (!(e = exp_rewriter(v, rel, e, depth)))
    2368             :                         return NULL;
    2369    77679626 :                 *changed |= v->changes > changes;
    2370             :         }
    2371             :         return e;
    2372             : }
    2373             : 
    2374             : static list *
    2375    22193142 : 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    22193142 :         bool changed = false;
    2378    22193142 :         if (list_empty(exps))
    2379             :                 return exps;
    2380    99455866 :         for (node *n = exps->h; n; n = n->next)
    2381    77305036 :                 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    22150830 :         if (changed && depth == 0) /* only level 0 exps use hash, so remove only on those */
    2384       20646 :                 list_hash_clear(exps);
    2385             :         return exps;
    2386             : }
    2387             : 
    2388             : static inline sql_rel *
    2389    16732131 : rel_exp_visitor(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool topdown, bool relations_topdown)
    2390             : {
    2391    16732131 :         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    16732908 :         if (!rel)
    2395             :                 return rel;
    2396             : 
    2397    16732886 :         if (relations_topdown) {
    2398     6171554 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
    2399             :                         return NULL;
    2400     6171581 :                 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    16732913 :         switch(rel->op){
    2405             :         case op_basetable:
    2406             :                 break;
    2407       48987 :         case op_table:
    2408       48987 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2409       48919 :                         bool changed = false;
    2410       48919 :                         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       48919 :                         if (rel->r)
    2414       48611 :                                 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     2691720 :         case op_ddl:
    2419     2691720 :                 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      231591 :                         if (rel->l)
    2421      229402 :                                 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        2668 :                         if (rel->l)
    2425        2354 :                                 if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2426             :                                         return NULL;
    2427        2668 :                         if (rel->r)
    2428        2401 :                                 if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2429             :                                         return NULL;
    2430             :                 }
    2431             :                 break;
    2432     2230557 :         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     2230557 :                 if (rel->l)
    2448     2230558 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2449             :                                 return NULL;
    2450     2230539 :                 if (rel->r)
    2451     2228630 :                         if ((rel->r = rel_exp_visitor(v, rel->r, exp_rewriter, topdown, relations_topdown)) == NULL)
    2452             :                                 return NULL;
    2453             :                 break;
    2454      501709 :         case op_munion:
    2455     1560226 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2456     1058517 :                         if ((n->data = rel_exp_visitor(v, n->data, exp_rewriter, topdown, relations_topdown)) == NULL)
    2457             :                                 return NULL;
    2458             :                 }
    2459             :                 break;
    2460     7310835 :         case op_select:
    2461             :         case op_topn:
    2462             :         case op_sample:
    2463             :         case op_project:
    2464             :         case op_groupby:
    2465             :         case op_truncate:
    2466     7310835 :                 if (rel->l)
    2467     6193746 :                         if ((rel->l = rel_exp_visitor(v, rel->l, exp_rewriter, topdown, relations_topdown)) == NULL)
    2468             :                                 return NULL;
    2469             :                 break;
    2470             :         }
    2471             : 
    2472    16732884 :         if (!relations_topdown) {
    2473    10561252 :                 if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
    2474             :                         return NULL;
    2475    10561321 :                 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      613384 : rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2484             : {
    2485      613384 :         return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
    2486             : }
    2487             : 
    2488             : sql_rel *
    2489     4002828 : rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2490             : {
    2491     4002828 :         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   350472765 : exp_rel_visitor(visitor *v, sql_exp *e, rel_rewrite_fptr rel_rewriter, bool topdown)
    2499             : {
    2500   350472765 :         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   350496808 :         assert(e);
    2504   350496808 :         switch(e->type) {
    2505             :         case e_column:
    2506             :                 break;
    2507     6290115 :         case e_convert:
    2508     6290115 :                 if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2509             :                         return NULL;
    2510             :                 break;
    2511    19890075 :         case e_aggr:
    2512             :         case e_func:
    2513    19890075 :                 if (e->r) /* rewrite rank */
    2514       93686 :                         if ((e->r = exps_exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2515             :                                 return NULL;
    2516    19890075 :                 if (e->l)
    2517    19327650 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2518             :                                 return NULL;
    2519             :                 break;
    2520    20062283 :         case e_cmp:
    2521    20062283 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2522      676775 :                         if ((e->l = exps_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2523             :                                 return NULL;
    2524      676775 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2525             :                                 return NULL;
    2526    19385508 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2527     1276407 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2528             :                                 return NULL;
    2529     1276407 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2530             :                                 return NULL;
    2531             :                 } else {
    2532    18109101 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2533             :                                 return NULL;
    2534    18109099 :                         if ((e->r = exp_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2535             :                                 return NULL;
    2536    18109099 :                         if (e->f && (e->f = exp_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2537             :                                 return NULL;
    2538             :                 }
    2539             :                 break;
    2540      673224 :         case e_psm:
    2541      673224 :                 if (e->flag & PSM_SET || e->flag & PSM_RETURN || e->flag & PSM_EXCEPTION) {
    2542      256956 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2543             :                                 return NULL;
    2544      416268 :                 } else if (e->flag & PSM_VAR) {
    2545             :                         return e;
    2546      356756 :                 } else if (e->flag & PSM_WHILE || e->flag & PSM_IF) {
    2547       79486 :                         if ((e->l = exp_rel_visitor(v, e->l, rel_rewriter, topdown)) == NULL)
    2548             :                                 return NULL;
    2549       79486 :                         if ((e->r = exps_rel_visitor(v, e->r, rel_rewriter, topdown)) == NULL)
    2550             :                                 return NULL;
    2551       79486 :                         if (e->flag == PSM_IF && e->f && (e->f = exps_rel_visitor(v, e->f, rel_rewriter, topdown)) == NULL)
    2552             :                                 return NULL;
    2553      277270 :                 } else if (e->flag & PSM_REL) {
    2554      277270 :                         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2555      277270 :                         if ((e->l = func(v, e->l, rel_rewriter)) == NULL)
    2556             :                                 return NULL;
    2557             :                 }
    2558             :                 break;
    2559    70939353 :         case e_atom:
    2560    70939353 :                 if (e->f)
    2561     1515846 :                         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    94090909 : exps_rel_visitor(visitor *v, list *exps, rel_rewrite_fptr rel_rewriter, bool topdown)
    2570             : {
    2571    94090909 :         if (list_empty(exps))
    2572             :                 return exps;
    2573   400138059 :         for (node *n = exps->h; n; n = n->next)
    2574   306325992 :                 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       93686 : exps_exps_rel_visitor(visitor *v, list *lists, rel_rewrite_fptr rel_rewriter, bool topdown)
    2581             : {
    2582       93686 :         if (list_empty(lists))
    2583             :                 return lists;
    2584      187372 :         for (node *n = lists->h; n; n = n->next)
    2585       93686 :                 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    71089486 : do_rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2592             : {
    2593    71089486 :         if (rel->exps && (rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2594             :                 return NULL;
    2595    71087855 :         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    71087855 :         int changes = v->changes;
    2598    71087855 :         rel = rel_rewriter(v, rel);
    2599    71090038 :         if (rel && rel->exps && v->changes > changes) {
    2600      342127 :                 list_hash_clear(rel->exps);
    2601      342127 :                 if ((is_groupby(rel->op) || is_simple_project(rel->op)) && rel->r)
    2602       13923 :                         list_hash_clear(rel->r);
    2603             :         }
    2604             :         return rel;
    2605             : }
    2606             : 
    2607             : static inline sql_rel *
    2608    71090281 : rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool topdown)
    2609             : {
    2610    71090281 :         sql_rel *parent = v->parent;
    2611             : 
    2612    71090281 :         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    71092130 :         if (!rel)
    2616             :                 return NULL;
    2617             : 
    2618    71092066 :         if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
    2619             :                 return NULL;
    2620             : 
    2621    71092036 :         sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? rel_visitor_topdown : rel_visitor_bottomup;
    2622             : 
    2623    71092036 :         v->parent = rel;
    2624    71092036 :         switch(rel->op){
    2625             :         case op_basetable:
    2626             :                 break;
    2627      144160 :         case op_table:
    2628      144160 :                 if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) {
    2629      143933 :                         if (rel->l)
    2630        2877 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2631             :                                         return NULL;
    2632             :                 }
    2633             :                 break;
    2634     4343018 :         case op_ddl:
    2635     4343018 :                 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      424772 :                         if (rel->l)
    2637      421076 :                                 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       14711 :                         if (rel->l)
    2641       10709 :                                 if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2642             :                                         return NULL;
    2643       14711 :                         if (rel->r)
    2644       13706 :                                 if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2645             :                                         return NULL;
    2646             :                 } else if (rel->flag == ddl_psm) {
    2647      377780 :                         if ((rel->exps = exps_rel_visitor(v, rel->exps, rel_rewriter, topdown)) == NULL)
    2648             :                                 return NULL;
    2649             :                 }
    2650             :                 break;
    2651    11621996 :         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    11621996 :                 if (rel->l)
    2667    11621996 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2668             :                                 return NULL;
    2669    11621932 :                 if (rel->r)
    2670    11617446 :                         if ((rel->r = func(v, rel->r, rel_rewriter)) == NULL)
    2671             :                                 return NULL;
    2672             :                 break;
    2673     2337515 :         case op_munion:
    2674     8709613 :                 for (node *n = ((list*)rel->l)->h; n; n = n->next) {
    2675     6372098 :                         if ((n->data = func(v, n->data, rel_rewriter)) == NULL)
    2676             :                                 return NULL;
    2677             :                 }
    2678             :                 break;
    2679    34366484 :         case op_select:
    2680             :         case op_topn:
    2681             :         case op_sample:
    2682             :         case op_project:
    2683             :         case op_groupby:
    2684             :         case op_truncate:
    2685    34366484 :                 if (rel->l)
    2686    32104887 :                         if ((rel->l = func(v, rel->l, rel_rewriter)) == NULL)
    2687             :                                 return NULL;
    2688             :                 break;
    2689             :         }
    2690    71091904 :         v->parent = parent;
    2691             : 
    2692    71091904 :         if (!topdown)
    2693    45155820 :                 rel = do_rel_visitor(v, rel, rel_rewriter, false);
    2694             :         return rel;
    2695             : }
    2696             : 
    2697             : sql_rel *
    2698    25934793 : rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2699             : {
    2700    25934793 :         v->depth++;
    2701    25934793 :         rel = rel_visitor(v, rel, rel_rewriter, true);
    2702    25934757 :         v->depth--;
    2703    25934757 :         return rel;
    2704             : }
    2705             : 
    2706             : sql_rel *
    2707    45156919 : rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
    2708             : {
    2709    45156919 :         v->depth++;
    2710    45156919 :         rel = rel_visitor(v, rel, rel_rewriter, false);
    2711    45156462 :         v->depth--;
    2712    45156462 :         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      598586 : exps_exp_visitor_bottomup(visitor *v, sql_rel *rel, list *exps, int depth, exp_rewrite_fptr exp_rewriter, bool relations_topdown)
    2723             : {
    2724      598586 :         return exps_exp_visitor(v, rel, exps, depth, exp_rewriter, false, relations_topdown, false);
    2725             : }
    2726             : 
    2727             : static bool
    2728       74931 : exps_rebind_exp(mvc *sql, sql_rel *rel, list *exps)
    2729             : {
    2730       74931 :         bool ok = true;
    2731             : 
    2732       74931 :         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       74931 :         if (list_empty(exps))
    2738             :                 return true;
    2739       86222 :         for (node *n = exps->h; n && ok; n = n->next)
    2740       53094 :                 ok &= rel_rebind_exp(sql, rel, n->data);
    2741             :         return ok;
    2742             : }
    2743             : 
    2744             : bool
    2745     2603166 : rel_rebind_exp(mvc *sql, sql_rel *rel, sql_exp *e)
    2746             : {
    2747     2626395 :         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     2626395 :         switch (e->type) {
    2753       23229 :         case e_convert:
    2754       23229 :                 return rel_rebind_exp(sql, rel, e->l);
    2755       14352 :         case e_aggr:
    2756             :         case e_func:
    2757       14352 :                 return exps_rebind_exp(sql, rel, e->l);
    2758     1051511 :         case e_cmp:
    2759     1051511 :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    2760        8691 :                         return rel_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2761     1045042 :                 if (e->flag == cmp_or || e->flag == cmp_filter)
    2762       18822 :                         return exps_rebind_exp(sql, rel, e->l) && exps_rebind_exp(sql, rel, e->r);
    2763     2068930 :                 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     1495291 :         case e_column:
    2765     1495291 :                 if (e->freevar)
    2766             :                         return true;
    2767     1495290 :                 return rel_find_exp(rel, e) != NULL;
    2768       42007 :         case e_atom:
    2769       42007 :                 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