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

Generated by: LCOV version 1.14