LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3700 4091 90.4 %
Date: 2024-12-20 21:24:02 Functions: 113 114 99.1 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "rel_select.h"
      15             : #include "sql_tokens.h"
      16             : #include "sql_privileges.h"
      17             : #include "sql_env.h"
      18             : #include "sql_decimal.h"
      19             : #include "sql_qc.h"
      20             : #include "rel_rel.h"
      21             : #include "rel_basetable.h"
      22             : #include "rel_exp.h"
      23             : #include "rel_xml.h"
      24             : #include "rel_dump.h"
      25             : #include "rel_prop.h"
      26             : #include "rel_psm.h"
      27             : #include "rel_schema.h"
      28             : #include "rel_unnest.h"
      29             : #include "rel_sequence.h"
      30             : #include "rel_file_loader.h"
      31             : #include "rel_optimizer_private.h"
      32             : 
      33             : #define VALUE_FUNC(f) (f->func->type == F_FUNC || f->func->type == F_FILT)
      34             : #define check_card(card,f) ((card == card_none && !f->res) || (CARD_VALUE(card) && f->res && VALUE_FUNC(f)) || card == card_loader || (card == card_relation && f->func->type == F_UNION))
      35             : 
      36             : /* return all expressions, with table name == tname */
      37             : static list *
      38       57824 : rel_table_projections( mvc *sql, sql_rel *rel, char *tname, int level )
      39             : {
      40       58346 :         list *exps;
      41             : 
      42       58346 :         if (mvc_highwater(sql))
      43           1 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
      44             : 
      45       58348 :         if (!rel)
      46             :                 return NULL;
      47             : 
      48       58348 :         if (!tname)
      49       42616 :                 return _rel_projections(sql, rel, NULL, 1, 0, 1);
      50             : 
      51       15732 :         switch(rel->op) {
      52         535 :         case op_join:
      53             :         case op_left:
      54             :         case op_right:
      55             :         case op_full:
      56         535 :                 exps = rel_table_projections( sql, rel->l, tname, level+1);
      57         535 :                 if (exps)
      58             :                         return exps;
      59          20 :                 return rel_table_projections( sql, rel->r, tname, level+1);
      60         502 :         case op_semi:
      61             :         case op_anti:
      62             :         case op_select:
      63         502 :                 return rel_table_projections( sql, rel->l, tname, level+1);
      64             : 
      65         139 :         case op_topn:
      66             :         case op_sample:
      67             :         case op_groupby:
      68             :         case op_union:
      69             :         case op_except:
      70             :         case op_inter:
      71             :         case op_project:
      72         139 :                 if (!is_processed(rel) && level == 0)
      73           0 :                         return rel_table_projections( sql, rel->l, tname, level+1);
      74             :                 /* fall through */
      75             :         case op_munion:
      76         148 :                 if (!is_processed(rel) && level == 0) {
      77           0 :                         node *n = ((list*)rel->l)->h;
      78           0 :                         if (n)
      79           0 :                                 return rel_table_projections(sql, n->data, tname, level+1);
      80             :                 }
      81             :         /* fall through */
      82             :         case op_table:
      83             :         case op_basetable:
      84       14695 :                 if (is_basetable(rel->op) && !rel->exps)
      85       14045 :                         return rel_base_project_all(sql, rel, tname);
      86         650 :                 if (rel->exps) {
      87         650 :                         int rename = 0;
      88         650 :                         node *en;
      89             : 
      90             :                         /* first check alias */
      91         650 :                         if (!is_base(rel->op) && !level) {
      92         131 :                                 list *exps = sa_list(sql->sa);
      93             : 
      94         651 :                                 for (en = rel->exps->h; en && !rename; en = en->next) {
      95         520 :                                         sql_exp *e = en->data;;
      96             : 
      97         520 :                                         if ((is_basecol(e) && exp_relname(e) && strcmp(exp_relname(e), tname) == 0) ||
      98         285 :                                             (is_basecol(e) && !exp_relname(e) && e->l && strcmp(e->l, tname) == 0)) {
      99         235 :                                                 if (exp_name(e) && exps_bind_column2(exps, tname, exp_name(e), NULL))
     100             :                                                         rename = 1;
     101             :                                                 else
     102         234 :                                                         append(exps, e);
     103             :                                         }
     104             :                                 }
     105             :                         }
     106             : 
     107         650 :                         exps = new_exp_list(sql->sa);
     108        5220 :                         for (en = rel->exps->h; en; en = en->next) {
     109        4570 :                                 sql_exp *e = en->data;
     110        4570 :                                 if (is_basecol(e) && exp_relname(e) && strcmp(exp_relname(e), tname) == 0) {
     111        4275 :                                         if (rename)
     112           2 :                                                 append(exps, exp_alias_ref(sql, e));
     113             :                                         else {
     114        4273 :                                                 sql_exp *ne = exp_ref(sql, e);
     115        4273 :                                                 exp_setname(sql, ne, tname, exp_name(e));
     116        4273 :                                                 append(exps, ne);
     117             :                                         }
     118             :                                 }
     119        4570 :                                 if (is_basecol(e) && !exp_relname(e) && e->l && strcmp(e->l, tname) == 0) {
     120           0 :                                         if (rename)
     121           0 :                                                 append(exps, exp_alias_ref(sql, e));
     122             :                                         else {
     123           0 :                                                 sql_exp *ne = exp_ref(sql, e);
     124           0 :                                                 exp_setname(sql, ne, tname, exp_name(e));
     125           0 :                                                 append(exps, ne);
     126             :                                         }
     127             :                                 }
     128             : 
     129             :                         }
     130         650 :                         if (exps && list_length(exps))
     131             :                                 return exps;
     132             :                 }
     133             :                 /* fall through */
     134             :         default:
     135             :                 return NULL;
     136             :         }
     137             : }
     138             : 
     139             : static sql_exp *
     140           0 : rel_lastexp(mvc *sql, sql_rel *rel )
     141             : {
     142           0 :         sql_exp *e;
     143             : 
     144           0 :         if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
     145           0 :                 rel = rel_parent(rel);
     146           0 :         assert(list_length(rel->exps));
     147           0 :         if (rel->op == op_project) {
     148           0 :                 list_hash_clear(rel->exps);
     149           0 :                 return exp_ref(sql, rel->exps->t->data);
     150             :         }
     151           0 :         assert(is_project(rel->op));
     152           0 :         e = rel->exps->t->data;
     153           0 :         return exp_ref(sql, e);
     154             : }
     155             : 
     156             : static sql_rel *
     157       37063 : rel_orderby(mvc *sql, sql_rel *l)
     158             : {
     159       37063 :         sql_rel *rel = rel_create(sql->sa);
     160       37063 :         if (!rel)
     161             :                 return NULL;
     162             : 
     163       37063 :         assert(l->op == op_project && !l->r);
     164       37063 :         rel->l = l;
     165       37063 :         rel->r = NULL;
     166       37063 :         rel->op = op_project;
     167       37063 :         rel->exps = rel_projections(sql, l, NULL, 1, 0);
     168       37063 :         rel->card = l->card;
     169       37063 :         rel->nrcols = l->nrcols;
     170       37063 :         return rel;
     171             : }
     172             : 
     173             : /* forward refs */
     174             : static sql_rel * rel_setquery(sql_query *query, symbol *sq);
     175             : static sql_rel * rel_joinquery(sql_query *query, symbol *sq, list *refs);
     176             : 
     177             : static sql_rel *
     178      209379 : rel_table_optname(mvc *sql, sql_rel *sq, symbol *optname, list *refs)
     179             : {
     180      209379 :         sql_rel *osq = sq;
     181      209379 :         node *ne;
     182             : 
     183      209379 :         if (optname && optname->token == SQL_NAME) {
     184       17073 :                 dlist *columnrefs = NULL;
     185       17073 :                 char *tname = optname->data.lval->h->data.sval;
     186       17073 :                 list *l = sa_list(sql->sa);
     187             : 
     188       17073 :                 columnrefs = optname->data.lval->h->next->data.lval;
     189       17073 :                 if (is_topn(sq->op) || is_sample(sq->op) || ((is_simple_project(sq->op) || is_groupby(sq->op)) && sq->r) || is_base(sq->op)) {
     190         138 :                         sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 0));
     191         138 :                         osq = sq;
     192             :                 }
     193       17073 :                 if (columnrefs && dlist_length(columnrefs) != list_length(sq->exps))
     194           6 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The number of aliases don't match the number of columns (%d != %d)", dlist_length(columnrefs), sq->nrcols);
     195        3860 :                 if (columnrefs && sq->exps) {
     196        3860 :                         dnode *d = columnrefs->h;
     197             : 
     198        3860 :                         ne = sq->exps->h;
     199        3860 :                         list_hash_clear(sq->exps);
     200       16131 :                         for (; d && ne; d = d->next, ne = ne->next) {
     201        8412 :                                 sql_exp *e = ne->data;
     202             : 
     203        8412 :                                 if (exps_bind_column2(l, tname, d->data.sval, NULL))
     204           1 :                                         return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: Duplicate column name '%s.%s'", tname, d->data.sval);
     205        8411 :                                 exp_setname(sql, e, tname, d->data.sval );
     206        8411 :                                 if (!is_intern(e))
     207        8411 :                                         set_basecol(e);
     208        8411 :                                 append(l, e);
     209             :                         }
     210             :                 }
     211       17066 :                 if (!columnrefs && sq->exps) {
     212       13207 :                         ne = sq->exps->h;
     213       13207 :                         list_hash_clear(sq->exps);
     214      125967 :                         for (; ne; ne = ne->next) {
     215       99553 :                                 sql_exp *e = ne->data;
     216       99553 :                                 char *name = NULL;
     217             : 
     218       99553 :                                 if (!is_intern(e)) {
     219       99553 :                                         if (!exp_name(e))
     220         109 :                                                 name = make_label(sql->sa, ++sql->label);
     221       99553 :                                         noninternexp_setname(sql, e, tname, name);
     222       99553 :                                         set_basecol(e);
     223             :                                 }
     224             :                         }
     225             :                 }
     226       17066 :                 if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
     227       17016 :                         if (list_find(refs, tname, (fcmp) &strcmp))
     228           6 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
     229       17010 :                         assert(tname);
     230       17010 :                         list_append(refs, tname);
     231             :                 }
     232             :         } else {
     233      192306 :                 if (!is_project(sq->op) || is_topn(sq->op) || is_sample(sq->op) || ((is_simple_project(sq->op) || is_groupby(sq->op)) && sq->r)) {
     234       59251 :                         sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 1));
     235       59251 :                         osq = sq;
     236             :                 }
     237     2404170 :                 for (ne = osq->exps->h; ne; ne = ne->next) {
     238     2211864 :                         sql_exp *e = ne->data;
     239             : 
     240     2211864 :                         if (!is_intern(e))
     241     2081187 :                                 set_basecol(e);
     242             :                 }
     243             :         }
     244             :         return osq;
     245             : }
     246             : 
     247             : static sql_rel *
     248      101908 : rel_subquery_optname(sql_query *query, symbol *ast, list *refs)
     249             : {
     250      101908 :         mvc *sql = query->sql;
     251      101908 :         SelectNode *sn = (SelectNode *) ast;
     252      101908 :         exp_kind ek = {type_value, card_relation, TRUE};
     253      101908 :         sql_rel *sq = rel_subquery(query, ast, ek);
     254             : 
     255      101908 :         assert(ast->token == SQL_SELECT);
     256      101908 :         if (!sq)
     257             :                 return NULL;
     258             : 
     259      101886 :         return rel_table_optname(sql, sq, sn->name, refs);
     260             : }
     261             : 
     262             : static void
     263       10066 : rel_rename(mvc *sql, sql_rel *nrel, char *rname, sql_rel *brel)
     264             : {
     265       10066 :         assert(is_project(nrel->op));
     266       10066 :         if (brel) {
     267         156 :                 if (is_project(nrel->op) && nrel->exps) {
     268         368 :                         for (node *ne = nrel->exps->h, *be = brel->exps->h; ne && be; ne = ne->next, be = be->next) {
     269         212 :                                 sql_exp *e = ne->data;
     270         212 :                                 sql_exp *b = be->data;
     271         212 :                                 char *name = NULL;
     272             : 
     273         212 :                                 if (!is_intern(e)) {
     274         212 :                                         if (!exp_name(e))
     275           0 :                                                 name = make_label(sql->sa, ++sql->label);
     276         212 :                                         noninternexp_setname(sql, e, rname, name);
     277         212 :                                         set_basecol(e);
     278         212 :                                         e->alias.label = b->alias.label;
     279             :                                 }
     280             :                         }
     281             :                 }
     282         156 :                 list_hash_clear(nrel->exps);
     283        9910 :         } else if (is_project(nrel->op) && nrel->exps) {
     284        9910 :                 node *ne = nrel->exps->h;
     285             : 
     286       40945 :                 for (; ne; ne = ne->next) {
     287       31035 :                         sql_exp *e = ne->data;
     288       31035 :                         char *name = NULL;
     289             : 
     290       31035 :                         if (!is_intern(e)) {
     291       31035 :                                 if (!exp_name(e))
     292          17 :                                         name = make_label(sql->sa, ++sql->label);
     293       31035 :                                 noninternexp_setname(sql, e, rname, name);
     294       31035 :                                 set_basecol(e);
     295             :                         }
     296             :                 }
     297        9910 :                 list_hash_clear(nrel->exps);
     298             :         }
     299       10066 : }
     300             : 
     301             : sql_rel *
     302        5871 : rel_with_query(sql_query *query, symbol *q )
     303             : {
     304        5871 :         mvc *sql = query->sql;
     305        5871 :         dnode *d = q->data.lval->h;
     306        5871 :         symbol *next = d->next->data.sym;
     307        5871 :         bool recursive = d->next->next->data.i_val;
     308        5871 :         sql_rel *rel;
     309             : 
     310        5871 :         if (!stack_push_frame(sql, NULL))
     311           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     312             :         /* first handle all with's (ie inlined views) */
     313       15859 :         for (d = d->data.lval->h; d; d = d->next) {
     314       10008 :                 symbol *sym = d->data.sym;
     315       10008 :                 dnode *dn = sym->data.lval->h->next;
     316       10008 :                 char *rname = qname_schema_object(dn->data.lval);
     317       10008 :                 sql_rel *nrel, *base_rel = NULL;
     318       10008 :                 symbol *recursive_part = NULL;
     319       10008 :                 sql_rel_view *recursive_union = NULL;
     320       10008 :                 int recursive_distinct = 0;
     321             : 
     322       10008 :                 if (frame_find_rel_view(sql, rname)) {
     323           3 :                         stack_pop_frame(sql);
     324           3 :                         return sql_error(sql, 01, SQLSTATE(42000) "View '%s' already declared", rname);
     325             :                 }
     326       10005 :                 if (recursive) {
     327         103 :                         symbol *union_stmt = dn->next->next->data.sym;
     328         103 :                         if (union_stmt->token == SQL_UNION) { /* split in base and recursive part */
     329          78 :                                 dnode *n = union_stmt->data.lval->h;
     330          78 :                                 symbol *base = n->data.sym;
     331          78 :                                 recursive_distinct = n->next->data.i_val;
     332          78 :                                 dlist *corresponding = n->next->next->data.lval;
     333          78 :                                 recursive_part = n->next->next->next->data.sym;
     334          78 :                                 if (corresponding)
     335           0 :                                         return sql_error(sql, 01, SQLSTATE(42000) "Recursive with corresponding is not supported");
     336          78 :                                 dn->next->next->data.sym = base;
     337             :                         }
     338             :                 }
     339       10005 :                 nrel = rel_semantic(query, sym);
     340       10005 :                 if (!nrel) {
     341          17 :                         stack_pop_frame(sql);
     342          17 :                         return NULL;
     343             :                 }
     344        9988 :                 if (!(recursive_union = stack_push_rel_view(sql, rname, nrel))) {
     345           0 :                         stack_pop_frame(sql);
     346           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     347             :                 }
     348        9988 :                 if (recursive && recursive_part) {
     349          78 :                         base_rel = nrel;
     350          78 :                         rel_rename(sql, base_rel, rname, base_rel);
     351          78 :                         dn->next->next->data.sym = recursive_part;
     352          78 :                         set_processed(nrel);
     353          78 :                         nrel = rel_semantic(query, sym);
     354          78 :                         if (!nrel) {
     355           0 :                                 stack_pop_frame(sql);
     356           0 :                                 return NULL;
     357             :                         }
     358          78 :                         list *ls = rel_projections(sql, base_rel, NULL, 0, 1);
     359          78 :                         list *rs = rel_projections(sql, nrel, NULL, 0, 1);
     360             : 
     361          78 :                         if (!rel_is_ref(base_rel)) { /* not recursive */
     362           3 :                                 nrel = rel_setop_n_ary_check_types(sql, base_rel, nrel, ls, rs, op_munion);
     363             :                         } else {
     364          75 :                                 base_rel->used |= statistics_gathered;
     365          75 :                                 prop *p = base_rel->p = prop_create(sql->sa, PROP_COUNT, base_rel->p);
     366          75 :                                 p->value.lval = 1000000; /* random ? */
     367             : 
     368             :                                 /* down cast the recursive side (on errors users should add casts on the base side) */
     369          75 :                                 list *nrs = new_exp_list(sql->sa);
     370          75 :                                 if(!nrs)
     371             :                                         return NULL;
     372             : 
     373         174 :                                 for (node *n = ls->h, *m = rs->h; n && m; n = n->next, m = m->next) {
     374          99 :                                         sql_subtype *t = exp_subtype(n->data);
     375          99 :                                         append(nrs, exp_check_type(sql, t, nrel, m->data, type_equal));
     376             :                                 }
     377          75 :                                 nrel = rel_project(sql->sa, nrel, nrs);
     378          75 :                                 nrel = rel_setop_n_ary(sql->sa, append(append(sa_list(sql->sa), base_rel), nrel), op_munion);
     379          75 :                                 set_recursive(nrel);
     380             :                         }
     381          78 :                         if (recursive_distinct)
     382          34 :                                 set_distinct(nrel);
     383          78 :                         rel_setop_n_ary_set_exps(sql, nrel, rel_projections(sql, nrel, NULL, 0, 1), false);
     384          78 :                         set_processed(nrel);
     385          78 :                         recursive_union->rel_view = rel_dup(nrel); /* extra incref for independent flow */
     386             :                 }
     387        9988 :                 if (!is_project(nrel->op)) {
     388           0 :                         if (is_topn(nrel->op) || is_sample(nrel->op)) {
     389           0 :                                 nrel = rel_project(sql->sa, nrel, rel_projections(sql, nrel, NULL, 1, 1));
     390             :                         } else {
     391           0 :                                 stack_pop_frame(sql);
     392           0 :                                 return NULL;
     393             :                         }
     394             :                 }
     395        9988 :                 rel_rename(sql, nrel, rname, base_rel);
     396             :         }
     397        5851 :         rel = rel_semantic(query, next);
     398        5851 :         stack_pop_frame(sql);
     399        5851 :         return rel;
     400             : }
     401             : 
     402             : static sql_rel *
     403       60354 : query_exp_optname(sql_query *query, symbol *q, list *refs)
     404             : {
     405       60354 :         mvc *sql = query->sql;
     406       60354 :         switch (q->token) {
     407         983 :         case SQL_WITH:
     408             :         {
     409         983 :                 sql_rel *tq = rel_with_query(query, q);
     410             : 
     411         983 :                 if (!tq)
     412             :                         return NULL;
     413         983 :                 if (q->data.lval->t->type == type_symbol)
     414         983 :                         return rel_table_optname(sql, tq, q->data.lval->t->data.sym, refs);
     415             :                 return tq;
     416             :         }
     417       59371 :         case SQL_JOIN:
     418             :         {
     419       59371 :                 sql_rel *tq = rel_joinquery(query, q, refs);
     420             : 
     421       59371 :                 if (!tq)
     422             :                         return NULL;
     423       59332 :                 return rel_table_optname(sql, tq, q->data.lval->t->data.sym, NULL);
     424             :         }
     425           0 :         default:
     426           0 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "case %d %s", (int) q->token, token2string(q->token));
     427             :         }
     428           0 :         return NULL;
     429             : }
     430             : 
     431             : static sql_subfunc *
     432      549841 : bind_func_(mvc *sql, char *sname, char *fname, list *ops, sql_ftype type, bool private, bool *found, bool exact)
     433             : {
     434      549841 :         sql_subfunc *sf = NULL;
     435             : 
     436      550298 :         if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
     437         459 :             list_cmp(sql->forward->ops, ops, (fcmp)&arg_subtype_cmp) == 0 &&
     438           4 :             execute_priv(sql, sql->forward) && type == sql->forward->type)
     439           2 :                 return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
     440      549839 :         sf = sql_bind_func_(sql, sname, fname, ops, type, private, exact);
     441      549839 :         if (found)
     442      549300 :                 *found |= sf != NULL;
     443      549839 :         if (sf && execute_priv(sql, sf->func))
     444             :                 return sf;
     445             :         return NULL;
     446             : }
     447             : 
     448             : static sql_subfunc *
     449      191684 : bind_func(mvc *sql, char *sname, char *fname, sql_subtype *t1, sql_subtype *t2, int nr, sql_ftype type, bool private, bool *found, bool exact)
     450             : {
     451      191684 :         list *tl = sa_list(sql->sa);
     452      191684 :         assert(nr >= 1 && nr <= 2);
     453      191684 :         append(tl, t1);
     454      191684 :         if (nr == 2)
     455      156510 :                 append(tl, t2);
     456      191684 :         sql_subfunc *sf = NULL;
     457             : 
     458      191684 :         if (sql->forward) {
     459       22625 :                 if (execute_priv(sql, sql->forward) &&
     460       22625 :                     strcmp(fname, sql->forward->base.name) == 0 &&
     461           0 :                    ((!t1 && list_length(sql->forward->ops) == 0) ||
     462           0 :                     (!t2 && list_length(sql->forward->ops) == 1 && arg_subtype_cmp(sql->forward->ops->h->data, t1) == 0) ||
     463           0 :                     (list_length(sql->forward->ops) == 2 &&
     464           0 :                         arg_subtype_cmp(sql->forward->ops->h->data, t1) == 0 &&
     465           0 :                         arg_subtype_cmp(sql->forward->ops->h->next->data, t2) == 0)) && type == sql->forward->type) {
     466           0 :                         return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
     467             :                 }
     468             :         }
     469      191684 :         sf = sql_bind_func_(sql, sname, fname, tl, type, private, exact);
     470      191684 :         if (found)
     471      191684 :                 *found |= sf != NULL;
     472      191684 :         if (sf && execute_priv(sql, sf->func))
     473             :                 return sf;
     474             :         return NULL;
     475             : }
     476             : 
     477             : static sql_subfunc *
     478      653830 : find_func(mvc *sql, char *sname, char *fname, int len, sql_ftype type, bool private, sql_subfunc *prev, bool *found)
     479             : {
     480      653830 :         sql_subfunc *sf = NULL;
     481             : 
     482      653830 :         if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 && list_length(sql->forward->ops) == len && execute_priv(sql, sql->forward) && type == sql->forward->type)
     483           0 :                 return sql_dup_subfunc(sql->sa, sql->forward, NULL, NULL);
     484      653830 :         sf = sql_find_func(sql, sname, fname, len, type, private, prev);
     485      653830 :         if (found)
     486           0 :                 *found |= sf != NULL;
     487      653830 :         if (sf && execute_priv(sql, sf->func))
     488             :                 return sf;
     489             :         return NULL;
     490             : }
     491             : 
     492             : static sql_exp *
     493      713075 : exp_fix_scale(mvc *sql, sql_subtype *ct, sql_exp *e)
     494             : {
     495      713075 :         sql_subtype *et = exp_subtype(e);
     496             : 
     497      713075 :         if (ct->type->scale == SCALE_FIX && et->type->scale == SCALE_FIX) {
     498       85152 :                 int scale_diff = ((int) ct->scale - (int) et->scale);
     499             : 
     500       85152 :                 if (scale_diff) {
     501         132 :                         if (scale_diff < 0)
     502             :                                 return e;
     503         102 :                         sql_subtype st;
     504         102 :                         int scale = ct->scale;
     505         102 :                         int digits = ((et->type->eclass == EC_NUM)?bits2digits(et->digits):et->digits)-et->scale+scale;
     506         102 :                         (void)sql_find_subtype(&st, ct->type->base.name, digits, scale);
     507         102 :                         return exp_convert(sql, e, et, &st);
     508             :                 }
     509             :         }
     510             :         return e;
     511             : }
     512             : 
     513             : static lng
     514        9733 : rel_get_count(sql_rel *rel)
     515             : {
     516       31322 :         if (!rel)
     517             :                 return 0;
     518       31318 :         prop *p = NULL;
     519       31318 :         if (rel->p && (p = find_prop(rel->p, PROP_COUNT)) != NULL)
     520        3073 :                 return p->value.lval;
     521       28245 :         else if(is_munion(rel->op)) {
     522         174 :                 lng cnt = 0;
     523         174 :                 list *l = rel->l;
     524         522 :                 for (node *n = l->h; n; n = n->next) {
     525         348 :                         lng lcnt = rel_get_count(n->data);
     526         348 :                         if (lcnt == BUN_MAX)
     527             :                                 return BUN_MAX;
     528         348 :                         cnt += lcnt;
     529             :                 }
     530         174 :                 return cnt;
     531       28071 :         } else if(rel->l) {
     532       25387 :                 if (is_select(rel->op) || is_project(rel->op))
     533             :                         return rel_get_count(rel->l);
     534             :         }
     535             :         return 0;
     536             : }
     537             : 
     538             : #define is_sum_aggr(f) (f->type == F_AGGR && strcmp(f->base.name, "sum") == 0)
     539             : 
     540             : list *
     541      753739 : check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, sql_subfunc *sf, int maybe_zero_or_one, bool internal)
     542             : {
     543      753739 :         list *nexps = new_exp_list(sql->sa);
     544      753740 :         sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? sf->res->h->data: NULL;
     545      753740 :         unsigned int digits = 0, scale = 0;
     546             : 
     547             :         /* find largest any type argument */
     548     2226192 :         for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) {
     549     1472454 :                 sql_arg *a = m->data;
     550     1472454 :                 sql_exp *e = n->data;
     551     1472454 :                 sql_subtype *t = exp_subtype(e);
     552             : 
     553     1472452 :                 if (a->type.type->eclass == EC_ANY) {
     554      267679 :                         if (t && atp) {
     555      117342 :                                 supertype(&super, t, atp);
     556      117342 :                                 atp = &super;
     557      150337 :                         } else if (t) {
     558             :                                 atp = t;
     559             :                         }
     560             :                 }
     561     1472449 :                 if (t && sf->func->fix_scale == SCALE_FIX && t->type->eclass == EC_DEC) {
     562        1260 :                         if (digits < t->digits)
     563             :                                 digits = t->digits;
     564        1260 :                         if (scale < t->scale)
     565             :                                 scale = t->scale;
     566             :                 }
     567             :         }
     568      753738 :         if (!atp && !list_empty(exps))
     569      601552 :                 atp = exp_subtype(exps->h->data);
     570             : 
     571      753740 :         if ((atp && atp->type->localtype == TYPE_void) || !atp) /* NULL */
     572       11917 :                 atp = sql_bind_localtype("str");
     573             : 
     574      753740 :         node *n, *m;
     575      753740 :         sql_arg *last = NULL;
     576     3698738 :         for (n = exps->h, m = sf->func->ops->h; n && ((sf->func->vararg && last) || m); n = n->next, m = m?m->next:NULL) {
     577     1472499 :                 sql_arg *a = m?m->data:last;
     578     1472499 :                 sql_exp *e = n->data;
     579     1472499 :                 sql_subtype *ntp = &a->type, *t = exp_subtype(e);
     580             : 
     581     1472499 :                 last = a;
     582     1472499 :                 if (!t) {
     583          38 :                         if (a->type.type->eclass == EC_ANY && atp)
     584           3 :                                 ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
     585          61 :                         rel_set_type_param(sql, ntp, rel, e, sf->func->fix_scale != INOUT && !UDF_LANG(sf->func->lang));
     586     1472461 :                 } else if (a->type.type->eclass == EC_ANY && atp) {
     587      267723 :                         ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
     588     1204738 :                 } else if (t && ntp->digits == 0 && EC_VARCHAR(a->type.type->eclass)) {
     589      527384 :                         ntp = sql_create_subtype(sql->sa, a->type.type, type_digits_to_char_digits(t), 0);
     590      677354 :                 } else if (t && ntp->digits > 0 && a->type.type->eclass == EC_NUM && t->type->eclass == EC_NUM) {
     591      365182 :                         ntp = sql_create_subtype(sql->sa, a->type.type, t->digits, 0);
     592      312172 :                 } else if (t && ntp->scale == 0 && ntp->type->eclass == EC_DEC && EC_VARCHAR(t->type->eclass)) {
     593           0 :                         sql_subtype *res = SA_NEW(sql->sa, sql_subtype);
     594           0 :                         int digits = t->digits?t->digits+3:ntp->digits;
     595           0 :                         (void)sql_find_subtype(res, a->type.type->base.name, digits, 3);
     596           0 :                         ntp = res;
     597      312172 :                 } else if (t && ntp->scale == 0 && ntp->type->eclass == EC_DEC) {
     598        4875 :                         ntp = sql_create_subtype(sql->sa, a->type.type, t->type->eclass == EC_NUM?bits2digits(t->digits):t->digits, t->scale);
     599      307297 :                 } else if (t->type == ntp->type) {
     600      305192 :                         ntp = t;
     601             :                 }
     602     1472499 :                 if (!(e = exp_check_type(sql, ntp, rel, e, type_equal)))
     603             :                         return NULL;
     604     1472499 :                 if (sf->func->fix_scale == SCALE_FIX) {
     605      534037 :                         ntp = sql_create_subtype(sql->sa, a->type.type->localtype?a->type.type:t?t->type:atp->type, digits, scale);
     606      534037 :                         e = exp_fix_scale(sql, ntp, e);
     607      938462 :                 } else if (sf->func->fix_scale == SCALE_EQ) {
     608      179038 :                         e = exp_fix_scale(sql, &a->type, e);
     609             :                 }
     610     1472499 :                 if (maybe_zero_or_one && e->card > CARD_ATOM) {
     611          22 :                         sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(e), NULL, F_AGGR, true, false);
     612          22 :                         e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e));
     613             :                 }
     614     1472499 :                 append(nexps, e);
     615             :         }
     616             :         /* handle any extra arguments for rel_dump/analytic funcs */
     617      753962 :         for ( ; n; n = n->next)
     618         223 :                 append(nexps, n->data);
     619      753739 :         if (sf->func->fix_scale == SCALE_FIX || IS_ANALYTIC(sf->func)) {
     620      269501 :                 exps_scale_fix(sf, nexps, atp);
     621      484238 :         } else if (sf->func->fix_scale == MAX_BITS) {
     622      113665 :                 exps_max_bits(sf, nexps);
     623      370573 :         } else if (sf->func->fix_scale == SCALE_MUL) {
     624       25254 :                 exps_sum_scales(sf, nexps);
     625      345319 :         } else if (!internal && sf->func->fix_scale == SCALE_DIV) {
     626        2613 :                 if (!exps_scale_algebra(sql, sf, rel, nexps))
     627             :                         return NULL;
     628      342706 :         } else if (sf->func->fix_scale == DIGITS_ADD) {
     629      186616 :                 exps_digits_add(sf, nexps);
     630      156090 :         } else if (sf->func->fix_scale == INOUT) {
     631       19444 :                 exps_inout(sf, nexps);
     632      136646 :         } else if (is_sum_aggr(sf->func))
     633        9385 :                 exps_largest_int(sf, nexps, rel_get_count(rel));
     634             : 
     635             :         /* dirty hack */
     636      753737 :         if (sf->func->type != F_PROC && sf->func->type != F_UNION && sf->func->type != F_LOADER && res) {
     637      747850 :                 if (res->type->eclass == EC_ANY && atp)
     638          73 :                         sf->res->h->data = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
     639             :         }
     640             :         return nexps;
     641             : }
     642             : 
     643             : static char *
     644         283 : nary_function_arg_types_2str(mvc *sql, list* types, int N)
     645             : {
     646         283 :         char *arg_list = NULL;
     647         283 :         int i = 0;
     648             : 
     649         764 :         for (node *n = types->h; n && i < N; n = n->next) {
     650         481 :                 sql_subtype *t = (sql_subtype *) n->data;
     651         481 :                 char *tpe = t ? sql_subtype_string(sql->ta, t) : "?";
     652             : 
     653         481 :                 if (arg_list) {
     654         215 :                         arg_list = sa_message(sql->ta, "%s, %s", arg_list, tpe);
     655             :                 } else {
     656             :                         arg_list = tpe;
     657             :                 }
     658         481 :                 i++;
     659             :         }
     660         283 :         return arg_list;
     661             : }
     662             : 
     663             : static char *
     664          35 : file_loader_add_table_column_types(mvc *sql, sql_subfunc *f, list *exps, list *res_exps, char *tname)
     665             : {
     666          35 :         sql_exp *file = exps->h->data;
     667          35 :         if (!exp_is_atom(file))
     668             :                 return "Filename missing";
     669             : 
     670          35 :         atom *a = file->l;
     671          35 :         if (a->data.vtype != TYPE_str || !a->data.val.sval)
     672             :                 return "Filename missing";
     673             : 
     674          35 :         char *filename = a->data.val.sval;
     675          35 :         if (strcmp(filename, "") == 0)
     676             :                 return "Filename missing";
     677             : 
     678          33 :         char *ext = strrchr(filename, '.'), *ep = ext;
     679             : 
     680          33 :         if (ext) {
     681          30 :                 ext = ext + 1;
     682          30 :                 ext = mkLower(sa_strdup(sql->sa, ext));
     683             :         }
     684          30 :         if (!ext)
     685           3 :                 return "Filename extension missing";
     686             : 
     687          30 :         file_loader_t *fl = fl_find(ext);
     688          30 :         if (!fl) {
     689             :                 /* maybe compressed */
     690          10 :                 char *p = ep - 1;
     691          66 :                 while (p > filename && *p != '.')
     692          56 :                         p--;
     693          10 :                 if (p != filename) {
     694           8 :                         ext = p + 1;
     695           8 :                         ext = sa_strdup(sql->sa, ext);
     696           8 :                         char *d = strchr(ext, '.');
     697           8 :                         assert(d);
     698           8 :                         *d = 0;
     699           8 :                         fl = fl_find(ext);
     700             :                 }
     701          10 :                 if (!fl) /* fallback */
     702           2 :                         fl = fl_find("csv");
     703           2 :                 if (!fl) /* not expected */
     704           0 :                         return sa_message(sql->ta, "Filename extension '%s' missing", ext?ext:"");
     705             :         }
     706          30 :         str err = fl->add_types(sql, f, filename, res_exps, tname);
     707          30 :         if (err)
     708             :                 return err;
     709          16 :         sql_subtype *st = sql_bind_localtype("str");
     710          16 :         sql_exp *ext_exp = exp_atom(sql->sa, atom_string(sql->sa, st, ext));
     711          16 :         if (!ext_exp)
     712             :                 return MAL_MALLOC_FAIL;
     713          16 :         append(exps, ext_exp);
     714          16 :         return NULL;
     715             : }
     716             : 
     717             : static sql_rel *
     718          35 : rel_file_loader(mvc *sql, list *exps, list *tl, char *tname)
     719             : {
     720          35 :         sql_subfunc *f = NULL;
     721          35 :         bool found = false;
     722             : 
     723          35 :         if ((f = bind_func_(sql, NULL, "file_loader", tl, F_UNION, true, &found, false))) {
     724          35 :                 list *nexps = exps;
     725          35 :                 if (list_empty(tl) || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false))) {
     726          35 :                         list *res_exps = sa_list(sql->sa);
     727          35 :                         if (list_length(exps) == 1 && f && f->func->varres && strlen(f->func->mod) == 0 && strlen(f->func->imp) == 0) {
     728          35 :                                 char *err = file_loader_add_table_column_types(sql, f, nexps, res_exps, tname);
     729          35 :                                 if (err)
     730          19 :                                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: file_loader function failed '%s'", err);
     731             :                         }
     732          16 :                         sql_exp *e = exp_op(sql->sa, nexps, f);
     733          16 :                         sql_rel *rel = rel_table_func(sql->sa, NULL, e, res_exps, TABLE_PROD_FUNC);
     734          16 :                         if (rel)
     735          16 :                                 rel = rel_project(sql->sa, rel, exps_alias(sql, res_exps));
     736          16 :                         return rel;
     737             :                 }
     738             :         }
     739             :         return NULL;
     740             : }
     741             : 
     742             : sql_exp *
     743       10805 : find_table_function(mvc *sql, char *sname, char *fname, list *exps, list *tl, sql_ftype type)
     744             : {
     745       10805 :         bool found = false;
     746       10805 :         sql_subfunc *f = NULL;
     747             : 
     748       10805 :         assert(type == F_UNION || type == F_LOADER);
     749       10805 :         if ((f = bind_func_(sql, sname, fname, tl, type, false, &found, false))) {
     750       10785 :                 list *nexps = exps;
     751       10785 :                 if (list_empty(tl) || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false)))
     752       10785 :                         return exp_op(sql->sa, nexps, f);
     753           0 :                 found = false;
     754             :         }
     755          20 :         char *arg_list = list_length(tl) ? nary_function_arg_types_2str(sql, tl, list_length(tl)) : NULL;
     756          55 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s %s function %s%s%s'%s'(%s)",
     757          20 :                                          found ? "insufficient privileges for" : "no such", type == F_UNION ? "table returning" : "loader", sname ? "'":"", sname ? sname : "",
     758             :                                          sname ? "'.":"", fname, arg_list ? arg_list : "");
     759             : }
     760             : 
     761             : static sql_rel *
     762       10821 : rel_named_table_function(sql_query *query, sql_rel *rel, symbol *ast, int lateral, list *refs)
     763             : {
     764       10821 :         mvc *sql = query->sql;
     765       10821 :         list *exps = NULL, *tl;
     766       10821 :         node *m;
     767       10821 :         exp_kind ek = {type_value, card_relation, TRUE};
     768       10821 :         sql_rel *sq = NULL, *outer = NULL;
     769       10821 :         sql_exp *e = NULL;
     770       10821 :         sql_subfunc *sf = NULL;
     771       10821 :         symbol *sym = ast->data.lval->h->data.sym, *subquery = NULL;
     772       10821 :         dnode *l = sym->data.lval->h, *n;
     773       10821 :         char *tname = NULL;
     774       10821 :         char *fname = qname_schema_object(l->data.lval);
     775       10821 :         char *sname = qname_schema(l->data.lval);
     776             : 
     777       10821 :         tl = sa_list(sql->sa);
     778       10821 :         exps = sa_list(sql->sa);
     779       10821 :         if (l->next)
     780       10821 :                 l = l->next; /* skip distinct */
     781       10821 :         if (l->next) { /* table call with subquery */
     782       10821 :                 int is_value = 1;
     783       10821 :                 if (l->next->type == type_symbol || l->next->type == type_list) {
     784       10821 :                         exp_kind iek = {type_value, card_set, TRUE};
     785       10821 :                         int count = 0;
     786             : 
     787       10821 :                         if (l->next->type == type_symbol)
     788             :                                 n = l->next;
     789             :                         else
     790       10821 :                                 n = l->next->data.lval?l->next->data.lval->h:NULL;
     791             : 
     792       13505 :                         for (dnode *m = n; m; m = m->next) {
     793        2684 :                                 if (m->type == type_symbol && m->data.sym->token == SQL_SELECT)
     794        2684 :                                         subquery = m->data.sym;
     795        2684 :                                 count++;
     796             :                         }
     797       10821 :                         if (subquery && count > 1)
     798          17 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The input for the table returning function %s%s%s'%s' must be either a single sub query, or a list of values",
     799             :                                                                  sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
     800             : 
     801       10816 :                         if (subquery) {
     802          40 :                                 if (!(sq = rel_subquery(query, subquery, ek)))
     803             :                                         return NULL;
     804             :                                 is_value = 0;
     805             :                         } else {
     806       13399 :                                 for ( ; n; n = n->next) {
     807        2629 :                                         sql_exp *e = rel_value_exp(query, &outer, n->data.sym, sql_sel | sql_from, iek);
     808             : 
     809        2629 :                                         if (!e)
     810             :                                                 return NULL;
     811        2623 :                                         append(exps, e);
     812        2623 :                                         is_value &= exp_is_atom(e);
     813             :                                 }
     814       10770 :                                 if (!is_value || (lateral && outer))
     815          14 :                                         sq = rel_project(sql->sa, NULL, exps);
     816          14 :                                 if (lateral && outer) {
     817           0 :                                         sq = rel_crossproduct(sql->sa, sq, outer, op_join);
     818           0 :                                         set_dependent(sq);
     819           0 :                                         set_processed(sq);
     820             :                                 }
     821             :                         }
     822             :                 }
     823       10809 :                 if (!is_value && (!sq || (!lateral && outer)))
     824           0 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such table returning function %s%s%s'%s'", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
     825       10809 :                 if (!is_value) {
     826          53 :                         if (list_length(exps))
     827          14 :                                 exps = sa_list(sql->sa);
     828         171 :                         for (node *en = sq->exps->h; en; en = en->next) {
     829         118 :                                 sql_exp *e = en->data;
     830             : 
     831         118 :                                 if (!e->alias.label)
     832          28 :                                         exp_label(sql->sa, e, ++sql->label);
     833         118 :                                 sql_exp *ne = exp_ref(sql, e);
     834             :                                 /* allow for table functions with table input */
     835         118 :                                 ne->card = CARD_ATOM;
     836         118 :                                 exp_setname(sql, ne, tname, exp_name(e));
     837         118 :                                 append(exps, ne);
     838         118 :                                 append(tl, exp_subtype(e));
     839             :                         }
     840             :                 } else {
     841       13354 :                         for (node *en = exps->h; en; en = en->next)
     842        2598 :                                 append(tl, exp_subtype(en->data));
     843             :                 }
     844             :         }
     845             : 
     846       10809 :         rel = NULL;
     847       10809 :         if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym)
     848        1219 :                 tname = ast->data.lval->t->data.sym->data.lval->h->data.sval;
     849             :         else
     850        9590 :                 tname = make_label(sql->sa, ++sql->label);
     851             : 
     852       10809 :         if (!sname && strcmp(fname, "file_loader") == 0) {
     853          35 :                 rel = rel_file_loader(sql, exps, tl, tname);
     854          35 :                 if (!rel)
     855             :                         return NULL;
     856       20537 :         } else if (!(e = find_table_function(sql, sname, fname, list_empty(exps) ? NULL : exps, tl, F_UNION)))
     857             :                 return NULL;
     858             : 
     859       10755 :         if (!rel) {
     860       10755 :                 rel = sq;
     861             : 
     862             :                 /* column or table function */
     863       10755 :                 sf = e->f;
     864       10755 :                 if (e->type != e_func || sf->func->type != F_UNION)
     865           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: '%s' does not return a table", exp_func_name(e));
     866             : 
     867       10755 :                 if (sq) {
     868         171 :                         for (node *n = sq->exps->h, *m = sf->func->ops->h ; n && m ; n = n->next, m = m->next) {
     869         118 :                                 sql_exp *e = (sql_exp*) n->data;
     870         118 :                                 sql_arg *a = (sql_arg*) m->data;
     871         118 :                                 if (!exp_subtype(e) && rel_set_type_param(sql, &(a->type), sq, e, 0) < 0)
     872             :                                         return NULL;
     873             :                         }
     874             :                 }
     875             : 
     876             :                 /* for each column add table.column name */
     877       10755 :                 exps = new_exp_list(sql->sa);
     878      106173 :                 for (m = sf->func->res->h; m; m = m->next) {
     879       95418 :                         sql_arg *a = m->data;
     880       95418 :                         sql_exp *e = exp_column(sql->sa, tname, a->name, &a->type, CARD_MULTI, 1, 0, 0);
     881       95418 :                         e->alias.label = -(sql->nid++);
     882             : 
     883       95418 :                         set_basecol(e);
     884       95418 :                         append(exps, e);
     885             :                 }
     886       21457 :                 rel = rel_table_func(sql->sa, rel, e, exps, (sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
     887             :         }
     888       10771 :         if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym && ast->data.lval->t->data.sym->data.lval->h->next->data.lval) {
     889          49 :                 rel = rel_table_optname(sql, rel, ast->data.lval->t->data.sym, refs);
     890       10722 :         } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
     891       10722 :                 if (list_find(refs, tname, (fcmp) &strcmp))
     892           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
     893       10722 :                 list_append(refs, tname);
     894             :         }
     895             :         return rel;
     896             : }
     897             : 
     898             : static sql_exp*
     899        4161 : exp_tuples_set_supertype(mvc *sql, list *tuple_values, sql_exp *tuples)
     900             : {
     901        4161 :         assert(is_values(tuples));
     902        4161 :         list *vals = exp_get_values(tuples);
     903        4161 :         if (!vals || !vals->h)
     904             :                 return NULL;
     905             : 
     906        4161 :         int tuple_width = list_length(tuple_values), i;
     907        4161 :         sql_subtype *types = SA_NEW_ARRAY(sql->sa, sql_subtype, tuple_width);
     908        4161 :         bool *has_type = SA_NEW_ARRAY(sql->sa, bool, tuple_width);
     909        4161 :         node *n;
     910             : 
     911        4161 :         memset(has_type, 0, sizeof(bool)*tuple_width);
     912       13555 :         for(n = tuple_values->h, i = 0; n; n = n->next, i++) {
     913        9394 :                 sql_exp *e = n->data;
     914        9394 :                 if (exp_subtype(e)) {
     915        9392 :                         types[i] = *exp_subtype(e);
     916        9392 :                         has_type[i] = 1;
     917             :                 }
     918             :         }
     919             : 
     920        8324 :         for (node *m = vals->h; m; m = m->next) {
     921        4163 :                 sql_exp *tuple = m->data;
     922        4163 :                 if (is_values(tuple)) {
     923           0 :                         list *exps = tuple->f;
     924           0 :                         for(n = exps->h, i = 0; n; n = n->next, i++) {
     925           0 :                                 sql_subtype *tpe;
     926           0 :                                 sql_exp *e = n->data;
     927             : 
     928           0 :                                 if (has_type[i] && e->type == e_atom && !e->l && !e->r && !e->f && !e->tpe.type) {
     929           0 :                                         if (set_type_param(sql, types+i, e->flag) == 0)
     930           0 :                                                 e->tpe = types[i];
     931             :                                         else
     932             :                                                 return NULL;
     933             :                                 }
     934           0 :                                 tpe = exp_subtype(e);
     935           0 :                                 if (!tpe)
     936             :                                         return NULL;
     937           0 :                                 if (has_type[i] && tpe) {
     938           0 :                                         supertype(types+i, types+i, tpe);
     939             :                                 } else {
     940           0 :                                         has_type[i] = 1;
     941           0 :                                         types[i] = *tpe;
     942             :                                 }
     943             :                         }
     944             :                 } else {
     945        4163 :                         sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
     946             : 
     947       13561 :                         for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
     948        9398 :                                 sql_subtype *tpe;
     949        9398 :                                 sql_exp *e = n->data;
     950             : 
     951        9398 :                                 if (has_type[i] && e->type == e_atom && !e->l && !e->r && !e->f && !e->tpe.type) {
     952           5 :                                         if (set_type_param(sql, types+i, e->flag) == 0)
     953           5 :                                                 e->tpe = types[i];
     954             :                                         else
     955             :                                                 return NULL;
     956             :                                 }
     957        9398 :                                 tpe = exp_subtype(e);
     958        9398 :                                 if (!tpe)
     959             :                                         return NULL;
     960        9398 :                                 if (has_type[i] && tpe) {
     961        9396 :                                         cmp_supertype(types+i, types+i, tpe);
     962             :                                 } else {
     963           2 :                                         has_type[i] = 1;
     964           2 :                                         types[i] = *tpe;
     965             :                                 }
     966             :                         }
     967             :                 }
     968             :         }
     969             : 
     970        8324 :         for (node *m = vals->h; m; m = m->next) {
     971        4163 :                 sql_exp *tuple = m->data;
     972        4163 :                 if (is_values(tuple)) {
     973           0 :                         list *exps = tuple->f;
     974           0 :                         list *nexps = sa_list(sql->sa);
     975           0 :                         for(n = exps->h, i = 0; n; n = n->next, i++) {
     976           0 :                                 sql_exp *e = n->data;
     977             : 
     978           0 :                                 e = exp_check_type(sql, types+i, NULL, e, type_equal);
     979           0 :                                 if (!e)
     980             :                                         return NULL;
     981           0 :                                 exp_label(sql->sa, e, ++sql->label);
     982           0 :                                 append(nexps, e);
     983             :                         }
     984           0 :                         tuple->f = nexps;
     985             :                 } else {
     986        4163 :                         sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
     987             : 
     988        4163 :                         list *nexps = sa_list(sql->sa);
     989       13561 :                         for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
     990        9398 :                                 sql_exp *e = n->data;
     991             : 
     992        9398 :                                 e = exp_check_type(sql, types+i, NULL, e, type_equal);
     993        9398 :                                 if (!e)
     994             :                                         return NULL;
     995        9398 :                                 append(nexps, e);
     996             :                         }
     997        4163 :                         tuple_relation->exps = nexps;
     998             :                 }
     999             :         }
    1000             :         return tuples;
    1001             : }
    1002             : 
    1003             : static int
    1004        9394 : rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int upcast)
    1005             : {
    1006        9394 :         sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs);
    1007             : 
    1008        9394 :         if (!t1 || !t2) {
    1009           2 :                 if (t2 && !t1 && rel_set_type_param(sql, t2, rel, ls, upcast) < 0)
    1010             :                         return -1;
    1011           2 :                 if (t1 && !t2 && rel_set_type_param(sql, t1, rel, rs, upcast) < 0)
    1012             :                         return -1;
    1013             :         }
    1014        9394 :         if (!exp_subtype(ls) && !exp_subtype(rs)) {
    1015           0 :                 (void) sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
    1016           0 :                 return -1;
    1017             :         }
    1018             :         return 0;
    1019             : }
    1020             : 
    1021             : static list *
    1022        4161 : tuples_check_types(mvc *sql, list *tuple_values, sql_exp *tuples)
    1023             : {
    1024        4161 :         list *tuples_list = exp_get_values(tuples);
    1025        4161 :         sql_exp *first_tuple = tuples_list->h->data;
    1026        4161 :         list *nvalues = sa_list(sql->sa);
    1027        4161 :         if (is_values(first_tuple)) {
    1028           0 :                 list *vals = first_tuple->f;
    1029             : 
    1030           0 :                 for (node *n = tuple_values->h, *m = vals->h; n && m; n = n->next, m = m->next) {
    1031           0 :                         sql_exp *le = n->data, *re = m->data;
    1032             : 
    1033           0 :                         if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
    1034             :                                 return NULL;
    1035           0 :                         if ((le = exp_check_type(sql, exp_subtype(re), NULL, le, type_equal)) == NULL)
    1036             :                                 return NULL;
    1037           0 :                         append(nvalues, le);
    1038             :                 }
    1039             :                 return nvalues;
    1040             :         } else {
    1041        4161 :                 sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, first_tuple);
    1042             : 
    1043        4161 :                 assert(list_length(tuple_values) == list_length(tuple_relation->exps));
    1044       13555 :                 for (node *n = tuple_values->h, *m = tuple_relation->exps->h; n && m; n = n->next, m = m->next) {
    1045        9394 :                         sql_exp *le = n->data, *re = m->data;
    1046             : 
    1047        9394 :                         if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
    1048             :                                 return NULL;
    1049        9394 :                         if ((le = exp_check_type(sql, exp_subtype(re), NULL, le, type_equal)) == NULL)
    1050             :                                 return NULL;
    1051        9394 :                         append(nvalues, le);
    1052             :                 }
    1053             :                 return nvalues;
    1054             :         }
    1055             :         return tuple_values;
    1056             : }
    1057             : 
    1058             : static sql_rel *
    1059        3838 : rel_values(sql_query *query, symbol *tableref, list *refs)
    1060             : {
    1061        3838 :         mvc *sql = query->sql;
    1062        3838 :         sql_rel *r = NULL;
    1063        3838 :         symbol *values = tableref;
    1064        3838 :         symbol *optname = NULL;
    1065        3838 :         if (tableref->token == SQL_TABLE) {
    1066        1333 :                 values = tableref->data.lval->h->data.sym;
    1067        1333 :                 optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
    1068             :         }
    1069        3838 :         dlist *rowlist = values->data.lval;
    1070        3838 :         node *m;
    1071        3838 :         list *exps = sa_list(sql->sa);
    1072        3838 :         exp_kind ek = {type_value, card_value, TRUE};
    1073             : 
    1074       15401 :         for (dnode *o = rowlist->h; o; o = o->next) {
    1075       11573 :                 dlist *values = o->data.lval;
    1076             : 
    1077       11573 :                 if (!list_empty(exps) && list_length(exps) != dlist_length(values)) {
    1078           3 :                         return sql_error(sql, 02, SQLSTATE(42000) "VALUES: number of columns doesn't match between rows");
    1079             :                 } else {
    1080       11570 :                         dnode *n;
    1081             : 
    1082       11570 :                         if (list_empty(exps)) {
    1083       10990 :                                 for (n = values->h; n; n = n->next) {
    1084        7152 :                                         sql_exp *vals = exp_values(sql->sa, sa_list(sql->sa));
    1085             : 
    1086        7152 :                                         exp_label(sql->sa, vals, ++sql->label);
    1087        7152 :                                         list_append(exps, vals);
    1088             :                                 }
    1089             :                         }
    1090       35466 :                         for (n = values->h, m = exps->h; n && m; n = n->next, m = m->next) {
    1091       23903 :                                 sql_exp *vals = m->data;
    1092       23903 :                                 list *vals_list = vals->f;
    1093       23903 :                                 sql_exp *e = rel_value_exp(query, NULL, n->data.sym, sql_sel | sql_values, ek);
    1094       23902 :                                 if (!e)
    1095             :                                         return NULL;
    1096       23895 :                                 list_append(vals_list, e);
    1097             :                         }
    1098             :                 }
    1099             :         }
    1100             : 
    1101             :         /* loop to check types and cardinality */
    1102        3828 :         unsigned int card = exps->h && list_length(((sql_exp*)exps->h->data)->f) > 1 ? CARD_MULTI : CARD_ATOM;
    1103       10963 :         for (m = exps->h; m; m = m->next) {
    1104        7138 :                 sql_exp *e = m->data;
    1105             : 
    1106        7138 :                 if (!(e = exp_values_set_supertype(sql, e, NULL)))
    1107             :                         return NULL;
    1108        7135 :                 e->card = card;
    1109        7135 :                 m->data = e;
    1110             :         }
    1111             : 
    1112        3825 :         r = rel_project(sql->sa, NULL, exps);
    1113        3825 :         r->nrcols = list_length(exps);
    1114        3825 :         r->card = card;
    1115        3825 :         return rel_table_optname(sql, r, optname, refs);
    1116             : }
    1117             : 
    1118             : static int
    1119      509423 : check_is_lateral(symbol *tableref)
    1120             : {
    1121      509423 :         if (tableref->token == SQL_NAME || tableref->token == SQL_TABLE ||
    1122             :                 tableref->token == SQL_VALUES) {
    1123      458966 :                 if (dlist_length(tableref->data.lval) == 3)
    1124      458968 :                         return tableref->data.lval->h->next->data.i_val;
    1125             :                 return 0;
    1126             :         } else if (tableref->token == SQL_WITH) {
    1127         981 :                 if (dlist_length(tableref->data.lval) == 5)
    1128          16 :                         return tableref->data.lval->h->next->next->next->data.i_val;
    1129             :                 return 0;
    1130             :         } else if (tableref->token == SQL_SELECT) {
    1131        2292 :                 SelectNode *sn = (SelectNode *) tableref;
    1132        2292 :                 return sn->lateral;
    1133             :         } else if (tableref->token == SQL_EXCEPT || tableref->token == SQL_INTERSECT ||
    1134             :                            tableref->token == SQL_UNION) {
    1135       10990 :                 if (dlist_length(tableref->data.lval) == 6)
    1136        9253 :                         return tableref->data.lval->h->next->next->next->next->data.i_val;
    1137             :                 return 0;
    1138             :         } else {
    1139             :                 return 0;
    1140             :         }
    1141             : }
    1142             : 
    1143             : static sql_rel *
    1144          25 : rel_reduce_on_column_privileges(mvc *sql, sql_rel *rel, sql_table *t)
    1145             : {
    1146          25 :         list *exps = sa_list(sql->sa);
    1147             : 
    1148          99 :         for (node *n = rel->exps->h, *m = ol_first_node(t->columns); n && m; n = n->next, m = m->next) {
    1149          74 :                 sql_exp *e = n->data;
    1150          74 :                 sql_column *c = m->data;
    1151             : 
    1152          74 :                 if (column_privs(sql, c, PRIV_SELECT))
    1153          12 :                         append(exps, e);
    1154             :         }
    1155          25 :         if (!list_empty(exps)) {
    1156           9 :                 rel->exps = exps;
    1157           9 :                 return rel;
    1158             :         }
    1159             :         return NULL;
    1160             : }
    1161             : 
    1162             : sql_rel *
    1163      697997 : table_ref(sql_query *query, symbol *tableref, int lateral, list *refs)
    1164             : {
    1165      697997 :         mvc *sql = query->sql;
    1166      697997 :         char *tname = NULL;
    1167      697997 :         sql_table *t = NULL;
    1168      697997 :         sql_rel *res = NULL;
    1169             : 
    1170      697997 :         if (tableref->token == SQL_NAME) {
    1171      480255 :                 dlist *name = tableref->data.lval->h->data.lval;
    1172      480255 :                 sql_rel *temp_table = NULL;
    1173      480255 :                 char *sname = qname_schema(name);
    1174      480271 :                 int allowed = 1;
    1175             : 
    1176      480271 :                 tname = qname_schema_object(name);
    1177             : 
    1178      480268 :                 if (dlist_length(name) > 2)
    1179           4 :                         return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: only a schema and table name expected");
    1180             : 
    1181      480258 :                 if (!sname)
    1182      109940 :                         temp_table = stack_find_rel_view(sql, tname);
    1183      109940 :                 if (!temp_table)
    1184      467423 :                         t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false);
    1185      480258 :                 if (!t && !temp_table)
    1186             :                         return NULL;
    1187      480151 :                 if (!temp_table && !table_privs(sql, t, PRIV_SELECT))
    1188      480147 :                         allowed = 0;
    1189             : 
    1190      480147 :                 if (tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym) /* AS */
    1191      283679 :                         tname = tableref->data.lval->t->data.sym->data.lval->h->data.sval;
    1192      480147 :                 if (temp_table && !t) {
    1193       12833 :                         node *n;
    1194       12833 :                         int needed = !is_simple_project(temp_table->op);
    1195             : 
    1196       12833 :                         if (is_basetable(temp_table->op) && !temp_table->exps) {
    1197           0 :                                 if (strcmp(rel_base_name(temp_table), tname) != 0)
    1198           0 :                                         rel_base_rename(temp_table, tname);
    1199             :                         } else {
    1200       42024 :                                 for (n = temp_table->exps->h; n && !needed; n = n->next) {
    1201       29191 :                                         sql_exp *e = n->data;
    1202             : 
    1203       29191 :                                         if (!exp_relname(e) || strcmp(exp_relname(e), tname) != 0)
    1204             :                                                 needed = 1;
    1205             :                                 }
    1206             : 
    1207       12833 :                                 if (needed) {
    1208        5767 :                                         list *exps = rel_projections(sql, temp_table, NULL, 1, 1);
    1209             : 
    1210        5767 :                                         temp_table = rel_project(sql->sa, temp_table, exps);
    1211       18548 :                                         for (n = exps->h; n; n = n->next) {
    1212       12781 :                                                 sql_exp *e = n->data;
    1213             : 
    1214       12781 :                                                 noninternexp_setname(sql, e, tname, NULL);
    1215       12781 :                                                 set_basecol(e);
    1216             :                                         }
    1217        5767 :                                         list_hash_clear(exps);
    1218             :                                 }
    1219             :                         }
    1220       12833 :                         if (temp_table && tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym && tableref->data.lval->t->data.sym->data.lval->h->next->data.lval) /* AS with column aliases */
    1221          10 :                                 temp_table = rel_table_optname(sql, temp_table, tableref->data.lval->t->data.sym, refs);
    1222       12833 :                         if (allowed)
    1223             :                                 return temp_table;
    1224           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to table '%s'", get_string_global_var(sql, "current_user"), tname);
    1225      467314 :                 } else if (isView(t)) {
    1226             :                         /* instantiate base view */
    1227       71331 :                         node *n,*m;
    1228       71331 :                         sql_rel *rel;
    1229             : 
    1230       71331 :                         if (sql->emode == m_deps) {
    1231       25016 :                                 rel = rel_basetable(sql, t, tname);
    1232       25016 :                                 if (!allowed)
    1233           0 :                                         rel_base_disallow(rel);
    1234             :                         } else {
    1235             :                                 /* when recreating a view, the view itself can't be found */
    1236       46315 :                                 if (sql->objid && sql->objid == t->base.id)
    1237           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: attempting to recursively bind view '%s'.'%s'", t->s->base.name, tname);
    1238       46314 :                                 rel = rel_parse(sql, t->s, t->query, m_instantiate);
    1239       46314 :                                 if (rel && sql->emode == m_deps)
    1240           0 :                                         rel = rel_unnest(sql, rel);
    1241             :                         }
    1242             : 
    1243       71328 :                         if (!rel)
    1244           2 :                                 return NULL;
    1245             :                         /* Rename columns of the rel_parse relation */
    1246       71328 :                         if (sql->emode != m_deps) {
    1247       46312 :                                 assert(is_project(rel->op));
    1248       46312 :                                 set_processed(rel);
    1249       46312 :                                 if (is_mset(rel->op) || is_simple_project(rel->op) || (is_groupby(rel->op) && !list_empty(rel->r))) {
    1250             :                                         /* it's unsafe to set the projection names because of possible dependent sorting/grouping columns */
    1251       46312 :                                         rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 0, 0));
    1252       46312 :                                         set_processed(rel);
    1253             :                                 }
    1254      416698 :                                 for (n = ol_first_node(t->columns), m = rel->exps->h; n && m; n = n->next, m = m->next) {
    1255      370386 :                                         sql_column *c = n->data;
    1256      370386 :                                         sql_exp *e = m->data;
    1257             : 
    1258      370386 :                                         exp_setname(sql, e, tname, c->base.name);
    1259      370386 :                                         set_basecol(e);
    1260             :                                 }
    1261       46312 :                                 list_hash_clear(rel->exps);
    1262             :                         }
    1263       71328 :                         if (rel && !allowed && t->query && (rel = rel_reduce_on_column_privileges(sql, rel, t)) == NULL)
    1264          16 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to view '%s.%s'", get_string_global_var(sql, "current_user"), t->s->base.name, tname);
    1265       71312 :                         return rel;
    1266             :                 }
    1267      395983 :                 if ((isMergeTable(t) || isReplicaTable(t)) && list_length(t->members)==0)
    1268          14 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s '%s'.'%s' should have at least one table associated",
    1269          14 :                                                         TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->s->base.name, tname);
    1270      395969 :                 res = rel_basetable(sql, t, tname);
    1271      395982 :                 if (!allowed) {
    1272          53 :                         rel_base_disallow(res);
    1273          53 :                         if (rel_base_has_column_privileges(sql, res) == 0)
    1274          62 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: access denied for %s to %s '%s.%s'", get_string_global_var(sql, "current_user"), isView(t) ? "view" : "table", t->s->base.name, tname);
    1275             :                 }
    1276      395951 :                 if (tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym && tableref->data.lval->t->data.sym->data.lval->h->next->data.lval) { /* AS with column aliases */
    1277          12 :                         res = rel_table_optname(sql, res, tableref->data.lval->t->data.sym, refs);
    1278      395939 :                 } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
    1279      395934 :                         if (list_find(refs, tname, (fcmp) &strcmp))
    1280           7 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: relation name \"%s\" specified more than once", tname);
    1281      395927 :                         assert(tname);
    1282      395927 :                         list_append(refs, tname);
    1283             :                 }
    1284      395944 :                 return res;
    1285      217742 :         } else if (tableref->token == SQL_VALUES || (tableref->token == SQL_TABLE && tableref->data.lval->h->data.sym->token == SQL_VALUES)) {
    1286        1370 :                 return rel_values(query, tableref, refs);
    1287      216372 :         } else if (tableref->token == SQL_TABLE) {
    1288       10821 :                 return rel_named_table_function(query, NULL, tableref, lateral, refs);
    1289             :         } else if (tableref->token == SQL_SELECT) {
    1290      101908 :                 return rel_subquery_optname(query, tableref, refs);
    1291             :         } else if (tableref->token == SQL_UNION || tableref->token == SQL_EXCEPT || tableref->token == SQL_INTERSECT) {
    1292             :                 /* subqueries will be called, ie no need to test for duplicate references */
    1293       43289 :                 sql_rel *tq = rel_setquery(query, tableref);
    1294             : 
    1295       43289 :                 if (!tq)
    1296             :                         return NULL;
    1297             :                 /* look for lateral joins */
    1298       43282 :                 symbol *optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
    1299       43282 :                 return rel_table_optname(sql, tq, optname, refs);
    1300             :         } else {
    1301       60354 :                 return query_exp_optname(query, tableref, refs);
    1302             :         }
    1303             : }
    1304             : 
    1305             : static sql_exp *
    1306      122379 : rel_exp_variable_on_scope(mvc *sql, const char *sname, const char *vname)
    1307             : {
    1308      122379 :         sql_subtype *tpe = NULL;
    1309      122379 :         sql_var *var = NULL;
    1310      122379 :         sql_arg *a = NULL;
    1311      122379 :         int level = 1;
    1312             : 
    1313      122379 :         if (find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SELECT")) {
    1314      121432 :                 if (var) /* if variable is known from the stack or a global var */
    1315       37504 :                         return exp_param_or_declared(sql->sa, var->sname ? sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, var->name), &(var->var.tpe), level);
    1316       88926 :                 if (a) /* if variable is a parameter */
    1317       88926 :                         return exp_param_or_declared(sql->sa, NULL, sa_strdup(sql->sa, vname), &(a->type), level);
    1318             :         }
    1319             :         return NULL;
    1320             : }
    1321             : 
    1322             : static sql_exp *
    1323        9257 : exps_get_exp(list *exps, int nth)
    1324             : {
    1325        9257 :         node *n = NULL;
    1326        9257 :         int i = 0;
    1327             : 
    1328        9257 :         if (exps)
    1329       27180 :                 for (n=exps->h, i=1; n && i<nth; n=n->next, i++)
    1330             :                         ;
    1331        9257 :         if (n && i == nth)
    1332        9254 :                 return n->data;
    1333             :         return NULL;
    1334             : }
    1335             : 
    1336             : static sql_rel *
    1337       30955 : rel_find_groupby(sql_rel *groupby)
    1338             : {
    1339       30955 :         if (groupby && !is_processed(groupby) && !is_base(groupby->op)) {
    1340       40640 :                 while(!is_processed(groupby) && !is_base(groupby->op)) {
    1341       32767 :                         if (is_groupby(groupby->op) || !groupby->l)
    1342             :                                 break;
    1343             :                         if (groupby->l)
    1344             :                                 groupby = groupby->l;
    1345             :                 }
    1346       30830 :                 if (groupby && is_groupby(groupby->op))
    1347       22957 :                         return groupby;
    1348             :         }
    1349             :         return NULL;
    1350             : }
    1351             : 
    1352             : static int
    1353         307 : is_groupby_col(sql_rel *gb, sql_exp *e)
    1354             : {
    1355         307 :         gb = rel_find_groupby(gb);
    1356             : 
    1357         307 :         if (gb) {
    1358         174 :                 if (exp_relname(e)) {
    1359         163 :                         if (exp_name(e) && exps_bind_column2(gb->r, exp_relname(e), exp_name(e), NULL))
    1360             :                                 return 1;
    1361             :                 } else {
    1362          11 :                         if (exp_name(e) && exps_bind_column(gb->r, exp_name(e), NULL, NULL, 1))
    1363             :                                 return 1;
    1364             :                 }
    1365             :         }
    1366             :         return 0;
    1367             : }
    1368             : 
    1369             : static void
    1370        4814 : set_dependent_( sql_rel *r)
    1371             : {
    1372        4814 :         if (is_select(r->op))
    1373        3642 :                 r = r->l;
    1374        4814 :         if (r && is_join(r->op))
    1375        1226 :                 set_dependent(r);
    1376        4814 : }
    1377             : 
    1378             : static
    1379          15 : sql_rel* find_union(visitor *v, sql_rel *rel) {
    1380          15 :         if (rel->op == op_union || rel->op == op_munion)
    1381           1 :                 v->data = rel;
    1382          15 :         return rel;
    1383             : }
    1384             : 
    1385             : static inline
    1386          54 : bool group_by_pk_project_uk_cond(mvc* sql, sql_rel* inner, sql_exp* exp,const char* sname, const char* tname) {
    1387          54 :         sql_table* t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false);
    1388          54 :         bool allow = false;
    1389          54 :         if (t) {
    1390          17 :                 sql_idx* pki = NULL;
    1391          17 :                 list *ukil = sa_list(sql->sa);
    1392             : 
    1393          23 :                 for (node * n = ol_first_node(t->idxs); n; n = n->next) {
    1394           6 :                         sql_idx *i = n->data;
    1395           6 :                         if (!i->key)
    1396           1 :                                 continue;
    1397           5 :                         switch (i->key->type) {
    1398           3 :                         case pkey:
    1399           3 :                                 pki = i;
    1400           3 :                                 continue;
    1401           2 :                         case ukey:
    1402             :                         case unndkey:
    1403           2 :                                 list_append(ukil, i);
    1404           2 :                                 continue;
    1405           0 :                         default:
    1406           0 :                                 continue;
    1407             :                         }
    1408             :                 }
    1409          17 :                 if (pki && pki->columns->cnt == 1 && inner->r && ((list*) inner->r)->cnt == 1) {
    1410             :                         /* for now only check simple case where primary key and group by expression is a single column*/
    1411           3 :                         sql_exp* gbe = ((list*) inner->r)->h->data;
    1412           3 :                         sql_column* pkc = ((sql_kc *)pki->columns->h->data)->c;
    1413           3 :                         if (gbe->type == e_column && strcmp(gbe->alias.name, pkc->base.name) == 0) {
    1414           2 :                                 node *n;
    1415           2 :                                 for (n = ukil->h; n; n = n->next){
    1416           2 :                                         sql_idx* uki = n->data;
    1417           2 :                                         if (uki->columns->cnt == 1) {
    1418             :                                                 /* for now only check simple case where unique key is a single column*/
    1419           2 :                                                 sql_column* ukc = ((sql_kc *)uki->columns->h->data)->c;
    1420           2 :                                                 if (strcmp(exp->alias.name, ukc->base.name) == 0) {
    1421             :                                                         allow = true;
    1422             :                                                         break;
    1423             :                                                 }
    1424             :                                         }
    1425             :                                 }
    1426             :                         }
    1427             :                 }
    1428             : 
    1429           2 :                 if (allow) {
    1430             :                         /* sufficiency condition: abort if relation contains union subrelation
    1431             :                         * because it may break functional dependency between pk and uk */
    1432           2 :                         visitor v = {.sql=sql};
    1433           2 :                         rel_visitor_topdown(&v, inner, &find_union);
    1434           2 :                         if (v.data)
    1435           1 :                                 allow = false;
    1436             :                 }
    1437             :         }
    1438             : 
    1439          54 :         return allow;
    1440             : 
    1441             : }
    1442             : 
    1443             : static sql_exp *
    1444     2386517 : rel_column_ref(sql_query *query, sql_rel **rel, symbol *column_r, int f)
    1445             : {
    1446     2386517 :         mvc *sql = query->sql;
    1447     2386517 :         sql_exp *exp = NULL;
    1448     2386517 :         dlist *l = NULL;
    1449     2386517 :         sql_rel *inner = rel?*rel:NULL, *outer = NULL;
    1450     2386517 :         int used_lower_after_processed = 0;
    1451             : 
    1452     2386517 :         assert((column_r->token == SQL_COLUMN || column_r->token == SQL_IDENT) && column_r->type == type_list);
    1453     2386517 :         l = column_r->data.lval;
    1454             : 
    1455     2386517 :         if (dlist_length(l) == 1) {
    1456     1101018 :                 const char *name = l->h->data.sval;
    1457     1101018 :                 if (!name)
    1458             :                         return NULL;
    1459             : 
    1460     1101018 :                 if (!exp && inner)
    1461     1005271 :                         if (!(exp = rel_bind_column(sql, inner, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    1462             :                                 return NULL;
    1463     1101004 :                 if (!exp && inner && ((is_sql_aggr(f) && (is_groupby(inner->op) || is_select(inner->op))) ||
    1464       24027 :                                                      (is_groupby(inner->op) && inner->flag))) {
    1465             :                         /* if inner is selection, ie having clause, get the left relation to reach group by */
    1466             :                         sql_rel *gp = inner;
    1467         258 :                         while (gp && is_select(gp->op))
    1468          27 :                                 gp = gp->l;
    1469         231 :                         if (gp && !is_basetable(gp->op) && gp->l && !(exp = rel_bind_column(sql, gp->l, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    1470             :                                 return NULL;
    1471             :                 }
    1472     1101004 :                 if (!exp && query && query_has_outer(query)) {
    1473         472 :                         int i;
    1474             : 
    1475         525 :                         for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
    1476         496 :                                 if (!(exp = rel_bind_column(sql, outer, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    1477             :                                         return NULL;
    1478          84 :                                 if (!exp && is_groupby(outer->op)) {
    1479          31 :                                         if (!(exp = rel_bind_column(sql, outer->l, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    1480             :                                                 return NULL;
    1481             :                                         else
    1482          31 :                                                 used_lower_after_processed = is_processed(outer);
    1483             :                                 }
    1484         496 :                                 if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
    1485           0 :                                         exp = rel_project_add_exp(sql, outer, exp);
    1486         443 :                                 if (exp)
    1487             :                                         break;
    1488             :                         }
    1489         472 :                         if (exp && exp->card != CARD_AGGR && is_groupby(outer->op) && !is_sql_aggr(f) && rel_find_exp(outer->l, exp))
    1490           5 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
    1491         467 :                         if (exp && outer && outer->card <= CARD_AGGR && exp->card > CARD_AGGR && !is_sql_aggr(f))
    1492           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
    1493         467 :                         if (exp && outer && !is_sql_aggr(f) && !is_sql_aggr(query_fetch_outer_state(query, i))) {
    1494         299 :                                 if (used_lower_after_processed || query_outer_used_exp( query, i, exp, f)) {
    1495           0 :                                         sql_exp *lu = used_lower_after_processed?exp:query_outer_last_used(query, i);
    1496           0 :                                         if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
    1497           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
    1498           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    1499             :                                 }
    1500             :                         }
    1501         467 :                         if (exp) {
    1502         438 :                                 int of = query_fetch_outer_state(query, i);
    1503         438 :                                 if (is_groupby(outer->op) && !is_sql_aggr(f)) {
    1504          37 :                                         exp = rel_groupby_add_aggr(sql, outer, exp);
    1505          37 :                                         exp->card = CARD_ATOM;
    1506         401 :                                 } else if (is_groupby(outer->op) && is_sql_aggr(f) && exps_any_match(outer->exps, exp))
    1507          57 :                                         exp = exp_ref(sql, exp);
    1508             :                                 else
    1509         344 :                                         exp->card = CARD_ATOM;
    1510         438 :                                 set_freevar(exp, i);
    1511             :                                 /*
    1512             :                                 if (exp->alias.label == exp->nid)
    1513             :                                         exp->alias.label = -(sql->nid++);
    1514             :                                         */
    1515         438 :                                 if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
    1516         147 :                                         set_outer(outer);
    1517             :                         }
    1518         467 :                         if (exp && outer && (is_select(outer->op) || is_join(outer->op)))
    1519          43 :                                 set_dependent_(outer);
    1520             :                 }
    1521             : 
    1522             :                 /* some views are just in the stack, like before and after updates views */
    1523     1100999 :                 if (rel && sql->use_views) {
    1524          13 :                         sql_rel *v = NULL;
    1525          13 :                         int dup = stack_find_rel_view_projection_columns(sql, name, &v); /* trigger views are basetables relations, so those may conflict */
    1526             : 
    1527          13 :                         if (dup < 0 || (v && exp && *rel && is_base(v->op) && v != *rel)) /* comparing pointers, ugh */
    1528           2 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", name);
    1529          11 :                         if (v && !exp) {
    1530           4 :                                 if (*rel)
    1531           1 :                                         *rel = rel_crossproduct(sql->sa, *rel, rel_dup(v), op_join);
    1532             :                                 else
    1533           3 :                                         *rel = rel_dup(v);
    1534           4 :                                 exp = rel_bind_column(sql, *rel, name, f, 0);
    1535             :                         }
    1536             :                 }
    1537     1100997 :                 if (!exp) /* If no column was found, try a variable or parameter */
    1538      119360 :                         exp = rel_exp_variable_on_scope(sql, NULL, name);
    1539             : 
    1540      119360 :                 if (!exp) {
    1541         947 :                         if (inner && !is_sql_aggr(f) && is_groupby(inner->op) && inner->l && (exp = rel_bind_column(sql, inner->l, name, f, 0)))
    1542          47 :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
    1543             :                 }
    1544             : 
    1545     1100050 :                 if (!exp)
    1546         900 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: identifier '%s' unknown", name);
    1547     1100050 :                 if (exp && inner && inner->card <= CARD_AGGR && exp->card > CARD_AGGR && (is_sql_sel(f) || is_sql_having(f)) && (!is_sql_aggr(f) && !(inner->flag)))
    1548           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", name);
    1549     1100050 :                 if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp) && !inner->flag)
    1550       26122 :                         exp = rel_groupby_add_aggr(sql, inner, exp);
    1551     1285499 :         } else if (dlist_length(l) == 2 || dlist_length(l) == 3) {
    1552     1285499 :                 const char *sname = NULL;
    1553     1285499 :                 const char *tname = l->h->data.sval;
    1554     1285499 :                 const char *cname = l->h->next->data.sval;
    1555     1285499 :                 if (dlist_length(l) == 3) {
    1556           1 :                         sname = l->h->data.sval;
    1557           1 :                         tname = l->h->next->data.sval;
    1558           1 :                         cname = l->h->next->next->data.sval;
    1559             :                 }
    1560     1285499 :                 if (!cname)
    1561             :                         return NULL;
    1562             : 
    1563     1270943 :                 if (!exp && rel && inner)
    1564     1270816 :                         if (!(exp = rel_bind_column3(sql, inner, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
    1565             :                                 return NULL;
    1566     1270942 :                 if (!exp && inner && is_sql_aggr(f) && (is_groupby(inner->op) || is_select(inner->op))) {
    1567             :                         /* if inner is selection, ie having clause, get the left relation to reach group by */
    1568             :                         sql_rel *gp = inner;
    1569          59 :                         while (gp && is_select(gp->op))
    1570           5 :                                 gp = gp->l;
    1571          54 :                         if (gp && !is_basetable(gp->op) && gp->l && !(exp = rel_bind_column3(sql, gp->l, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
    1572             :                                 return NULL;
    1573             :                 }
    1574     1270942 :                 if (!exp && query && query_has_outer(query)) {
    1575       12008 :                         int i;
    1576             : 
    1577       12218 :                         for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
    1578       12217 :                                 if (!(exp = rel_bind_column3(sql, outer, sname, tname, cname, f | sql_outer)) && sql->session->status == -ERR_AMBIGUOUS)
    1579             :                                         return NULL;
    1580         293 :                                 if (!exp && is_groupby(outer->op)) {
    1581         102 :                                         if (!(exp = rel_bind_column3(sql, outer->l, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
    1582             :                                                 return NULL;
    1583             :                                         else
    1584         102 :                                                 used_lower_after_processed = is_processed(outer);
    1585             :                                 }
    1586       12217 :                                 if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
    1587           0 :                                         exp = rel_project_add_exp(sql, outer, exp);
    1588       12007 :                                 if (exp)
    1589             :                                         break;
    1590             :                         }
    1591       12008 :                         if (exp && exp->card != CARD_AGGR && is_groupby(outer->op) && !is_sql_aggr(f) && rel_find_exp(outer->l, exp))
    1592           6 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
    1593       12002 :                         if (exp && outer && outer->card <= CARD_AGGR && exp->card > CARD_AGGR && !is_sql_aggr(f))
    1594           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
    1595       12002 :                         if (exp && outer && !is_sql_aggr(f)) {
    1596       11725 :                                 if (used_lower_after_processed || query_outer_used_exp( query, i, exp, f)) {
    1597           0 :                                         sql_exp *lu = used_lower_after_processed?exp:query_outer_last_used(query, i);
    1598           0 :                                         if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
    1599           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
    1600           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    1601             :                                 }
    1602             :                         }
    1603       12002 :                         if (exp) {
    1604       12001 :                                 int of = query_fetch_outer_state(query, i);
    1605       12001 :                                 if (is_groupby(outer->op) && !is_sql_aggr(f)) {
    1606          64 :                                         exp = rel_groupby_add_aggr(sql, outer, exp);
    1607          64 :                                         exp->card = CARD_ATOM;
    1608       11937 :                                 } else if (is_groupby(outer->op) && is_sql_aggr(f) && exps_any_match(outer->exps, exp))
    1609          52 :                                         exp = exp_ref(sql, exp);
    1610             :                                 else
    1611       11885 :                                         exp->card = CARD_ATOM;
    1612       12001 :                                 set_freevar(exp, i);
    1613             :                                 /*
    1614             :                                 if (exp->alias.label == exp->nid)
    1615             :                                         exp->alias.label = -(sql->nid++);
    1616             :                                         */
    1617       12001 :                                 if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
    1618       10289 :                                         set_outer(outer);
    1619             :                         }
    1620       12002 :                         if (exp && outer && (is_select(outer->op) || is_join(outer->op)))
    1621        4771 :                                 set_dependent_(outer);
    1622             :                 }
    1623             : 
    1624             :                 /* some views are just in the stack, like before and after updates views */
    1625     1270936 :                 if (rel && sql->use_views) {
    1626          40 :                         sql_rel *v = stack_find_rel_view(sql, tname);
    1627             : 
    1628          40 :                         if (v && exp && *rel && is_base(v->op) && v != *rel) /* trigger views are basetables relations, so those may conflict */
    1629           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s.%s' ambiguous", tname, cname);
    1630          40 :                         if (v && !exp) {
    1631          20 :                                 if (*rel)
    1632           0 :                                         *rel = rel_crossproduct(sql->sa, *rel, rel_dup(v), op_join);
    1633             :                                 else
    1634          20 :                                         *rel = rel_dup(v);
    1635          20 :                                 if (!(exp = rel_bind_column3(sql, *rel, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
    1636             :                                         return NULL;
    1637             :                         }
    1638             :                 }
    1639     1270916 :                 if (!exp) { /* If no column was found, try a global variable */
    1640       67016 :                         sql_var *var = NULL;
    1641       67016 :                         sql_subtype *tpe = NULL;
    1642       67016 :                         int level = 0;
    1643       67016 :                         sql_arg *a = NULL;
    1644             : 
    1645       67016 :                         if (find_variable_on_scope(sql, tname, cname, &var, &a, &tpe, &level, "SELECT")) { /* search schema with table name, ugh */
    1646          10 :                                 assert(level == 0);
    1647          10 :                                 exp = exp_param_or_declared(sql->sa, sa_strdup(sql->sa, var->sname), sa_strdup(sql->sa, var->name), &(var->var.tpe), 0);
    1648             :                         }
    1649             :                 }
    1650       67016 :                 if (!exp) {
    1651       67006 :                         if (inner && !is_sql_aggr(f) && is_groupby(inner->op) && inner->l && (exp = rel_bind_column3(sql, inner->l, sname, tname, cname, f))) {
    1652          54 :                                 if (group_by_pk_project_uk_cond(sql, inner, exp, sname, tname)) {
    1653             :                                         /* SQL23 feature: very special case where primary key is used in GROUP BY expression and
    1654             :                                          * unique key is in the project list or ORDER BY clause */
    1655           1 :                                         sql->session->status = 0;
    1656           1 :                                         sql->errstr[0] = 0;
    1657           1 :                                         exp->card = CARD_AGGR;
    1658           1 :                                         list_append(inner->exps, exp);
    1659             :                                 }
    1660             :                                 else
    1661          53 :                                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
    1662             :                         }
    1663             :                 }
    1664             : 
    1665           1 :                 if (!exp)
    1666       66952 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "SELECT: no such column '%s.%s'", tname, cname);
    1667     1203931 :                 if (exp && inner && inner->card <= CARD_AGGR && exp->card > CARD_AGGR && (is_sql_sel(f) || is_sql_having(f)) && !is_sql_aggr(f))
    1668           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", tname, cname);
    1669     1203931 :                 if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp))
    1670       17530 :                         exp = rel_groupby_add_aggr(sql, inner, exp);
    1671           0 :         } else if (dlist_length(l) > 3) {
    1672           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "cross-database references are not implemented");
    1673             :         }
    1674     2303981 :         if (exp && !exp_is_atom(exp) && rel && !outer) {
    1675     2173125 :                 if (query->last_exp && query->last_rel == *rel && !is_sql_aggr(query->last_state) && is_sql_aggr(f)) {
    1676          55 :                         if (!is_groupby(query->last_rel->op) || list_empty(query->last_rel->r) || !exps_find_exp(query->last_rel->r, query->last_exp)) {
    1677          34 :                                 if (exp_relname(query->last_exp) && exp_name(query->last_exp) && !has_label(query->last_exp))
    1678          34 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(query->last_exp), exp_name(query->last_exp));
    1679           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    1680             :                         }
    1681             :                 }
    1682     2173091 :                 query->prev = query->last_exp;
    1683     2173091 :                 query->last_exp = exp;
    1684     2173091 :                 query->last_state = f;
    1685     2173091 :                 query->last_rel = *rel;
    1686             :         }
    1687             :         return exp;
    1688             : }
    1689             : 
    1690             : int
    1691     1006204 : rel_convert_types(mvc *sql, sql_rel *ll, sql_rel *rr, sql_exp **L, sql_exp **R, int scale_fixing, check_type tpe)
    1692             : {
    1693     1006204 :         sql_exp *ls = *L;
    1694     1006204 :         sql_exp *rs = *R;
    1695     1006204 :         sql_subtype *lt = exp_subtype(ls);
    1696     1006204 :         sql_subtype *rt = exp_subtype(rs);
    1697             : 
    1698     1006204 :         if (!rt && !lt) {
    1699           2 :                 sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
    1700           2 :                 return -1;
    1701             :         }
    1702     1006202 :         if (rt && (!lt || !lt->type))
    1703           7 :                  return rel_set_type_param(sql, rt, ll, ls, 0);
    1704     1006195 :         if (lt && (!rt || !rt->type))
    1705         648 :                  return rel_set_type_param(sql, lt, rr, rs, 0);
    1706             : 
    1707     1005547 :         if (rt && lt) {
    1708     1005547 :                 sql_subtype *i = lt;
    1709     1005547 :                 sql_subtype *r = rt;
    1710             : 
    1711     1005547 :                 if (subtype_cmp(lt, rt) != 0 || (tpe == type_equal_no_any && (lt->type->localtype==0 || rt->type->localtype==0))) {
    1712      277551 :                         sql_subtype super;
    1713             : 
    1714      277551 :                         cmp_supertype(&super, r, i);
    1715      277551 :                         if (scale_fixing) {
    1716             :                                 /* convert ls to super type */
    1717      277551 :                                 ls = exp_check_type(sql, &super, ll, ls, tpe);
    1718             :                                 /* convert rs to super type */
    1719      277551 :                                 rs = exp_check_type(sql, &super, rr, rs, tpe);
    1720             :                         } else {
    1721             :                                 /* convert ls to super type */
    1722           0 :                                 super.scale = lt->scale;
    1723           0 :                                 ls = exp_check_type(sql, &super, ll, ls, tpe);
    1724             :                                 /* convert rs to super type */
    1725           0 :                                 super.scale = rt->scale;
    1726           0 :                                 rs = exp_check_type(sql, &super, rr, rs, tpe);
    1727             :                         }
    1728             :                 }
    1729     1005547 :                 *L = ls;
    1730     1005547 :                 *R = rs;
    1731     1005547 :                 if (!ls || !rs)
    1732             :                         return -1;
    1733             :                 return 0;
    1734             :         }
    1735             :         return -1;
    1736             : }
    1737             : 
    1738             : static sql_rel *
    1739      108038 : push_select_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *ls, int f)
    1740             : {
    1741      108038 :         if (is_outerjoin(rel->op)) {
    1742        1182 :                 if ((is_left(rel->op) || is_full(rel->op)) && rel_find_exp(rel->l, ls)) {
    1743          38 :                         rel_join_add_exp(sql->sa, rel, e);
    1744          38 :                         return rel;
    1745        1144 :                 } else if ((is_right(rel->op) || is_full(rel->op)) && rel_find_exp(rel->r, ls)) {
    1746           5 :                         rel_join_add_exp(sql->sa, rel, e);
    1747           5 :                         return rel;
    1748             :                 }
    1749        1139 :                 if (is_left(rel->op) && rel_find_exp(rel->r, ls)) {
    1750        1113 :                         rel->r = rel_push_select(sql, rel->r, ls, e, f);
    1751        1113 :                         return rel;
    1752          26 :                 } else if (is_right(rel->op) && rel_find_exp(rel->l, ls)) {
    1753          11 :                         rel->l = rel_push_select(sql, rel->l, ls, e, f);
    1754          11 :                         return rel;
    1755             :                 }
    1756             :         }
    1757             :         /* push select into the given relation */
    1758      106871 :         return rel_push_select(sql, rel, ls, e, f);
    1759             : }
    1760             : 
    1761             : static sql_rel *
    1762      209671 : push_join_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *L, sql_exp *R, sql_exp *R2, int f)
    1763             : {
    1764      209671 :         sql_rel *r;
    1765      209671 :         if (/*is_semi(rel->op) ||*/ (is_outerjoin(rel->op) && !is_processed((rel)))) {
    1766       21212 :                 rel_join_add_exp(sql->sa, rel, e);
    1767       21212 :                 return rel;
    1768             :         }
    1769             :         /* push join into the given relation */
    1770      188459 :         if ((r = rel_push_join(sql, rel, L, R, R2, e, f)) != NULL)
    1771             :                 return r;
    1772           0 :         rel_join_add_exp(sql->sa, rel, e);
    1773           0 :         return rel;
    1774             : }
    1775             : 
    1776             : static sql_rel *
    1777        3734 : rel_select_push_filter_exp_down(mvc *sql, sql_rel *rel, sql_exp *e, list *l, list *r, int ff)
    1778             : {
    1779        3734 :         sql_exp *ll;
    1780        3734 :         if (exps_card(r) <= CARD_ATOM && (exps_are_atoms(r) || exps_have_freevar(sql, r) || exps_have_freevar(sql, l))) {
    1781        3637 :                 if (exps_card(l) == exps_card(r) || rel->processed)  /* bin compare op */
    1782          98 :                         return rel_select(sql->sa, rel, e);
    1783        3539 :                 if ((ll = exps_find_one_multi_exp(l)))
    1784        3539 :                         return push_select_exp(sql, rel, e, ll, ff);
    1785             :         }
    1786          97 :         if (is_outerjoin(rel->op))
    1787           8 :                 return rel_select(sql->sa, rel, e);
    1788          89 :         return rel_select_add_exp(sql->sa, rel, e);
    1789             : }
    1790             : 
    1791             : static sql_rel *
    1792        3617 : rel_filter(mvc *sql, sql_rel *rel, list *l, list *r, char *sname, char *filter_op, int anti, int ff)
    1793             : {
    1794        3617 :         node *n;
    1795        3617 :         sql_exp *e = NULL;
    1796        3617 :         sql_subfunc *f = NULL;
    1797        3617 :         list *tl = sa_list(sql->sa);
    1798        3617 :         bool found = false;
    1799             : 
    1800        7234 :         for (n = l->h; n; n = n->next){
    1801        3617 :                 sql_exp *e = n->data;
    1802             : 
    1803        3617 :                 list_append(tl, exp_subtype(e));
    1804             :         }
    1805       14391 :         for (n = r->h; n; n = n->next){
    1806       10774 :                 sql_exp *e = n->data;
    1807             : 
    1808       10774 :                 list_append(tl, exp_subtype(e));
    1809             :         }
    1810             :         /* find filter function */
    1811        3617 :         f = bind_func_(sql, sname, filter_op, tl, F_FILT, false, &found, false);
    1812        3617 :         if (f) {
    1813        3615 :                 node *n,*m = f->func->ops->h;
    1814        3615 :                 list *nexps = sa_list(sql->sa);
    1815             : 
    1816        7230 :                 for(n=l->h; m && n; m = m->next, n = n->next) {
    1817        3615 :                         sql_arg *a = m->data;
    1818        3615 :                         sql_exp *e = n->data;
    1819             : 
    1820        3615 :                         e = exp_check_type(sql, &a->type, rel, e, type_equal);
    1821        3615 :                         if (!e)
    1822             :                                 return NULL;
    1823        3615 :                         list_append(nexps, e);
    1824             :                 }
    1825        3615 :                 l = nexps;
    1826        3615 :                 nexps = sa_list(sql->sa);
    1827       14381 :                 for(n=r->h; m && n; m = m->next, n = n->next) {
    1828       10766 :                         sql_arg *a = m->data;
    1829       10766 :                         sql_exp *e = n->data;
    1830             : 
    1831       10766 :                         e = exp_check_type(sql, &a->type, rel, e, type_equal);
    1832       10766 :                         if (!e)
    1833             :                                 return NULL;
    1834       10766 :                         list_append(nexps, e);
    1835             :                 }
    1836             :                 r = nexps;
    1837             :         }
    1838        3617 :         if (!f)
    1839           4 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s FILTER function %s%s%s'%s'",
    1840           2 :                                                  found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", filter_op);
    1841        3615 :         e = exp_filter(sql->sa, l, r, f, anti);
    1842             : 
    1843        3615 :         if (exps_one_is_rel(l) || exps_one_is_rel(r)) /* uncorrelated subquery case */
    1844           9 :                 return rel_select(sql->sa, rel, e);
    1845             :         /* atom or row => select */
    1846        7212 :         for (node *n=l->h; n; n = n->next) {
    1847        3606 :                 sql_exp *ls = n->data;
    1848             : 
    1849        3606 :                 if (ls->card > rel->card) {
    1850           0 :                         if (exp_name(ls) && !has_label(ls))
    1851           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ls));
    1852           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    1853             :                 }
    1854             :         }
    1855       14345 :         for (node *n=r->h; n; n = n->next) {
    1856       10739 :                 sql_exp *rs = n->data;
    1857             : 
    1858       10739 :                 if (rs->card > rel->card) {
    1859           0 :                         if (exp_name(rs) && !has_label(rs))
    1860           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(rs));
    1861           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    1862             :                 }
    1863             :         }
    1864        3606 :         return rel_select_push_filter_exp_down(sql, rel, e, l, r, ff);
    1865             : }
    1866             : 
    1867             : static sql_rel *
    1868        3557 : rel_filter_exp_(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *r1, sql_exp *r2, sql_exp *r3, char *filter_op, int anti, int f)
    1869             : {
    1870        3557 :         list *l = sa_list(sql->sa);
    1871        3557 :         list *r = sa_list(sql->sa);
    1872             : 
    1873        3557 :         list_append(l, ls);
    1874        3557 :         list_append(r, r1);
    1875        3557 :         if (r2)
    1876        3557 :                 list_append(r, r2);
    1877        3557 :         if (r3)
    1878        3557 :                 list_append(r, r3);
    1879        3557 :         return rel_filter(sql, rel, l, r, "sys", filter_op, anti, f);
    1880             : }
    1881             : 
    1882             : static sql_rel *
    1883      382356 : rel_select_push_compare_exp_down(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int f)
    1884             : {
    1885      382356 :         if (!is_join(rel->op) && !is_select(rel->op))
    1886       85573 :                 return rel_select(sql->sa, rel, e);
    1887      384445 :         if ((rs->card <= CARD_ATOM || (rs2 && ls->card <= CARD_ATOM)) &&
    1888      175324 :                 (exp_is_atom(rs) || (rs2 && exp_is_atom(ls)) || exp_has_freevar(sql, rs) || exp_has_freevar(sql, ls)) &&
    1889         485 :                 (!rs2 || (rs2->card <= CARD_ATOM && (exp_is_atom(rs2) || exp_has_freevar(sql, rs2))))) {
    1890       87112 :                 if (ls->card == rs->card || (rs2 && (ls->card == rs2->card || rs->card == rs2->card)) || rel->processed) /* bin compare op */
    1891        1008 :                         return rel_select(sql->sa, rel, e);
    1892             : 
    1893       86104 :                 return push_select_exp(sql, rel, e, ls, f);
    1894             :         } else { /* join */
    1895      209671 :                 return push_join_exp(sql, rel, e, ls, rs, rs2, f);
    1896             :         }
    1897             :         return rel;
    1898             : }
    1899             : 
    1900             : static sql_rel *
    1901      357976 : rel_compare_exp_(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int type, int anti, int quantifier, int f, int symmetric, int is_semantics)
    1902             : {
    1903      357976 :         mvc *sql = query->sql;
    1904      357976 :         sql_exp *e = NULL;
    1905             : 
    1906      357976 :         if (quantifier || exp_is_rel(ls) || exp_is_rel(rs) || (rs2 && exp_is_rel(rs2))) {
    1907        3517 :                 if (rs2) {
    1908           7 :                         e = exp_compare2(sql->sa, ls, rs, rs2, type, symmetric);
    1909           7 :                         if (anti)
    1910           0 :                                 set_anti(e);
    1911             :                 } else {
    1912        3510 :                         assert(!symmetric);
    1913        3510 :                         if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    1914             :                                 return NULL;
    1915        3510 :                         e = exp_compare_func(sql, ls, rs, compare_func((comp_type)type, anti), quantifier);
    1916             :                 }
    1917        3517 :                 return rel_select(sql->sa, rel, e);
    1918      354459 :         } else if (!rs2) {
    1919      351512 :                 assert(!symmetric);
    1920      351512 :                 if (ls->card < rs->card) {
    1921       12642 :                         sql_exp *swap = ls;
    1922       12642 :                         ls = rs;
    1923       12642 :                         rs = swap;
    1924       12642 :                         type = (int)swap_compare((comp_type)type);
    1925             :                 }
    1926      351512 :                 if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    1927             :                         return NULL;
    1928      351509 :                 e = exp_compare(sql->sa, ls, rs, type);
    1929      351509 :                 if (is_semantics) set_semantics(e);
    1930             :         } else {
    1931        2947 :                 assert(rs2);
    1932        2947 :                 if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    1933             :                         return NULL;
    1934        2947 :                 if (!(rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal)))
    1935             :                         return NULL;
    1936        2947 :                 e = exp_compare2(sql->sa, ls, rs, rs2, type, symmetric);
    1937             :         }
    1938      354456 :         if (anti)
    1939         847 :                 set_anti(e);
    1940             : 
    1941      354456 :         if (!rel)
    1942           0 :                 return rel_select(sql->sa, rel_project_exp(sql, exp_atom_bool(sql->sa, 1)), e);
    1943             : 
    1944             :         /* atom or row => select */
    1945      354456 :         if (ls->card > rel->card || rs->card > rel->card || (rs2 && rs2->card > rel->card)) {
    1946           0 :                 sql_exp *e = ls->card > rel->card ? ls : rs->card > rel->card ? rs : rs2;
    1947           0 :                 if (exp_name(e) && !has_label(e))
    1948           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
    1949           0 :                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    1950             :         }
    1951      354456 :         return rel_select_push_compare_exp_down(sql, rel, e, ls, rs, rs2, f);
    1952             : }
    1953             : 
    1954             : static sql_rel *
    1955      355022 : rel_compare_exp(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, char *compare_op, int reduce, int quantifier, int need_not, int f, int is_semantics)
    1956             : {
    1957      355022 :         mvc *sql = query->sql;
    1958      355022 :         comp_type type = cmp_equal;
    1959             : 
    1960      355022 :         if (!ls || !rs)
    1961             :                 return NULL;
    1962             : 
    1963      355022 :         if (!quantifier && ((!rel && !query_has_outer(query)) || !reduce)) {
    1964             :                 /* TODO to handle filters here */
    1965           0 :                 sql_exp *e;
    1966             : 
    1967           0 :                 if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    1968             :                         return NULL;
    1969           0 :                 e = rel_binop_(sql, rel, ls, rs, "sys", compare_op, card_value, true);
    1970             : 
    1971           0 :                 if (!e)
    1972             :                         return NULL;
    1973           0 :                 if (!reduce) {
    1974           0 :                         if (rel->op == op_project) {
    1975           0 :                                 append(rel->exps, e);
    1976             :                         } else {
    1977           0 :                                 list *exps = new_exp_list(sql->sa);
    1978             : 
    1979           0 :                                 append(exps, e);
    1980           0 :                                 return rel_project(sql->sa, rel, exps);
    1981             :                         }
    1982             :                 } else {
    1983           0 :                         return rel_select(sql->sa, rel, e);
    1984             :                 }
    1985             :         }
    1986      355022 :         type = compare_str2type(compare_op);
    1987      355022 :         assert(type != cmp_filter);
    1988      355022 :         return rel_compare_exp_(query, rel, ls, rs, NULL, type, need_not, quantifier, f, 0, is_semantics);
    1989             : }
    1990             : 
    1991             : static sql_rel *
    1992      354995 : rel_compare(sql_query *query, sql_rel *rel, symbol *sc, symbol *lo, symbol *ro, char *compare_op, int f, exp_kind k, int quantifier, int is_semantics)
    1993             : {
    1994      354995 :         mvc *sql = query->sql;
    1995      354995 :         sql_exp *rs = NULL, *ls;
    1996      354995 :         comp_type cmp_type = compare_str2type(compare_op);
    1997      354995 :         exp_kind ek = {type_value, card_column, FALSE};
    1998      354995 :         int need_not = 0;
    1999             : 
    2000      354995 :         if ((quantifier == 1 && cmp_type == cmp_equal) ||
    2001      354960 :             (quantifier == 2 && cmp_type == cmp_notequal)) {
    2002          63 :                 dnode *n = sc->data.lval->h;
    2003          63 :                 dlist *dl = dlist_create(sql->sa);
    2004             :                 /* map into IN/NOT IN */
    2005          63 :                 sc->token = cmp_type==cmp_equal?SQL_IN:SQL_NOT_IN;
    2006          63 :                 n->next->type = type_list;
    2007          63 :                 n->next->data.lval = dl;
    2008          63 :                 n->next->next->next = NULL; /* remove quantifier */
    2009          63 :                 dl->h = n->next->next;
    2010          63 :                 n->next->next = NULL; /* (remove comparison) moved righthand side */
    2011          63 :                 return rel_logical_exp(query, rel, sc, f);
    2012             :         }
    2013             :         /* <> ANY -> NOT (= ALL) */
    2014      354932 :         if (quantifier == 1 && cmp_type == cmp_notequal) {
    2015           5 :                 need_not = 1;
    2016           5 :                 quantifier = 2;
    2017           5 :                 cmp_type = cmp_equal;
    2018           5 :                 compare_op = "=";
    2019             :         }
    2020             : 
    2021      354932 :         if ((lo->token == SQL_SELECT || lo->token == SQL_UNION || lo->token == SQL_EXCEPT || lo->token == SQL_INTERSECT || lo->token == SQL_VALUES) &&
    2022          43 :                 (ro->token != SQL_SELECT && ro->token != SQL_UNION && ro->token != SQL_EXCEPT && ro->token != SQL_INTERSECT && ro->token != SQL_VALUES)) {
    2023          30 :                 symbol *tmp = lo; /* swap subquery to the right hand side */
    2024             : 
    2025          30 :                 lo = ro;
    2026          30 :                 ro = tmp;
    2027             : 
    2028          30 :                 if (compare_op[0] == '>')
    2029          16 :                         compare_op[0] = '<';
    2030          14 :                 else if (compare_op[0] == '<' && compare_op[1] != '>')
    2031           1 :                         compare_op[0] = '>';
    2032          30 :                 cmp_type = swap_compare(cmp_type);
    2033             :         }
    2034             : 
    2035      354932 :         ls = rel_value_exp(query, &rel, lo, f|sql_farg, ek);
    2036      354932 :         if (!ls)
    2037             :                 return NULL;
    2038      354884 :         if (ls && rel && exp_has_freevar(sql, ls) && is_sql_sel(f))
    2039           0 :                 ls = rel_project_add_exp(sql, rel, ls);
    2040      354884 :         if (quantifier)
    2041          58 :                 ek.card = card_set;
    2042             : 
    2043      354884 :         rs = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
    2044      354884 :         if (!rs)
    2045             :                 return NULL;
    2046      354854 :         if (ls->card > rs->card && rs->card == CARD_AGGR && is_sql_having(f)) {
    2047           0 :                 if (exp_name(ls) && exp_relname(ls) && !has_label(ls))
    2048           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(ls), exp_name(ls));
    2049           0 :                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    2050             :         }
    2051      354854 :         if (rs->card > ls->card && ls->card == CARD_AGGR && is_sql_having(f)) {
    2052           0 :                 if (exp_name(rs) && exp_relname(rs) && !has_label(rs))
    2053           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(rs), exp_name(rs));
    2054           0 :                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    2055             :         }
    2056      354854 :         return rel_compare_exp(query, rel, ls, rs, compare_op, k.reduce, quantifier, need_not, f, is_semantics);
    2057             : }
    2058             : 
    2059             : static sql_exp*
    2060      522194 : _rel_nop(mvc *sql, char *sname, char *fname, list *tl, sql_rel *rel, list *exps, exp_kind ek)
    2061             : {
    2062      522194 :         bool found = false;
    2063      522194 :         int table_func = (ek.card == card_relation);
    2064      522194 :         sql_ftype type = (ek.card == card_loader)?F_LOADER:((ek.card == card_none)?F_PROC:
    2065             :                    ((ek.card == card_relation)?F_UNION:F_FUNC));
    2066             : 
    2067      522194 :         sql_subfunc *f = bind_func_(sql, sname, fname, tl, type, false, &found, false);
    2068      522194 :         if (f && !(exps = check_arguments_and_find_largest_any_type(sql, rel, exps, f, table_func, false)))
    2069             :                 f = NULL;
    2070             : 
    2071      521927 :         if (f)
    2072      521927 :                 return exp_op(sql->sa, exps, f);
    2073         267 :         char *arg_list = nary_function_arg_types_2str(sql, tl, list_length(tl));
    2074         551 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s operator %s%s%s'%s'(%s)",
    2075         267 :                                          found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname, arg_list ? arg_list : "");
    2076             : }
    2077             : 
    2078             : static sql_exp *
    2079        2096 : exp_exist(sql_query *query, sql_rel *rel, sql_exp *le, int exists)
    2080             : {
    2081        2096 :         mvc *sql = query->sql;
    2082        2096 :         sql_subfunc *exists_func = NULL;
    2083        2096 :         sql_subtype *t;
    2084        2096 :         sql_exp *res;
    2085             : 
    2086        2096 :         if (!exp_name(le))
    2087         753 :                 exp_label(sql->sa, le, ++sql->label);
    2088        2096 :         if (exp_is_rel(le)) { /* for the subquery case, propagate to the inner query */
    2089        2096 :                 sql_rel *r = exp_rel_get_rel(sql->sa, le);
    2090        2096 :                 if (is_project(r->op) && !list_empty(r->exps)) {
    2091        6109 :                         for (node *n = r->exps->h; n; n = n->next)
    2092        4013 :                                 if (!exp_subtype(n->data) && rel_set_type_param(sql, sql_bind_localtype("bit"), r, n->data, 0) < 0) /* workaround */
    2093             :                                         return NULL;
    2094        2096 :                         le->tpe = *exp_subtype(r->exps->h->data); /* just take the first expression type */
    2095             :                 }
    2096           0 :         } else if (!exp_subtype(le) && rel_set_type_param(sql, sql_bind_localtype("bit"), rel, le, 0) < 0) /* workaround */
    2097             :                 return NULL;
    2098        2096 :         t = exp_subtype(le);
    2099             : 
    2100        2157 :         if (!(exists_func = sql_bind_func(sql, "sys", exists ? "sql_exists" : "sql_not_exists", t, NULL, F_FUNC, true, true)))
    2101           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "exist operator on type %s missing", t ? t->type->base.name : "unknown");
    2102        2096 :         res = exp_unop(sql->sa, le, exists_func);
    2103        2096 :         set_has_no_nil(res);
    2104        2096 :         return res;
    2105             : }
    2106             : 
    2107             : static sql_exp *
    2108        1093 : rel_exists_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
    2109             : {
    2110        1093 :         exp_kind ek = {type_value, card_exists, FALSE};
    2111        1093 :         sql_exp *le, *e;
    2112             : 
    2113        1093 :         le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2114        1093 :         if (!le)
    2115             :                 return NULL;
    2116        1092 :         if (!(e = exp_exist(query, rel ? *rel : NULL, le, sc->token == SQL_EXISTS)))
    2117             :                 return NULL;
    2118             :         /* only freevar should have CARD_AGGR */
    2119        1092 :         e->card = CARD_ATOM;
    2120        1092 :         return e;
    2121             : }
    2122             : 
    2123             : static sql_rel *
    2124        1012 : rel_exists_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    2125             : {
    2126        1012 :         exp_kind ek = {type_value, card_exists, TRUE};
    2127        1012 :         mvc *sql = query->sql;
    2128        1012 :         sql_rel *sq = NULL;
    2129             : 
    2130        1012 :         if (is_psm_call(f) || is_sql_merge(f))
    2131           3 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
    2132        1011 :         if (rel) {
    2133        1011 :                 query_processed(query);
    2134        1011 :                 query_push_outer(query, rel, f);
    2135             :         }
    2136        1011 :         sq = rel_subquery(query, sc->data.sym, ek);
    2137        1011 :         if (rel)
    2138        1011 :                 rel = query_pop_outer(query);
    2139        1011 :         assert(!is_sql_sel(f));
    2140        1011 :         if (sq) {
    2141        1004 :                 sql_exp *e = exp_rel(sql, sq);
    2142        1004 :                 if (!(e = exp_exist(query, rel, e, sc->token == SQL_EXISTS)))
    2143             :                         return NULL;
    2144             :                 /* only freevar should have CARD_AGGR */
    2145        1004 :                 e->card = CARD_ATOM;
    2146        1004 :                 rel = rel_select_add_exp(sql->sa, rel, e);
    2147        1004 :                 return rel;
    2148             :         }
    2149             :         return NULL;
    2150             : }
    2151             : 
    2152             : static int
    2153        8597 : is_project_true(sql_rel *r)
    2154             : {
    2155        8597 :         if (r && !r->l && list_length(r->exps) == 1) {
    2156          82 :                 sql_exp *e = r->exps->h->data;
    2157          82 :                 if (exp_is_atom(e) && exp_is_true(e))
    2158             :                         return 1;
    2159             :         }
    2160             :         return 0;
    2161             : }
    2162             : 
    2163             : static sql_exp *
    2164       64493 : rel_in_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
    2165             : {
    2166       64493 :         mvc *sql = query->sql;
    2167       64493 :         exp_kind ek = {type_value, card_column, TRUE};
    2168       64493 :         dlist *dl = sc->data.lval;
    2169       64493 :         symbol *lo = NULL;
    2170       64493 :         dnode *n = dl->h->next, *dn = NULL;
    2171       64493 :         sql_exp *le = NULL, *re, *e = NULL;
    2172       64493 :         list *ll = sa_list(sql->sa);
    2173       64493 :         int is_tuple = 0, add_select = 0;
    2174             : 
    2175             :         /* complex case */
    2176             :         //if (dl->h->type == type_list) { /* (a,b..) in (.. ) */
    2177       64493 :         if (dl->h->type == type_symbol && dl->h->data.sym->token == SQL_VALUES) {
    2178        4178 :                 lo = dl->h->data.sym;
    2179        4178 :                 dn = lo->data.lval->h->data.lval->h;
    2180        4178 :                 lo = dn->data.sym;
    2181        4178 :                 dn = dn->next;
    2182             :         } else {
    2183       60315 :                 lo = dl->h->data.sym;
    2184             :         }
    2185      203967 :         for( ; lo; lo = dn?dn->data.sym:NULL, dn = dn?dn->next:NULL ) {
    2186       69741 :                 le = rel_value_exp(query, rel, lo, f|sql_farg, ek);
    2187       69741 :                 if (!le)
    2188             :                         return NULL;
    2189       69737 :                 append(ll, le);
    2190             :         }
    2191       64489 :         if (list_length(ll) == 1) {
    2192       60313 :                 le = ll->h->data;
    2193       60313 :                 ek.card = card_set;
    2194             :         } else {
    2195        4176 :                 le = exp_values(sql->sa, ll);
    2196        4176 :                 exp_label(sql->sa, le, ++sql->label);
    2197        4176 :                 ek.type = list_length(ll);
    2198        4176 :                 is_tuple = list_length(ll);
    2199             :         }
    2200             :         /* list of values or subqueries */
    2201             :         /* 3 right hand side cases,
    2202             :          *      1 - value/tuple list of atoms
    2203             :          *      2 - list of scalar sub queries (needs check on 1 row/column per query)
    2204             :          *      3 - single tabular ie. multi column, multi row query
    2205             :          */
    2206       64489 :         if (n->type == type_list) {
    2207       64489 :                 sql_exp *values;
    2208       64489 :                 list *vals = sa_list(sql->sa);
    2209             : 
    2210       64489 :                 n = dl->h->next;
    2211       64489 :                 n = n->data.lval->h;
    2212             : 
    2213      316392 :                 for (; n; n = n->next) {
    2214      251942 :                         if (n->type == type_list) {
    2215           0 :                                 dnode *m = n->data.lval->h;
    2216           0 :                                 list *rl = sa_list(sql->sa);
    2217           0 :                                 for (; m; m = m->next) {
    2218           0 :                                         assert(m->type == type_symbol);
    2219           0 :                                         sql_exp *re = rel_value_exp(query, rel, m->data.sym, f|sql_farg, ek);
    2220           0 :                                         if (!re)
    2221             :                                                 return NULL;
    2222           0 :                                         append(rl, re);
    2223             :                                 }
    2224           0 :                                 re = exp_values(sql->sa, rl);
    2225             :                         } else {
    2226      251942 :                                 assert(n->type == type_symbol);
    2227      251942 :                                 re = rel_value_exp(query, rel, n->data.sym, f|sql_farg, ek);
    2228             :                         }
    2229      251942 :                         if (!re)
    2230             :                                 return NULL;
    2231      251918 :                         if (is_tuple && (!exp_is_rel(re) && !is_values(re)))
    2232           4 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Cannot match a tuple to a single value");
    2233        4174 :                         if (is_tuple && exp_is_rel(re)) {
    2234        4174 :                                 sql_rel *r = exp_rel_get_rel(sql->sa, re);
    2235             : 
    2236        4174 :                                 if (!r)
    2237           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "Subquery missing");
    2238        4174 :                                 if (r->nrcols != ek.type)
    2239          12 :                                         return sql_error(sql, 02, SQLSTATE(42000) "Subquery has too %s columns", (r->nrcols < ek.type) ? "few" : "many");
    2240        4165 :                                 re = exp_rel_label(sql, re);
    2241        4165 :                                 if (r && r->l && n->next) /* not a value list */
    2242           2 :                                         return sql_error(sql, 02, SQLSTATE(42000) "subquery must return only one column");
    2243      247740 :                         } else if (exp_is_rel(re)) {
    2244        8598 :                                 sql_rel *r = exp_rel_get_rel(sql->sa, re);
    2245        8598 :                                 add_select = 1;
    2246        8598 :                                 if (rel && *rel && is_join((*rel)->op))
    2247        4469 :                                         set_dependent((*rel));
    2248        8598 :                                 if (is_project(r->op) && is_project_true(r->l) && list_length(r->exps) == 1)
    2249          80 :                                         re = r->exps->h->data;
    2250      239142 :                         } else if (is_values(re) && is_tuple != list_length(exp_get_values(re))) {
    2251           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Tuple sizes do not match");
    2252             :                         }
    2253      251903 :                         append(vals, re);
    2254             :                 }
    2255             : 
    2256       64450 :                 if (list_empty(vals))
    2257           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "The list of values for IN operator cannot be empty");
    2258             : 
    2259       64450 :                 values = exp_values(sql->sa, vals);
    2260       64450 :                 exp_label(sql->sa, values, ++sql->label);
    2261       64450 :                 if (is_tuple) {
    2262        4161 :                         if (!(values = exp_tuples_set_supertype(sql, exp_get_values(le), values)))
    2263             :                                 return NULL;
    2264        4161 :                         if (!(le->f = tuples_check_types(sql, exp_get_values(le), values)))
    2265             :                                 return NULL;
    2266             :                 } else { /* if it's not a tuple, enforce coercion on the type for every element on the list */
    2267       60289 :                         sql_subtype super, *le_tpe = exp_subtype(le), *values_tpe = NULL;
    2268             : 
    2269      308028 :                         for (node *m = vals->h; m; m = m->next) { /* first get values supertype */
    2270      247739 :                                 sql_exp *e = m->data;
    2271      247739 :                                 sql_subtype *tpe = exp_subtype(e);
    2272             : 
    2273      247739 :                                 if (values_tpe && tpe) {
    2274      187447 :                                         cmp_supertype(&super, values_tpe, tpe);
    2275      187447 :                                         *values_tpe = super;
    2276       60292 :                                 } else if (!values_tpe && tpe) {
    2277       60285 :                                         super = *tpe;
    2278       60285 :                                         values_tpe = &super;
    2279             :                                 }
    2280             :                         }
    2281       60289 :                         if (!le_tpe)
    2282           2 :                                 le_tpe = values_tpe;
    2283       60289 :                         if (!values_tpe)
    2284           4 :                                 values_tpe = le_tpe;
    2285       60289 :                         if (!le_tpe || !values_tpe)
    2286           1 :                                 return sql_error(sql, 01, SQLSTATE(42000) "For the IN operator, both sides must have a type defined");
    2287       60288 :                         cmp_supertype(&super, values_tpe, le_tpe); /* compute supertype */
    2288             : 
    2289             :                         /* on selection/join cases we can generate cmp expressions instead of anyequal for trivial cases */
    2290       60288 :                         if ((is_sql_where(f) || is_sql_having(f)) && !is_sql_farg(f) && !exp_has_rel(le) && exps_are_atoms(vals)) {
    2291       23850 :                                 if (list_length(vals) == 1) { /* use cmp_equal instead of cmp_in for 1 expression */
    2292         117 :                                         sql_exp *first = vals->h->data;
    2293         117 :                                         if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &le, &first, 1, type_equal_no_any) < 0)
    2294           0 :                                                 return NULL;
    2295         142 :                                         e = exp_compare(sql->sa, le, first, (sc->token == SQL_IN) ? cmp_equal : cmp_notequal);
    2296             :                                 } else { /* use cmp_in instead of anyequal for n simple expressions */
    2297      120743 :                                         for (node *n = vals->h ; n ; n = n->next)
    2298       97010 :                                                 if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
    2299             :                                                         return NULL;
    2300       23733 :                                         if ((le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)) == NULL)
    2301             :                                                 return NULL;
    2302       32413 :                                         e = exp_in(sql->sa, le, vals, (sc->token == SQL_IN) ? cmp_in : cmp_notin);
    2303             :                                 }
    2304             :                         }
    2305       23850 :                         if (!e) { /* after computing supertype, check types for each IN value */
    2306      187049 :                                 for (node *n = vals->h ; n ; n = n->next)
    2307      150611 :                                         if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
    2308             :                                                 return NULL;
    2309       36438 :                                 values->tpe = *exp_subtype(vals->h->data);
    2310       36438 :                                 if (!(le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)))
    2311             :                                         return NULL;
    2312             :                         }
    2313             :                 }
    2314       60288 :                 if (!e) {
    2315       40599 :                         if (add_select && rel && *rel && !is_project((*rel)->op) && !is_select((*rel)->op) && !is_base((*rel)->op))
    2316        4468 :                                 *rel = rel_select(sql->sa, *rel, NULL);
    2317       40599 :                         if ((rel && *rel) || exp_has_rel(le) || exp_has_rel(values))
    2318       35013 :                                 e = exp_in_func(sql, le, values, (sc->token == SQL_IN), is_tuple);
    2319             :                         else
    2320        5586 :                                 e = exp_in_aggr(sql, le, values, (sc->token == SQL_IN), is_tuple);
    2321             :                 }
    2322             :         }
    2323             :         return e;
    2324             : }
    2325             : 
    2326             : static sql_rel *
    2327       34048 : rel_in_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    2328             : {
    2329       34048 :         mvc *sql = query->sql;
    2330       34048 :         sql_exp *e = rel_in_value_exp(query, &rel, sc, f);
    2331             : 
    2332       34048 :         assert(!is_sql_sel(f));
    2333       34048 :         if (!e || !rel)
    2334             :                 return NULL;
    2335             : 
    2336       34021 :         if (e->type == e_cmp) { /* it's a exp_in or cmp_equal of simple expressions, push down early on if possible */
    2337       23848 :                 sql_exp *ls = e->l;
    2338       23848 :                 bool rlist = (e->flag == cmp_in || e->flag == cmp_notin);
    2339       23848 :                 unsigned int rcard = rlist ? exps_card(e->r) : exp_card(e->r);
    2340       23848 :                 int r_is_atoms = rlist ? exps_are_atoms(e->r) : exp_is_atom(e->r);
    2341       23848 :                 int r_has_freevar = rlist ? exps_have_freevar(sql, e->r) : exp_has_freevar(sql, e->r);
    2342             : 
    2343       23848 :                 if (rcard <= CARD_ATOM && (r_is_atoms || r_has_freevar || exp_has_freevar(sql, ls))) {
    2344       23848 :                         if ((exp_card(ls) == rcard) || rel->processed) /* bin compare op */
    2345        5453 :                                 return rel_select(sql->sa, rel, e);
    2346             : 
    2347       18395 :                         return push_select_exp(sql, rel, e, ls, f);
    2348             :                 } else { /* join */
    2349           0 :                         sql_exp *rs = rlist ? exps_find_one_multi_exp(e->r) : e->r;
    2350           0 :                         if (rs)
    2351           0 :                                 return push_join_exp(sql, rel, e, ls, rs, NULL, f);
    2352             :                 }
    2353             :         }
    2354       10173 :         if (is_outerjoin(rel->op))
    2355          13 :                 return rel_select(sql->sa, rel, e);
    2356       10160 :         return rel_select_add_exp(sql->sa, rel, e);
    2357             : }
    2358             : 
    2359             : static bool
    2360       53565 : not_symbol_can_be_propagated(mvc *sql, symbol *sc)
    2361             : {
    2362       53565 :         switch (sc->token) {
    2363             :         case SQL_IN:
    2364             :         case SQL_NOT_IN:
    2365             :         case SQL_EXISTS:
    2366             :         case SQL_NOT_EXISTS:
    2367             :         case SQL_LIKE:
    2368             :         case SQL_NOT_LIKE:
    2369             :         case SQL_BETWEEN:
    2370             :         case SQL_NOT_BETWEEN:
    2371             :         case SQL_IS_NULL:
    2372             :         case SQL_IS_NOT_NULL:
    2373             :         case SQL_NOT:
    2374             :         case SQL_COMPARE:
    2375             :                 return true;
    2376        6822 :         case SQL_AND:
    2377             :         case SQL_OR: {
    2378        6822 :                 symbol *lo = sc->data.lval->h->data.sym;
    2379        6822 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2380        6826 :                 return not_symbol_can_be_propagated(sql, lo) && not_symbol_can_be_propagated(sql, ro);
    2381             :         }
    2382       37495 :         default:
    2383       37495 :                 return false;
    2384             :         }
    2385             : }
    2386             : 
    2387             : /* Warning, this function assumes the entire bison tree can be negated, so call it after 'not_symbol_can_be_propagated' */
    2388             : static symbol *
    2389       16065 : negate_symbol_tree(mvc *sql, symbol *sc)
    2390             : {
    2391       16065 :         switch (sc->token) {
    2392        1454 :         case SQL_IN:
    2393        1454 :                 sc->token = SQL_NOT_IN;
    2394        1454 :                 break;
    2395          22 :         case SQL_NOT_IN:
    2396          22 :                 sc->token = SQL_IN;
    2397          22 :                 break;
    2398           0 :         case SQL_EXISTS:
    2399           0 :                 sc->token = SQL_NOT_EXISTS;
    2400           0 :                 break;
    2401           0 :         case SQL_NOT_EXISTS:
    2402           0 :                 sc->token = SQL_EXISTS;
    2403           0 :                 break;
    2404           7 :         case SQL_LIKE:
    2405           7 :                 sc->token = SQL_NOT_LIKE;
    2406           7 :                 break;
    2407           0 :         case SQL_NOT_LIKE:
    2408           0 :                 sc->token = SQL_LIKE;
    2409           0 :                 break;
    2410          17 :         case SQL_BETWEEN:
    2411          17 :                 sc->token = SQL_NOT_BETWEEN;
    2412          17 :                 break;
    2413          11 :         case SQL_NOT_BETWEEN:
    2414          11 :                 sc->token = SQL_BETWEEN;
    2415          11 :                 break;
    2416          32 :         case SQL_IS_NULL:
    2417          32 :                 sc->token = SQL_IS_NOT_NULL;
    2418          32 :                 break;
    2419          15 :         case SQL_IS_NOT_NULL:
    2420          15 :                 sc->token = SQL_IS_NULL;
    2421          15 :                 break;
    2422          27 :         case SQL_NOT: { /* nested NOTs eliminate each other */
    2423          27 :                 if (sc->data.sym->token == SQL_ATOM) {
    2424           5 :                         AtomNode *an = (AtomNode*) sc->data.sym;
    2425           5 :                         sc = newAtomNode(sql->sa, an->a);
    2426          22 :                 } else if (sc->data.sym->token == SQL_SELECT) {
    2427           2 :                         SelectNode *sn = (SelectNode*) sc->data.sym;
    2428           2 :                         sc = newSelectNode(sql->sa, sn->distinct, sn->selection, sn->into, sn->from, sn->where, sn->groupby, sn->having,
    2429             :                                                            sn->orderby, sn->name, sn->limit, sn->offset, sn->sample, sn->seed, sn->window);
    2430             :                 } else {
    2431          20 :                         memmove(sc, sc->data.sym, sizeof(symbol));
    2432             :                 }
    2433             :         } break;
    2434        7662 :         case SQL_COMPARE: {
    2435        7662 :                 dnode *cmp_n = sc->data.lval->h;
    2436        7662 :                 comp_type neg_cmp_type = negate_compare(compare_str2type(cmp_n->next->data.sval)); /* negate the comparator */
    2437        7662 :                 if (cmp_n->next->next->next) {
    2438          22 :                         switch(cmp_n->next->next->next->data.i_val)
    2439             :                         {
    2440          12 :                         case 0: /* negating ANY/ALL */
    2441          12 :                                 cmp_n->next->next->next->data.i_val = 1;
    2442          12 :                                 break;
    2443           7 :                         case 1: /* negating ANY/ALL */
    2444           7 :                                 cmp_n->next->next->next->data.i_val = 0;
    2445           7 :                                 break;
    2446           2 :                         case 2: /* negating IS [NOT] DINSTINCT FROM */
    2447           2 :                                 cmp_n->next->next->next->data.i_val = 3;
    2448           2 :                                 break;
    2449           1 :                         case 3: /* negating IS [NOT] DINSTINCT FROM */
    2450           1 :                                 cmp_n->next->next->next->data.i_val = 2;
    2451           1 :                                 break;
    2452             :                         }
    2453             :                 }
    2454        7662 :                 cmp_n->next->data.sval = sa_strdup(sql->sa, compare_func(neg_cmp_type, 0));
    2455        7662 :         } break;
    2456        6818 :         case SQL_AND:
    2457             :         case SQL_OR: {
    2458        6818 :                 sc->data.lval->h->data.sym = negate_symbol_tree(sql, sc->data.lval->h->data.sym);
    2459        6818 :                 sc->data.lval->h->next->data.sym= negate_symbol_tree(sql, sc->data.lval->h->next->data.sym);
    2460        6818 :                 sc->token = sc->token == SQL_AND ? SQL_OR : SQL_AND;
    2461        6818 :         } break;
    2462             :         default:
    2463             :                 break;
    2464             :         }
    2465       16065 :         return sc;
    2466             : }
    2467             : 
    2468             : static int
    2469        3111 : exp_between_check_types(sql_subtype *res, sql_subtype *t1, sql_subtype *t2, sql_subtype *t3)
    2470             : {
    2471        3111 :         bool type_found = false;
    2472        3111 :         sql_subtype super;
    2473             : 
    2474        3111 :         if (t1 && t2) {
    2475        3105 :                 cmp_supertype(&super, t2, t1);
    2476        3105 :                 type_found = true;
    2477           6 :         } else if (t1) {
    2478           3 :                 super = *t1;
    2479           3 :                 type_found = true;
    2480           3 :         } else if (t2) {
    2481           1 :                 super = *t2;
    2482           1 :                 type_found = true;
    2483             :         }
    2484        3111 :         if (t3) {
    2485        3108 :                 if (type_found)
    2486        3107 :                         cmp_supertype(&super, t3, &super);
    2487             :                 else
    2488           1 :                         super = *t3;
    2489             :                 type_found = true;
    2490             :         }
    2491           3 :         if (!type_found)
    2492             :                 return -1;
    2493        3110 :         *res = super;
    2494        3110 :         return 0;
    2495             : }
    2496             : 
    2497             : static bool
    2498      119056 : exp_is_null_no_value_opt(sql_exp *e)
    2499             : {
    2500      119056 :         if (!e)
    2501             :                 return false;
    2502      122982 :         while (is_convert(e->type))
    2503        3926 :                 e = e->l;
    2504      238085 :         return e->type == e_atom && e->l && atom_null(e->l);
    2505             : }
    2506             : 
    2507             : sql_exp *
    2508     2670276 : rel_logical_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f, exp_kind ek)
    2509             : {
    2510     2670375 :         mvc *sql = query->sql;
    2511             : 
    2512     2670375 :         if (!sc)
    2513             :                 return NULL;
    2514             : 
    2515     2670375 :         if (mvc_highwater(sql))
    2516          53 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    2517             : 
    2518     2670928 :         switch (sc->token) {
    2519       52430 :         case SQL_OR:
    2520             :         case SQL_AND:
    2521             :         {
    2522       52430 :                 symbol *lo = sc->data.lval->h->data.sym;
    2523       52430 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2524       52430 :                 sql_exp *ls, *rs;
    2525             : 
    2526       52430 :                 if (!(ls = rel_value_exp(query, rel, lo, f|sql_farg, ek)))
    2527             :                         return NULL;
    2528       52429 :                 if (!(rs = rel_value_exp(query, rel, ro, f|sql_farg, ek)))
    2529             :                         return NULL;
    2530       92640 :                 return rel_binop_(sql, rel ? *rel : NULL, ls, rs, "sys", sc->token == SQL_OR ? "or": "and", card_value, false);
    2531             :         }
    2532           5 :         case SQL_FILTER:
    2533             :                 /* [ x,..] filter [ y,..] */
    2534             :                 /* todo add anti, [ x,..] not filter [ y,...] */
    2535             :                 /* no correlation */
    2536             :         {
    2537           5 :                 dnode *ln = sc->data.lval->h->data.lval->h;
    2538           5 :                 dnode *rn = sc->data.lval->h->next->next->data.lval->h;
    2539           5 :                 dlist *filter_op = sc->data.lval->h->next->data.lval;
    2540           5 :                 char *fname = qname_schema_object(filter_op);
    2541           5 :                 char *sname = qname_schema(filter_op);
    2542           5 :                 list *exps, *tl;
    2543           5 :                 sql_subtype *obj_type = NULL;
    2544             : 
    2545           5 :                 exps = sa_list(sql->sa);
    2546           5 :                 tl = sa_list(sql->sa);
    2547          15 :                 for (; ln; ln = ln->next) {
    2548           5 :                         symbol *sym = ln->data.sym;
    2549             : 
    2550           5 :                         sql_exp *e = rel_value_exp(query, rel, sym, f|sql_farg, ek);
    2551           5 :                         if (!e)
    2552             :                                 return NULL;
    2553           5 :                         if (!obj_type)
    2554           5 :                                 obj_type = exp_subtype(e);
    2555           5 :                         list_append(exps, e);
    2556           5 :                         append(tl, exp_subtype(e));
    2557             :                 }
    2558          13 :                 for (; rn; rn = rn->next) {
    2559          10 :                         symbol *sym = rn->data.sym;
    2560             : 
    2561          10 :                         sql_exp *e = rel_value_exp(query, rel, sym, f|sql_farg, ek);
    2562          10 :                         if (!e)
    2563             :                                 return NULL;
    2564           8 :                         list_append(exps, e);
    2565           8 :                         append(tl, exp_subtype(e));
    2566             :                 }
    2567             :                 /* find the predicate filter function */
    2568           3 :                 return _rel_nop(sql, sname, fname, tl, rel ? *rel : NULL, exps, ek);
    2569             :         }
    2570      118773 :         case SQL_COMPARE:
    2571             :         {
    2572      118773 :                 dnode *n = sc->data.lval->h;
    2573      118773 :                 symbol *lo = n->data.sym;
    2574      118773 :                 symbol *ro = n->next->next->data.sym;
    2575      118773 :                 char *compare_op = n->next->data.sval;
    2576      118773 :                 int quantifier = 0, need_not = 0;
    2577      118773 :                 sql_exp *rs = NULL, *ls;
    2578      118773 :                 comp_type cmp_type = compare_str2type(compare_op);
    2579      118773 :                 bool is_not_distinct_from = false;
    2580      118773 :                 bool is_distinct_from = false;
    2581             : 
    2582             :                 /*
    2583             :                  * = ANY -> IN, <> ALL -> NOT( = ANY) -> NOT IN
    2584             :                  * = ALL -> all(groupby(all, nil)), <> ANY -> NOT ( = ALL )
    2585             :                  */
    2586      118773 :                 if (n->next->next->next)
    2587         258 :                         quantifier = n->next->next->next->data.i_val + 1;
    2588         258 :                 assert(quantifier == 0 || quantifier == 1 || quantifier == 2 || quantifier == 3 || quantifier == 4);
    2589             : 
    2590             :                 /* [NOT] DISTINCT FROM */
    2591      118773 :                 if (quantifier == 3) {
    2592             :                                 is_not_distinct_from = true;
    2593             :                                 quantifier = 0;
    2594             :                 }
    2595      118759 :                 else if (quantifier == 4) {
    2596          14 :                                 is_distinct_from = true;
    2597          14 :                                 quantifier = 0;
    2598             :                 }
    2599             : 
    2600      118773 :                 if ((quantifier == 1 && cmp_type == cmp_equal) ||
    2601      118707 :                     (quantifier == 2 && cmp_type == cmp_notequal)) {
    2602          93 :                         dlist *dl = dlist_create(sql->sa);
    2603             :                         /* map into IN/NOT IN */
    2604          93 :                         sc->token = cmp_type==cmp_equal?SQL_IN:SQL_NOT_IN;
    2605          93 :                         n->next->type = type_list;
    2606          93 :                         n->next->data.lval = dl;
    2607          93 :                         n->next->next->next = NULL; /* remove quantifier */
    2608          93 :                         dl->h = n->next->next;
    2609          93 :                         n->next->next = NULL; /* (remove comparison) moved righthand side */
    2610          93 :                         return rel_logical_value_exp(query, rel, sc, f, ek);
    2611             :                 }
    2612             :                 /* <> ANY -> NOT (= ALL) */
    2613      118680 :                 if (quantifier == 1 && cmp_type == cmp_notequal) {
    2614          15 :                         need_not = 1;
    2615          15 :                         quantifier = 2;
    2616          15 :                         cmp_type = cmp_equal;
    2617          15 :                         compare_op = "=";
    2618             :                 }
    2619             : 
    2620      118680 :                 ls = rel_value_exp(query, rel, lo, f|sql_farg, ek);
    2621      118680 :                 if (!ls)
    2622             :                         return NULL;
    2623      118668 :                 if (quantifier)
    2624         137 :                         ek.card = card_set;
    2625             : 
    2626      118668 :                 rs = rel_value_exp(query, rel, ro, f|sql_farg, ek);
    2627      118668 :                 if (!rs)
    2628             :                         return NULL;
    2629             : 
    2630      118658 :                 if (is_distinct_from || is_not_distinct_from) {
    2631          28 :                         if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0)
    2632             :                                 return NULL;
    2633          42 :                         sql_exp* e = exp_compare(sql->sa, ls, rs, is_not_distinct_from?cmp_equal:cmp_notequal);
    2634          28 :                         set_semantics(e);
    2635          28 :                         return e;
    2636             :                 }
    2637             : 
    2638      118630 :                 if (rs->type == e_atom)
    2639      107177 :                         quantifier = 0;
    2640             : 
    2641      118630 :                 if (!exp_is_rel(ls) && !exp_is_rel(rs) && ls->card < rs->card) {
    2642          13 :                         sql_exp *swap = ls; /* has to swap parameters like in the rel_logical_exp case */
    2643          13 :                         ls = rs;
    2644          13 :                         rs = swap;
    2645          13 :                         cmp_type = swap_compare(cmp_type);
    2646             :                 }
    2647             : 
    2648      118630 :                 if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0)
    2649             :                         return NULL;
    2650      118627 :                 if (exp_is_null_no_value_opt(ls) && exp_is_null_no_value_opt(rs))
    2651           7 :                         return exp_atom(sql->sa, atom_general(sql->sa, sql_bind_localtype("bit"), NULL, 0));
    2652             : 
    2653      118620 :                 return exp_compare_func(sql, ls, rs, compare_func(cmp_type, need_not), quantifier);
    2654             :         }
    2655             :         /* Set Member ship */
    2656       30445 :         case SQL_IN:
    2657             :         case SQL_NOT_IN:
    2658       30445 :                 return rel_in_value_exp(query, rel, sc, f);
    2659        1093 :         case SQL_EXISTS:
    2660             :         case SQL_NOT_EXISTS:
    2661        1093 :                 return rel_exists_value_exp(query, rel, sc, f);
    2662         347 :         case SQL_LIKE:
    2663             :         case SQL_NOT_LIKE:
    2664             :         {
    2665         347 :                 symbol *lo = sc->data.lval->h->data.sym;
    2666         347 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2667         347 :                 int insensitive = sc->data.lval->h->next->next->data.i_val;
    2668         347 :                 int anti = (sc->token == SQL_NOT_LIKE) != (sc->data.lval->h->next->next->next->data.i_val != 0);
    2669         347 :                 sql_subtype *st = sql_bind_localtype("str");
    2670         347 :                 sql_exp *le = rel_value_exp(query, rel, lo, f|sql_farg, ek), *re, *ee = NULL, *ie = exp_atom_bool(sql->sa, insensitive);
    2671             : 
    2672         347 :                 if (!le)
    2673             :                         return NULL;
    2674             : 
    2675         347 :                 if (!exp_subtype(le))
    2676           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameter not allowed on "
    2677             :                                         "left hand side of LIKE operator");
    2678             : 
    2679         347 :                 lo = ro->data.lval->h->data.sym;
    2680             :                 /* like uses a single string pattern */
    2681         347 :                 ek.card = card_value;
    2682         347 :                 re = rel_value_exp(query, rel, lo, f|sql_farg, ek);
    2683         347 :                 if (!re)
    2684             :                         return NULL;
    2685         343 :                 if ((re = exp_check_type(sql, st, rel ? *rel : NULL, re, type_equal)) == NULL)
    2686           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
    2687         343 :                 if ((le = exp_check_type(sql, st, rel ? *rel : NULL, le, type_equal)) == NULL)
    2688           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
    2689             :                 /* Do we need to escape ? */
    2690         343 :                 if (dlist_length(ro->data.lval) == 2) {
    2691          63 :                         char *escape = ro->data.lval->h->next->data.sval;
    2692          63 :                         ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, escape)));
    2693             :                 } else {
    2694         280 :                         ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, "")));
    2695             :                 }
    2696         573 :                 return rel_nop_(sql, rel ? *rel : NULL, le, re, ee, ie, "sys", anti ? "not_like" : "like", card_value);
    2697             :         }
    2698         165 :         case SQL_BETWEEN:
    2699             :         case SQL_NOT_BETWEEN:
    2700             :         {
    2701         165 :                 symbol *lo = sc->data.lval->h->data.sym;
    2702         165 :                 int symmetric = sc->data.lval->h->next->data.i_val;
    2703         165 :                 symbol *ro1 = sc->data.lval->h->next->next->data.sym;
    2704         165 :                 symbol *ro2 = sc->data.lval->h->next->next->next->data.sym;
    2705         165 :                 sql_exp *le, *re1, *re2;
    2706         165 :                 sql_subtype super;
    2707             : 
    2708         165 :                 assert(sc->data.lval->h->next->type == type_int);
    2709             : 
    2710         165 :                 if (!(le = rel_value_exp(query, rel, lo, f|sql_farg, ek)))
    2711             :                         return NULL;
    2712         164 :                 if (!(re1 = rel_value_exp(query, rel, ro1, f|sql_farg, ek)))
    2713             :                         return NULL;
    2714         161 :                 if (!(re2 = rel_value_exp(query, rel, ro2, f|sql_farg, ek)))
    2715             :                         return NULL;
    2716             : 
    2717         156 :                 if (exp_between_check_types(&super, exp_subtype(le), exp_subtype(re1), exp_subtype(re2)) < 0)
    2718           0 :                         return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
    2719             : 
    2720         156 :                 if ((le = exp_check_type(sql, &super, rel ? *rel:NULL, le, type_equal)) == NULL ||
    2721         156 :                     (re1 = exp_check_type(sql, &super, rel ? *rel:NULL, re1, type_equal)) == NULL ||
    2722         156 :                     (re2 = exp_check_type(sql, &super, rel ? *rel:NULL, re2, type_equal)) == NULL)
    2723           0 :                         return NULL;
    2724             : 
    2725         156 :                 le = exp_compare2(sql->sa, le, re1, re2, 3, symmetric);
    2726         156 :                 if (sc->token == SQL_NOT_BETWEEN)
    2727          56 :                         set_anti(le);
    2728             :                 return le;
    2729             :         }
    2730       15227 :         case SQL_IS_NULL:
    2731             :         case SQL_IS_NOT_NULL:
    2732             :         /* is (NOT) NULL */
    2733             :         {
    2734       15227 :                 sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2735             : 
    2736       15227 :                 if (!le)
    2737             :                         return NULL;
    2738       19527 :                 le = rel_unop_(sql, rel ? *rel : NULL, le, "sys", sc->token == SQL_IS_NULL ? "isnull" : "isnotnull", card_value);
    2739       15224 :                 if (!le)
    2740             :                         return NULL;
    2741       15224 :                 set_has_no_nil(le);
    2742       15224 :                 return le;
    2743             :         }
    2744       19249 :         case SQL_NOT: {
    2745       19249 :                 if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
    2746          99 :                         sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
    2747          99 :                         return rel_logical_value_exp(query, rel, sc->data.sym, f, ek);
    2748             :                 }
    2749       19150 :                 sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2750             : 
    2751       19150 :                 if (!le)
    2752             :                         return NULL;
    2753       19149 :                 return rel_unop_(sql, rel ? *rel : NULL, le, "sys", "not", card_value);
    2754             :         }
    2755             :         case SQL_ATOM: {
    2756     2411917 :                 AtomNode *an = (AtomNode *) sc;
    2757     2411917 :                 assert(an && an->a);
    2758     2411917 :                 return exp_atom(sql->sa, an->a);
    2759             :         }
    2760       20759 :         case SQL_IDENT:
    2761             :         case SQL_COLUMN:
    2762       20759 :                 return rel_column_ref(query, rel, sc, f);
    2763         202 :         case SQL_UNION:
    2764             :         case SQL_EXCEPT:
    2765             :         case SQL_INTERSECT: {
    2766         202 :                 sql_rel *sq;
    2767             : 
    2768         202 :                 if (is_psm_call(f) || is_sql_merge(f))
    2769           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
    2770         200 :                 if (rel && *rel)
    2771         142 :                         query_push_outer(query, *rel, f);
    2772         200 :                 sq = rel_setquery(query, sc);
    2773         200 :                 if (rel && *rel) {
    2774         142 :                         *rel = query_pop_outer(query);
    2775         142 :                         if (is_sql_join(f) && is_groupby((*rel)->op)) {
    2776           0 :                                 return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
    2777         142 :                         } else if (is_sql_where(f) && is_groupby((*rel)->op)) {
    2778           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
    2779         142 :                         } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby((*rel)->op)) {
    2780           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
    2781             :                         }
    2782             :                 }
    2783         200 :                 if (!sq)
    2784             :                         return NULL;
    2785         198 :                 if (ek.type == type_value && ek.card <= card_set && is_project(sq->op) && list_length(sq->exps) > 1)
    2786           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
    2787         197 :                 if (ek.type == type_relation && is_project(sq->op) && list_length(sq->exps) != ek.type)
    2788           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery has too %s columns", list_length(sq->exps) < ek.type ? "few" : "many");
    2789         303 :                 if (ek.type == type_value && ek.card < card_set && sq->card >= CARD_AGGR && (is_sql_sel(f) | is_sql_having(f) | is_sql_farg(f) |
    2790         106 :                         ( is_sql_where(f) && rel && (!*rel || is_basetable((*rel)->op) || is_simple_project((*rel)->op) || is_joinop((*rel)->op)))))
    2791         106 :                         sq = rel_zero_or_one(sql, sq, ek);
    2792         197 :                 return exp_rel(sql, sq);
    2793             :         }
    2794           1 :         case SQL_DEFAULT:
    2795           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "DEFAULT keyword not allowed outside insert and update statements");
    2796         315 :         default: {
    2797         315 :                 sql_exp *le = rel_value_exp(query, rel, sc, f|sql_farg, ek);
    2798         315 :                 sql_subtype bt;
    2799             : 
    2800         315 :                 if (!le)
    2801             :                         return NULL;
    2802         313 :                 sql_find_subtype(&bt, "boolean", 0, 0);
    2803         313 :                 if ((le = exp_check_type(sql, &bt, rel ? *rel : NULL, le, type_equal)) == NULL)
    2804             :                         return NULL;
    2805         313 :                 return rel_binop_(sql, rel ? *rel : NULL, le, exp_atom_bool(sql->sa, 1), "sys", "=", 0, true);
    2806             :         }
    2807             :         }
    2808             :         /* never reached, as all switch cases have a `return` */
    2809             : }
    2810             : 
    2811             : sql_rel *
    2812      640820 : rel_logical_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    2813             : {
    2814      640820 :         mvc *sql = query->sql;
    2815      640820 :         exp_kind ek = {type_value, card_column, TRUE};
    2816             : 
    2817      640820 :         if (!sc)
    2818             :                 return NULL;
    2819             : 
    2820      640820 :         if (mvc_highwater(sql))
    2821           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    2822             : 
    2823      640820 :         switch (sc->token) {
    2824       17675 :         case SQL_OR:
    2825             :         {
    2826       17675 :                 list *exps = NULL, *lexps = NULL, *rexps = NULL;
    2827       17675 :                 symbol *lo = sc->data.lval->h->data.sym;
    2828       17675 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2829       17675 :                 sql_rel *lr, *rr;
    2830             : 
    2831       17675 :                 if (!rel)
    2832             :                         return NULL;
    2833             : 
    2834       17675 :                 lr = rel;
    2835       17675 :                 rr = rel_dup(lr);
    2836             : 
    2837       17675 :                 if (is_outerjoin(rel->op) && !is_processed(rel)) {
    2838          44 :                         exps = rel->exps;
    2839             : 
    2840          44 :                         lr = rel_select_copy(sql->sa, lr, sa_list(sql->sa));
    2841          44 :                         lr = rel_logical_exp(query, lr, lo, f | sql_or);
    2842          44 :                         if (!lr)
    2843             :                                 return NULL;
    2844          43 :                         query_processed(query);
    2845          43 :                         rr = rel_select_copy(sql->sa, rr, sa_list(sql->sa));
    2846          43 :                         rr = rel_logical_exp(query, rr, ro, f | sql_or);
    2847          43 :                         if (!rr)
    2848             :                                 return NULL;
    2849          42 :                         if (lr->l == rr->l) {
    2850          42 :                                 lexps = lr->exps;
    2851          42 :                                 lr = lr->l;
    2852          42 :                                 rexps = rr->exps;
    2853          42 :                                 rr = rr->l;
    2854             :                         }
    2855          42 :                         rel = NULL;
    2856             :                 } else {
    2857       17631 :                         lr = rel_logical_exp(query, lr, lo, f | sql_or);
    2858       17631 :                         if (!lr)
    2859             :                                 return NULL;
    2860       17629 :                         rr = rel_logical_exp(query, rr, ro, f | sql_or);
    2861             :                 }
    2862             : 
    2863       17671 :                 if (!lr || !rr)
    2864             :                         return NULL;
    2865       17671 :                 return rel_or(sql, rel, lr, rr, exps, lexps, rexps);
    2866             :         }
    2867      196115 :         case SQL_AND:
    2868             :         {
    2869      196115 :                 symbol *lo = sc->data.lval->h->data.sym;
    2870      196115 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2871      196115 :                 rel = rel_logical_exp(query, rel, lo, f);
    2872      196115 :                 if (!rel)
    2873             :                         return NULL;
    2874      196108 :                 return rel_logical_exp(query, rel, ro, f);
    2875             :         }
    2876          60 :         case SQL_FILTER:
    2877             :                 /* [ x,..] filter [ y,..] */
    2878             :                 /* todo add anti, [ x,..] NOT filter [ y,...] */
    2879             :                 /* no correlation */
    2880             :         {
    2881          60 :                 dnode *ln = sc->data.lval->h->data.lval->h;
    2882          60 :                 dnode *rn = sc->data.lval->h->next->next->data.lval->h;
    2883          60 :                 dlist *filter_op = sc->data.lval->h->next->data.lval;
    2884          60 :                 char *fname = qname_schema_object(filter_op);
    2885          60 :                 char *sname = qname_schema(filter_op);
    2886          60 :                 list *l, *r;
    2887             : 
    2888          60 :                 l = sa_list(sql->sa);
    2889          60 :                 r = sa_list(sql->sa);
    2890         180 :                 for (; ln; ln = ln->next) {
    2891          60 :                         symbol *sym = ln->data.sym;
    2892             : 
    2893          60 :                         sql_exp *e = rel_value_exp(query, &rel, sym, f|sql_farg, ek);
    2894          60 :                         if (!e)
    2895             :                                 return NULL;
    2896          60 :                         list_append(l, e);
    2897             :                 }
    2898         163 :                 for (; rn; rn = rn->next) {
    2899         103 :                         symbol *sym = rn->data.sym;
    2900             : 
    2901         103 :                         sql_exp *e = rel_value_exp(query, &rel, sym, f|sql_farg, ek);
    2902         103 :                         if (!e)
    2903             :                                 return NULL;
    2904         103 :                         list_append(r, e);
    2905             :                 }
    2906          60 :                 return rel_filter(sql, rel, l, r, sname, fname, 0, f);
    2907             :         }
    2908      354995 :         case SQL_COMPARE:
    2909             :         {
    2910      354995 :                 dnode *n = sc->data.lval->h;
    2911      354995 :                 symbol *lo = n->data.sym;
    2912      354995 :                 symbol *ro = n->next->next->data.sym;
    2913      354995 :                 char *compare_op = n->next->data.sval;
    2914      354995 :                 int quantifier = 0;
    2915      354995 :                 int is_semantics = 0;
    2916             : 
    2917      354995 :                 if (n->next->next->next)
    2918         131 :                         quantifier = n->next->next->next->data.i_val + 1;
    2919         131 :                 assert(quantifier == 0 || quantifier == 1 || quantifier == 2 || quantifier == 3 || quantifier == 4);
    2920             : 
    2921      354995 :                 if (quantifier >= 3) {
    2922          10 :                         if (quantifier == 4)
    2923           6 :                                 compare_op = "<>";
    2924             :                         quantifier = 0;
    2925             :                         is_semantics = 1;
    2926             :                 }
    2927      354995 :                 return rel_compare(query, rel, sc, lo, ro, compare_op, f, ek, quantifier, is_semantics);
    2928             :         }
    2929             :         /* Set Member ship */
    2930       34048 :         case SQL_IN:
    2931             :         case SQL_NOT_IN:
    2932       34048 :                 return rel_in_exp(query, rel, sc, f);
    2933        1012 :         case SQL_EXISTS:
    2934             :         case SQL_NOT_EXISTS:
    2935        1012 :                 return rel_exists_exp(query, rel , sc, f);
    2936        3560 :         case SQL_LIKE:
    2937             :         case SQL_NOT_LIKE:
    2938             :         {
    2939        3560 :                 symbol *lo = sc->data.lval->h->data.sym;
    2940        3560 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2941        3560 :                 int insensitive = sc->data.lval->h->next->next->data.i_val;
    2942        3560 :                 int anti = (sc->token == SQL_NOT_LIKE) != (sc->data.lval->h->next->next->next->data.i_val != 0);
    2943        3560 :                 sql_subtype *st = sql_bind_localtype("str");
    2944        3560 :                 sql_exp *le = rel_value_exp(query, &rel, lo, f|sql_farg, ek), *re, *ee = NULL, *ie = exp_atom_bool(sql->sa, insensitive);
    2945             : 
    2946        3560 :                 if (!le)
    2947             :                         return NULL;
    2948             : 
    2949        3558 :                 if (!exp_subtype(le))
    2950           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameter not allowed on "
    2951             :                                         "left hand side of LIKE operator");
    2952             : 
    2953             :                 /* Do we need to escape ? */
    2954        3558 :                 if (dlist_length(ro->data.lval) == 2) {
    2955          82 :                         char *escape = ro->data.lval->h->next->data.sval;
    2956          82 :                         ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, escape)));
    2957             :                 } else {
    2958        3476 :                         ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, "")));
    2959             :                 }
    2960        3558 :                 ro = ro->data.lval->h->data.sym;
    2961        3558 :                 re = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
    2962        3558 :                 if (!re)
    2963             :                         return NULL;
    2964        3557 :                 if ((re = exp_check_type(sql, st, rel, re, type_equal)) == NULL)
    2965           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
    2966        3557 :                 if ((le = exp_check_type(sql, st, rel, le, type_equal)) == NULL)
    2967           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "LIKE: wrong type, should be string");
    2968        3557 :                 return rel_filter_exp_(sql, rel, le, re, ee, ie, "like", anti, f);
    2969             :         }
    2970        2959 :         case SQL_BETWEEN:
    2971             :         case SQL_NOT_BETWEEN:
    2972             :         {
    2973        2959 :                 symbol *lo = sc->data.lval->h->data.sym;
    2974        2959 :                 int symmetric = sc->data.lval->h->next->data.i_val;
    2975        2959 :                 symbol *ro1 = sc->data.lval->h->next->next->data.sym;
    2976        2959 :                 symbol *ro2 = sc->data.lval->h->next->next->next->data.sym;
    2977        2959 :                 sql_exp *le, *re1, *re2;
    2978        2959 :                 sql_subtype super;
    2979             : 
    2980        2959 :                 assert(sc->data.lval->h->next->type == type_int);
    2981             : 
    2982        2959 :                 if (!(le = rel_value_exp(query, &rel, lo, f|sql_farg, ek)))
    2983             :                         return NULL;
    2984        2957 :                 if (!(re1 = rel_value_exp(query, &rel, ro1, f|sql_farg, ek)))
    2985             :                         return NULL;
    2986        2955 :                 if (!(re2 = rel_value_exp(query, &rel, ro2, f|sql_farg, ek)))
    2987             :                         return NULL;
    2988             : 
    2989        2955 :                 if (exp_between_check_types(&super, exp_subtype(le), exp_subtype(re1), exp_subtype(re2)) < 0)
    2990           1 :                         return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
    2991             : 
    2992        2954 :                 if ((le = exp_check_type(sql, &super, rel, le, type_equal)) == NULL ||
    2993        2954 :                     (re1 = exp_check_type(sql, &super, rel, re1, type_equal)) == NULL ||
    2994        2954 :                     (re2 = exp_check_type(sql, &super, rel, re2, type_equal)) == NULL)
    2995           0 :                         return NULL;
    2996             : 
    2997        2954 :                 return rel_compare_exp_(query, rel, le, re1, re2, 3, sc->token == SQL_NOT_BETWEEN ? 1 : 0, 0, f, symmetric, 0);
    2998             :         }
    2999        7928 :         case SQL_IS_NULL:
    3000             :         case SQL_IS_NOT_NULL:
    3001             :         /* is (NOT) NULL */
    3002             :         {
    3003        7928 :                 sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
    3004        7928 :                 sql_subtype *t;
    3005             : 
    3006        7928 :                 if (!le)
    3007             :                         return NULL;
    3008        7924 :                 if (!(t = exp_subtype(le)))
    3009           1 :                         return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for IS%s NULL operator", sc->token == SQL_IS_NOT_NULL ? " NOT" : "");
    3010        7923 :                 le = exp_compare(sql->sa, le, exp_atom(sql->sa, atom_general(sql->sa, t, NULL, 0)), cmp_equal);
    3011        7923 :                 if (sc->token == SQL_IS_NOT_NULL)
    3012        2603 :                         set_anti(le);
    3013        7923 :                 set_has_no_nil(le);
    3014        7923 :                 set_semantics(le);
    3015        7923 :                 return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
    3016             :         }
    3017       20675 :         case SQL_NOT: {
    3018       20675 :                 if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
    3019        2330 :                         sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
    3020        2330 :                         return rel_logical_exp(query, rel, sc->data.sym, f);
    3021             :                 }
    3022       18345 :                 sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
    3023       18345 :                 sql_subtype bt;
    3024             : 
    3025       18345 :                 sql_find_subtype(&bt, "boolean", 0, 0);
    3026       18345 :                 if (!le || !(le = exp_check_type(sql, &bt, rel, le, type_equal)))
    3027           1 :                         return NULL;
    3028       18344 :                 le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 0), cmp_equal);
    3029       18344 :                 return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
    3030             :         }
    3031         629 :         case SQL_ATOM: {
    3032             :                 /* TRUE or FALSE */
    3033         629 :                 sql_rel *or = rel;
    3034         629 :                 AtomNode *an = (AtomNode *) sc;
    3035         629 :                 sql_exp *e = exp_atom(sql->sa, an->a);
    3036             : 
    3037         629 :                 if (e) {
    3038         629 :                         sql_subtype bt;
    3039             : 
    3040         629 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3041         629 :                         e = exp_check_type(sql, &bt, rel, e, type_equal);
    3042             :                 }
    3043         629 :                 if (!e || or != rel)
    3044           2 :                         return NULL;
    3045         627 :                 e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
    3046         627 :                 return rel_select_push_compare_exp_down(sql, rel, e, e->l, e->r, NULL, f);
    3047             :         }
    3048         710 :         case SQL_IDENT:
    3049             :         case SQL_COLUMN: {
    3050         710 :                 sql_rel *or = rel;
    3051         710 :                 sql_exp *e = rel_column_ref(query, &rel, sc, f);
    3052             : 
    3053         710 :                 if (e) {
    3054         707 :                         sql_subtype bt;
    3055             : 
    3056         707 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3057         707 :                         e = exp_check_type(sql, &bt, rel, e, type_equal);
    3058             :                 }
    3059         707 :                 if (!e || or != rel)
    3060           3 :                         return NULL;
    3061         707 :                 e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
    3062         707 :                 return rel_select_push_compare_exp_down(sql, rel, e, e->l, e->r, NULL, f);
    3063             :         }
    3064          12 :         case SQL_UNION:
    3065             :         case SQL_EXCEPT:
    3066             :         case SQL_INTERSECT: {
    3067          12 :                 sql_rel *sq;
    3068             : 
    3069          12 :                 if (is_psm_call(f) || is_sql_merge(f))
    3070           3 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: set operations not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
    3071          11 :                 if (rel)
    3072          11 :                         query_push_outer(query, rel, f);
    3073          11 :                 sq = rel_setquery(query, sc);
    3074          11 :                 if (rel) {
    3075          11 :                         rel = query_pop_outer(query);
    3076          11 :                         if (is_sql_join(f) && is_groupby(rel->op)) {
    3077           0 :                                 return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
    3078          11 :                         } else if (is_sql_where(f) && is_groupby(rel->op)) {
    3079           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
    3080          11 :                         } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby(rel->op)) {
    3081           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
    3082             :                         }
    3083             :                 }
    3084          11 :                 if (!sq)
    3085             :                         return NULL;
    3086          11 :                 assert(ek.type == type_value); /* I don't expect IN tuple matching calls to land here */
    3087          11 :                 if (is_sql_where(f) && is_groupby(rel->op))
    3088           0 :                         assert(0);
    3089          11 :                 if (ek.card <= card_set && is_project(sq->op) && list_length(sq->exps) > 1)
    3090           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
    3091          10 :                 if (!rel)
    3092             :                         return sq;
    3093          10 :                 sq = rel_zero_or_one(sql, sq, ek);
    3094          10 :                 if (is_sql_where(f) || is_sql_having(f)) {
    3095          10 :                         sql_exp *le = exp_rel(sql, sq);
    3096          10 :                         sql_subtype bt;
    3097             : 
    3098          10 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3099          10 :                         le = exp_check_type(sql, &bt, rel, le, type_equal);
    3100          10 :                         if (!le)
    3101             :                                 return NULL;
    3102          10 :                         le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 1), cmp_equal);
    3103          10 :                         return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
    3104             :                 } else {
    3105           0 :                         sq = rel_crossproduct(sql->sa, rel, sq, (f==sql_sel || is_single(sq))?op_left:op_join);
    3106           0 :                         set_processed(sq);
    3107             :                 }
    3108           0 :                 return sq;
    3109             :         }
    3110           0 :         case SQL_DEFAULT:
    3111           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DEFAULT keyword not allowed outside insert and update statements");
    3112         442 :         default: {
    3113         442 :                 sql_exp *le = rel_value_exp(query, &rel, sc, f|sql_farg, ek);
    3114         442 :                 sql_subtype bt;
    3115             : 
    3116         442 :                 if (!le)
    3117             :                         return NULL;
    3118         417 :                 if (le && (!is_compare(le->type) || le->flag > cmp_filter)) {
    3119         288 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3120         288 :                         if (!(le = exp_check_type(sql, &bt, rel, le, type_equal)))
    3121             :                                 return NULL;
    3122         288 :                         le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 1), cmp_equal);
    3123             :                 }
    3124         417 :                 if (le->flag == cmp_filter)
    3125         128 :                         return rel_select_push_filter_exp_down(sql, rel, le, le->l, le->r, f);
    3126             :                 else
    3127         289 :                         return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, le->f, f);
    3128             :         }
    3129             :         }
    3130             :         /* never reached, as all switch cases have a `return` */
    3131             : }
    3132             : 
    3133             : static sql_exp * _rel_aggr(sql_query *query, sql_rel **rel, int distinct, char *sname, char *aname, dnode *arguments, int f);
    3134             : static sql_exp *rel_aggr(sql_query *query, sql_rel **rel, symbol *se, int f);
    3135             : 
    3136             : sql_exp *
    3137       35174 : rel_unop_(mvc *sql, sql_rel *rel, sql_exp *e, char *sname, char *fname, int card)
    3138             : {
    3139       35174 :         bool found = false;
    3140       35174 :         sql_subtype *t = exp_subtype(e);
    3141       35174 :         sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:
    3142             :                    ((card == card_relation)?F_UNION:F_FUNC));
    3143             : 
    3144       35174 :         sql_subfunc *f = bind_func(sql, sname, fname, t, NULL, 1, type, false, &found, false);
    3145       35174 :         if (f) {
    3146       35173 :                 sql_arg *a = f->func->ops->h->data;
    3147       35173 :                 t = &a->type;
    3148             :         }
    3149       35174 :         if (f && t && type_has_tz(t) && f->func->fix_scale == SCALE_FIX) {
    3150             :                 /* set timezone (using msec (.3)) */
    3151           0 :                 sql_subtype *intsec = sql_bind_subtype(sql->sa, "sec_interval", 10 /*hour to second */, 3);
    3152           0 :                 atom *a = atom_int(sql->sa, intsec, sql->timezone);
    3153           0 :                 sql_exp *tz = exp_atom(sql->sa, a);
    3154             : 
    3155           0 :                 e = rel_binop_(sql, rel, e, tz, "sys", "sql_add", card, true);
    3156           0 :                 if (!e)
    3157             :                         return NULL;
    3158             :         }
    3159       35174 :         if (f) {
    3160       35173 :                 if (check_card(card, f)) {
    3161       35173 :                         list *args = list_append(sa_list(sql->sa), e);
    3162       70346 :                         args = check_arguments_and_find_largest_any_type(sql, rel, args, f, card == card_relation && e->card > CARD_ATOM, false);
    3163       35173 :                         if (args)
    3164       35173 :                                 return exp_op(sql->sa, args, f);
    3165             :                 }
    3166           0 :                 found = false; /* reset found */
    3167           0 :                 f = NULL;
    3168             :         }
    3169             :         /* reset error */
    3170           1 :         sql->session->status = 0;
    3171           1 :         sql->errstr[0] = '\0';
    3172           3 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s unary operator %s%s%s'%s'(%s)",
    3173           2 :                                          found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname, t ? t->type->base.name : "?");
    3174             : }
    3175             : 
    3176             : sql_exp *
    3177      156510 : rel_binop_(mvc *sql, sql_rel *rel, sql_exp *l, sql_exp *r, char *sname, char *fname, int card, bool exact)
    3178             : {
    3179      156510 :         sql_subtype *t1 = exp_subtype(l), *t2 = exp_subtype(r);
    3180      156510 :         sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC));
    3181      156510 :         bool found = false;
    3182             : 
    3183      156510 :         if (card == card_loader)
    3184           0 :                 card = card_none;
    3185             : 
    3186      156510 :         if (is_commutative(sname, fname) && l->card < r->card) { /* move constants to the right if possible */
    3187             :                 sql_subtype *tmp = t1;
    3188      156510 :                 t1 = t2;
    3189      156510 :                 t2 = tmp;
    3190             :                 sql_exp *res = l;
    3191      156510 :                 l = r;
    3192      156510 :                 r = res;
    3193             :         }
    3194             :         /* swap complex types (intervals) to left side of +, * */
    3195      156510 :         if (t1 && t2 && is_commutative(sname, fname)) {
    3196          68 :                 if ((EC_INTERVAL(t1->type->eclass) && EC_TEMP(t2->type->eclass)) ||
    3197          68 :            ((!EC_TEMP(t1->type->eclass) && !EC_INTERVAL(t1->type->eclass)) && EC_INTERVAL(t2->type->eclass))) {
    3198             :                         sql_subtype *tmp = t1;
    3199      156510 :                         t1 = t2;
    3200      156510 :                         t2 = tmp;
    3201             :                         sql_exp *res = l;
    3202      156510 :                         l = r;
    3203      156510 :                         r = res;
    3204             :                 }
    3205             :         }
    3206             : 
    3207      156510 :         sql_subfunc *f = bind_func(sql, sname, fname, t1, t2, 2, type, false, &found, exact);
    3208      156510 :         if (f && check_card(card,f)) {
    3209      156510 :                 t1 = exp_subtype(l);
    3210      156510 :                 t2 = exp_subtype(r);
    3211      156510 :                 list *args = list_append(list_append(sa_list(sql->sa), l), r);
    3212             : 
    3213      156510 :                 args = check_arguments_and_find_largest_any_type(sql, rel, args, f, 0, false);
    3214      156510 :                 if (args)
    3215      156510 :                                 return exp_op(sql->sa, args, f);
    3216             :                 return NULL;
    3217             :         }
    3218             : 
    3219           0 :         if (!exp_subtype(l) || !exp_subtype(r))
    3220           0 :                 return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) on both sides of an expression");
    3221           0 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s binary operator %s%s%s'%s'(%s,%s)",
    3222           0 :                                          found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname,
    3223           0 :                                          exp_subtype(l)->type->base.name, exp_subtype(r)->type->base.name);
    3224             : }
    3225             : 
    3226             : sql_exp *
    3227         539 : rel_nop_(mvc *sql, sql_rel *rel, sql_exp *a1, sql_exp *a2, sql_exp *a3, sql_exp *a4, char *sname, char *fname, int card)
    3228             : {
    3229         539 :         list *tl = sa_list(sql->sa);
    3230         539 :         sql_subfunc *f = NULL;
    3231         539 :         sql_ftype type = (card == card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC);
    3232             : 
    3233             :         /* rel_nop_ should only be called for functions available to everyone, ie defined at sql_types! */
    3234         539 :         (void) rel;
    3235         539 :         append(tl, exp_subtype(a1));
    3236         539 :         append(tl, exp_subtype(a2));
    3237         539 :         append(tl, exp_subtype(a3));
    3238         539 :         if (a4)
    3239         371 :                 append(tl, exp_subtype(a4));
    3240             : 
    3241         539 :         if (!(f = bind_func_(sql, sname, fname, tl, type, false, NULL, true)))
    3242             :                 return NULL;
    3243         539 :         if (!a4)
    3244         168 :                 return exp_op3(sql->sa, a1,a2,a3,f);
    3245         371 :         return exp_op4(sql->sa, a1,a2,a3,a4,f);
    3246             : }
    3247             : 
    3248             : static sql_func *
    3249           3 : inplace_func(mvc *sql)
    3250             : {
    3251           3 :         sql_func *f = SA_NEW(sql->sa, sql_func);
    3252             : 
    3253           3 :     *f = (sql_func) {
    3254             :         .mod = "",
    3255             :         .imp = "",
    3256             :         .type = F_PROC,
    3257             :         .lang = FUNC_LANG_INT,
    3258             :         .query = NULL,
    3259           3 :         .ops = sql->params,
    3260             :         .res = NULL,
    3261             :     };
    3262           3 :     base_init(sql->sa, &f->base, 0, true, NULL);
    3263           3 :     f->base.new = 1;
    3264           3 :     f->base.id = -1;
    3265           3 :     f->base.name = "-1";
    3266           3 :     f->instantiated = TRUE;
    3267           3 :         return f;
    3268             : }
    3269             : 
    3270             : static list *
    3271           3 : reorder_args(mvc *sql, list *exps, list *names, list *params)
    3272             : {
    3273           3 :         list *nexps = sa_list(sql->sa);
    3274           8 :         for(node *n = params->h; n; n = n->next) {
    3275           5 :                 sql_arg *a = n->data;
    3276           5 :                 int found =0;
    3277           7 :                 for(node *m = names->h, *o = exps->h; m && o; m = m->next, o = o->next) {
    3278           7 :                         if (strcmp(m->data, a->name) == 0) {
    3279           5 :                                 append(nexps, o->data);
    3280           5 :                                 found = 1;
    3281           5 :                                 break;
    3282             :                         }
    3283             :                 }
    3284           5 :                 if (!found)
    3285             :                         return NULL;
    3286             :         }
    3287             :         return nexps;
    3288             : }
    3289             : 
    3290             : static sql_exp *
    3291      554470 : rel_nop(sql_query *query, sql_rel **rel, symbol *se, int fs, exp_kind ek)
    3292             : {
    3293      554470 :         mvc *sql = query->sql;
    3294      554470 :         dnode *l = se->data.lval->h;
    3295      554470 :         dnode *ops = l->next->next->data.lval?l->next->next->data.lval->h:NULL;
    3296      554470 :         list *names = NULL;
    3297      554470 :         char *fname = NULL, *sname = NULL;;
    3298             : 
    3299      554470 :         if (l->type != type_int) {
    3300      548561 :                 int nargs = 0;
    3301      548561 :                 fname = qname_schema_object(l->data.lval);
    3302      548561 :                 sname = qname_schema(l->data.lval);
    3303             : 
    3304     1656483 :                 for (dnode *n = ops; n; n = n->next)
    3305     1107922 :                         nargs++;
    3306             : 
    3307             :                 /* first try aggregate */
    3308      548561 :                 if (find_func(sql, sname, fname, nargs, F_AGGR, false, NULL, NULL))
    3309       26284 :                         return _rel_aggr(query, rel, l->next->data.i_val, sname, fname, l->next->next->data.lval->h, fs);
    3310             :         }
    3311             : 
    3312      528186 :         int nr_args = 0;
    3313      528186 :         int split = (l->type == type_int && l->data.i_val == -1);
    3314      528186 :         list *exps = sa_list(sql->sa), *tl = sa_list(sql->sa);
    3315      528186 :         exp_kind iek = {type_value, card_column, FALSE};
    3316             : 
    3317      528186 :         if (split)
    3318           3 :                 names = sa_list(sql->sa);
    3319     1617109 :         for (; ops; ops = ops->next, nr_args++) {
    3320     1089009 :                 sql_exp *e = rel_value_exp(query, rel, ops->data.sym, fs|sql_farg, iek);
    3321     1089009 :                 if (!e)
    3322             :                         return NULL;
    3323     1088923 :                 if (split) {
    3324           5 :                         ops = ops->next;
    3325           5 :                         append(names, ops->data.sval);
    3326             :                 }
    3327     1088923 :                 append(exps, e);
    3328     1088923 :                 append(tl, exp_subtype(e));
    3329             :         }
    3330      528100 :         if (l->type == type_int) {
    3331             :                 /* exec nr (ops)*/
    3332        5908 :                 int nr = l->data.i_val;
    3333        5908 :                 cq *q = NULL;
    3334             : 
    3335        5908 :                 if (nr == -1 || (q = qc_find(sql->qc, nr))) {
    3336        5906 :                         list *nexps = new_exp_list(sql->sa);
    3337        5906 :                         sql_func *f = q?q->f:inplace_func(sql);
    3338        5906 :                         list *ops = q?f->ops:sql->params;
    3339             : 
    3340        5906 :                         tl = sa_list(sql->sa);
    3341        5906 :                         if (list_length(ops) != list_length(exps))
    3342           3 :                                 return sql_error(sql, 02, SQLSTATE(42000) "EXEC called with wrong number of arguments: expected %d, got %d", list_length(ops), list_length(exps));
    3343        5903 :                         if (split) {
    3344           3 :                                 exps = reorder_args(sql, exps, names, ops);
    3345           3 :                                 if (!exps)
    3346           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "EXEC called with wrong arguments");
    3347             :                         }
    3348        5903 :                         if (exps->h && ops) {
    3349       21927 :                                 for (node *n = exps->h, *m = ops->h; n && m; n = n->next, m = m->next) {
    3350       16115 :                                         sql_arg *a = m->data;
    3351       16115 :                                         sql_exp *e = n->data;
    3352       16115 :                                         sql_subtype *ntp = &a->type;
    3353             : 
    3354       16115 :                                         if (ntp && ntp->type)
    3355       16115 :                                                 e = exp_check_type(sql, ntp, NULL, e, type_equal);
    3356             :                                         else
    3357           0 :                                                 a->type = *exp_subtype(e);
    3358       16115 :                                         if (!e)
    3359             :                                                 return NULL;
    3360       16114 :                                         append(nexps, e);
    3361       16114 :                                         append(tl, exp_subtype(e));
    3362             :                                 }
    3363             :                         }
    3364             : 
    3365        5902 :                         if (q)
    3366        5899 :                                 sql->type = q->type;
    3367        5992 :                         return exp_op(sql->sa, list_empty(nexps) ? NULL : nexps, sql_dup_subfunc(sql->sa, f, tl, NULL));
    3368             :                 } else {
    3369           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "EXEC: PREPARED Statement missing '%d'", nr);
    3370             :                 }
    3371             :         }
    3372             : 
    3373      522192 :         if (nr_args == 2 && is_commutative(sname, fname)) {
    3374      123227 :                 sql_subtype *t1 = tl->h->data;
    3375      123227 :                 sql_subtype *t2 = tl->t->data;
    3376             : 
    3377      123227 :                 if (t1 && t2 && ((EC_INTERVAL(t1->type->eclass) && EC_TEMP(t2->type->eclass)) ||
    3378      123218 :            ((!EC_TEMP(t1->type->eclass) && !EC_INTERVAL(t1->type->eclass)) && EC_INTERVAL(t2->type->eclass)))) {
    3379           8 :                         list_revert(exps);
    3380           8 :                         list_revert(tl);
    3381             :                 }
    3382             : 
    3383             :         }
    3384             : 
    3385      522192 :         if (!sname && strcmp(fname, "field") == 0) { /* map into join */
    3386           1 :                 if (list_length(exps) < 2)
    3387           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "Field function called with not enough arguments");
    3388           0 :                 sql_exp *le = exps->h->data;
    3389           0 :                 set_freevar(le, 1);
    3390           0 :                 list_remove_data(exps, NULL, le);
    3391           0 :                 sql_exp *re = exp_values(sql->sa, exps);
    3392           0 :                 exp_label(sql->sa, re, ++sql->label);
    3393           0 :                 sql_rel *r = rel_project(sql->sa, NULL, append(sa_list(sql->sa), re));
    3394           0 :                 sql_exp *id = NULL;
    3395           0 :                 rel_add_identity(sql, r, &id);
    3396           0 :                 re = exp_ref(sql, re);
    3397           0 :                 id = exp_ref(sql, id);
    3398           0 :                 if (r) {
    3399           0 :                         r->nrcols = list_length(exps);
    3400           0 :                         sql_exp *e = exp_compare(sql->sa, le, re, cmp_equal);
    3401           0 :                         r = rel_select(sql->sa, r, e);
    3402           0 :                         r = rel_project(sql->sa, r, append(sa_list(sql->sa), exp_convert(sql, id, exp_subtype(id), sql_bind_localtype("int"))));
    3403           0 :                         re = exp_rel(sql, r);
    3404           0 :                         return re;
    3405             :                 }
    3406             :         }
    3407      522191 :         return _rel_nop(sql, sname, fname, tl, rel ? *rel : NULL, exps, ek);
    3408             : }
    3409             : 
    3410             : typedef struct aggr_input {
    3411             :         sql_query *query;
    3412             :         int groupby;
    3413             :         char *err;
    3414             : } aggr_input;
    3415             : 
    3416             : static sql_exp *
    3417         373 : exp_valid(visitor *v, sql_rel *rel, sql_exp *e, int depth)
    3418             : {
    3419         373 :         aggr_input *ai = v->data;
    3420         373 :         (void)rel; (void)depth;
    3421             : 
    3422         373 :         int vf = is_freevar(e);
    3423         373 :         if (!v->changes && vf && vf < ai->groupby) { /* check need with outer query */
    3424          14 :                 sql_rel *sq = query_fetch_outer(ai->query, vf-1);
    3425             : 
    3426             :                 /* problem freevar have cardinality CARD_ATOM */
    3427          14 :                 if (sq->card <= CARD_AGGR && exp_card(e) != CARD_AGGR && is_alias(e->type)) {
    3428           4 :                         if (!exps_bind_column(sq->exps, e->l, e->r, NULL, 0)) {
    3429           1 :                                 v->changes = 1;
    3430           1 :                                 ai->err = SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query";
    3431             :                         }
    3432             :                 }
    3433         359 :         } else if (!v->changes && vf && vf == ai->groupby) { /* check if input is already aggregated */
    3434         280 :                 sql_rel *sq = query_fetch_outer(ai->query, vf-1);
    3435         280 :                 sql_exp *a = NULL;
    3436             : 
    3437         280 :                 if (sq->card <= CARD_AGGR && is_alias(e->type)) {
    3438         187 :                         if ((a = exps_bind_column(sq->exps, e->l, e->r, NULL, 0)) && is_aggr(a->type)) { /* aggregate */
    3439           9 :                                 v->changes = 1;
    3440           9 :                                 ai->err = SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested";
    3441             :                         }
    3442             :                 }
    3443             :         }
    3444         373 :         return e;
    3445             : }
    3446             : 
    3447             : static char *
    3448         273 : exps_valid(sql_query *query, list *exps, int groupby)
    3449             : {
    3450         273 :         aggr_input ai = { .query = query, .groupby = groupby };
    3451         273 :         visitor v = { .sql = query->sql, .data = &ai };
    3452             : 
    3453         273 :         exps_exp_visitor_topdown(&v, NULL, exps, 0, &exp_valid, true);
    3454         273 :         if (v.changes)
    3455          10 :                 return ai.err;
    3456             :         return NULL;
    3457             : }
    3458             : 
    3459             : static list * rel_order_by(sql_query *query, sql_rel **R, symbol *orderby, int needs_distinct, int f);
    3460             : 
    3461             : static sql_exp *
    3462       45740 : _rel_aggr(sql_query *query, sql_rel **rel, int distinct, char *sname, char *aname, dnode *args, int f)
    3463             : {
    3464       45740 :         mvc *sql = query->sql;
    3465       45740 :         exp_kind ek = {type_value, card_column, FALSE};
    3466       45740 :         sql_subfunc *a = NULL;
    3467       45740 :         int no_nil = 0, group = 0, all_aggr = query_has_outer(query), i;
    3468       45740 :         unsigned int all_freevar = 0;
    3469       45740 :         sql_rel *groupby = rel ? *rel : NULL, *sel = NULL, *gr, *og = NULL, *res = groupby;
    3470       45740 :         sql_rel *subquery = NULL;
    3471       45740 :         list *exps = NULL, *ungrouped_cols = NULL;
    3472       45740 :         bool is_grouping = !strcmp(aname, "grouping"), has_args = false, found = false, used_rel = false;
    3473             : 
    3474       45740 :         if (!all_aggr) {
    3475       30797 :                 if (!groupby) {
    3476           4 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3477           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: missing group by", toUpperCopy(uaname, aname));
    3478       30793 :                 } else if (is_sql_groupby(f)) {
    3479           8 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3480           8 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", toUpperCopy(uaname, aname), aname);
    3481       30785 :                 } else if (is_sql_values(f)) {
    3482           1 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3483           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed on an unique value", toUpperCopy(uaname, aname));
    3484       30784 :                 } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */
    3485           3 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3486           3 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", toUpperCopy(uaname, aname));
    3487       30781 :                 } else if (is_sql_where(f)) {
    3488           4 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3489           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
    3490       30777 :                 } else if (is_sql_update_set(f) || is_sql_psm(f)) {
    3491           1 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3492           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses (use subquery)", toUpperCopy(uaname, aname));
    3493       30776 :                 } else if (is_sql_aggr(f)) {
    3494           4 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3495           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
    3496       30772 :                 } else if (is_psm_call(f)) {
    3497           0 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3498           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed inside CALL", toUpperCopy(uaname, aname));
    3499       30772 :                 } else if (is_sql_from(f)) {
    3500           0 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3501           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in functions in FROM", toUpperCopy(uaname, aname));
    3502             :                 }
    3503             :         }
    3504             : 
    3505       45715 :         exps = sa_list(sql->sa);
    3506       45715 :         if (args && args->data.sym) {
    3507       26374 :                 bool arguments_correlated = true, all_const = true;
    3508             : 
    3509       26374 :                 all_freevar = all_aggr?1:0;
    3510       61464 :                 for (i = 0; args && args->data.sym && args->data.sym->token != SQL_ORDERBY; args = args->next, i++) {
    3511       35150 :                         int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
    3512       27189 :                         sql_rel *gl = base?groupby:groupby->l, *ogl = gl; /* handle case of subqueries without correlation */
    3513       35150 :                         sql_exp *e = rel_value_exp(query, &gl, args->data.sym, (f | sql_aggr)& ~sql_farg, ek);
    3514       35150 :                         bool found_one_freevar = false;
    3515             : 
    3516       35150 :                         if (!e)
    3517          60 :                                 return NULL;
    3518       35096 :                         used_rel |= (rel_has_exp(gl, e, true) == 0);
    3519       35096 :                         has_args = true;
    3520       35096 :                         if (gl && gl != ogl) {
    3521           5 :                                 if (gl->grouped) {
    3522           5 :                                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3523           5 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
    3524             :                                 }
    3525           0 :                                 if (!base)
    3526           0 :                                         groupby->l = subquery = gl;
    3527             :                                 else
    3528             :                                         groupby = subquery = gl;
    3529             :                         }
    3530       35091 :                         sql_subtype *t = exp_subtype(e);
    3531       35091 :                         if (!t) { /* we also do not expect parameters here */
    3532           1 :                                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3533           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to aggregate functions", toUpperCopy(uaname, aname));
    3534             :                         }
    3535       35090 :                         if (!t->type->localtype) {
    3536          47 :                                 if (e->type == e_atom && !e->f) {
    3537          44 :                                         t = sql_bind_localtype("bte");
    3538          44 :                                         e->tpe = *t;
    3539          44 :                                         if (e->l)
    3540          44 :                                                 e->l = atom_set_type(sql->sa, e->l, t);
    3541             :                                 }
    3542             :                         }
    3543             : 
    3544       35090 :                         all_aggr &= (exp_card(e) <= CARD_AGGR && !exp_is_atom(e) && is_aggr(e->type) && !is_func(e->type) && (!groupby || !is_groupby(groupby->op) || !groupby->r || !exps_find_exp(groupby->r, e)));
    3545       35090 :                         exp_only_freevar(query, e, &arguments_correlated, &found_one_freevar, &ungrouped_cols);
    3546       35090 :                         all_freevar &= (arguments_correlated && found_one_freevar) || (is_atom(e->type)?all_freevar:0); /* no uncorrelated variables must be found, plus at least one correlated variable to push this aggregate to an outer query */
    3547       35090 :                         all_const &= is_atom(e->type);
    3548       35090 :                         list_append(exps, e);
    3549             :                 }
    3550       26314 :                 if (all_const)
    3551         206 :                         all_freevar = 0;
    3552             :         }
    3553       45655 :         if (!all_freevar) {
    3554       45362 :                 if (is_sql_groupby(f)) {
    3555           1 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3556           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", toUpperCopy(uaname, aname), aname);
    3557       45361 :                 } else if (is_sql_from(f)) {
    3558           2 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3559           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in functions in FROM", toUpperCopy(uaname, aname));
    3560       45359 :                 } else if (is_sql_aggr(f) && groupby->grouped) {
    3561           2 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3562           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
    3563       45357 :                 } else if (is_sql_values(f)) {
    3564           1 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3565           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed on an unique value", toUpperCopy(uaname, aname));
    3566       45356 :                 } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */
    3567           1 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3568           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", toUpperCopy(uaname, aname));
    3569       45355 :                 } else if (is_sql_where(f)) {
    3570           5 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3571           5 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
    3572       45350 :                 } else if (!all_aggr && !list_empty(ungrouped_cols)) {
    3573         123 :                         for (node *n = ungrouped_cols->h ; n ; n = n->next) {
    3574          66 :                                 sql_rel *outer;
    3575          66 :                                 sql_exp *e = (sql_exp*) n->data;
    3576             : 
    3577          66 :                                 if ((outer = query_fetch_outer(query, is_freevar(e)-1))) {
    3578          66 :                                         int of = query_fetch_outer_state(query, is_freevar(e)-1);
    3579          66 :                                         if (outer->grouped) {
    3580          24 :                                                 bool err = false, was_processed = false;
    3581             : 
    3582          24 :                                                 if (is_processed(outer)) {
    3583           5 :                                                         was_processed = true;
    3584           5 :                                                         reset_processed(outer);
    3585             :                                                 }
    3586          24 :                                                 if (!is_groupby_col(outer, e))
    3587           3 :                                                         err = true;
    3588          24 :                                                 if (was_processed)
    3589           5 :                                                         set_processed(outer);
    3590          24 :                                                 if (err) {
    3591           3 :                                                         if (exp_name(e) && exp_relname(e) && !has_label(e))
    3592           3 :                                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(e), exp_name(e));
    3593           0 :                                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    3594             :                                                 }
    3595          42 :                                         } else if (!used_rel && is_sql_where(of)) {
    3596           2 :                                                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3597           2 :                                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", toUpperCopy(uaname, aname));
    3598          40 :                                         } else if (!is_sql_aggr(of)) {
    3599          36 :                                                 set_outer(outer);
    3600             :                                         }
    3601             :                                 }
    3602             :                         }
    3603             :                 }
    3604             :         }
    3605             : 
    3606       45638 :         if (all_freevar) { /* case 2, ie use outer */
    3607         293 :                 int card;
    3608         293 :                 sql_exp *exp = NULL;
    3609             :                 /* find proper groupby relation */
    3610         593 :                 for (node *n = exps->h; n; n = n->next) {
    3611         300 :                         sql_exp *e = n->data;
    3612             : 
    3613         300 :                         int vf = exp_freevar_offset(sql, e);
    3614         300 :                         if (vf > (int)all_freevar)
    3615          23 :                                 all_freevar = vf;
    3616         300 :                         exp = e;
    3617             :                 }
    3618         293 :                 if (query_has_outer(query) >= all_freevar) {
    3619         293 :                         int sql_state = query_fetch_outer_state(query,all_freevar-1);
    3620         293 :                         res = groupby = query_fetch_outer(query, all_freevar-1);
    3621         293 :                         card = query_outer_used_card(query, all_freevar-1);
    3622             :                         /* given groupby validate all input expressions */
    3623         293 :                         char *err;
    3624         293 :                         if (groupby && !is_groupby(groupby->op)) {
    3625         112 :                                 sql_exp *p = query_outer_last_used(query, all_freevar-1);
    3626         112 :                                 if (p && !is_aggr(p->type) && !is_groupby_col(groupby, p)) {
    3627          20 :                                         if (p->type == e_column)
    3628          20 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", (char*)p->l, (char*)p->r);
    3629           0 :                                         if (exp_name(p) && exp_relname(p) && !has_label(p))
    3630           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(p), exp_name(p));
    3631           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    3632             :                                 }
    3633             :                         }
    3634         273 :                         if ((err = exps_valid(query, exps, all_freevar)) != NULL) {
    3635          10 :                                 strcpy(sql->errstr, err);
    3636          10 :                                 sql->session->status = -ERR_GROUPBY;
    3637          10 :                                 return NULL;
    3638             :                         }
    3639         263 :                         if (exp && !is_groupby_col(res, exp)) {
    3640         192 :                                 if (is_sql_groupby(sql_state))
    3641           2 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate function '%s' not allowed in GROUP BY clause", aname);
    3642         190 :                                 if (is_sql_aggr(sql_state) && groupby->grouped) {
    3643           3 :                                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3644           3 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", toUpperCopy(uaname, aname));
    3645             :                                 }
    3646         187 :                                 if (is_sql_values(sql_state))
    3647           0 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed on an unique value");
    3648         187 :                                 if (is_sql_update_set(sql_state) || is_sql_psm(f))
    3649           2 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
    3650         185 :                                 if (is_sql_join(sql_state))
    3651           4 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
    3652         181 :                                 if (is_sql_where(sql_state))
    3653           3 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
    3654         178 :                                 if (is_psm_call(sql_state))
    3655           0 :                                         return sql_error(sql, 05, SQLSTATE(42000) "CALL: aggregate functions not allowed inside CALL");
    3656         178 :                                 if (is_sql_from(sql_state))
    3657           0 :                                         return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in functions in FROM");
    3658         178 :                                 if (card > CARD_AGGR) { /* used an expression before on the non grouped relation */
    3659           0 :                                         sql_exp *lu = query_outer_last_used(query, all_freevar-1);
    3660           0 :                                         if (lu->type == e_column)
    3661           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", (char*)lu->l, (char*)lu->r);
    3662           0 :                                         if (exp_name(lu) && exp_relname(lu) && !has_label(lu))
    3663           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu));
    3664           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    3665             :                                 }
    3666         178 :                                 if (is_outer(groupby))
    3667           2 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    3668             :                         }
    3669             :                 } else {
    3670             :                         all_freevar = 0;
    3671             :                 }
    3672       45345 :         } else if (!subquery && groupby && is_outer(groupby) && !is_groupby(groupby->op))
    3673           1 :                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query");
    3674             : 
    3675             :         /* find having select */
    3676       45591 :         if (!subquery && groupby && !is_processed(groupby) && is_sql_having(f)) {
    3677         108 :                 og = groupby;
    3678         108 :                 while(!is_processed(groupby) && !is_base(groupby->op)) {
    3679          63 :                         if (is_select(groupby->op) || !groupby->l)
    3680             :                                 break;
    3681             :                         if (groupby->l)
    3682             :                                 groupby = groupby->l;
    3683             :                 }
    3684          67 :                 if (groupby && is_select(groupby->op) && !is_processed(groupby)) {
    3685          22 :                         group = 1;
    3686          22 :                         sel = groupby;
    3687             :                         /* At the end we switch back to the old projection relation og.
    3688             :                          * During the partitioning and ordering we add the expressions to the intermediate relations. */
    3689             :                 }
    3690          22 :                 if (!sel)
    3691             :                         groupby = og;
    3692          22 :                 if (sel && sel->l)
    3693          22 :                         groupby = sel->l;
    3694             :         }
    3695             : 
    3696             :         /* find groupby */
    3697       45591 :         if (!subquery && groupby && !is_processed(groupby) && !is_base(groupby->op)) {
    3698       30648 :                 og = groupby;
    3699       30648 :                 groupby = rel_find_groupby(groupby);
    3700       30648 :                 if (groupby)
    3701             :                         group = 1;
    3702             :                 else
    3703             :                         groupby = og;
    3704             :         }
    3705             : 
    3706        7865 :         if (!groupby && exps_card(exps) > CARD_ATOM) {
    3707           0 :                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3708           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: missing group by", toUpperCopy(uaname, aname));
    3709             :         }
    3710             : 
    3711       45591 :         if (!subquery && groupby && groupby->op != op_groupby) {             /* implicit groupby */
    3712       21069 :                 if (!all_freevar && query->last_exp && !is_sql_aggr(query->last_state)) {
    3713           9 :                         if (exp_relname(query->last_exp) && exp_name(query->last_exp) && !has_label(query->last_exp))
    3714           9 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query results without an aggregate function", exp_relname(query->last_exp), exp_name(query->last_exp));
    3715           0 :                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    3716             :                 }
    3717       21060 :                 res = groupby = rel_groupby(sql, groupby, NULL);
    3718             :         }
    3719       45582 :         if (subquery) {
    3720           0 :                 assert(!all_freevar);
    3721           0 :                 res = groupby;
    3722           0 :                 if (is_sql_sel(f) && is_left(subquery->op) && !is_groupby(groupby->op)) {
    3723           0 :                         res = groupby = rel_groupby(sql, groupby, NULL);
    3724           0 :                         exps_set_freevar(sql, exps, groupby); /* mark free variables */
    3725           0 :                 } else if (!is_groupby(groupby->op)) {
    3726           0 :                         res = groupby = rel_groupby(sql, groupby, NULL);
    3727             :                 }
    3728           0 :                 assert(!is_base(groupby->op));
    3729             :         }
    3730       45582 :         if ((!exps || exps_card(exps) > CARD_ATOM) && (!res || !groupby))
    3731             :                 return NULL;
    3732             : 
    3733       45582 :         list *obe = NULL;
    3734       45582 :         bool handled_order = true;
    3735       45582 :         if (args && args->data.sym && args->data.sym->token != SQL_ORDERBY)
    3736             :                         return NULL;
    3737       19337 :         if (args && args->data.sym) { /* handle order by */
    3738           0 :                 int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
    3739           0 :                 sql_rel *gl = base?groupby:groupby->l;//, *ogl = gl; /* handle case of subqueries without correlation */
    3740           0 :                 obe = rel_order_by(query, &gl, args->data.sym, 0, f);
    3741           0 :                 if (!obe)
    3742           0 :                         return NULL;
    3743           0 :                 handled_order = false;
    3744             :         }
    3745             : 
    3746       45582 :         if (all_freevar) {
    3747         247 :                 query_update_outer(query, res, all_freevar-1);
    3748       45335 :         } else if (rel) {
    3749       45335 :                 *rel = res;
    3750       45335 :                 if (query->last_rel != res) {
    3751       41397 :                         query->last_rel = res;
    3752       41397 :                         query->last_state |= sql_aggr;
    3753             :                 }
    3754             :         }
    3755             : 
    3756       45582 :         if (!has_args) {        /* count(*) case */
    3757       19337 :                 obe = NULL; /* no errors, although the order by is useless */
    3758       19337 :                 sql_exp *e;
    3759             : 
    3760       19337 :                 if (strcmp(aname, "count") != 0) {
    3761           2 :                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3762           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: unable to perform '%s(*)'", toUpperCopy(uaname, aname), aname);
    3763             :                 }
    3764       19335 :                 a = sql_bind_func(sql, "sys", aname, sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    3765       19335 :                 e = exp_aggr(sql->sa, NULL, a, distinct, 0, groupby?groupby->card:CARD_ATOM, 0);
    3766             : 
    3767       19335 :                 if (!groupby)
    3768             :                         return e;
    3769       19335 :                 if (all_freevar)
    3770           0 :                         query_outer_used_exp(query, all_freevar-1, e, sql_aggr);
    3771       19335 :                 e = rel_groupby_add_aggr(sql, groupby, e);
    3772       19335 :                 if (!group && !all_freevar)
    3773             :                         return e;
    3774        3212 :                 if (all_freevar) {
    3775           0 :                         assert(!is_simple_project(res->op));
    3776           0 :                         e->card = CARD_ATOM;
    3777           0 :                         set_freevar(e, all_freevar-1);
    3778           0 :                         return e;
    3779             :                 }
    3780             :                 return e;
    3781             :         }
    3782             : 
    3783             :         /* use cnt as nils shouldn't be counted */
    3784       26245 :         no_nil = 1;
    3785             : 
    3786       26245 :         gr = groupby;
    3787       26245 :         if (gr && gr->op == op_project && gr->l)
    3788             :                 gr = gr->l;
    3789             : 
    3790       26245 :         if (is_grouping) {
    3791         109 :                 sql_subtype *tpe;
    3792         109 :                 list *l = (list*) groupby->r;
    3793             : 
    3794         109 :                 if (list_length(l) <= 7)
    3795         107 :                         tpe = sql_bind_localtype("bte");
    3796           2 :                 else if (list_length(l) <= 15)
    3797           2 :                         tpe = sql_bind_localtype("sht");
    3798           0 :                 else if (list_length(l) <= 31)
    3799           0 :                         tpe = sql_bind_localtype("int");
    3800           0 :                 else if (list_length(l) <= 63)
    3801           0 :                         tpe = sql_bind_localtype("lng");
    3802             : #ifdef HAVE_HGE
    3803           0 :                 else if (list_length(l) <= 127)
    3804           0 :                         tpe = sql_bind_localtype("hge");
    3805             : #endif
    3806             :                 else
    3807           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUPING the number of grouping columns is larger"
    3808             :                                                                 " than the maximum number of representable bits from this server (%d > %d)", list_length(l),
    3809             : #ifdef HAVE_HGE
    3810             :                                                         127
    3811             : #else
    3812             :                                                          63
    3813             : #endif
    3814             :                                                         );
    3815         109 :                 a = sql_bind_func_result(sql, sname, aname, F_AGGR, true, tpe, 1, exp_subtype(exps->h->data));
    3816             :         } else {
    3817       26136 :                 a = sql_bind_func_(sql, sname, aname, exp_types(sql->sa, exps), F_AGGR, false, false);
    3818       26136 :                 if (!a && obe && list_length(obe) == 1) { /* try to find aggregation function with requires order by column */
    3819           0 :                         list *nexps = append(sa_list(sql->sa), obe->h->data);
    3820           0 :                         nexps = list_merge(nexps, exps, (fdup) NULL);
    3821           0 :                         a = sql_bind_func_(sql, sname, aname, exp_types(sql->sa, nexps), F_AGGR, false, false);
    3822           0 :                         if (a && a->func->order_required) {
    3823             :                                 /* reset error */
    3824           0 :                                 handled_order = true;
    3825           0 :                                 sql->session->status = 0;
    3826           0 :                                 sql->errstr[0] = '\0';
    3827           0 :                                 exps = nexps;
    3828           0 :                                 obe = NULL;
    3829             :                         }
    3830             :                 }
    3831             :         }
    3832             : 
    3833       26245 :         if (a) {
    3834       26240 :                 found = true;
    3835       26240 :                 if (!execute_priv(sql, a->func))
    3836           0 :                         a = NULL;
    3837       26240 :                 if (!is_grouping && a && !(exps = check_arguments_and_find_largest_any_type(sql, rel ? *rel : NULL, exps, a, 0, false)))
    3838           0 :                         a = NULL;
    3839             :         }
    3840             : 
    3841       26245 :         if (a) {
    3842       26240 :                 bool hasnil = have_nil(exps) || (strcmp(aname, "count") != 0 && (!groupby || list_empty(groupby->r))); /* for global case, the aggregate may return NULL */
    3843       26240 :                 sql_exp *e = exp_aggr(sql->sa, exps, a, distinct, no_nil, groupby?groupby->card:CARD_ATOM, hasnil);
    3844             : 
    3845       26240 :                 if (!obe && a->func->order_required && !handled_order) {
    3846             :                         /* TODO preper error on missing order by */
    3847             :                         return NULL;
    3848             :                 }
    3849           0 :                 if (obe && !a->func->order_required && !a->func->opt_order)
    3850             :                         obe = NULL;
    3851           0 :                 if (obe) /* add order by expressions */
    3852           0 :                         e->r = append(sa_list(sql->sa), obe);
    3853       26240 :                 if (!groupby)
    3854             :                         return e;
    3855       26240 :                 if (all_freevar)
    3856         247 :                         query_outer_aggregated(query, all_freevar-1, e);
    3857       26240 :                 e = rel_groupby_add_aggr(sql, groupby, e);
    3858       26240 :                 if (!group && !all_freevar)
    3859             :                         return e;
    3860       19689 :                 if (all_freevar) {
    3861         247 :                         rel_bind_vars(sql, groupby->l, exps);
    3862         247 :                         assert(!is_simple_project(res->op));
    3863         247 :                         e->card = CARD_ATOM;
    3864         247 :                         set_freevar(e, all_freevar-1);
    3865         247 :                         return e;
    3866             :                 }
    3867             :                 return e;
    3868             :         }
    3869           5 :         const char *type = "unknown";
    3870           5 :         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    3871             : 
    3872           5 :         if (!list_empty(exps)) {
    3873           5 :                 sql_exp *e = exps->h->data;
    3874           5 :                 type = exp_subtype(e)->type->base.name;
    3875             :         }
    3876          15 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "%s: %s aggregate %s%s%s'%s'(%s)", toUpperCopy(uaname, aname), found ? "insufficient privileges for" : "no such",
    3877             :                                          sname ? "'":"", sname ? sname : "", sname ? "'.":"", aname, type);
    3878             : }
    3879             : 
    3880             : static sql_exp *
    3881       19456 : rel_aggr(sql_query *query, sql_rel **rel, symbol *se, int f)
    3882             : {
    3883       19456 :         dlist *l = se->data.lval;
    3884       19456 :         dnode *d = l->h->next->next;
    3885       19456 :         int distinct = l->h->next->data.i_val;
    3886       19456 :         char *aname = qname_schema_object(l->h->data.lval);
    3887       19456 :         char *sname = qname_schema(l->h->data.lval);
    3888             : 
    3889       19456 :         return _rel_aggr(query, rel, distinct, sname, aname, d, f);
    3890             : }
    3891             : 
    3892             : static sql_exp *
    3893      101268 : rel_case(sql_query *query, sql_rel **rel, symbol *opt_cond, dlist *when_search_list, symbol *opt_else, int f)
    3894             : {
    3895      101268 :         mvc *sql = query->sql;
    3896      101268 :         sql_subtype *tpe = NULL;
    3897      101268 :         list *conds = new_exp_list(sql->sa), *results = new_exp_list(sql->sa);
    3898      101268 :         sql_subtype *restype = NULL, *condtype = NULL, ctype, rtype, bt;
    3899      101268 :         sql_exp *res = NULL, *opt_cond_exp = NULL;
    3900      101268 :         exp_kind ek = {type_value, card_column, FALSE};
    3901             : 
    3902      101268 :         if (opt_cond) {
    3903        9532 :                 if (!(opt_cond_exp = rel_value_exp(query, rel, opt_cond, f, ek)))
    3904             :                         return NULL;
    3905        9531 :                 condtype = exp_subtype(opt_cond_exp);
    3906             :         }
    3907             : 
    3908      250105 :         for (dnode *dn = when_search_list->h; dn; dn = dn->next) {
    3909      148847 :                 sql_exp *cond = NULL, *result = NULL;
    3910      148847 :                 dlist *when = dn->data.sym->data.lval;
    3911             : 
    3912      148847 :                 if (opt_cond)
    3913       45936 :                         cond = rel_value_exp(query, rel, when->h->data.sym, f, ek);
    3914             :                 else
    3915      102911 :                         cond = rel_logical_value_exp(query, rel, when->h->data.sym, f, ek);
    3916      148847 :                 if (!cond)
    3917             :                         return NULL;
    3918      148841 :                 append(conds, cond);
    3919      148841 :                 tpe = exp_subtype(cond);
    3920      148841 :                 if (tpe && condtype) {
    3921       57105 :                         result_datatype(&ctype, condtype, tpe);
    3922       57105 :                         condtype = &ctype;
    3923       91736 :                 } else if (tpe) {
    3924       91734 :                         condtype = tpe;
    3925             :                 }
    3926             : 
    3927      148841 :                 if (!(result = rel_value_exp(query, rel, when->h->next->data.sym, f, ek)))
    3928             :                         return NULL;
    3929      148838 :                 append(results, result);
    3930      148838 :                 tpe = exp_subtype(result);
    3931      148838 :                 if (tpe && restype) {
    3932       47577 :                         result_datatype(&rtype, restype, tpe);
    3933       47577 :                         restype = &rtype;
    3934      101261 :                 } else if (tpe) {
    3935      101255 :                         restype = tpe;
    3936             :                 }
    3937             :         }
    3938      101258 :         if (opt_else) {
    3939       98664 :                 if (!(res = rel_value_exp(query, rel, opt_else, f, ek)))
    3940             :                         return NULL;
    3941             : 
    3942       98664 :                 tpe = exp_subtype(res);
    3943       98664 :                 if (tpe && restype) {
    3944       98659 :                         result_datatype(&rtype, restype, tpe);
    3945       98659 :                         restype = &rtype;
    3946           5 :                 } else if (tpe) {
    3947             :                         restype = tpe;
    3948             :                 }
    3949             : 
    3950       98662 :                 if (!restype)
    3951           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
    3952       98662 :                 if (restype->type->localtype == TYPE_void) /* NULL */
    3953           0 :                         restype = sql_bind_localtype("str");
    3954             : 
    3955       98662 :                 if (!(res = exp_check_type(sql, restype, rel ? *rel : NULL, res, type_equal)))
    3956             :                         return NULL;
    3957             :         } else {
    3958        2594 :                 if (!restype)
    3959           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
    3960        2594 :                 if (restype->type->localtype == TYPE_void) /* NULL */
    3961           7 :                         restype = sql_bind_localtype("str");
    3962        2594 :                 res = exp_null(sql->sa, restype);
    3963             :         }
    3964             : 
    3965      101256 :         if (!condtype)
    3966           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "Condition type missing");
    3967      101256 :         if (condtype->type->localtype == TYPE_void) /* NULL */
    3968           0 :                 condtype = sql_bind_localtype("str");
    3969      101256 :         if (opt_cond_exp && !(opt_cond_exp = exp_check_type(sql, condtype, rel ? *rel : NULL, opt_cond_exp, type_equal)))
    3970             :                 return NULL;
    3971      101256 :         sql_find_subtype(&bt, "boolean", 0, 0);
    3972      101256 :         list *args = sa_list(sql->sa);
    3973      101256 :         if (opt_cond_exp)
    3974        9525 :                 append(args, opt_cond_exp);
    3975      250087 :         for (node *n = conds->h, *m = results->h; n && m; n = n->next, m = m->next) {
    3976      148832 :                 sql_exp *cond = n->data;
    3977      148832 :                 sql_exp *result = m->data;
    3978             : 
    3979      148832 :                 if (!(result = exp_check_type(sql, restype, rel ? *rel : NULL, result, type_equal)))
    3980             :                         return NULL;
    3981             : 
    3982      148832 :                 if (!(cond = exp_check_type(sql, condtype, rel ? *rel : NULL, cond, type_equal)))
    3983             :                         return NULL;
    3984      148831 :                 if (!opt_cond_exp && !(cond = exp_check_type(sql, &bt, rel ? *rel : NULL, cond, type_equal)))
    3985             :                         return NULL;
    3986      148831 :                 append(args, cond);
    3987      148831 :                 append(args, result);
    3988             :         }
    3989      101255 :         assert(res);
    3990      101255 :         list_append(args, res);
    3991      101255 :         list *types = sa_list(sql->sa);
    3992      101255 :         types = append(append(types, restype), restype);
    3993      192986 :         sql_subfunc *case_func = find_func(sql, NULL, opt_cond_exp?"casewhen":"case", list_length(types), F_FUNC, true, NULL, NULL);
    3994      101255 :         res = exp_op(sql->sa, args, case_func);
    3995      101255 :         ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(sql->sa, restype->type, restype->digits, restype->scale);
    3996      101255 :         return res;
    3997             : }
    3998             : 
    3999             : static sql_exp *
    4000        4027 : rel_complex_case(sql_query *query, sql_rel **rel, dlist *case_args, int f, str func)
    4001             : {
    4002        4027 :         exp_kind ek = {type_value, card_column, FALSE};
    4003        4027 :         list *args = sa_list(query->sql->sa);
    4004        4027 :         sql_subtype *restype = NULL, rtype;
    4005        4027 :         sql_exp *res;
    4006             : 
    4007             :         /* generate nested func calls */
    4008       12537 :         for(dnode *dn = case_args->h; dn; dn = dn->next) {
    4009        8523 :                 sql_exp *a = rel_value_exp(query, rel, dn->data.sym, f, ek);
    4010        8523 :                 if (!a)
    4011             :                         return NULL;
    4012        8510 :                 append(args, a);
    4013             :                 /* all arguments should have the same type */
    4014        8510 :                 sql_subtype *tpe = exp_subtype(a);
    4015        8510 :                 if (tpe && restype) {
    4016        4485 :                         result_datatype(&rtype, restype, tpe);
    4017        4485 :                         restype = &rtype;
    4018        4025 :                 } else if (tpe) {
    4019        4025 :                         restype = tpe;
    4020             :                 }
    4021             :         }
    4022        4014 :         if (!restype)
    4023           0 :                 return sql_error(query->sql, 02, SQLSTATE(42000) "Result type missing");
    4024        4014 :         if (restype->type->localtype == TYPE_void) /* NULL */
    4025           0 :                 restype = sql_bind_localtype("str");
    4026        4014 :         list *nargs = sa_list(query->sql->sa);
    4027       12509 :         for (node *m = args->h; m; m = m->next) {
    4028        8495 :                 sql_exp *result = m->data;
    4029             : 
    4030        8495 :                 if (!(result = exp_check_type(query->sql, restype, rel ? *rel : NULL, result, type_equal)))
    4031             :                         return NULL;
    4032        8495 :                 append(nargs, result);
    4033             :         }
    4034        4014 :         list *types = append(append(sa_list(query->sql->sa), restype), restype);
    4035        4014 :         sql_subfunc *fnc = find_func(query->sql, NULL, func, list_length(types), F_FUNC, true, NULL, NULL);
    4036        4014 :         res = exp_op(query->sql->sa, nargs, fnc);
    4037        4014 :         ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(query->sql->sa, restype->type, restype->digits, restype->scale);
    4038        4014 :         return res;
    4039             : }
    4040             : 
    4041             : static sql_exp *
    4042      105295 : rel_case_exp(sql_query *query, sql_rel **rel, symbol *se, int f)
    4043             : {
    4044      105295 :         dlist *l = se->data.lval;
    4045             : 
    4046      105295 :         if (se->token == SQL_COALESCE) {
    4047        3876 :                 return rel_complex_case(query, rel, l, f | sql_farg, "coalesce");
    4048      101419 :         } else if (se->token == SQL_NULLIF) {
    4049         151 :                 return rel_complex_case(query, rel, l, f | sql_farg, "nullif");
    4050      101268 :         } else if (l->h->type == type_list) {
    4051       91736 :                 dlist *when_search_list = l->h->data.lval;
    4052       91736 :                 symbol *opt_else = l->h->next->data.sym;
    4053             : 
    4054       91736 :                 return rel_case(query, rel, NULL, when_search_list, opt_else, f | sql_farg);
    4055             :         } else {
    4056        9532 :                 symbol *scalar_exp = l->h->data.sym;
    4057        9532 :                 dlist *when_value_list = l->h->next->data.lval;
    4058        9532 :                 symbol *opt_else = l->h->next->next->data.sym;
    4059             : 
    4060        9532 :                 return rel_case(query, rel, scalar_exp, when_value_list, opt_else, f | sql_farg);
    4061             :         }
    4062             : }
    4063             : 
    4064             : #define E_ATOM_STRING(e) ((atom*)(e)->l)->data.val.sval
    4065             : 
    4066             : static sql_exp *
    4067      172563 : rel_cast(sql_query *query, sql_rel **rel, symbol *se, int f)
    4068             : {
    4069      172563 :         mvc *sql = query->sql;
    4070      172563 :         dlist *dl = se->data.lval;
    4071      172563 :         symbol *s = dl->h->data.sym;
    4072      172563 :         sql_subtype *tpe = &dl->h->next->data.typeval;
    4073      172563 :         exp_kind ek = {type_value, card_column, FALSE};
    4074      172563 :         sql_exp *e = rel_value_exp(query, rel, s, f|sql_farg, ek);
    4075             : 
    4076      172563 :         if (!e)
    4077             :                 return NULL;
    4078             : 
    4079             :         /* strings may need to be truncated */
    4080      172548 :         if (EC_VARCHAR(tpe->type->eclass) && tpe->digits > 0) {
    4081       84358 :                 sql_subtype *et = exp_subtype(e);
    4082             :                 /* truncate only if the number of digits are smaller or from clob */
    4083       84358 :                 if (et && EC_VARCHAR(et->type->eclass) && (tpe->digits < et->digits || et->digits == 0)) {
    4084        2882 :                         sql_subfunc *c = sql_bind_func(sql, "sys", "truncate", et, sql_bind_localtype("int"), F_FUNC, true, true);
    4085        2882 :                         if (c)
    4086        2882 :                                 e = exp_binop(sql->sa, e, exp_atom_int(sql->sa, tpe->digits), c);
    4087             :                 }
    4088             :         }
    4089             : 
    4090      172548 :         if (tpe->type->eclass == EC_DEC) {
    4091         447 :                 sql_subtype *et = exp_subtype(e);
    4092         447 :                 if (e->type == e_atom && !tpe->digits) {
    4093           9 :                         if (et->type->eclass == EC_NUM || et->type->eclass == EC_DEC) {
    4094           6 :                                 tpe->digits = atom_num_digits(e->l);
    4095           6 :                                 tpe = sql_bind_subtype(sql->sa, "decimal", tpe->digits, et->scale);
    4096           3 :                         } else if (EC_VARCHAR(et->type->eclass)) {
    4097           2 :                                 char *s = E_ATOM_STRING(e);
    4098           2 :                                 unsigned int min_precision = 0, min_scale = 0;
    4099           2 :                                 bool dot_seen = false;
    4100          16 :                                 for (size_t i = 0; i < strlen(s); i++) {
    4101          14 :                                         if (isdigit(s[i])) {
    4102          12 :                                                 min_precision++;
    4103          12 :                                                 if (dot_seen)
    4104          10 :                                                         min_scale++;
    4105           2 :                                         } else if (s[i] == '.') {
    4106           2 :                                                 dot_seen = true;
    4107             :                                         }
    4108             :                                 }
    4109           2 :                                 tpe = sql_bind_subtype(sql->sa, "decimal", min_precision, min_scale);
    4110             :                         } else { /* fallback */
    4111           1 :                                 tpe = sql_bind_subtype(sql->sa, "decimal", 18, 3);
    4112             :                         }
    4113         438 :                 } else if (!tpe->digits && !tpe->scale) {
    4114         105 :                         if (et->type->eclass == EC_NUM)
    4115          36 :                                 tpe = sql_bind_subtype(sql->sa, "decimal", et->digits, 0);
    4116             :                         else /* fallback */
    4117          69 :                                 tpe = sql_bind_subtype(sql->sa, "decimal", 18, 3);
    4118             :                 }
    4119             :         }
    4120             : 
    4121      172548 :         if (e)
    4122      172548 :                 e = exp_check_type(sql, tpe, rel ? *rel : NULL, e, type_cast);
    4123             : 
    4124      172548 :         if (e && e->type == e_convert)
    4125       49059 :                 exp_label(sql->sa, e, ++sql->label);
    4126             : 
    4127             :         return e;
    4128             : }
    4129             : 
    4130             : static sql_exp *
    4131        1584 : rel_next_value_for( mvc *sql, symbol *se )
    4132             : {
    4133        1584 :         char *sname = qname_schema(se->data.lval);
    4134        1584 :         char *seqname = qname_schema_object(se->data.lval);
    4135        1584 :         sql_sequence *seq = NULL;
    4136        1584 :         sql_subtype t;
    4137        1584 :         sql_subfunc *f;
    4138             : 
    4139        1584 :         if (!sname)
    4140         222 :                 sname = "sys";
    4141        1584 :         if (!stack_find_rel_view(sql, seqname)) {
    4142        1388 :                 if (!(seq = find_sequence_on_scope(sql, sname, seqname, "NEXT VALUE FOR")))
    4143             :                         return NULL;
    4144        1386 :                 if (!mvc_schema_privs(sql, seq->s))
    4145           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "NEXT VALUE FOR: access denied for %s to schema '%s'", get_string_global_var(sql, "current_user"), seq->s->base.name);
    4146             :         }
    4147        1582 :         sql_find_subtype(&t, "varchar", 0, 0);
    4148        1582 :         f = sql_bind_func(sql, "sys", "next_value_for", &t, &t, F_FUNC, true, true);
    4149        1582 :         assert(f);
    4150             :         /* sequence found in the stack, ie just created. use given schema? */
    4151        1582 :         return exp_binop(sql->sa, exp_atom_str(sql->sa, seq && seq->s ? seq->s->base.name : sname, &t), exp_atom_str(sql->sa, seqname, &t), f);
    4152             : }
    4153             : 
    4154             : /* some users like to use aliases already in the groupby */
    4155             : static sql_exp *
    4156         165 : rel_selection_ref(sql_query *query, sql_rel **rel, char *name, dlist *selection)
    4157             : {
    4158         165 :         allocator *sa = query->sql->sa;
    4159         165 :         dlist *nl;
    4160         165 :         exp_kind ek = {type_value, card_column, FALSE};
    4161         165 :         sql_exp *res = NULL;
    4162         165 :         symbol *nsym;
    4163             : 
    4164         165 :         if (!selection)
    4165             :                 return NULL;
    4166             : 
    4167         679 :         for (dnode *n = selection->h; n; n = n->next) {
    4168             :                 /* we only look for columns */
    4169         517 :                 tokens to = n->data.sym->token;
    4170         517 :                 if (to == SQL_COLUMN || to == SQL_IDENT) {
    4171         515 :                         dlist *l = n->data.sym->data.lval;
    4172             :                         /* AS name */
    4173         515 :                         if (l->h->next->data.sval && strcmp(l->h->next->data.sval, name) == 0) {
    4174         146 :                                 sql_exp *ve = rel_value_exp(query, rel, l->h->data.sym, sql_sel|sql_groupby, ek);
    4175         146 :                                 if (ve) {
    4176         145 :                                         if (res)
    4177           1 :                                                 return sql_error(query->sql, ERR_AMBIGUOUS, SQLSTATE(42000) "SELECT: identifier '%s' ambiguous", name);
    4178         144 :                                         res = ve;
    4179             : 
    4180         144 :                                         nl = dlist_create(sa);
    4181         144 :                                         exp_setname(query->sql, ve, NULL, name);
    4182             :                                         /* now we should rewrite the selection such that it uses the new group by column */
    4183         144 :                                         dlist_append_string(sa, nl, sa_strdup(sa, name));
    4184         144 :                                         nsym = symbol_create_list(sa, to, nl);
    4185         144 :                                         nl = dlist_create(sa);
    4186         144 :                                         dlist_append_symbol(sa, nl, nsym);
    4187             :                                         /* no alias */
    4188         144 :                                         dlist_append_symbol(sa, nl, NULL);
    4189         144 :                                         n->data.sym = symbol_create_list(sa, to, nl);
    4190             :                                 }
    4191             :                         }
    4192             :                 }
    4193             :         }
    4194             :         return res;
    4195             : }
    4196             : 
    4197             : static char*
    4198         197 : symbol_get_identifier(symbol *sym)
    4199             : {
    4200         197 :         dlist *syml;
    4201             : 
    4202         197 :         if (sym->token != SQL_COLUMN && sym->token != SQL_IDENT)
    4203             :                 return NULL;
    4204         182 :         syml = sym->data.lval;
    4205         182 :         if (dlist_length(syml) > 1)
    4206             :                 return NULL;
    4207             : 
    4208         165 :         return syml->h->data.sval;
    4209             : }
    4210             : 
    4211             : static sql_exp*
    4212       36415 : rel_group_column(sql_query *query, sql_rel **rel, symbol *grp, dlist *selection, list *exps, int f)
    4213             : {
    4214       36415 :         sql_query *lquery = query_create(query->sql);
    4215       36415 :         mvc *sql = query->sql;
    4216       36415 :         exp_kind ek = {type_value, card_value, TRUE};
    4217       36415 :         sql_exp *e = rel_value_exp2(lquery, rel, grp, f, ek);
    4218             : 
    4219       36415 :         if (e && exp_is_atom(e)) {
    4220          35 :                 sql_subtype *tpe = exp_subtype(e);
    4221          35 :                 if (!is_atom(e->type) ||!tpe || tpe->type->eclass != EC_NUM) {
    4222           3 :                         if (!tpe)
    4223           2 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Cannot have a parameter (?) for group by column");
    4224           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: non-integer constant in GROUP BY");
    4225             :                 }
    4226             :         }
    4227             : 
    4228         192 :         if (!e) {
    4229         192 :                 char buf[ERRSIZE], *name;
    4230         192 :                 int status = sql->session->status;
    4231         192 :                 strcpy(buf, sql->errstr);
    4232             :                 /* reset error */
    4233         192 :                 sql->session->status = 0;
    4234         192 :                 sql->errstr[0] = '\0';
    4235             : 
    4236         192 :                 if ((name = symbol_get_identifier(grp))) {
    4237         163 :                         e = rel_selection_ref(query, rel, name, selection);
    4238         163 :                         if (!e) { /* attempt to find in the existing list of group by expressions */
    4239          29 :                                 for (node *n = exps->h ; n && !e ; n = n->next) {
    4240           9 :                                         sql_exp *ge = (sql_exp *) n->data;
    4241           9 :                                         const char *gen = exp_name(ge);
    4242             : 
    4243           9 :                                         if (gen && strcmp(name, gen) == 0)
    4244           5 :                                                 e = exp_ref(sql, ge);
    4245             :                                 }
    4246             :                         }
    4247             :                 }
    4248          49 :                 if (!e && query_has_outer(query)) {
    4249             :                         /* reset error */
    4250          32 :                         sql->session->status = 0;
    4251          32 :                         sql->errstr[0] = '\0';
    4252          32 :                         e = rel_value_exp2(query, rel, grp, f, ek);
    4253             :                 }
    4254          44 :                 if (!e) {
    4255          13 :                         if (sql->errstr[0] == 0) {
    4256          10 :                                 sql->session->status = status;
    4257          10 :                                 strcpy(sql->errstr, buf);
    4258             :                         }
    4259          13 :                         return NULL;
    4260             :                 }
    4261             :         }
    4262       36396 :         if (!exp_subtype(e))
    4263           0 :                 return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for group by column");
    4264             :         return e;
    4265             : }
    4266             : 
    4267             : static list*
    4268          44 : list_power_set(allocator *sa, list* input) /* cube */
    4269             : {
    4270          44 :         list *res = sa_list(sa);
    4271             :         /* N stores total number of subsets */
    4272          44 :         int N = (int) pow(2, input->cnt);
    4273             : 
    4274             :         /* generate each subset one by one */
    4275         266 :         for (int i = 0; i < N; i++) {
    4276         222 :                 list *ll = sa_list(sa);
    4277         222 :                 int j = 0; /* check every bit of i */
    4278         844 :                 for (node *n = input->h ; n ; n = n->next) {
    4279             :                         /* if j'th bit of i is set, then append */
    4280         622 :                         if (i & (1 << j))
    4281         311 :                                 list_prepend(ll, n->data);
    4282         622 :                         j++;
    4283             :                 }
    4284         222 :                 list_prepend(res, ll);
    4285             :         }
    4286          44 :         return res;
    4287             : }
    4288             : 
    4289             : static list*
    4290          61 : list_rollup(allocator *sa, list* input)
    4291             : {
    4292          61 :         list *res = sa_list(sa);
    4293             : 
    4294         188 :         for (int counter = input->cnt; counter > 0; counter--) {
    4295         127 :                 list *ll = sa_list(sa);
    4296         127 :                 int j = 0;
    4297         376 :                 for (node *n = input->h; n && j < counter; j++, n = n->next)
    4298         249 :                         list_append(ll, n->data);
    4299         127 :                 list_append(res, ll);
    4300             :         }
    4301          61 :         list_append(res, sa_list(sa)); /* global aggregate case */
    4302          61 :         return res;
    4303             : }
    4304             : 
    4305             : static int
    4306         320 : list_equal(list* list1, list* list2)
    4307             : {
    4308         375 :         for (node *n = list1->h; n ; n = n->next) {
    4309         328 :                 sql_exp *e = (sql_exp*) n->data;
    4310         328 :                 if (!exps_find_exp(list2, e))
    4311             :                         return 1;
    4312             :         }
    4313          78 :         for (node *n = list2->h; n ; n = n->next) {
    4314          47 :                 sql_exp *e = (sql_exp*) n->data;
    4315          47 :                 if (!exps_find_exp(list1, e))
    4316             :                         return 1;
    4317             :         }
    4318             :         return 0;
    4319             : }
    4320             : 
    4321             : static list*
    4322          26 : lists_cartesian_product_and_distinct(allocator *sa, list *l1, list *l2)
    4323             : {
    4324          26 :         list *res = sa_list(sa);
    4325             : 
    4326             :         /* for each list of l2, merge into each list of l1 while removing duplicates */
    4327         116 :         for (node *n = l1->h ; n ; n = n->next) {
    4328          90 :                 list *sub_list = (list*) n->data;
    4329             : 
    4330         279 :                 for (node *m = l2->h ; m ; m = m->next) {
    4331         189 :                         list *other = (list*) m->data;
    4332         189 :                         list_append(res, list_distinct(list_merge(list_dup(sub_list, (fdup) NULL), other, (fdup) NULL), (fcmp) list_equal, (fdup) NULL));
    4333             :                 }
    4334             :         }
    4335          26 :         return res;
    4336             : }
    4337             : 
    4338             : static list*
    4339       13440 : rel_groupings(sql_query *query, sql_rel **rel, symbol *groupby, dlist *selection, int f, bool grouping_sets, list **sets)
    4340             : {
    4341       13440 :         mvc *sql = query->sql;
    4342       13440 :         list *exps = new_exp_list(sql->sa);
    4343             : 
    4344       13440 :         if (mvc_highwater(sql))
    4345           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    4346             : 
    4347       49762 :         for (dnode *o = groupby->data.lval->h; o; o = o->next) {
    4348       36342 :                 symbol *grouping = o->data.sym;
    4349       36342 :                 list *next_set = NULL;
    4350             : 
    4351       36342 :                 if (grouping->token == SQL_GROUPING_SETS) { /* call recursively, and merge the generated sets */
    4352          39 :                         list *other = rel_groupings(query, rel, grouping, selection, f, true, &next_set);
    4353          39 :                         if (!other)
    4354          20 :                                 return NULL;
    4355          39 :                         exps = list_distinct(list_merge(exps, other, (fdup) NULL), (fcmp) exp_equal, (fdup) NULL);
    4356             :                 } else {
    4357       36303 :                         dlist *dl = grouping->data.lval;
    4358       36303 :                         if (dl) {
    4359       36277 :                                 list *set_cols = new_exp_list(sql->sa); /* columns and combination of columns to be used for the next set */
    4360             : 
    4361       72643 :                                 for (dnode *oo = dl->h; oo; oo = oo->next) {
    4362       36385 :                                         symbol *grp = oo->data.sym;
    4363       36385 :                                         list *next_tuple = new_exp_list(sql->sa); /* next tuple of columns */
    4364             : 
    4365       36385 :                                         if (grp->token == SQL_COLUMN_GROUP) { /* set of columns */
    4366          71 :                                                 assert(is_sql_group_totals(f));
    4367         172 :                                                 for (dnode *ooo = grp->data.lval->h; ooo; ooo = ooo->next) {
    4368         101 :                                                         symbol *elm = ooo->data.sym;
    4369         101 :                                                         sql_exp *e = rel_group_column(query, rel, elm, selection, exps, f);
    4370         101 :                                                         if (!e)
    4371             :                                                                 return NULL;
    4372         101 :                                                         assert(e->type == e_column);
    4373         101 :                                                         list_append(next_tuple, e);
    4374         101 :                                                         list_append(exps, e);
    4375             :                                                 }
    4376             :                                         } else { /* single column or expression */
    4377       36314 :                                                 sql_exp *e = rel_group_column(query, rel, grp, selection, exps, f);
    4378       36314 :                                                 if (!e)
    4379             :                                                         return NULL;
    4380       36295 :                                                 if (e->type != e_column && !exp_is_atom(e)) { /* store group by expressions in the stack */
    4381         142 :                                                         if (is_sql_group_totals(f))
    4382           0 :                                                                 return sql_error(sql, 02, SQLSTATE(42000) "GROUP BY: grouping expressions not possible with ROLLUP, CUBE and GROUPING SETS");
    4383         142 :                                                         if (!exp_has_rel(e) && !frame_push_groupby_expression(sql, grp, e))
    4384             :                                                                 return NULL;
    4385             :                                                 }
    4386       36295 :                                                 list_append(next_tuple, e);
    4387       36295 :                                                 list_append(exps, e);
    4388             :                                         }
    4389       36366 :                                         list_append(set_cols, next_tuple);
    4390             :                                 }
    4391       36258 :                                 if (is_sql_group_totals(f)) {
    4392         178 :                                         if (grouping->token == SQL_ROLLUP)
    4393          61 :                                                 next_set = list_rollup(sql->sa, set_cols);
    4394         117 :                                         else if (grouping->token == SQL_CUBE)
    4395          44 :                                                 next_set = list_power_set(sql->sa, set_cols);
    4396             :                                         else /* the list of sets is not used in the "GROUP BY a, b, ..." case */
    4397          73 :                                                 next_set = list_append(new_exp_list(sql->sa), set_cols);
    4398             :                                 }
    4399          26 :                         } else if (is_sql_group_totals(f) && grouping_sets) /* The GROUP BY () case is the global aggregate which is always added by ROLLUP and CUBE */
    4400          17 :                                 next_set = list_append(new_exp_list(sql->sa), new_exp_list(sql->sa));
    4401             :                 }
    4402       36323 :                 if (is_sql_group_totals(f)) { /* if there are no sets, set the found one, otherwise calculate cartesian product and merge the distinct ones */
    4403         235 :                         if (!next_set)
    4404           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "GROUP BY: GROUPING SETS is empty");
    4405         234 :                         if (!*sets)
    4406         157 :                                 *sets = next_set;
    4407             :                         else
    4408          77 :                                 *sets = grouping_sets ? list_merge(*sets, next_set, (fdup) NULL) : lists_cartesian_product_and_distinct(sql->sa, *sets, next_set);
    4409             :                 }
    4410             :         }
    4411             :         return exps;
    4412             : }
    4413             : 
    4414             : static list*
    4415        2321 : rel_partition_groupings(sql_query *query, sql_rel **rel, symbol *partitionby, dlist *selection, int f)
    4416             : {
    4417        2321 :         mvc *sql = query->sql;
    4418        2321 :         dnode *o = partitionby->data.lval->h;
    4419        2321 :         list *exps = new_exp_list(sql->sa);
    4420             : 
    4421        6994 :         for (; o; o = o->next) {
    4422        2360 :                 symbol *grp = o->data.sym;
    4423        2360 :                 exp_kind ek = {type_value, card_value, TRUE};
    4424        2360 :                 sql_exp *e = rel_value_exp2(query, rel, grp, f, ek);
    4425             : 
    4426        2360 :                 if (!e) {
    4427           5 :                         int status = sql->session->status;
    4428           5 :                         char buf[ERRSIZE], *name;
    4429             : 
    4430             :                         /* reset error */
    4431           5 :                         sql->session->status = 0;
    4432           5 :                         strcpy(buf, sql->errstr);
    4433           5 :                         sql->errstr[0] = '\0';
    4434             : 
    4435           5 :                         if ((name = symbol_get_identifier(grp))) {
    4436           2 :                                 e = rel_selection_ref(query, rel, name, selection);
    4437           2 :                                 if (!e) { /* attempt to find in the existing list of partition by expressions */
    4438           3 :                                         for (node *n = exps->h ; n ; n = n->next) {
    4439           1 :                                                 sql_exp *ge = (sql_exp *) n->data;
    4440           1 :                                                 const char *gen = exp_name(ge);
    4441             : 
    4442           1 :                                                 if (gen && strcmp(name, gen) == 0) {
    4443           0 :                                                         e = exp_ref(sql, ge);
    4444           0 :                                                         break;
    4445             :                                                 }
    4446             :                                         }
    4447             :                                 }
    4448             :                         }
    4449           5 :                         if (!e) {
    4450           5 :                                 if (sql->errstr[0] == 0) {
    4451           5 :                                         sql->session->status = status;
    4452           5 :                                         strcpy(sql->errstr, buf);
    4453             :                                 }
    4454           5 :                                 return NULL;
    4455             :                         }
    4456             :                 }
    4457             : 
    4458        2355 :                 if (exp_has_rel(e))
    4459           3 :                         return sql_error(sql, 02, SQLSTATE(42000) "PARTITION BY: subqueries not allowed in PARTITION BY clause");
    4460             : 
    4461        2352 :                 if (e->type != e_column) { /* store group by expressions in the stack */
    4462          42 :                         if (!frame_push_groupby_expression(sql, grp, e))
    4463             :                                 return NULL;
    4464             :                 }
    4465             : 
    4466        2352 :                 if (e->card > CARD_AGGR)
    4467        2230 :                         e->card = CARD_AGGR;
    4468        2352 :                 append(exps, e);
    4469             :         }
    4470             :         return exps;
    4471             : }
    4472             : 
    4473             : /* find selection expressions matching the order by column expression */
    4474             : /* complex columns only */
    4475             : static sql_exp *
    4476       67743 : rel_order_by_column_exp(sql_query *query, sql_rel **R, symbol *column_r, int needs_distinct, int f)
    4477             : {
    4478       67743 :         mvc *sql = query->sql;
    4479       67743 :         sql_rel *r = *R, *p = NULL;
    4480       67743 :         sql_exp *e = NULL, *found = NULL;
    4481       67743 :         exp_kind ek = {type_value, card_column, FALSE};
    4482             : 
    4483       67743 :         if (!r)
    4484             :                 return e;
    4485             : 
    4486       67743 :         if (is_simple_project(r->op) && r->l && is_processed(r)) {
    4487       67681 :                 p = r;
    4488       67681 :                 r = r->l;
    4489             :         }
    4490             : 
    4491       67743 :         e = rel_value_exp(query, &r, column_r, f, ek);
    4492             : 
    4493       67743 :         if (r && !p)
    4494          62 :                 *R = r;
    4495       67681 :         else if (r)
    4496       67681 :                 p->l = r;
    4497       67743 :         if (e && p) {
    4498       67654 :                 if (is_project(p->op) && (found = exps_any_match(p->exps, e))) { /* if one of the projections matches, return a reference to it */
    4499       60010 :                         e = exp_ref(sql, found);
    4500             :                 } else {
    4501        7644 :                         if (needs_distinct)
    4502           2 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
    4503        7642 :                         e = rel_project_add_exp(sql, p, e);
    4504        7642 :                         if (r) {
    4505      125343 :                                 for (node *n = p->exps->h ; n ; n = n->next) {
    4506      117703 :                                         sql_exp *ee = n->data;
    4507             : 
    4508      117703 :                                         if (ee->card > r->card) {
    4509           2 :                                                 if (exp_name(ee) && !has_label(ee))
    4510           2 :                                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ee));
    4511           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    4512             :                                         }
    4513             :                                 }
    4514             :                         }
    4515             :                 }
    4516       67650 :                 return e;
    4517             :         }
    4518          89 :         if (e && r && is_project(r->op)) {
    4519          28 :                 sql_exp *found = exps_find_exp(r->exps, e);
    4520             : 
    4521          28 :                 if (!found) {
    4522           8 :                         if (needs_distinct)
    4523           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
    4524           8 :                         if (!is_simple_project(r->op) && !is_groupby(r->op))
    4525           1 :                                 *R = r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 0));
    4526           8 :                         append(r->exps, e);
    4527             :                 } else {
    4528             :                         e = found;
    4529             :                 }
    4530          28 :                 e = exp_ref(sql, e);
    4531             :         }
    4532             :         return e;
    4533             : }
    4534             : 
    4535             : static dlist *
    4536      110037 : simple_selection(symbol *sq)
    4537             : {
    4538      110037 :         if (sq->token == SQL_SELECT) {
    4539          13 :                 SelectNode *sn;
    4540          13 :                 sn = (SelectNode *) sq;
    4541             : 
    4542          13 :                 if (!sn->from && !sn->where && !sn->distinct && !sn->window && dlist_length(sn->selection) == 1)
    4543           7 :                         return sn->selection;
    4544             :         }
    4545             :         return NULL;
    4546             : }
    4547             : 
    4548             : static list *
    4549       40092 : rel_order_by(sql_query *query, sql_rel **R, symbol *orderby, int needs_distinct, int f)
    4550             : {
    4551       40092 :         mvc *sql = query->sql;
    4552       40092 :         sql_rel *rel = *R, *or = rel; /* the order by relation */
    4553       40092 :         list *exps = new_exp_list(sql->sa);
    4554             : 
    4555       40092 :         if (!orderby->data.lval) { /* by all */
    4556           6 :                 if (is_sql_orderby(f)) {
    4557           6 :                         assert(is_project(rel->op));
    4558          22 :                         for(node *n = rel->exps->h; n; n = n->next) {
    4559          16 :                                 sql_exp *e = n->data;
    4560          16 :                                 append(exps, exp_ref(sql, e));
    4561             :                         }
    4562             :                         return exps;
    4563             :                 }
    4564             :                 return NULL;
    4565             :         }
    4566             : 
    4567       40086 :         dnode *o = orderby->data.lval->h;
    4568       40086 :         dlist *selection = NULL;
    4569             : 
    4570       40086 :         if (is_sql_orderby(f)) {
    4571       37057 :                 assert(is_project(rel->op));
    4572       37057 :                 rel = rel->l;
    4573             :         }
    4574             : 
    4575      150075 :         for (; o; o = o->next) {
    4576      110037 :                 symbol *order = o->data.sym;
    4577             : 
    4578      110037 :                 if (order->token == SQL_COLUMN || order->token == SQL_IDENT) {
    4579      110037 :                         symbol *col = order->data.lval->h->data.sym;
    4580      110037 :                         int direction = order->data.lval->h->next->data.i_val;
    4581      110037 :                         sql_exp *e = NULL;
    4582             : 
    4583      110037 :                         assert(order->data.lval->h->next->type == type_int);
    4584      110037 :                         if ((selection = simple_selection(col)) != NULL) {
    4585           7 :                                 dnode *o = selection->h;
    4586           7 :                                 order = o->data.sym;
    4587           7 :                                 if (order->data.lval->h->type == type_symbol)
    4588           6 :                                         col = order->data.lval->h->data.sym;
    4589             :                                 /* remove optional name from selection */
    4590           7 :                                 order->data.lval->h->next = NULL;
    4591             :                         }
    4592             : 
    4593      110037 :                         if (col->token == SQL_COLUMN || col->token == SQL_IDENT || col->token == SQL_ATOM) {
    4594      109815 :                                 exp_kind ek = {type_value, card_column, FALSE};
    4595             : 
    4596      109815 :                                 e = rel_value_exp2(query, &rel, col, f, ek);
    4597             : 
    4598      109815 :                                 if (e && e->card <= CARD_ATOM) {
    4599        9374 :                                         sql_subtype *tpe = exp_subtype(e);
    4600             :                                         /* integer atom on the stack */
    4601        9374 :                                         if (!is_sql_window(f) && e->type == e_atom &&
    4602        9266 :                                             tpe->type->eclass == EC_NUM) {
    4603        9257 :                                                 atom *a = e->l;
    4604        9257 :                                                 int nr = (int)atom_get_int(a);
    4605             : 
    4606        9257 :                                                 e = exps_get_exp(rel->exps, nr);
    4607        9257 :                                                 if (!e)
    4608           3 :                                                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: the order by column number (%d) is not in the number of projections range (%d)", nr, list_length(rel->exps));
    4609        9254 :                                                 e = exp_ref(sql, e);
    4610             :                                         }
    4611       32914 :                                 } else if (e && exp_card(e) > rel->card) {
    4612           0 :                                         if (exp_name(e) && !has_label(e))
    4613           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
    4614           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    4615             :                                 }
    4616      109812 :                                 if (e && !exp_name(e))
    4617          23 :                                         exp_label(sql->sa, e, ++sql->label);
    4618       42285 :                                 if (e && rel && is_project(rel->op)) {
    4619       39757 :                                         sql_exp *found = exps_find_exp(rel->exps, e);
    4620             : 
    4621       39757 :                                         if (!found) {
    4622          33 :                                                 if (needs_distinct)
    4623           0 :                                                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
    4624          33 :                                                 if (!is_freevar(e))
    4625          16 :                                                         append(rel->exps, e);
    4626             :                                         } else {
    4627             :                                                 e = found;
    4628             :                                         }
    4629       39757 :                                         if (!is_freevar(e))
    4630       39740 :                                                 e = exp_ref(sql, e);
    4631             :                                 }
    4632             :                         }
    4633             : 
    4634      110034 :                         if (rel && !e && sql->session->status != -ERR_AMBIGUOUS) {
    4635             :                                 /* reset error */
    4636       67743 :                                 sql->session->status = 0;
    4637       67743 :                                 sql->errstr[0] = '\0';
    4638             : 
    4639       67743 :                                 e = rel_order_by_column_exp(query, &rel, col, needs_distinct, sql_sel | sql_orderby | (f & sql_group_totals) | (f & sql_window));
    4640             :                         }
    4641       67749 :                         if (!e)
    4642             :                                 return NULL;
    4643      109990 :                         if (!exp_subtype(e))
    4644           1 :                                 return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for order by column");
    4645      109989 :                         set_direction(e, direction);
    4646      109989 :                         list_append(exps, e);
    4647             :                 } else {
    4648           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: order not of type SQL_COLUMN");
    4649             :                 }
    4650             :         }
    4651       40038 :         if (is_sql_orderby(f) && or != rel)
    4652       37016 :                 or->l = rel;
    4653       40038 :         if (is_sql_window(f))
    4654        3022 :                 *R = rel;
    4655             :         return exps;
    4656             : }
    4657             : 
    4658             : static int
    4659         814 : generate_window_bound(tokens sql_token, bool first_half)
    4660             : {
    4661         814 :         switch (sql_token) {
    4662         408 :                 case SQL_PRECEDING:
    4663         408 :                         return first_half ? BOUND_FIRST_HALF_PRECEDING : BOUND_SECOND_HALF_PRECEDING;
    4664         284 :                 case SQL_FOLLOWING:
    4665         284 :                         return first_half ? BOUND_FIRST_HALF_FOLLOWING : BOUND_SECOND_HALF_FOLLOWING;
    4666         122 :                 case SQL_CURRENT_ROW:
    4667         122 :                         return first_half ? CURRENT_ROW_PRECEDING : CURRENT_ROW_FOLLOWING;
    4668             :                 default:
    4669           0 :                         assert(0);
    4670             :         }
    4671             :         return 0;
    4672             : }
    4673             : 
    4674             : /* window functions */
    4675             : static sql_exp*
    4676         407 : generate_window_bound_call(mvc *sql, sql_exp **estart, sql_exp **eend, sql_exp *pe, sql_exp *e,
    4677             :                                                    sql_exp *start, sql_exp *fend, int frame_type, int excl, tokens t1, tokens t2)
    4678             : {
    4679         407 :         list *rargs1 = sa_list(sql->sa), *rargs2 = sa_list(sql->sa), *targs1 = sa_list(sql->sa), *targs2 = sa_list(sql->sa);
    4680         407 :         sql_subfunc *dc1, *dc2;
    4681         407 :         sql_subtype *it = sql_bind_localtype("int");
    4682             : 
    4683         407 :         if (pe) {
    4684         186 :                 append(targs1, exp_subtype(pe));
    4685         186 :                 append(targs2, exp_subtype(pe));
    4686         186 :                 append(rargs1, exp_copy(sql, pe));
    4687         186 :                 append(rargs2, exp_copy(sql, pe));
    4688             :         }
    4689         407 :         append(rargs1, exp_copy(sql, e));
    4690         407 :         append(rargs2, exp_copy(sql, e));
    4691         407 :         append(targs1, exp_subtype(e));
    4692         407 :         append(targs2, exp_subtype(e));
    4693         407 :         append(targs1, it);
    4694         407 :         append(targs2, it);
    4695         407 :         append(targs1, it);
    4696         407 :         append(targs2, it);
    4697         407 :         append(targs1, it);
    4698         407 :         append(targs2, it);
    4699         407 :         append(targs1, exp_subtype(start));
    4700         407 :         append(targs2, exp_subtype(fend));
    4701             : 
    4702         407 :         dc1 = sql_bind_func_(sql, "sys", "window_bound", targs1, F_ANALYTIC, true, false);
    4703         407 :         dc2 = sql_bind_func_(sql, "sys", "window_bound", targs2, F_ANALYTIC, true, false);
    4704         407 :         if (!dc1 || !dc2)
    4705           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: function 'window_bound' not found");
    4706         407 :         append(rargs1, exp_atom_int(sql->sa, frame_type));
    4707         407 :         append(rargs2, exp_atom_int(sql->sa, frame_type));
    4708         407 :         append(rargs1, exp_atom_int(sql->sa, generate_window_bound(t1, true)));
    4709         407 :         append(rargs2, exp_atom_int(sql->sa, generate_window_bound(t2, false)));
    4710         407 :         append(rargs1, exp_atom_int(sql->sa, excl));
    4711         407 :         append(rargs2, exp_atom_int(sql->sa, excl));
    4712         407 :         append(rargs1, start);
    4713         407 :         append(rargs2, fend);
    4714             : 
    4715         407 :         *estart = exp_op(sql->sa, rargs1, dc1);
    4716         407 :         *eend = exp_op(sql->sa, rargs2, dc2);
    4717         407 :         return e; /* return something to say there were no errors */
    4718             : }
    4719             : 
    4720             : #define EC_NUMERIC(e) (e==EC_NUM||EC_INTERVAL(e)||e==EC_DEC||e==EC_FLT)
    4721             : 
    4722             : static sql_exp*
    4723         601 : calculate_window_bound(sql_query *query, sql_rel *p, tokens token, symbol *bound, sql_exp *ie, int frame_type, int f)
    4724             : {
    4725         601 :         mvc *sql = query->sql;
    4726         601 :         sql_subtype *bt, *bound_tp = sql_bind_localtype("lng"), *iet = exp_subtype(ie);
    4727         601 :         sql_exp *res = NULL;
    4728             : 
    4729         792 :         if ((bound->token == SQL_PRECEDING || bound->token == SQL_FOLLOWING || bound->token == SQL_CURRENT_ROW) && bound->type == type_int) {
    4730         191 :                 atom *a = NULL;
    4731         191 :                 bt = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : iet;
    4732             : 
    4733         191 :                 if ((bound->data.i_val == UNBOUNDED_PRECEDING_BOUND || bound->data.i_val == UNBOUNDED_FOLLOWING_BOUND)) {
    4734          69 :                         a = atom_max_value(sql->sa, EC_NUMERIC(bt->type->eclass) ? bt : bound_tp);
    4735         122 :                 } else if (bound->data.i_val == CURRENT_ROW_BOUND) {
    4736         124 :                         a = atom_zero_value(sql->sa, EC_NUMERIC(bt->type->eclass) ? bt : bound_tp);
    4737             :                 } else {
    4738           0 :                         assert(0);
    4739             :                 }
    4740         191 :                 res = exp_atom(sql->sa, a);
    4741             :         } else { /* arbitrary expression case */
    4742         410 :                 exp_kind ek = {type_value, card_column, FALSE};
    4743         410 :                 const char *bound_desc = (token == SQL_PRECEDING) ? "PRECEDING" : "FOLLOWING";
    4744             : 
    4745         410 :                 assert(token == SQL_PRECEDING || token == SQL_FOLLOWING);
    4746         410 :                 if (!(res = rel_value_exp2(query, &p, bound, f, ek)))
    4747           3 :                         return NULL;
    4748         410 :                 if (!(bt = exp_subtype(res))) { /* frame bound is a parameter */
    4749           3 :                         sql_subtype *t = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : iet;
    4750           3 :                         if (rel_set_type_param(sql, t, p, res, 0) < 0) /* workaround */
    4751             :                                 return NULL;
    4752           3 :                         bt = exp_subtype(res);
    4753             :                 }
    4754         410 :                 if (exp_is_null_no_value_opt(res))
    4755           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s offset must not be NULL", bound_desc);
    4756         409 :                 if ((frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) && bt->type->eclass != EC_NUM && !(res = exp_check_type(sql, bound_tp, p, res, type_equal)))
    4757             :                         return NULL;
    4758         409 :                 if (frame_type == FRAME_RANGE) {
    4759          70 :                         sql_class iet_class = iet->type->eclass;
    4760             : 
    4761          70 :                         if (!EC_NUMERIC(iet_class) && !EC_TEMP(iet_class))
    4762           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Ranges with arbitrary expressions are available to numeric, interval and temporal types only");
    4763          12 :                         if (EC_NUMERIC(iet_class) && !(res = exp_check_type(sql, iet, p, res, type_equal)))
    4764             :                                 return NULL;
    4765          69 :                         if ((iet_class == EC_TIME || iet_class == EC_TIME_TZ) && bt->type->eclass != EC_SEC) {
    4766           1 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "For %s input the %s boundary must be an interval type up to the day", subtype2string2(sql->ta, iet), bound_desc);
    4767           1 :                                 sa_reset(sql->ta);
    4768           1 :                                 return NULL;
    4769             :                         }
    4770          68 :                         if (EC_TEMP(iet->type->eclass) && !EC_INTERVAL(bt->type->eclass)) {
    4771           0 :                                 (void) sql_error(sql, 02, SQLSTATE(42000) "For %s input the %s boundary must be an interval type", subtype2string2(sql->ta, iet), bound_desc);
    4772           0 :                                 sa_reset(sql->ta);
    4773           0 :                                 return NULL;
    4774             :                         }
    4775             :                 }
    4776             :         }
    4777             :         return res;
    4778             : }
    4779             : 
    4780             : static dlist*
    4781          16 : get_window_clauses(mvc *sql, char* ident, symbol **partition_by_clause, symbol **order_by_clause, symbol **frame_clause)
    4782             : {
    4783          16 :         dlist *window_specification = NULL;
    4784          16 :         char *window_ident;
    4785          16 :         int pos;
    4786             : 
    4787          16 :         if (mvc_highwater(sql))
    4788           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    4789             : 
    4790          16 :         if ((window_specification = frame_get_window_def(sql, ident, &pos)) == NULL)
    4791           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window '%s' not found", ident);
    4792             : 
    4793             :         /* avoid infinite lookups */
    4794          15 :         if (frame_check_var_visited(sql, pos))
    4795           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cyclic references to window '%s' found", ident);
    4796          14 :         frame_set_var_visited(sql, pos);
    4797             : 
    4798          14 :         if (window_specification->h->next->data.sym) {
    4799           2 :                 if (*partition_by_clause)
    4800           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of PARTITION BY clause from window '%s'", ident);
    4801           2 :                 *partition_by_clause = window_specification->h->next->data.sym;
    4802             :         }
    4803          14 :         if (window_specification->h->next->next->data.sym) {
    4804           4 :                 if (*order_by_clause)
    4805           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of ORDER BY clause from window '%s'", ident);
    4806           3 :                 *order_by_clause = window_specification->h->next->next->data.sym;
    4807             :         }
    4808          13 :         if (window_specification->h->next->next->next->data.sym) {
    4809           0 :                 if (*frame_clause)
    4810           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: redefinition of frame clause from window '%s'", ident);
    4811           0 :                 *frame_clause = window_specification->h->next->next->next->data.sym;
    4812             :         }
    4813             : 
    4814          13 :         window_ident = window_specification->h->data.sval;
    4815          13 :         if (window_ident && !get_window_clauses(sql, window_ident, partition_by_clause, order_by_clause, frame_clause))
    4816             :                 return NULL; /* the error was already set */
    4817             : 
    4818             :         return window_specification; /* return something to say there were no errors */
    4819             : }
    4820             : 
    4821             : /*
    4822             :  * select x, y, rank_op() over (partition by x order by y) as, ...
    4823             :                 aggr_op(z) over (partition by y order by x) as, ...
    4824             :  * from table [x,y,z,w,v]
    4825             :  *
    4826             :  * project and order by over x,y / y,x
    4827             :  * a = project( table ) [ x, y, z, w, v ], [ x, y]
    4828             :  * b = project( table ) [ x, y, z, w, v ], [ y, x]
    4829             :  *
    4830             :  * project with order dependent operators, ie combined prev/current value
    4831             :  * aa = project (a) [ x, y, r = rank_op(diff(x) (marks a new partition), rediff(diff(x), y) (marks diff value with in partition)), z, w, v ]
    4832             :  * project(aa) [ aa.x, aa.y, aa.r ] -- only keep current output list
    4833             :  * bb = project (b) [ x, y, a = aggr_op(z, diff(y), rediff(diff(y), x)), z, w, v ]
    4834             :  * project(bb) [ bb.x, bb.y, bb.a ]  -- only keep current output list
    4835             :  */
    4836             : static sql_exp *
    4837       12707 : rel_rankop(sql_query *query, sql_rel **rel, symbol *se, int f)
    4838             : {
    4839       12707 :         mvc *sql = query->sql;
    4840       12707 :         node *n;
    4841       12707 :         dlist *l = se->data.lval, *window_specification = NULL;
    4842       12707 :         symbol *window_function = l->h->data.sym, *partition_by_clause = NULL, *order_by_clause = NULL, *frame_clause = NULL;
    4843       12707 :         char *aname = NULL, *sname = NULL, *window_ident = NULL;
    4844       12707 :         sql_subfunc *wf = NULL;
    4845       12707 :         sql_exp *in = NULL, *pe = NULL, *oe = NULL, *call = NULL, *start = NULL, *eend = NULL, *fstart = NULL, *fend = NULL, *ie = NULL;
    4846       12707 :         sql_rel *p;
    4847       12707 :         list *gbe = NULL, *obe = NULL, *args = NULL, *types = NULL, *fargs = NULL;
    4848       12707 :         dnode *dn = window_function->data.lval->h, *dargs = NULL;
    4849       12707 :         int distinct = 0, frame_type, pos, nf = f, nfargs = 0;
    4850       12707 :         bool is_nth_value, supports_frames = false, found = false;
    4851             : 
    4852       12707 :         frame_clear_visited_flag(sql); /* clear visited flags before iterating */
    4853             : 
    4854       12707 :         if (l->h->next->type == type_list) {
    4855       12691 :                 window_specification = l->h->next->data.lval;
    4856          16 :         } else if (l->h->next->type == type_string) {
    4857          16 :                 const char* window_alias = l->h->next->data.sval;
    4858          16 :                 if ((window_specification = frame_get_window_def(sql, window_alias, &pos)) == NULL)
    4859           1 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: window '%s' not found", window_alias);
    4860          15 :                 frame_set_var_visited(sql, pos);
    4861             :         } else {
    4862           0 :                 assert(0);
    4863             :         }
    4864             : 
    4865       12706 :         window_ident = window_specification->h->data.sval;
    4866       12706 :         partition_by_clause = window_specification->h->next->data.sym;
    4867       12706 :         order_by_clause = window_specification->h->next->next->data.sym;
    4868       12706 :         frame_clause = window_specification->h->next->next->next->data.sym;
    4869             : 
    4870       12706 :         if (window_ident && !get_window_clauses(sql, window_ident, &partition_by_clause, &order_by_clause, &frame_clause))
    4871             :                 return NULL;
    4872             : 
    4873       12703 :         frame_type = frame_clause ? frame_clause->data.lval->h->next->next->data.i_val : FRAME_RANGE;
    4874       12703 :         aname = qname_schema_object(dn->data.lval);
    4875       12703 :         sname = qname_schema(dn->data.lval);
    4876             : 
    4877       12703 :         is_nth_value = !strcmp(aname, "nth_value");
    4878       12703 :         bool is_value = is_nth_value || !strcmp(aname, "first_value") || !strcmp(aname, "last_value");
    4879       12703 :         bool rank = false;
    4880       12703 :         if (strcmp(aname, "row_number") == 0 || strcmp(aname, "rank") == 0 || strcmp(aname, "dense_rank") == 0 ||
    4881        2917 :             strcmp(aname, "percent_rank") == 0 || strcmp(aname, "cume_dist") == 0 || strcmp(aname, "ntile") == 0 ||
    4882        2813 :             strcmp(aname, "lag") == 0 || strcmp(aname, "lead") == 0 || strcmp(aname, "fetch") == 0)
    4883        9962 :                 rank = true;
    4884       12703 :         supports_frames = (!rank || is_value);
    4885             : 
    4886       12703 :         if (is_sql_update_set(f) || is_sql_psm(f) || is_sql_values(f) || is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f) || is_psm_call(f) || is_sql_from(f)) {
    4887          13 :                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4888          13 :                 const char *clause = is_sql_update_set(f)||is_sql_psm(f)?"in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses (use subquery)":is_sql_values(f)?"on an unique value":
    4889           8 :                                                          is_sql_join(f)?"in JOIN conditions":is_sql_where(f)?"in WHERE clause":is_sql_groupby(f)?"in GROUP BY clause":
    4890           4 :                                                          is_psm_call(f)?"in CALL":is_sql_from(f)?"in functions in FROM":"in HAVING clause";
    4891          13 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: window function '%s' not allowed %s", toUpperCopy(uaname, aname), aname, clause);
    4892       12690 :         } else if (is_sql_aggr(f)) {
    4893           2 :                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4894           2 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: window functions not allowed inside aggregation functions", toUpperCopy(uaname, aname));
    4895       12688 :         } else if (is_sql_window(f)) {
    4896           6 :                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4897           6 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: window functions cannot be nested", toUpperCopy(uaname, aname));
    4898             :         }
    4899       12682 :         if (window_function->token == SQL_AGGR) {
    4900         106 :                 dn->next->next->type = type_list;
    4901         106 :                 dn->next->next->data.lval = dlist_append_symbol(sql->sa, dlist_create( sql->sa ), dn->next->next->data.sym); /* make a list */
    4902             :         }
    4903       12682 :         if (window_function->token == SQL_NOP)
    4904       12576 :                 window_function->token = SQL_AGGR;
    4905       12682 :         if (window_function->token != SQL_RANK && window_function->token != SQL_AGGR) {
    4906           0 :                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4907           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window function '%s' unknown", toUpperCopy(uaname, aname));
    4908             :         }
    4909             : 
    4910             :         /* window operations are only allowed in the projection */
    4911       12682 :         if (!is_sql_sel(f))
    4912           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "OVER: only possible within the selection");
    4913             : 
    4914       12682 :         p = *rel;
    4915             :         /* Partition By */
    4916       12682 :         if (partition_by_clause) {
    4917        2321 :                 gbe = rel_partition_groupings(query, &p, partition_by_clause, NULL /* cannot use (selection) column references, as this result is a selection column */, nf | sql_window);
    4918        2321 :                 if (!gbe)
    4919             :                         return NULL;
    4920        4662 :                 for (n = gbe->h ; n ; n = n->next) {
    4921        2349 :                         sql_exp *en = n->data;
    4922             : 
    4923        2349 :                         set_ascending(en);
    4924        2349 :                         set_nulls_first(en);
    4925             :                 }
    4926             :         }
    4927             : 
    4928             :         /* Order By */
    4929       12674 :         if (order_by_clause) {
    4930        3029 :                 obe = rel_order_by(query, &p, order_by_clause, 0, sql_window);
    4931        3029 :                 if (!obe)
    4932             :                         return NULL;
    4933             :         }
    4934             : 
    4935       12667 :         fargs = sa_list(sql->sa);
    4936       12667 :         if (rank) { /* rank function call */
    4937        9948 :                 dlist *dl = dn->next->next->data.lval;
    4938        9948 :                 bool is_lag = !strcmp(aname, "lag"), is_lead = !strcmp(aname, "lead"),
    4939        9948 :                          extra_input = !strcmp(aname, "ntile") || !strcmp(aname, "rank") || !strcmp(aname, "dense_rank") || !strcmp(aname, "row_number") || !strcmp(aname, "percent_rank") || !strcmp(aname, "cume_dist");
    4940             : 
    4941        9948 :                 distinct = dn->next->data.i_val;
    4942        9948 :                 if (extra_input) { /* pass an input column for analytic functions that don't require it */
    4943        9877 :                         sql_subfunc *star = sql_bind_func(sql, "sys", "star", NULL, NULL, F_FUNC, true, true);
    4944        9877 :                         in = exp_op(sql->sa, NULL, star);
    4945        9877 :                         append(fargs, in);
    4946             :                 }
    4947        9948 :                 if (dl)
    4948         324 :                         for (dargs = dl->h ; dargs ; dargs = dargs->next) {
    4949         182 :                                 exp_kind ek = {type_value, card_column, FALSE};
    4950         182 :                                 sql_subtype *empty = sql_bind_localtype("void"), *bte = sql_bind_localtype("bte");
    4951             : 
    4952         182 :                                 in = rel_value_exp2(query, &p, dargs->data.sym, f | sql_window | sql_farg, ek);
    4953         182 :                                 if (!in)
    4954           0 :                                         return NULL;
    4955         182 :                                 if (!exp_subtype(in)) { /* we also do not expect parameters here */
    4956           0 :                                         char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4957           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to window functions", toUpperCopy(uaname, aname));
    4958             :                                 }
    4959         182 :                                 if (!exp_name(in))
    4960          99 :                                         exp_label(sql->sa, in, ++sql->label);
    4961             : 
    4962             :                                 /* corner case, if the argument is null convert it into something countable such as bte */
    4963         182 :                                 if (subtype_cmp(exp_subtype(in), empty) == 0)
    4964          13 :                                         in = exp_convert(sql, in, empty, bte);
    4965         182 :                                 if ((is_lag || is_lead) && nfargs == 2) { /* lag and lead 3rd arg must have same type as 1st arg */
    4966          10 :                                         sql_exp *first = (sql_exp*) fargs->h->data;
    4967          10 :                                         if (!(in = exp_check_type(sql, exp_subtype(first), p, in, type_equal)))
    4968             :                                                 return NULL;
    4969             :                                 }
    4970         172 :                                 if (!in)
    4971             :                                         return NULL;
    4972             : 
    4973         182 :                                 append(fargs, in);
    4974         182 :                                 in = exp_ref_save(sql, in);
    4975         182 :                                 nfargs++;
    4976             :                         }
    4977             :         } else { /* aggregation function call */
    4978        2719 :                 distinct = dn->next->data.i_val;
    4979        2719 :                 assert(dn->next->next->type == type_list);
    4980        2719 :                 dlist *dl = dn->next->next->data.lval;
    4981        9152 :                 for (dargs = dl?dl->h:NULL; dargs && dargs->data.sym ; dargs = dargs->next) {
    4982        3722 :                         exp_kind ek = {type_value, card_column, FALSE};
    4983        3722 :                         sql_subtype *empty = sql_bind_localtype("void"), *bte = sql_bind_localtype("bte");
    4984             : 
    4985        3722 :                         in = rel_value_exp2(query, &p, dargs->data.sym, f | sql_window | sql_farg, ek);
    4986        3722 :                         if (!in)
    4987           8 :                                 return NULL;
    4988        3715 :                         if (!exp_subtype(in)) { /* we also do not expect parameters here */
    4989           1 :                                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    4990           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: parameters not allowed as arguments to window functions", toUpperCopy(uaname, aname));
    4991             :                         }
    4992        3714 :                         if (!exp_name(in))
    4993        1994 :                                 exp_label(sql->sa, in, ++sql->label);
    4994             : 
    4995             :                         /* corner case, if the argument is null convert it into something countable such as bte */
    4996        3714 :                         if (subtype_cmp(exp_subtype(in), empty) == 0)
    4997          53 :                                 in = exp_convert(sql, in, empty, bte);
    4998        3714 :                         if (!in)
    4999             :                                 return NULL;
    5000             : 
    5001        3714 :                         append(fargs, in);
    5002        3714 :                         in = exp_ref_save(sql, in);
    5003        3714 :                         nfargs++;
    5004             : 
    5005        3714 :                         if (!strcmp(aname, "count"))
    5006          86 :                                 append(fargs, exp_atom_bool(sql->sa, 1)); /* ignore nills */
    5007             :                 }
    5008             : 
    5009        2711 :                 if (!nfargs) { /* count(*) */
    5010         110 :                         if (window_function->token == SQL_AGGR && strcmp(aname, "count") != 0) {
    5011           3 :                                 char *uaname = SA_NEW_ARRAY(sql->ta, char, strlen(aname) + 1);
    5012           3 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: unable to perform '%s(*)'", toUpperCopy(uaname, aname), aname);
    5013             :                         }
    5014         107 :                         sql_subfunc *star = sql_bind_func(sql, "sys", "star", NULL, NULL, F_FUNC, true, true);
    5015         107 :                         in = exp_op(sql->sa, NULL, star);
    5016         107 :                         append(fargs, in);
    5017         107 :                         append(fargs, exp_atom_bool(sql->sa, 0)); /* don't ignore nills */
    5018             :                 }
    5019             :         }
    5020             : 
    5021       12656 :         if (distinct)
    5022           4 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: DISTINCT clause is not implemented for window functions");
    5023             : 
    5024             :         /* diff for partitions */
    5025       12652 :         if (gbe) {
    5026        2304 :                 sql_subtype *bt = sql_bind_localtype("bit");
    5027             : 
    5028        4643 :                 for( n = gbe->h; n; n = n->next) {
    5029        2340 :                         sql_subfunc *df;
    5030        2340 :                         sql_exp *e = n->data;
    5031             : 
    5032        2340 :                         if (!exp_subtype(e))
    5033           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters not allowed at PARTITION BY clause from window functions");
    5034             : 
    5035        2339 :                         e = exp_copy(sql, e);
    5036        2339 :                         args = sa_list(sql->sa);
    5037        2339 :                         if (pe) {
    5038          36 :                                 df = sql_bind_func(sql, "sys", "diff", bt, exp_subtype(e), F_ANALYTIC, true, true);
    5039          36 :                                 append(args, pe);
    5040             :                         } else {
    5041        2303 :                                 df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
    5042             :                         }
    5043        2339 :                         if (!df)
    5044           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: function 'diff' not found");
    5045        2339 :                         append(args, e);
    5046        2339 :                         pe = exp_op(sql->sa, args, df);
    5047             :                 }
    5048             :         } else {
    5049       10348 :                 pe = exp_atom_bool(sql->sa, 0);
    5050             :         }
    5051             : 
    5052             :         /* diff for orderby */
    5053       12651 :         if (obe) {
    5054        3020 :                 sql_subtype *bt = sql_bind_localtype("bit");
    5055             : 
    5056        6196 :                 for( n = obe->h; n; n = n->next) {
    5057        3176 :                         sql_subfunc *df;
    5058        3176 :                         sql_exp *e = n->data;
    5059             : 
    5060        3176 :                         if (!exp_subtype(e))
    5061           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters not allowed at ORDER BY clause from window functions");
    5062             : 
    5063        3176 :                         e = exp_copy(sql, e);
    5064        3176 :                         args = sa_list(sql->sa);
    5065        3176 :                         if (oe) {
    5066         156 :                                 df = sql_bind_func(sql, "sys", "diff", bt, exp_subtype(e), F_ANALYTIC, true, true);
    5067         156 :                                 append(args, oe);
    5068             :                         } else {
    5069        3020 :                                 df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
    5070             :                         }
    5071        3176 :                         if (!df)
    5072           0 :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: function 'diff' not found");
    5073        3176 :                         append(args, e);
    5074        3176 :                         oe = exp_op(sql->sa, args, df);
    5075             :                 }
    5076             :         } else {
    5077        9631 :                 oe = exp_atom_bool(sql->sa, 0);
    5078             :         }
    5079             : 
    5080       12651 :         if (frame_clause || supports_frames) {
    5081        2708 :                 if (frame_type == FRAME_RANGE)
    5082        2397 :                         ie = obe ? (sql_exp*) obe->t->data : in;
    5083             :                 else
    5084         311 :                         ie = obe ? oe : in;
    5085             :         }
    5086       12651 :         assert(oe && pe);
    5087             : 
    5088       12651 :         types = exp_types(sql->sa, fargs);
    5089       12651 :         wf = bind_func_(sql, sname, aname, types, F_ANALYTIC, false, &found, false);
    5090       12651 :         if (wf && !list_empty(fargs) && !(fargs = check_arguments_and_find_largest_any_type(sql, NULL, fargs, wf, 0, false)))
    5091             :                 wf = NULL;
    5092       12647 :         if (!wf) {
    5093           4 :                 char *arg_list = nfargs ? nary_function_arg_types_2str(sql, types, nfargs) : NULL;
    5094           8 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: %s window function %s%s%s'%s'(%s)",
    5095           4 :                                                  found ? "insufficient privileges for" : "no such", sname ? "'":"", sname ? sname : "", sname ? "'.":"", aname, arg_list ? arg_list : "");
    5096             :         }
    5097             : 
    5098             :         /* Frame */
    5099       12647 :         if (frame_clause) {
    5100         410 :                 dnode *d = frame_clause->data.lval->h;
    5101         410 :                 symbol *wstart = d->data.sym, *wend = d->next->data.sym, *rstart = wstart->data.lval->h->data.sym,
    5102         410 :                            *rend = wend->data.lval->h->data.sym;
    5103         410 :                 int excl = d->next->next->next->data.i_val;
    5104         410 :                 bool shortcut = false;
    5105             : 
    5106         410 :                 if (!supports_frames)
    5107           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "OVER: frame extend only possible with aggregation and first_value, last_value and nth_value functions");
    5108         406 :                 if (excl != EXCLUDE_NONE)
    5109           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented");
    5110         406 :                 if (list_empty(obe) && frame_type == FRAME_GROUPS)
    5111           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "GROUPS frame requires an order by expression");
    5112         404 :                 if (wstart->token == SQL_FOLLOWING && wend->token == SQL_PRECEDING)
    5113           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "FOLLOWING offset must come after PRECEDING offset");
    5114         403 :                 if (wstart->token == SQL_CURRENT_ROW && wend->token == SQL_PRECEDING)
    5115           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "CURRENT ROW offset must come after PRECEDING offset");
    5116         402 :                 if (wstart->token == SQL_FOLLOWING && wend->token == SQL_CURRENT_ROW)
    5117           1 :                         return sql_error(sql, 02, SQLSTATE(42000) "FOLLOWING offset must come after CURRENT ROW offset");
    5118         401 :                 if (wstart->token != SQL_CURRENT_ROW && wend->token != SQL_CURRENT_ROW && wstart->token == wend->token && frame_type != FRAME_ROWS)
    5119           4 :                         return sql_error(sql, 02, SQLSTATE(42000) "Non-centered windows are only supported in row frames");
    5120         367 :                 if (frame_type == FRAME_RANGE) {
    5121          97 :                         if (((wstart->token == SQL_PRECEDING || wstart->token == SQL_FOLLOWING) && rstart->token != SQL_PRECEDING && rstart->token != SQL_CURRENT_ROW && rstart->token != SQL_FOLLOWING) ||
    5122          59 :                                 ((wend->token == SQL_PRECEDING || wend->token == SQL_FOLLOWING) && rend->token != SQL_PRECEDING && rend->token != SQL_CURRENT_ROW && rend->token != SQL_FOLLOWING)) {
    5123          40 :                                 if (list_empty(obe))
    5124           2 :                                         return sql_error(sql, 02, SQLSTATE(42000) "RANGE frame with PRECEDING/FOLLOWING offset requires an order by expression");
    5125          38 :                                 if (list_length(obe) > 1)
    5126           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY column");
    5127             :                         }
    5128             :                 }
    5129             : 
    5130         395 :                 if (list_empty(obe) && frame_type == FRAME_RANGE) { /* window functions are weird */
    5131             :                         frame_type = FRAME_ALL;
    5132             :                         shortcut = true;
    5133         383 :                 } else if (!is_value && (rstart->token == SQL_PRECEDING || rstart->token == SQL_CURRENT_ROW || rstart->token == SQL_FOLLOWING) && rstart->type == type_int &&
    5134         150 :                         (rend->token == SQL_PRECEDING || rend->token == SQL_CURRENT_ROW || rend->token == SQL_FOLLOWING) && rend->type == type_int) {
    5135             :                          /* special cases, don't calculate bounds */
    5136         146 :                         if (frame_type != FRAME_ROWS && rstart->data.i_val == UNBOUNDED_PRECEDING_BOUND && rend->data.i_val == CURRENT_ROW_BOUND) {
    5137             :                                 frame_type = FRAME_UNBOUNDED_TILL_CURRENT_ROW;
    5138             :                                 shortcut = true;
    5139          21 :                         } else if (frame_type != FRAME_ROWS && rstart->data.i_val == CURRENT_ROW_BOUND && rend->data.i_val == UNBOUNDED_FOLLOWING_BOUND) {
    5140             :                                 frame_type = FRAME_CURRENT_ROW_TILL_UNBOUNDED;
    5141             :                                 shortcut = true;
    5142          86 :                         } else if (rstart->data.i_val == UNBOUNDED_PRECEDING_BOUND && rend->data.i_val == UNBOUNDED_FOLLOWING_BOUND) {
    5143             :                                 frame_type = FRAME_ALL;
    5144             :                                 shortcut = true;
    5145          76 :                         } else if (rstart->data.i_val == CURRENT_ROW_BOUND && rend->data.i_val == CURRENT_ROW_BOUND) {
    5146         395 :                                 frame_type = FRAME_CURRENT_ROW;
    5147         395 :                                 shortcut = true;
    5148             :                         }
    5149             :                 }
    5150         395 :                 if (!shortcut) {
    5151         302 :                         if (!(fstart = calculate_window_bound(query, p, wstart->token, rstart, ie, frame_type, f | sql_window)))
    5152             :                                 return NULL;
    5153         299 :                         if (!(fend = calculate_window_bound(query, p, wend->token, rend, ie, frame_type, f | sql_window)))
    5154             :                                 return NULL;
    5155         471 :                         if (!generate_window_bound_call(sql, &start, &eend, gbe ? pe : NULL, ie, fstart, fend, frame_type, excl,
    5156             :                                                                                         wstart->token, wend->token))
    5157             :                                 return NULL;
    5158             :                 }
    5159       12237 :         } else if (supports_frames) { /* for analytic functions with no frame clause, we use the standard default values */
    5160        2296 :                 if (is_value) {
    5161         108 :                         sql_subtype *bound_tp = sql_bind_localtype("lng"), *bt = (frame_type == FRAME_ROWS || frame_type == FRAME_GROUPS) ? bound_tp : exp_subtype(ie);
    5162         108 :                         unsigned char sclass = bt->type->eclass;
    5163             : 
    5164         136 :                         fstart = exp_atom(sql->sa, atom_max_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp));
    5165         108 :                         fend = order_by_clause ? exp_atom(sql->sa, atom_zero_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp)) :
    5166          23 :                                                                          exp_atom(sql->sa, atom_max_value(sql->sa, EC_NUMERIC(sclass) ? bt : bound_tp));
    5167             : 
    5168         157 :                         if (generate_window_bound_call(sql, &start, &eend, gbe ? pe : NULL, ie, fstart, fend, frame_type, EXCLUDE_NONE, SQL_PRECEDING, SQL_FOLLOWING) == NULL)
    5169             :                                 return NULL;
    5170             :                 } else {
    5171        2188 :                         frame_type = list_empty(obe) ? FRAME_ALL : FRAME_UNBOUNDED_TILL_CURRENT_ROW;
    5172             :                 }
    5173             :         }
    5174             : 
    5175       12629 :         args = sa_list(sql->sa);
    5176       26652 :         for (node *n = fargs->h ; n ; n = n->next)
    5177       14023 :                 list_append(args, n->data);
    5178       12629 :         list_append(args, pe);
    5179       12629 :         list_append(args, oe);
    5180       12629 :         if (supports_frames) {
    5181        2688 :                 list_append(args, exp_atom_int(sql->sa, frame_type));
    5182        2688 :                 list_append(args, start ? start : exp_atom_oid(sql->sa, 1));
    5183        2688 :                 list_append(args, eend ? eend : exp_atom_oid(sql->sa, 1));
    5184             :         }
    5185       12629 :         call = exp_rank_op(sql->sa, list_empty(args) ? NULL : args, gbe, obe, wf);
    5186       12629 :         *rel = p;
    5187       12629 :         return call;
    5188             : }
    5189             : 
    5190             : sql_exp *
    5191     5948947 : rel_value_exp2(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
    5192             : {
    5193     5948947 :         mvc *sql = query->sql;
    5194     5948947 :         if (!se)
    5195             :                 return NULL;
    5196             : 
    5197     5948947 :         if (mvc_highwater(sql))
    5198          30 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    5199             : 
    5200     5949168 :         if (rel && *rel && (*rel)->card == CARD_AGGR) { /* group by expression case, handle it before */
    5201      136260 :                 sql_exp *exp = NULL;
    5202      136260 :                 if (!is_sql_aggr(f) && !is_sql_window(f))
    5203      135801 :                         exp = frame_get_groupby_expression(sql, se);
    5204      136260 :                 if (sql->errstr[0] != '\0')
    5205             :                         return NULL;
    5206      136260 :                 if (exp) {
    5207          80 :                         sql_exp *res = exp_ref(sql, exp);
    5208          80 :                         res->card = (*rel)->card;
    5209          80 :                         if (se->token == SQL_AGGR) {
    5210           0 :                                 dlist *l = se->data.lval;
    5211           0 :                                 int distinct = l->h->next->data.i_val;
    5212           0 :                                 if (distinct)
    5213           0 :                                         set_distinct(res);
    5214             :                         }
    5215          80 :                         if (!query_has_outer(query) && is_groupby((*rel)->op))
    5216          76 :                                 res = rel_groupby_add_aggr(sql, *rel, res);
    5217          80 :                         return res;
    5218             :                 }
    5219             :         }
    5220             : 
    5221     5949088 :         switch (se->token) {
    5222      554470 :         case SQL_NOP:
    5223      554470 :                 return rel_nop(query, rel, se, f, ek);
    5224       19456 :         case SQL_AGGR:
    5225       19456 :                 return rel_aggr(query, rel, se, f);
    5226       12707 :         case SQL_WINDOW:
    5227       12707 :                 return rel_rankop(query, rel, se, f);
    5228     2365048 :         case SQL_IDENT:
    5229             :         case SQL_COLUMN:
    5230     2365048 :                 return rel_column_ref(query, rel, se, f );
    5231        3019 :         case SQL_NAME: {
    5232        3019 :                 dlist *l = se->data.lval;
    5233        3019 :                 const char *sname = qname_schema(l);
    5234        3019 :                 const char *vname = qname_schema_object(l);
    5235        3019 :                 return rel_exp_variable_on_scope(sql, sname, vname);
    5236             :         }
    5237       50914 :         case SQL_VALUES:
    5238             :         case SQL_WITH:
    5239             :         case SQL_SELECT: {
    5240       50914 :                 sql_rel *r = NULL;
    5241             : 
    5242       50914 :                 if (is_psm_call(f) || is_sql_merge(f))
    5243           8 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: subqueries not supported inside %s", is_psm_call(f) ? "CALL" : "MERGE", is_psm_call(f) ? "CALL statements" : "MERGE conditions");
    5244       50910 :                 if (rel && *rel)
    5245       36797 :                         query_push_outer(query, *rel, f);
    5246       50910 :                 if (se->token == SQL_WITH) {
    5247          36 :                         r = rel_with_query(query, se);
    5248       50874 :                 } else if (se->token == SQL_VALUES) {
    5249         238 :                         r = rel_values(query, se, NULL);
    5250             :                 } else {
    5251       50636 :                         assert(se->token == SQL_SELECT);
    5252       50636 :                         exp_kind nek = ek;
    5253       50636 :                         nek.aggr = is_sql_aggr(f);
    5254       50636 :                         if (is_sql_no_subquery(f))
    5255           3 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery not allowed");
    5256             : 
    5257       50633 :                         r = rel_subquery(query, se, nek);
    5258       50633 :                         if (r)
    5259       50532 :                                 exps_label(sql, r->exps);
    5260             :                 }
    5261       50907 :                 if (rel && *rel) {
    5262       36794 :                         *rel = query_pop_outer(query);
    5263       36794 :                         if (is_sql_join(f) && is_groupby((*rel)->op)) {
    5264           0 :                                 return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions");
    5265       36794 :                         } else if (is_sql_where(f) && is_groupby((*rel)->op)) {
    5266           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause");
    5267       36794 :                         } else if ((is_sql_update_set(f) || is_sql_psm(f)) && is_groupby((*rel)->op)) {
    5268           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, WHEN, RETURN, ANALYZE clauses");
    5269             :                         }
    5270             :                 }
    5271       50907 :                 if (!r)
    5272             :                         return NULL;
    5273       50803 :                 if (ek.type == type_value && ek.card <= card_set && is_project(r->op) && list_length(r->exps) > 1)
    5274          17 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column");
    5275       50786 :                 if (ek.type == type_relation && is_project(r->op) && list_length(r->exps) != ek.type)
    5276           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery has too %s columns", list_length(r->exps) < ek.type ? "few" : "many");
    5277       50786 :                 if (ek.type == type_value && list_length(r->exps) == 1 && !is_sql_psm(f)) /* for now don't rename multi attribute results */
    5278       38527 :                         r = rel_zero_or_one(sql, r, ek);
    5279       50786 :                 return exp_rel(sql, r);
    5280             :         }
    5281         215 :         case SQL_TABLE: {
    5282             :                 /* turn a subquery into a tabular result */
    5283         215 :                 *rel = rel_selects(query, se->data.sym);
    5284         215 :                 if (*rel)
    5285         213 :                         return lastexp(*rel);
    5286             :                 return NULL;
    5287             :         }
    5288        1612 :         case SQL_PARAMETER: {
    5289        1612 :                 assert(se->type == type_int);
    5290        1612 :                 sql_arg *a = sql_bind_paramnr(sql, se->data.i_val);
    5291        1612 :                 if (sql->emode != m_prepare) {
    5292           1 :                         if (a && a->name && a->name[0])
    5293           1 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: named placeholder ('%s') but named values list is missing", a->name);
    5294             :                         else
    5295           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: parameters ('?') not allowed in normal queries, use PREPARE");
    5296             :                 }
    5297        1611 :                 return exp_atom_ref(sql->sa, se->data.i_val, a?&a->type:NULL);
    5298             :         }
    5299      107840 :         case SQL_NULL:
    5300      107840 :                 return exp_null(sql->sa, sql_bind_localtype("void"));
    5301        1584 :         case SQL_NEXT:
    5302        1584 :                 return rel_next_value_for(sql, se);
    5303      172563 :         case SQL_CAST:
    5304      172563 :                 return rel_cast(query, rel, se, f);
    5305      105295 :         case SQL_CASE:
    5306             :         case SQL_COALESCE:
    5307             :         case SQL_NULLIF:
    5308      105295 :                 return rel_case_exp(query, rel, se, f);
    5309           0 :         case SQL_RANK:
    5310           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: window function %s requires an OVER clause", qname_schema_object(se->data.lval->h->data.lval));
    5311          25 :         case SQL_XMLELEMENT:
    5312             :         case SQL_XMLFOREST:
    5313             :         case SQL_XMLCOMMENT:
    5314             :         case SQL_XMLATTRIBUTE:
    5315             :         case SQL_XMLCONCAT:
    5316             :         case SQL_XMLDOCUMENT:
    5317             :         case SQL_XMLPI:
    5318             :         case SQL_XMLTEXT:
    5319          25 :                 return rel_xml(query, rel, se, f, ek);
    5320     2554340 :         default:
    5321     2554340 :                 return rel_logical_value_exp(query, rel, se, f, ek);
    5322             :         }
    5323             : }
    5324             : 
    5325             : static int exps_has_rank(list *exps);
    5326             : 
    5327             : static int
    5328             : exp_has_rank(sql_exp *e)
    5329             : {
    5330             :         switch(e->type) {
    5331             :         case e_convert:
    5332             :                 return exp_has_rank(e->l);
    5333             :         case e_func:
    5334             :                 if (e->r)
    5335             :                         return 1;
    5336             :                 /* fall through */
    5337             :         case e_aggr:
    5338             :                 return exps_has_rank(e->l);
    5339             :         case e_cmp:
    5340             :                 if (e->flag == cmp_or || e->flag == cmp_filter)
    5341             :                         return exps_has_rank(e->l) || exps_has_rank(e->r);
    5342             :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    5343             :                         return exp_has_rank(e->l) || exps_has_rank(e->r);
    5344             :                 return exp_has_rank(e->l) || exp_has_rank(e->r) || (e->f && exp_has_rank(e->f));
    5345             :         default:
    5346             :                 return 0;
    5347             :         }
    5348             : }
    5349             : 
    5350             : /* TODO create exps_has (list, fptr ) */
    5351             : static int
    5352             : exps_has_rank(list *exps)
    5353             : {
    5354             :         if (!exps || list_empty(exps))
    5355             :                 return 0;
    5356             :         for(node *n = exps->h; n; n=n->next){
    5357             :                 sql_exp *e = n->data;
    5358             : 
    5359             :                 if (exp_has_rank(e))
    5360             :                         return 1;
    5361             :         }
    5362             :         return 0;
    5363             : }
    5364             : 
    5365             : sql_exp *
    5366     4527525 : rel_value_exp(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
    5367             : {
    5368     4527525 :         if (!se)
    5369             :                 return NULL;
    5370             : 
    5371     4527525 :         if (mvc_highwater(query->sql))
    5372           0 :                 return sql_error(query->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    5373             : 
    5374     4527588 :         sql_exp *e = rel_value_exp2(query, rel, se, f, ek);
    5375     4527617 :         if (e && (se->token == SQL_SELECT || se->token == SQL_TABLE) && !exp_is_rel(e)) {
    5376           0 :                 assert(*rel);
    5377           0 :                 return rel_lastexp(query->sql, *rel);
    5378             :         }
    5379             :         return e;
    5380             : }
    5381             : 
    5382             : static sql_exp *
    5383     1339590 : column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
    5384             : {
    5385     1339590 :         dlist *l = column_e->data.lval;
    5386     1339590 :         exp_kind ek = {type_value, card_column, FALSE};
    5387     1339590 :         sql_exp *ve;
    5388             : 
    5389     1339590 :         if (f == sql_sel && rel && *rel && (*rel)->card < CARD_AGGR)
    5390       82660 :                 ek.card = card_value;
    5391     1339590 :         ve = rel_value_exp(query, rel, l->h->data.sym, f, ek);
    5392     1339681 :         if (!ve)
    5393             :                 return NULL;
    5394             :         /* AS name */
    5395     1324001 :         if (ve && l->h->next->data.sval)
    5396      507184 :                 exp_setname(query->sql, ve, NULL, l->h->next->data.sval);
    5397             :         return ve;
    5398             : }
    5399             : 
    5400             : static int
    5401      843498 : exp_is_not_intern(sql_exp *e)
    5402             : {
    5403      843498 :         return is_intern(e)?-1:0;
    5404             : }
    5405             : 
    5406             : static void
    5407      129319 : rel_remove_internal_exp(sql_rel *rel)
    5408             : {
    5409      129319 :         if (rel->exps) {
    5410      129319 :                 list *n_exps = list_select(rel->exps, rel, (fcmp)&exp_is_not_intern, (fdup)NULL);
    5411             : 
    5412      129319 :                 rel->exps = n_exps;
    5413             :         }
    5414      129319 : }
    5415             : 
    5416             : static inline int
    5417          39 : exp_key(sql_exp *e)
    5418             : {
    5419          39 :         if (e->alias.name)
    5420          39 :                 return hash_key(e->alias.name);
    5421             :         return 0;
    5422             : }
    5423             : 
    5424             : static list *
    5425          17 : group_merge_exps(mvc *sql, list *gexps, list *exps)
    5426             : {
    5427          17 :         int nexps = list_length(gexps) + list_length(exps);
    5428             : 
    5429          17 :         sql_hash *ht = hash_new(sql->ta, nexps, (fkeyvalue)&exp_key);
    5430             : 
    5431          27 :         for (node *n = gexps->h; n ; n = n->next) { /* first add grouping expressions */
    5432          10 :                 sql_exp *e = n->data;
    5433          10 :                 int key = ht->key(e);
    5434             : 
    5435          10 :                 hash_add(ht, key, e);
    5436             :         }
    5437             : 
    5438          46 :         for (node *n = exps->h; n ; n = n->next) { /* then test if the new grouping expressions are already there */
    5439          29 :                 sql_exp *e = n->data;
    5440          29 :                 int key = ht->key(e);
    5441          29 :                 sql_hash_e *he = ht->buckets[key&(ht->size-1)];
    5442          29 :                 bool duplicates = false;
    5443             : 
    5444          37 :                 for (; he && !duplicates; he = he->chain) {
    5445           8 :                         sql_exp *f = he->value;
    5446             : 
    5447           8 :                         if (!exp_equal(e, f))
    5448           4 :                                 duplicates = true;
    5449             :                 }
    5450          29 :                 hash_add(ht, key, e);
    5451          29 :                 if (!duplicates) {
    5452          25 :                         list_append(gexps, e);
    5453          25 :                         n->data = exp_ref(sql, e);
    5454             :                 }
    5455             :         }
    5456          17 :         return gexps;
    5457             : }
    5458             : 
    5459             : static list *
    5460       58776 : rel_table_exp(sql_query *query, sql_rel **rel, symbol *column_e, bool single_exp )
    5461             : {
    5462       58776 :         mvc *sql = query->sql;
    5463       58776 :         if (column_e->token == SQL_TABLE && column_e->data.lval->h->type == type_symbol) {
    5464           0 :                 sql_rel *r;
    5465             : 
    5466           0 :                 if (!is_project((*rel)->op))
    5467             :                         return NULL;
    5468           0 :                 r = rel_named_table_function(query, (*rel)->l, column_e, 0, NULL);
    5469           0 :                 if (!r)
    5470             :                         return NULL;
    5471           0 :                 *rel = r;
    5472           0 :                 return sa_list(sql->sa);
    5473             :         }
    5474       58776 :         char *tname = NULL;
    5475       58776 :         if (column_e->token == SQL_TABLE) {
    5476       43107 :                 tname = column_e->data.lval->h->data.sval;
    5477       15669 :         } else if (column_e->token == SQL_COLUMN && column_e->data.lval->h->type == type_symbol) {
    5478       15669 :                 symbol *sym = column_e->data.lval->h->data.sym;
    5479       15669 :                 if (sym->token == SQL_COLUMN)
    5480       14675 :                         tname = sym->data.lval->h->data.sval;
    5481             :                 else
    5482             :                         return NULL;
    5483             :         } else {
    5484             :                 return NULL;
    5485             :         }
    5486             : 
    5487             : 
    5488       57782 :                 list *exps = NULL;
    5489       57782 :                 sql_rel *project = *rel, *groupby = NULL;
    5490             : 
    5491             :                 /* if there's a group by relation in the tree, skip it for the '*' case and use the underlying projection */
    5492       57782 :                 if (project) {
    5493       67124 :                         while (is_groupby(project->op) || is_select(project->op)) {
    5494        9342 :                                 if (is_groupby(project->op))
    5495          37 :                                         groupby = project;
    5496        9342 :                                 if (project->l)
    5497        9342 :                                         project = project->l;
    5498             :                         }
    5499             :                         assert(project);
    5500             :                 }
    5501             : 
    5502       57782 :                 if (project->op == op_project && project->l && project == *rel && !tname && !rel_is_ref(project) && !need_distinct(project) && single_exp) {
    5503         498 :                         sql_rel *l = project->l;
    5504         498 :                         if (!l || !is_project(l->op) || list_length(project->exps) == list_length(l->exps)) {
    5505         491 :                                 rel_remove_internal_exp(*rel);
    5506         491 :                                 exps = project->exps;
    5507         491 :                                 *rel = project->l;
    5508             :                         }
    5509             :                 }
    5510       57782 :                 if ((exps || (exps = rel_table_projections(sql, project, tname, 0)) != NULL) && !list_empty(exps)) {
    5511       57679 :                         if (!(exps = check_distinct_exp_names(sql, exps)))
    5512           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Duplicate column names in table%s%s%s projection list", tname ? " '" : "", tname ? tname : "", tname ? "'" : "");
    5513       57677 :                         if (groupby) {
    5514          17 :                                 groupby->exps = group_merge_exps(sql, groupby->exps, exps);
    5515          40 :                                 for (node *n = groupby->exps->h ; n ; n = n->next) {
    5516          30 :                                         sql_exp *e = n->data;
    5517             : 
    5518          30 :                                         if (e->card > groupby->card) {
    5519           7 :                                                 if (exp_name(e) && !has_label(e))
    5520           7 :                                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(e));
    5521           0 :                                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    5522             :                                         }
    5523             :                                 }
    5524             :                         }
    5525       57670 :                         return exps;
    5526             :                 }
    5527         105 :                 if (!tname)
    5528           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "Table expression without table name");
    5529         103 :                 return sql_error(sql, 02, SQLSTATE(42000) "Column expression Table '%s' unknown", tname);
    5530             :         //return NULL;
    5531             : }
    5532             : 
    5533             : sql_exp *
    5534     1382698 : rel_column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
    5535             : {
    5536     1382698 :         if (column_e->token == SQL_COLUMN || column_e->token == SQL_IDENT)
    5537     1339594 :                 return column_exp(query, rel, column_e, f);
    5538             :         return NULL;
    5539             : }
    5540             : 
    5541             : static sql_rel*
    5542      374883 : rel_where_groupby_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, int *group_totals)
    5543             : {
    5544      374883 :         mvc *sql = query->sql;
    5545             : 
    5546      374883 :         if (sn->where) {
    5547      146695 :                 rel = rel_logical_exp(query, rel, sn->where, sql_where);
    5548      146695 :                 if (!rel) {
    5549          76 :                         if (sql->errstr[0] == 0)
    5550           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "Subquery result missing");
    5551             :                         return NULL;
    5552             :                 }
    5553             :         }
    5554      374807 :         query_processed(query);
    5555             : 
    5556      374803 :         if (rel && sn->groupby) {
    5557       13409 :                 list *gbe = NULL, *sets = NULL;
    5558       13409 :                 int all = 0;
    5559       13409 :                 if (sn->groupby->data.lval == NULL) { /* ALL */
    5560             :                         all = 1;
    5561             :                 } else {
    5562       49517 :                         for (dnode *o = sn->groupby->data.lval->h; o ; o = o->next) {
    5563       36235 :                                 symbol *grouping = o->data.sym;
    5564       36235 :                                 if (grouping->token == SQL_ROLLUP || grouping->token == SQL_CUBE || grouping->token == SQL_GROUPING_SETS) {
    5565         119 :                                         *group_totals |= sql_group_totals;
    5566         119 :                                         break;
    5567             :                                 }
    5568             :                         }
    5569       13401 :                         gbe = rel_groupings(query, &rel, sn->groupby, sn->selection, sql_sel | sql_groupby | *group_totals, false, &sets);
    5570       13401 :                         if (!gbe)
    5571          20 :                                 return NULL;
    5572             :                 }
    5573       13389 :                 rel = rel_groupby(sql, rel, gbe);
    5574       13389 :                 if (rel && all)
    5575           8 :                         rel->flag = 2;
    5576       13389 :                 if (sets && list_length(sets) > 1) { /* if there is only one combination, there is no reason to generate unions */
    5577         114 :                         prop *p = prop_create(sql->sa, PROP_GROUPINGS, rel->p);
    5578         114 :                         p->value.pval = sets;
    5579         114 :                         rel->p = p;
    5580             :                 }
    5581             :         }
    5582             : 
    5583      374783 :         if (rel && sn->having) {
    5584             :                 /* having implies group by, ie if not supplied do a group by */
    5585        1766 :                 if (rel->op != op_groupby)
    5586         128 :                         rel = rel_groupby(sql, rel, NULL);
    5587             :         }
    5588      374783 :         query_processed(query);
    5589      374814 :         return rel;
    5590             : }
    5591             : 
    5592             : static sql_rel*
    5593      373670 : rel_having_limits_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek, int group_totals)
    5594             : {
    5595      373670 :         mvc *sql = query->sql;
    5596      373670 :         sql_rel *inner = NULL;
    5597      373670 :         int single_value = 1;
    5598             : 
    5599      373670 :         if (is_project(rel->op) && rel->l) {
    5600      373670 :                 inner = rel->l;
    5601      373670 :                 single_value = 0;
    5602             :         }
    5603             : 
    5604      373670 :         if (sn->having) {
    5605        1759 :                 if (inner && is_groupby(inner->op))
    5606        1759 :                         set_processed(inner);
    5607        1759 :                 if (!(inner = rel_logical_exp(query, inner, sn->having, sql_having | group_totals)))
    5608             :                         return NULL;
    5609        1718 :                 if (inner->exps && exps_card(inner->exps) > CARD_AGGR)
    5610           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cannot compare sets with values, probably an aggregate function missing");
    5611        1718 :                 if (!single_value)
    5612        1718 :                         rel->l = inner;
    5613             :         }
    5614             : 
    5615      373629 :         if (rel && sn->distinct)
    5616        1031 :                 rel = rel_distinct(rel);
    5617             : 
    5618      373629 :         if (rel && sn->orderby) {
    5619       37063 :                 list *obe = NULL;
    5620       37063 :                 sql_rel *sel = NULL, *l = rel->l;
    5621             : 
    5622             :                 /* project( select ) */
    5623       37063 :                 if (sn->having && is_select(l->op)) {
    5624          52 :                         sel = l;
    5625          52 :                         rel->l = l->l;
    5626             :                 }
    5627       37063 :                 rel = rel_orderby(sql, rel);
    5628       37063 :                 set_processed(rel);
    5629       37063 :                 obe = rel_order_by(query, &rel, sn->orderby, sn->distinct, sql_orderby | group_totals);
    5630       37063 :                 if (!obe)
    5631             :                         return NULL;
    5632       37022 :                 rel->r = obe;
    5633       37022 :                 if (sel) {
    5634          51 :                         sql_rel *o = rel, *p = o->l;
    5635          51 :                         p->l = sel;
    5636             :                 }
    5637             :         }
    5638      373588 :         if (!rel)
    5639             :                 return NULL;
    5640             : 
    5641      373588 :         if (sn->limit || sn->offset) {
    5642       16719 :                 sql_subtype *lng = sql_bind_localtype("lng");
    5643       16731 :                 list *exps = new_exp_list(sql->sa);
    5644             : 
    5645       16729 :                 if (sn->limit) {
    5646       16703 :                         sql_exp *l = rel_value_exp(query, NULL, sn->limit, 0, ek);
    5647             : 
    5648       16702 :                         if (!l || !(l=exp_check_type(sql, lng, NULL, l, type_equal)))
    5649           0 :                                 return NULL;
    5650       16705 :                         if ((ek.card != card_relation && sn->limit) &&
    5651             :                                 (ek.card == card_value && sn->limit)) {
    5652          12 :                                 sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", exp_subtype(l), NULL, F_AGGR, true, true);
    5653          12 :                                 l = exp_aggr1(sql->sa, l, zero_or_one, 0, 0, CARD_ATOM, has_nil(l));
    5654             :                         }
    5655       16705 :                         list_append(exps, l);
    5656             :                 } else
    5657          26 :                         list_append(exps, exp_atom(sql->sa, atom_general(sql->sa, lng, NULL, 0)));
    5658       16729 :                 if (sn->offset) {
    5659          86 :                         sql_exp *o = rel_value_exp( query, NULL, sn->offset, 0, ek);
    5660          86 :                         if (!o || !(o=exp_check_type(sql, lng, NULL, o, type_equal)))
    5661           0 :                                 return NULL;
    5662          86 :                         list_append(exps, o);
    5663             :                 }
    5664       16729 :                 rel = rel_topn(sql->sa, rel, exps);
    5665             :         }
    5666             : 
    5667      373596 :         if (sn->sample || sn->seed) {
    5668          40 :                 list *exps = new_exp_list(sql->sa);
    5669             : 
    5670          23 :                 if (sn->sample) {
    5671          23 :                         sql_exp *s = rel_value_exp(query, NULL, sn->sample, 0, ek);
    5672          23 :                         if (!s)
    5673             :                                 return NULL;
    5674          23 :                         if (!exp_subtype(s) && rel_set_type_param(sql, sql_bind_localtype("lng"), NULL, s, 0) < 0)
    5675             :                                 return NULL;
    5676          23 :                         list_append(exps, s);
    5677             :                 } else {
    5678           0 :                         assert(sn->seed);
    5679           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SEED: cannot have SEED without SAMPLE");
    5680             :                 }
    5681          23 :                 if (sn->seed) {
    5682          12 :                         sql_exp *e = rel_value_exp(query, NULL, sn->seed, 0, ek);
    5683          12 :                         if (!e || !(e=exp_check_type(sql, sql_bind_localtype("int"), NULL, e, type_equal)))
    5684           0 :                                 return NULL;
    5685          12 :                         list_append(exps, e);
    5686             :                 }
    5687          23 :                 rel = rel_sample(sql->sa, rel, exps);
    5688             :         }
    5689             : 
    5690             :         /* after parsing the current query, set the group by relation as processed */
    5691      373579 :         if (!sn->having && inner && is_groupby(inner->op))
    5692       32682 :                 set_processed(inner);
    5693      373579 :         if (rel)
    5694      373579 :                 set_processed(rel);
    5695             :         return rel;
    5696             : }
    5697             : 
    5698             : static sql_rel *
    5699          62 : join_on_column_name(sql_query *query, sql_rel *rel, sql_rel *t1, sql_rel *t2, int op, int l_nil, int r_nil)
    5700             : {
    5701          62 :         mvc *sql = query->sql;
    5702          62 :         int found = 0, full = (op == op_full), right = (op == op_right);
    5703          62 :         list *exps = rel_projections(sql, t1, NULL, 1, 0);
    5704          62 :         list *r_exps = rel_projections(sql, t2, NULL, 1, 0);
    5705          62 :         list *outexps = new_exp_list(sql->sa);
    5706             : 
    5707          62 :         if (!exps || !r_exps)
    5708             :                 return NULL;
    5709         244 :         for (node *n = exps->h; n; n = n->next) {
    5710         185 :                 sql_exp *le = n->data;
    5711         185 :                 int multi = 0;
    5712         185 :                 const char *rname = exp_relname(le), *name = exp_name(le);
    5713         185 :                 sql_exp *re = exps_bind_column(r_exps, name, NULL, &multi, 0);
    5714             : 
    5715         185 :                 if (re) {
    5716         140 :                         if (multi)
    5717           3 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "NATURAL JOIN: common column name '%s' appears more than once in right table", rname);
    5718         138 :                         multi = 0;
    5719         138 :                         le = exps_bind_column(exps, name, NULL, &multi, 0);
    5720         138 :                         if (multi)
    5721           0 :                                 return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "NATURAL JOIN: common column name '%s' appears more than once in left table", rname);
    5722             : 
    5723         138 :                         found = 1;
    5724         138 :                         if (!(rel = rel_compare_exp(query, rel, le, re, "=", TRUE, 0, 0, 0, 0)))
    5725             :                                 return NULL;
    5726         137 :                         list_remove_data(r_exps, NULL, re);
    5727         137 :                         if (full) {
    5728          12 :                                 sql_exp *cond = rel_unop_(sql, rel, le, "sys", "isnull", card_value);
    5729          12 :                                 if (!cond)
    5730             :                                         return NULL;
    5731          12 :                                 set_has_no_nil(cond);
    5732          12 :                                 if (rel_convert_types(sql, NULL, NULL, &le, &re, 1, type_equal_no_any) < 0)
    5733             :                                         return NULL;
    5734          12 :                                 if (!(le = rel_nop_(sql, rel, cond, re, le, NULL, "sys", "ifthenelse", card_value)))
    5735             :                                         return NULL;
    5736         125 :                         } else if (right) {
    5737           3 :                                 le = re;
    5738             :                         }
    5739         137 :                         exp_setname(sql, le, rname, name);
    5740         137 :                         set_not_unique(le);
    5741         137 :                         append(outexps, le);
    5742             :                 } else {
    5743          45 :                         if (l_nil)
    5744           5 :                                 set_has_nil(le);
    5745          45 :                         set_not_unique(le);
    5746          45 :                         append(outexps, le);
    5747             :                 }
    5748             :         }
    5749          59 :         if (!found)
    5750           2 :                 return sql_error(sql, 02, SQLSTATE(42000) "JOIN: no columns of tables '%s' and '%s' match", rel_name(t1)?rel_name(t1):"", rel_name(t2)?rel_name(t2):"");
    5751          90 :         for (node *n = r_exps->h; n; n = n->next) {
    5752          33 :                 sql_exp *re = n->data;
    5753          33 :                 if (r_nil)
    5754           3 :                         set_has_nil(re);
    5755          33 :                 set_not_unique(re);
    5756          33 :                 append(outexps, re);
    5757             :         }
    5758          57 :         rel = rel_project(sql->sa, rel, outexps);
    5759          57 :         return rel;
    5760             : }
    5761             : 
    5762             : static sql_rel *
    5763      374907 : rel_select_exp(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek)
    5764             : {
    5765      374907 :         mvc *sql = query->sql;
    5766      374907 :         sql_rel *inner = NULL;
    5767      374907 :         int group_totals = 0;
    5768      374907 :         list *pexps = NULL;
    5769             : 
    5770      374907 :         assert(sn->s.token == SQL_SELECT);
    5771      374907 :         if (!sn->selection)
    5772           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: the selection or from part is missing");
    5773             : 
    5774      374907 :         if (!rel)
    5775       72659 :                 rel = rel_project_exp(sql, exp_atom_bool(sql->sa, 1));
    5776      374953 :         rel = rel_where_groupby_nodes(query, rel, sn, &group_totals);
    5777      374924 :         if (sql->session->status) /* rel might be NULL as input, so we have to check for the session status for errors */
    5778             :                 return NULL;
    5779             : 
    5780      374825 :         inner = rel;
    5781      374825 :         pexps = sa_list(sql->sa);
    5782     1756480 :         for (dnode *n = sn->selection->h; n; n = n->next) {
    5783             :                 /* Here we could get real column expressions
    5784             :                  * (including single atoms) but also table results.
    5785             :                  * Therefore we try both rel_column_exp
    5786             :                  * and rel_table_exp.
    5787             :                  */
    5788     1382766 :                 list *te = NULL;
    5789     2765457 :                 sql_exp *ce = rel_column_exp(query, &inner, n->data.sym, sql_sel | group_totals | (ek.aggr?sql_aggr:0));
    5790             : 
    5791     1382743 :                 if (ce) {
    5792     1323966 :                         if (inner && inner->flag && is_groupby(inner->op)) {
    5793          62 :                                 int found = 0;
    5794          62 :                                 list *gbe = inner->r;
    5795             :                                 /* flag == 2 just add to group by/ aggrs and ref-to pexps*/
    5796             :                                 /* flag == 1 find group by exp referencing this column nr */
    5797          62 :                                 if (inner->flag == 2) {
    5798          25 :                                         if (ce->card > CARD_AGGR) {
    5799           9 :                                                 if (!gbe)
    5800           8 :                                                         inner->r = gbe = sa_list(sql->sa);
    5801           9 :                                                 append(gbe, ce);
    5802           9 :                                                 ce = exp_ref(sql, ce);
    5803           9 :                                                 ce->card = CARD_AGGR;
    5804           9 :                                                 list_append(inner->exps, ce);
    5805           9 :                                                 ce = exp_ref(sql, ce);
    5806           9 :                                                 found = 1;
    5807             :                                         }
    5808             :                                 } else {
    5809          81 :                                         for(node *n = gbe->h; n && !found; n = n->next) {
    5810          44 :                                                 sql_exp *e = n->data;
    5811          44 :                                                 if (is_atom(e->type) && !e->alias.name) {
    5812          29 :                                                         atom *a = e->l;
    5813          29 :                                                         int nr = (int)atom_get_int(a);
    5814          29 :                                                         if (nr == (list_length(pexps) + 1)) {
    5815          27 :                                                                 n->data = ce;
    5816          27 :                                                                 ce = exp_ref(sql, ce);
    5817          27 :                                                                 ce->card = CARD_AGGR;
    5818          27 :                                                                 list_append(inner->exps, ce);
    5819          27 :                                                                 ce = exp_ref(sql, ce);
    5820          27 :                                                                 found = 1;
    5821             :                                                         }
    5822             :                                                 }
    5823             :                                         }
    5824             :                                 }
    5825             :                         }
    5826     1323966 :                         pexps = append(pexps, ce);
    5827     1323971 :                         rel = inner;
    5828     1323971 :                         continue;
    5829             :                 } else {
    5830       63338 :                         te = rel_table_exp(query, &rel, n->data.sym, !list_length(pexps) && !n->next);
    5831             :                 }
    5832       58776 :                 if (!ce && !te) {
    5833        1106 :                         if (sql->errstr[0])
    5834             :                                 return NULL;
    5835           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery result missing");
    5836             :                 }
    5837             :                 /* here we should merge the column expressions we
    5838             :                  * obtained so far with the table expression, ie
    5839             :                  * t1.* or a subquery.
    5840             :                  */
    5841       57670 :                 pexps = list_merge(pexps, te, (fdup)NULL);
    5842             :         }
    5843      373714 :         if (rel && is_groupby(rel->op) && rel->flag) {
    5844          34 :                 list *gbe = rel->r;
    5845          34 :                 if (!list_empty(gbe)) {
    5846          68 :                         for (node *n=gbe->h; n; n = n->next) {
    5847          37 :                                 sql_exp *e = n->data;
    5848          37 :                                 if (rel->flag == 1 && is_atom(e->type) && !e->alias.name) {
    5849           1 :                                         atom *a = e->l;
    5850           1 :                                         int nr = (int)atom_get_int(a);
    5851           1 :                                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUP BY position %d is not in select list", nr);
    5852             :                                 }
    5853          36 :                                 if (exp_has_aggr(rel, e))
    5854           2 :                                         return sql_error(sql, 02, SQLSTATE(42000) "SELECT: aggregate functions are not allowed in GROUP BY");
    5855             :                         }
    5856             :                 }
    5857             :         }
    5858      373711 :         if (rel && is_groupby(rel->op) && (!sn->groupby || rel->flag) && !is_processed(rel)) {
    5859       43235 :                 for (node *n=pexps->h; n; n = n->next) {
    5860       22081 :                         sql_exp *ce = n->data;
    5861       22081 :                         if (rel->card < ce->card && !exp_is_aggr(rel, ce)) {
    5862           0 :                                 if (exp_name(ce) && !has_label(ce))
    5863           0 :                                         return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results without an aggregate function", exp_name(ce));
    5864           0 :                                 return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function");
    5865             :                         }
    5866             :                 }
    5867       21154 :                 set_processed(rel);
    5868             :         }
    5869      373711 :         rel = rel_project(sql->sa, rel, pexps);
    5870             : 
    5871      373721 :         rel = rel_having_limits_nodes(query, rel, sn, ek, group_totals);
    5872      373721 :         return rel;
    5873             : }
    5874             : 
    5875             : static sql_rel*
    5876      128780 : rel_unique_names(mvc *sql, sql_rel *rel)
    5877             : {
    5878      128780 :         list *l;
    5879             : 
    5880      128780 :         if (!is_project(rel->op))
    5881             :                 return rel;
    5882      128780 :         l = sa_list(sql->sa);
    5883      969710 :         for (node *n = rel->exps->h; n; n = n->next) {
    5884      840930 :                 sql_exp *e = n->data;
    5885      840930 :                 const char *name = exp_name(e);
    5886             : 
    5887             :                 /* If there are two identical expression names, there will be ambiguity */
    5888      840930 :                 if (!name || exps_bind_column(l, name, NULL, NULL, 0))
    5889       58509 :                         exp_label(sql->sa, e, ++sql->label);
    5890      840930 :                 append(l,e);
    5891             :         }
    5892      128780 :         rel->exps = l;
    5893      128780 :         return rel;
    5894             : }
    5895             : 
    5896             : static sql_rel *
    5897      375228 : rel_query(sql_query *query, symbol *sq, exp_kind ek)
    5898             : {
    5899      375228 :         mvc *sql = query->sql;
    5900      375228 :         sql_rel *res = NULL;
    5901      375228 :         SelectNode *sn = NULL;
    5902             : 
    5903      375228 :         if (sq->token != SQL_SELECT)
    5904          22 :                 return table_ref(query, sq, 0, NULL);
    5905             : 
    5906             :         /* select ... into is currently not handled here ! */
    5907      375206 :         sn = (SelectNode *) sq;
    5908      375206 :         if (sn->into)
    5909             :                 return NULL;
    5910             : 
    5911      375206 :         if (ek.card != card_relation && sn->orderby)
    5912           2 :                 return sql_error(sql, 01, SQLSTATE(42000) "SELECT: ORDER BY only allowed on outermost SELECT");
    5913             : 
    5914      375204 :         if (sn->window) {
    5915          20 :                 dlist *wl = sn->window->data.lval;
    5916          51 :                 for (dnode *n = wl->h; n ; n = n->next) {
    5917          32 :                         dlist *wd = n->data.sym->data.lval;
    5918          32 :                         const char *name = wd->h->data.sval;
    5919          32 :                         dlist *wdef = wd->h->next->data.lval;
    5920          32 :                         if (frame_get_window_def(sql, name, NULL)) {
    5921           1 :                                 return sql_error(sql, 01, SQLSTATE(42000) "SELECT: Redefinition of window '%s'", name);
    5922          31 :                         } else if (!frame_push_window_def(sql, name, wdef)) {
    5923           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5924             :                         }
    5925             :                 }
    5926             :         }
    5927             : 
    5928      375203 :         if (sn->from) {
    5929      302516 :                 dlist *fl = sn->from->data.lval;
    5930      302516 :                 sql_rel *fnd = NULL;
    5931      302516 :                 list *refs = new_exp_list(sql->sa); /* Keep list of relation names in order to test for duplicates */
    5932             : 
    5933      752561 :                 for (dnode *n = fl->h; n ; n = n->next) {
    5934      450319 :                         int lateral = check_is_lateral(n->data.sym);
    5935             : 
    5936             :                         /* just used current expression */
    5937      450325 :                         if (lateral && res)
    5938          22 :                                 query_push_outer(query, res, sql_from);
    5939      450325 :                         fnd = table_ref(query, n->data.sym, lateral, refs);
    5940      450332 :                         if (lateral && res)
    5941          22 :                                 res = query_pop_outer(query);
    5942      450332 :                         if (!fnd)
    5943             :                                 break;
    5944      450051 :                         if (res) {
    5945      147797 :                                 res = rel_crossproduct(sql->sa, res, fnd, op_join);
    5946      147797 :                                 if (lateral)
    5947          22 :                                         set_dependent(res);
    5948             :                         } else {
    5949             :                                 res = fnd;
    5950             :                         }
    5951             :                 }
    5952      302523 :                 if (!fnd) {
    5953         281 :                         if (res)
    5954          12 :                                 rel_destroy(res);
    5955         281 :                         return NULL;
    5956             :                 }
    5957       72687 :         } else if (!query_has_outer(query) || !res) {/* only on top level query */
    5958       72667 :                 return rel_select_exp(query, NULL, sn, ek);
    5959             :         }
    5960             : 
    5961      302242 :         sql_rel *rel = NULL;
    5962      302242 :         if (res)
    5963      302242 :                 rel = rel_select_exp(query, res, sn, ek);
    5964      302236 :         if (!rel && res)
    5965        1041 :                 rel_destroy(res);
    5966             :         return rel;
    5967             : }
    5968             : 
    5969             : /* NOTE: does NOT "set" query but instead generate set ops (union, except, intersect) */
    5970             : static sql_rel *
    5971          23 : rel_setquery_corresponding(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer, bool n_ary_op)
    5972             : {
    5973          23 :         mvc *sql = query->sql;
    5974          23 :         const char *opname = op==SQL_EXCEPT?"EXCEPT":op==SQL_INTERSECT?"INTERSECT":outer?"OUTER UNION":"UNION";
    5975          23 :         list *lexps = sa_list(query->sql->sa), *rexps = sa_list(query->sql->sa);
    5976          23 :         if (!lexps || !rexps)
    5977             :                 return NULL;
    5978          23 :         assert(cols);
    5979          23 :         if (dlist_length(cols)) {
    5980          22 :                 for (dnode *dn = cols->h; dn; dn = dn ->next) {
    5981          13 :                         char *nm = dn->data.sym->data.lval->h->data.sval;
    5982          13 :                         sql_exp *ls, *rs;
    5983             : 
    5984          13 :                         if (!(ls = rel_bind_column(sql, l, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    5985             :                                 return NULL;
    5986          13 :                         if (!(rs = rel_bind_column(sql, r, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    5987             :                                 return NULL;
    5988          13 :                         if ((!outer && (!ls || !rs)) || (outer && !ls && !rs))
    5989           2 :                                 return sql_error(sql, 02, SQLSTATE(42000) "%s: tables '%s' and '%s' do not have a matching column '%s'", opname, rel_name(l)?rel_name(l):"", rel_name(r)?rel_name(r):"", nm);
    5990          11 :                         if (outer && !ls)
    5991           4 :                                 ls = exp_null(sql->sa, exp_subtype(rs));
    5992          11 :                         if (outer && !rs)
    5993           4 :                                 rs = exp_null(sql->sa, exp_subtype(ls));
    5994          11 :                         append(lexps, ls);
    5995          11 :                         append(rexps, rs);
    5996             :                 }
    5997             :         } else {
    5998          12 :                 int found = 0;
    5999          12 :                 list *exps = rel_projections(sql, l, NULL, 1, 0), *r_exps = rel_projections(sql, r, NULL, 1, 0);
    6000          12 :                 if (!exps || !r_exps)
    6001             :                         return NULL;
    6002             :                 /* find cols which exist on both sides */
    6003          35 :                 for (node *n = exps->h; n; n = n->next) {
    6004          23 :                         sql_exp *le = n->data;
    6005          23 :                         int multi = 0;
    6006          23 :                         const char *rname = exp_relname(le), *name = exp_name(le);
    6007          23 :                         sql_exp *re = exps_bind_column(r_exps, name, NULL, &multi, 0);
    6008          23 :                         if (re) {
    6009          13 :                                 if (multi)
    6010           0 :                                         return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "%s: common column name '%s' appears more than once in right table", opname, rname);
    6011          13 :                                 multi = 0;
    6012          13 :                                 le = exps_bind_column(exps, name, NULL, &multi, 0);
    6013          13 :                                 if (multi)
    6014           0 :                                         return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) "%s: common column name '%s' appears more than once in left table", opname, rname);
    6015             : 
    6016          13 :                                 found = 1;
    6017          13 :                                 append(lexps, le);
    6018          13 :                                 append(rexps, re);
    6019          13 :                                 list_remove_data(r_exps, NULL, re);
    6020          10 :                         } else if (outer) {
    6021           3 :                                 append(lexps, le);
    6022           3 :                                 re = exp_null(sql->sa, exp_subtype(le));
    6023           3 :                                 append(rexps, re); /* nils */
    6024             :                         }
    6025             :                 }
    6026          12 :                 if (!found)
    6027           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "%s: no columns of tables '%s' and '%s' match", opname, rel_name(l)?rel_name(l):"", rel_name(r)?rel_name(r):"");
    6028          12 :                 if (outer) {
    6029           7 :                         for (node *n = r_exps->h; n; n = n->next) {
    6030           4 :                                 sql_exp *re = n->data, *le;
    6031           4 :                                 append(rexps, re);
    6032           4 :                                 le = exp_null(sql->sa, exp_subtype(re));
    6033           4 :                                 append(lexps, le); /* nils */
    6034             :                         }
    6035             :                 }
    6036             :         }
    6037          21 :         return n_ary_op ?
    6038          21 :                 rel_setop_n_ary_check_types(sql, l, r, lexps, rexps, (operator_type)op) :
    6039           2 :                 rel_setop_check_types(sql, l, r, lexps, rexps, (operator_type)op);
    6040             : }
    6041             : 
    6042             : static sql_rel *
    6043        2484 : rel_setquery_(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer)
    6044             : {
    6045        2484 :         mvc *sql = query->sql;
    6046        2484 :         sql_rel *rel;
    6047             : 
    6048        2484 :         if (outer && !cols)
    6049           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "UNION: OUTER needs to be combined with CORRESPONDING [ BY ( column list ) ]");
    6050        2484 :         if (!cols) {
    6051        2482 :                 list *ls, *rs;
    6052             : 
    6053        2482 :                 l = rel_unique_names(sql, l);
    6054        2482 :                 r = rel_unique_names(sql, r);
    6055        2482 :                 ls = rel_projections(sql, l, NULL, 0, 1);
    6056        2482 :                 rs = rel_projections(sql, r, NULL, 0, 1);
    6057        2482 :                 rel = rel_setop_check_types(sql, l, r, ls, rs, (operator_type)op);
    6058             :         } else {
    6059           2 :                 rel = rel_setquery_corresponding(query, l, r, cols, op, outer, false);
    6060             :         }
    6061        2484 :         if (rel) {
    6062        2481 :                 rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 1), false);
    6063        2481 :                 set_processed(rel);
    6064             :         }
    6065             :         return rel;
    6066             : }
    6067             : 
    6068             : /* Generate n-ary set operator */
    6069             : static sql_rel *
    6070       61929 : rel_setquery_n_ary_(sql_query *query, sql_rel *l, sql_rel *r, dlist *cols, int op, int outer)
    6071             : {
    6072             :         /* even though this is for a general n-ary operators in this phase of the query
    6073             :          * processing we gonna have only two operands (so technically it's binary). In
    6074             :          * general this op supports arbitrary number of operands.
    6075             :          */
    6076             :         // TODO: for now we support only multi-union
    6077       61929 :         assert(op == op_munion);
    6078             : 
    6079       61929 :         mvc *sql = query->sql;
    6080       61929 :         sql_rel *rel;
    6081             : 
    6082       61929 :         if (outer && !cols)
    6083           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "UNION: OUTER needs to be combined with CORRESPONDING [ BY ( column list ) ]");
    6084       61929 :         if (!cols) {
    6085             :                 // TODO: make rel_setop_n_ary_check_types to accept a list of rels
    6086             :                 // and a list of lists of exps
    6087       61908 :                 list *ls, *rs;
    6088             : 
    6089       61908 :                 l = rel_unique_names(sql, l);
    6090       61908 :                 r = rel_unique_names(sql, r);
    6091       61908 :                 ls = rel_projections(sql, l, NULL, 0, 1);
    6092       61908 :                 rs = rel_projections(sql, r, NULL, 0, 1);
    6093       61908 :                 rel = rel_setop_n_ary_check_types(sql, l, r, ls, rs, (operator_type)op);
    6094             :         } else {
    6095          21 :                 rel = rel_setquery_corresponding(query, l, r, cols, op, outer, true);
    6096             :         }
    6097             : 
    6098       61929 :         if (rel) {
    6099       61923 :                 rel_setop_n_ary_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 1), false);
    6100       61923 :                 set_processed(rel);
    6101             :         }
    6102             : 
    6103             :         return rel;
    6104             : 
    6105             : }
    6106             : 
    6107             : static sql_rel *
    6108       64426 : rel_setquery(sql_query *query, symbol *q)
    6109             : {
    6110       64426 :         mvc *sql = query->sql;
    6111       64426 :         sql_rel *res = NULL;
    6112       64426 :         dnode *n = q->data.lval->h;
    6113       64426 :         symbol *tab_ref1 = n->data.sym;
    6114       64426 :         int distinct = n->next->data.i_val;
    6115       64426 :         dlist *corresponding = n->next->next->data.lval;
    6116       64426 :         symbol *tab_ref2 = n->next->next->next->data.sym;
    6117       64426 :         sql_rel *t1, *t2;
    6118             : 
    6119       64426 :         assert(n->next->type == type_int);
    6120       64426 :         t1 = table_ref(query, tab_ref1, 0, NULL);
    6121       64426 :         if (!t1)
    6122             :                 return NULL;
    6123       64422 :         t2 = table_ref(query, tab_ref2, 0, NULL);
    6124       64422 :         if (!t2)
    6125             :                 return NULL;
    6126             : 
    6127       64414 :         rel_remove_internal_exp(t1);
    6128       64414 :         rel_remove_internal_exp(t2);
    6129       64414 :         if (!corresponding && list_length(t1->exps) != list_length(t2->exps)) {
    6130           1 :                 int t1nrcols = list_length(t1->exps);
    6131           1 :                 int t2nrcols = list_length(t2->exps);
    6132           1 :                 const char *op = "UNION";
    6133           1 :                 if (q->token == SQL_EXCEPT)
    6134             :                         op = "EXCEPT";
    6135           0 :                 else if (q->token == SQL_INTERSECT)
    6136           0 :                         op = "INTERSECT";
    6137           1 :                 rel_destroy(t1);
    6138           1 :                 rel_destroy(t2);
    6139           1 :                 return sql_error(sql, 02, SQLSTATE(42000) "%s: column counts (%d and %d) do not match", op, t1nrcols, t2nrcols);
    6140             :         }
    6141       64413 :         if ( q->token == SQL_UNION) {
    6142       61929 :                 int outer = n->next->next->next->next->data.i_val;
    6143             :                 /* For EXCEPT/INTERSECT the group by is always done within the implementation */
    6144             :                 /* TODO add those later in an optimizer ! */
    6145       61929 :                 if (t1 && distinct)
    6146        3481 :                         t1 = rel_distinct(t1);
    6147       61929 :                 if (t2 && distinct)
    6148        3481 :                         t2 = rel_distinct(t2);
    6149             :                 // TODO: this has to be fixed
    6150             :                 /*res = rel_setquery_(query, t1, t2, corresponding, op_union, outer);*/
    6151       61929 :                 res = rel_setquery_n_ary_(query, t1, t2, corresponding, op_munion, outer);
    6152        2484 :         } else if ( q->token == SQL_EXCEPT)
    6153        2026 :                 res = rel_setquery_(query, t1, t2, corresponding, op_except, 0);
    6154         458 :         else if ( q->token == SQL_INTERSECT)
    6155         458 :                 res = rel_setquery_(query, t1, t2, corresponding, op_inter, 0);
    6156       64413 :         if (res) {
    6157       64404 :                 set_processed(res);
    6158       64404 :                 if (distinct)
    6159        5839 :                         res = rel_distinct(res);
    6160             :         }
    6161             :         return res;
    6162             : }
    6163             : 
    6164             : static sql_rel *
    6165       59371 : rel_joinquery_(sql_query *query, symbol *tab1, int natural, jt jointype, symbol *tab2, symbol *js, list *refs)
    6166             : {
    6167       59371 :         mvc *sql = query->sql;
    6168       59371 :         operator_type op = op_join;
    6169       59371 :         sql_rel *t1 = NULL, *t2 = NULL, *inner, *rel = NULL;
    6170       59371 :         int l_nil = 0, r_nil = 0, lateral = 0;
    6171             : 
    6172       59371 :         switch(jointype) {
    6173             :         case jt_inner:
    6174             :         case jt_cross: op = op_join;
    6175             :                 break;
    6176             :         case jt_left: op = op_left;
    6177             :                 r_nil = 1;
    6178             :                 break;
    6179             :         case jt_right: op = op_right;
    6180             :                 l_nil = 1;
    6181             :                 break;
    6182             :         case jt_full: op = op_full;
    6183             :                 l_nil = 1;
    6184             :                 r_nil = 1;
    6185             :                 break;
    6186             :         }
    6187             : 
    6188             :         /* a dependent join cannot depend on the right side, so disable lateral check for right and full joins */
    6189       59371 :         lateral = (op == op_join || op == op_left) && check_is_lateral(tab2);
    6190       59371 :         t1 = table_ref(query, tab1, 0, refs);
    6191       59371 :         if (t1) {
    6192       59366 :                 if (!lateral) {
    6193       59331 :                         t2 = table_ref(query, tab2, 0, refs);
    6194             :                 } else {
    6195          35 :                         query_processed(query);
    6196          35 :                         query_push_outer(query, t1, sql_from);
    6197          35 :                         t2 = table_ref(query, tab2, 0, refs);
    6198          35 :                         t1 = query_pop_outer(query);
    6199             :                 }
    6200             :         }
    6201       59371 :         if (!t1 || !t2)
    6202             :                 return NULL;
    6203             : 
    6204       59350 :         query_processed(query);
    6205       59350 :         if (strcmp(rel_name(t1), rel_name(t2)) == 0) {
    6206           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: ERROR:  table name '%s' specified more than once", rel_name(t1));
    6207             :         }
    6208       59350 :         inner = rel = rel_crossproduct(sql->sa, t1, t2, op);
    6209       59350 :         if (!rel)
    6210             :                 return NULL;
    6211       59350 :         if (lateral)
    6212          34 :                 set_dependent(rel);
    6213             : 
    6214       59350 :         assert(jointype != jt_cross || (!natural && !js)); /* there are no natural cross joins, or cross joins with conditions */
    6215       59350 :         if (js && natural)
    6216           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: cannot have a NATURAL JOIN with a join specification (ON or USING)");
    6217       59350 :         if (jointype != jt_cross && !js && !natural)
    6218           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: must have NATURAL JOIN or a JOIN with a join specification (ON or USING)");
    6219             : 
    6220       59350 :         if (js && js->token != SQL_USING) {  /* On sql_logical_exp */
    6221       59173 :                 rel = rel_logical_exp(query, rel, js, sql_where | sql_join);
    6222         177 :         } else if (js) {        /* using */
    6223          24 :                 char rname[16], *rnme;
    6224          24 :                 dnode *n = js->data.lval->h;
    6225          24 :                 list *outexps = new_exp_list(sql->sa), *exps;
    6226          24 :                 node *m;
    6227             : 
    6228          24 :                 rnme = sa_strdup(sql->sa, number2name(rname, sizeof(rname), ++sql->label));
    6229          54 :                 for (; n; n = n->next) {
    6230          30 :                         char *nm = n->data.sval;
    6231          30 :                         sql_exp *cond, *ls, *rs;
    6232             : 
    6233          30 :                         if (!(ls = rel_bind_column(sql, t1, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    6234           0 :                                 return NULL;
    6235          30 :                         if (!(rs = rel_bind_column(sql, t2, nm, sql_where | sql_join, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    6236             :                                 return NULL;
    6237          30 :                         if (!ls || !rs)
    6238           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "JOIN: tables '%s' and '%s' do not have a matching column '%s'", rel_name(t1)?rel_name(t1):"", rel_name(t2)?rel_name(t2):"", nm);
    6239          30 :                         if (!(rel = rel_compare_exp(query, rel, ls, rs, "=", TRUE, 0, 0, 0, 0)))
    6240             :                                 return NULL;
    6241          30 :                         if (op != op_join) {
    6242          12 :                                 if (!(cond = rel_unop_(sql, rel, ls, "sys", "isnull", card_value)))
    6243             :                                         return NULL;
    6244          12 :                                 set_has_no_nil(cond);
    6245          12 :                                 if (rel_convert_types(sql, t1, t2, &ls, &rs, 1, type_equal) < 0)
    6246             :                                         return NULL;
    6247          12 :                                 if (!(ls = rel_nop_(sql, rel, cond, rs, ls, NULL, "sys", "ifthenelse", card_value)))
    6248             :                                         return NULL;
    6249             :                         }
    6250          30 :                         exp_setname(sql, ls, rnme, nm);
    6251          30 :                         append(outexps, ls);
    6252          30 :                         if (!rel)
    6253             :                                 return NULL;
    6254             :                 }
    6255          24 :                 exps = rel_projections(sql, t1, NULL, 1, 1);
    6256         207 :                 for (m = exps->h; m; m = m->next) {
    6257         183 :                         const char *nm = exp_name(m->data);
    6258         183 :                         int fnd = 0;
    6259             : 
    6260         433 :                         for (n = js->data.lval->h; n; n = n->next) {
    6261         280 :                                 if (strcmp(nm, n->data.sval) == 0) {
    6262             :                                         fnd = 1;
    6263             :                                         break;
    6264             :                                 }
    6265             :                         }
    6266         183 :                         if (!fnd) {
    6267         153 :                                 sql_exp *ls = m->data;
    6268         153 :                                 if (l_nil)
    6269          18 :                                         set_has_nil(ls);
    6270         153 :                                 set_not_unique(ls);
    6271         153 :                                 append(outexps, ls);
    6272             :                         }
    6273             :                 }
    6274          24 :                 exps = rel_projections(sql, t2, NULL, 1, 1);
    6275         108 :                 for (m = exps->h; m; m = m->next) {
    6276          84 :                         const char *nm = exp_name(m->data);
    6277          84 :                         int fnd = 0;
    6278             : 
    6279         234 :                         for (n = js->data.lval->h; n; n = n->next) {
    6280         180 :                                 if (strcmp(nm, n->data.sval) == 0) {
    6281             :                                         fnd = 1;
    6282             :                                         break;
    6283             :                                 }
    6284             :                         }
    6285          84 :                         if (!fnd) {
    6286          54 :                                 sql_exp *rs = m->data;
    6287          54 :                                 if (r_nil)
    6288          14 :                                         set_has_nil(rs);
    6289          54 :                                 set_not_unique(rs);
    6290          54 :                                 append(outexps, rs);
    6291             :                         }
    6292             :                 }
    6293          24 :                 rel = rel_project(sql->sa, rel, outexps);
    6294         153 :         } else if (jointype != jt_cross) {              /* ! js -> natural join */
    6295          62 :                 rel = join_on_column_name(query, rel, t1, t2, op, l_nil, r_nil);
    6296             :         }
    6297       59350 :         if (!rel)
    6298             :                 return NULL;
    6299       59332 :         if (inner && is_outerjoin(inner->op))
    6300       20877 :                 set_processed(inner);
    6301       59332 :         set_processed(rel);
    6302       59332 :         query_processed(query);
    6303       59332 :         return rel;
    6304             : }
    6305             : 
    6306             : static sql_rel *
    6307       59371 : rel_joinquery(sql_query *query, symbol *q, list *refs)
    6308             : {
    6309       59371 :         dnode *n = q->data.lval->h;
    6310       59371 :         symbol *tab_ref1 = n->data.sym;
    6311       59371 :         int natural = n->next->data.i_val;
    6312       59371 :         jt jointype = (jt) n->next->next->data.i_val;
    6313       59371 :         symbol *tab_ref2 = n->next->next->next->data.sym;
    6314       59371 :         symbol *joinspec = n->next->next->next->next->data.sym;
    6315             : 
    6316       59371 :         assert(n->next->type == type_int);
    6317       59371 :         assert(n->next->next->type == type_int);
    6318       59371 :         return rel_joinquery_(query, tab_ref1, natural, jointype, tab_ref2, joinspec, refs);
    6319             : }
    6320             : 
    6321             : sql_rel *
    6322      375193 : rel_subquery(sql_query *query, symbol *sq, exp_kind ek)
    6323             : {
    6324      375193 :         mvc *sql = query->sql;
    6325             : 
    6326      375193 :         query_processed(query);
    6327      375188 :         if (!stack_push_frame(sql, NULL))
    6328           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    6329      375258 :         sql_rel *rel = rel_query(query, sq, ek);
    6330      375183 :         stack_pop_frame(sql);
    6331      375270 :         if (!query_has_outer(query))
    6332      336438 :                 query_processed(query);
    6333      375250 :         if (rel && ek.type == type_relation && ek.card < card_set && rel->card >= CARD_AGGR)
    6334          15 :                 return rel_zero_or_one(sql, rel, ek);
    6335             :         return rel;
    6336             : }
    6337             : 
    6338             : sql_rel *
    6339      237188 : rel_selects(sql_query *query, symbol *s)
    6340             : {
    6341      237188 :         mvc *sql = query->sql;
    6342      237188 :         sql_rel *ret = NULL;
    6343             : 
    6344      237188 :         switch (s->token) {
    6345        4469 :         case SQL_WITH:
    6346        4469 :                 ret = rel_with_query(query, s);
    6347        4469 :                 sql->type = Q_TABLE;
    6348        4469 :                 break;
    6349        2230 :         case SQL_VALUES:
    6350        2230 :                 ret = rel_values(query, s, NULL);
    6351        2230 :                 sql->type = Q_TABLE;
    6352        2230 :                 break;
    6353      209563 :         case SQL_SELECT: {
    6354      209563 :                 exp_kind ek = {type_value, card_relation, TRUE};
    6355      209563 :                 SelectNode *sn = (SelectNode *) s;
    6356             : 
    6357      209563 :                 if (sn->into) {
    6358           1 :                         sql->type = Q_SCHEMA;
    6359           1 :                         ret = rel_select_with_into(query, s);
    6360             :                 } else {
    6361      209562 :                         ret = rel_subquery(query, s, ek);
    6362      209607 :                         sql->type = Q_TABLE;
    6363             :                 }
    6364      209609 :         }       break;
    6365           0 :         case SQL_JOIN:
    6366           0 :                 ret = rel_joinquery(query, s, NULL);
    6367           0 :                 sql->type = Q_TABLE;
    6368           0 :                 break;
    6369       20926 :         case SQL_UNION:
    6370             :         case SQL_EXCEPT:
    6371             :         case SQL_INTERSECT:
    6372       20926 :                 ret = rel_setquery(query, s);
    6373       20926 :                 sql->type = Q_TABLE;
    6374       20926 :                 break;
    6375             :         default:
    6376             :                 return NULL;
    6377             :         }
    6378      237234 :         if (!ret && sql->errstr[0] == 0)
    6379           0 :                 (void) sql_error(sql, 02, SQLSTATE(42000) "relational query without result");
    6380             :         return ret;
    6381             : }
    6382             : 
    6383             : sql_rel *
    6384       77650 : schema_selects(sql_query *query, sql_schema *schema, symbol *s)
    6385             : {
    6386       77650 :         mvc *sql = query->sql;
    6387       77650 :         sql_rel *res;
    6388       77650 :         sql_schema *os = cur_schema(sql);
    6389             : 
    6390       77650 :         sql->session->schema = schema;
    6391       77650 :         res = rel_selects(query, s);
    6392       77650 :         sql->session->schema = os;
    6393       77650 :         return res;
    6394             : }
    6395             : 
    6396             : sql_rel *
    6397          26 : rel_loader_function(sql_query *query, symbol* fcall, list *fexps, sql_subfunc **loader_function)
    6398             : {
    6399          26 :         mvc *sql = query->sql;
    6400          26 :         sql_rel *sq = NULL;
    6401          26 :         dnode *l = fcall->data.lval->h;
    6402          26 :         char *sname = qname_schema(l->data.lval);
    6403          26 :         char *fname = qname_schema_object(l->data.lval);
    6404             : 
    6405          26 :         list *tl = sa_list(sql->sa);
    6406          26 :         list *exps = sa_list(sql->sa);
    6407          26 :         if (l->next)
    6408          26 :                 l = l->next; /* skip distinct */
    6409          26 :         if (l->next) { /* table call with subquery */
    6410          26 :                 if (l->next->type == type_symbol || l->next->type == type_list) {
    6411          26 :                         int count = 0;
    6412          26 :                         symbol *subquery = NULL;
    6413          26 :                         dnode *n = NULL;
    6414             : 
    6415          26 :                         if (l->next->type == type_symbol)
    6416             :                                 n = l->next;
    6417             :                         else
    6418          26 :                                 n = l->next->data.lval?l->next->data.lval->h:NULL;
    6419             : 
    6420          70 :                         for (dnode *m = n; m; m = m->next) {
    6421          44 :                                 if (m->type == type_symbol && m->data.sym->token == SQL_SELECT)
    6422          44 :                                         subquery = m->data.sym;
    6423          44 :                                 count++;
    6424             :                         }
    6425          26 :                         if (subquery && count > 1)
    6426           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: The input for the loader function '%s' must be either a single sub query, or a list of values", fname);
    6427             : 
    6428          26 :                         if (subquery) {
    6429           0 :                                 exp_kind ek = { type_value, card_relation, TRUE };
    6430           0 :                                 if (!(sq = rel_subquery(query, subquery, ek)))
    6431           0 :                                         return NULL;
    6432             :                         } else {
    6433          26 :                                 exp_kind ek = { type_value, card_column, TRUE };
    6434          26 :                                 list *exps = sa_list(sql->sa);
    6435          96 :                                 for ( ; n; n = n->next) {
    6436          44 :                                         sql_exp *e = rel_value_exp(query, NULL, n->data.sym, sql_sel | sql_from, ek);
    6437             : 
    6438          44 :                                         if (!e)
    6439           0 :                                                 return NULL;
    6440          44 :                                         append(exps, e);
    6441             :                                 }
    6442          26 :                                 sq = rel_project(sql->sa, NULL, exps);
    6443             :                         }
    6444             :                 }
    6445          26 :                 if (!sq)
    6446           0 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such loader function %s%s%s'%s'", sname ? "'":"", sname ? sname : "", sname ? "'.":"", fname);
    6447          70 :                 for (node *en = sq->exps->h; en; en = en->next) {
    6448          44 :                         sql_exp *e = en->data;
    6449             : 
    6450          44 :                         append(exps, e = exp_ref(sql, e));
    6451          44 :                         append(tl, exp_subtype(e));
    6452             :                 }
    6453             :         }
    6454             : 
    6455          26 :         sql_exp *e = NULL;
    6456          26 :         if (!(e = find_table_function(sql, sname, fname, exps, tl, F_LOADER)))
    6457             :                 return NULL;
    6458          25 :         sql_subfunc *sf = e->f;
    6459          25 :         if (sq) {
    6460          69 :                 for (node *n = sq->exps->h, *m = sf->func->ops->h ; n && m ; n = n->next, m = m->next) {
    6461          44 :                         sql_exp *e = (sql_exp*) n->data;
    6462          44 :                         sql_arg *a = (sql_arg*) m->data;
    6463          44 :                         if (!exp_subtype(e) && rel_set_type_param(sql, &(a->type), sq, e, 0) < 0)
    6464             :                                 return NULL;
    6465             :                 }
    6466             :         }
    6467             : 
    6468          25 :         if (loader_function)
    6469          25 :                 *loader_function = sf;
    6470             : 
    6471          25 :         return rel_table_func(sql->sa, sq, e, fexps, (sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
    6472             : }

Generated by: LCOV version 1.14