LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3741 4207 88.9 %
Date: 2025-03-25 21:27:32 Functions: 118 120 98.3 %

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

Generated by: LCOV version 1.14