LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3591 3908 91.9 %
Date: 2024-04-26 00:35:57 Functions: 118 119 99.2 %

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

Generated by: LCOV version 1.14