LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3709 4207 88.2 %
Date: 2025-03-24 21:28:01 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       58399 : rel_table_projections( mvc *sql, sql_rel *rel, char *tname, int level )
      40             : {
      41       58927 :         list *exps;
      42             : 
      43       58927 :         if (mvc_highwater(sql))
      44           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
      45             : 
      46       58928 :         if (!rel)
      47             :                 return NULL;
      48             : 
      49       58928 :         if (!tname)
      50       43010 :                 return _rel_projections(sql, rel, NULL, 1, 0, 1);
      51             : 
      52       15918 :         switch(rel->op) {
      53         541 :         case op_join:
      54             :         case op_left:
      55             :         case op_right:
      56             :         case op_full:
      57         541 :                 exps = rel_table_projections( sql, rel->l, tname, level+1);
      58         541 :                 if (exps)
      59             :                         return exps;
      60          20 :                 return rel_table_projections( sql, rel->r, tname, level+1);
      61         508 :         case op_semi:
      62             :         case op_anti:
      63             :         case op_select:
      64         508 :                 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       14869 :                 if (is_basetable(rel->op) && !rel->exps)
      86       14215 :                         return rel_base_project_all(sql, rel, tname);
      87         654 :                 if (rel->exps) {
      88         654 :                         int rename = 0;
      89         654 :                         node *en;
      90             : 
      91             :                         /* first check alias */
      92         654 :                         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         654 :                         exps = new_exp_list(sql->sa);
     109        5270 :                         for (en = rel->exps->h; en; en = en->next) {
     110        4616 :                                 sql_exp *e = en->data;
     111        4616 :                                 if (is_basecol(e) && exp_relname(e) && a_cmp_obj_name(exp_relname(e), tname)) {
     112        4323 :                                         if (rename)
     113           2 :                                                 append(exps, exp_alias_ref(sql, e));
     114             :                                         else {
     115        4321 :                                                 sql_exp *ne = exp_ref(sql, e);
     116             :                                                 //exp_setname(sql, ne, exp_relname(e), exp_name(e));
     117        4321 :                                                 append(exps, ne);
     118             :                                         }
     119             :                                 }
     120        4616 :                                 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         654 :                         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       39860 : rel_orderby(mvc *sql, sql_rel *l)
     159             : {
     160       39860 :         sql_rel *rel = rel_create(sql->sa);
     161       39860 :         if (!rel)
     162             :                 return NULL;
     163             : 
     164       39860 :         assert(l->op == op_project && !l->r);
     165       39860 :         rel->l = l;
     166       39860 :         rel->r = NULL;
     167       39860 :         rel->op = op_project;
     168       39860 :         rel->exps = rel_projections(sql, l, NULL, 1, 0);
     169       39860 :         rel->card = l->card;
     170       39860 :         rel->nrcols = l->nrcols;
     171       39860 :         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      211667 : rel_table_optname(mvc *sql, sql_rel *sq, symbol *optname, list *refs)
     180             : {
     181      211667 :         sql_rel *osq = sq;
     182      211667 :         node *ne;
     183             : 
     184      211667 :         if (optname && optname->token == SQL_NAME) {
     185       17309 :                 dlist *columnrefs = NULL;
     186       17309 :                 char *tname = optname->data.lval->h->data.sval;
     187       17309 :                 sql_alias *ta = a_create(sql->sa, tname);
     188       17309 :                 list *l = sa_list(sql->sa);
     189             : 
     190       17309 :                 columnrefs = optname->data.lval->h->next->data.lval;
     191       17309 :                 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       17309 :                 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        3959 :                 if (columnrefs && sq->exps) {
     198        3959 :                         dnode *d = columnrefs->h;
     199             : 
     200        3959 :                         ne = sq->exps->h;
     201        3959 :                         list_hash_clear(sq->exps);
     202       17729 :                         for (; d && ne; d = d->next, ne = ne->next) {
     203        9812 :                                 sql_exp *e = ne->data;
     204             : 
     205        9812 :                                 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        9811 :                                 exp_setname(sql, e, ta, d->data.sval );
     208        9811 :                                 if (!is_intern(e))
     209        9811 :                                         set_basecol(e);
     210        9811 :                                 append(l, e);
     211             :                         }
     212             :                 }
     213       17302 :                 if (!columnrefs && sq->exps) {
     214       13344 :                         ne = sq->exps->h;
     215       13344 :                         list_hash_clear(sq->exps);
     216      141385 :                         for (; ne; ne = ne->next) {
     217      114697 :                                 sql_exp *e = ne->data;
     218             : 
     219      114697 :                                 if (!is_intern(e)) {
     220      114697 :                                         noninternexp_settname(sql, e, ta);
     221      114697 :                                         set_basecol(e);
     222             :                                 }
     223             :                         }
     224             :                 }
     225       17302 :                 if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
     226       17252 :                         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       17246 :                         assert(tname);
     229       17246 :                         list_append(refs, ta);
     230             :                 }
     231             :         } else {
     232      194358 :                 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       59946 :                         sq = rel_project(sql->sa, sq, rel_projections(sql, sq, NULL, 1, 1));
     234       59946 :                         osq = sq;
     235             :                 }
     236     2472868 :                 for (ne = osq->exps->h; ne; ne = ne->next) {
     237     2278510 :                         sql_exp *e = ne->data;
     238             : 
     239     2278510 :                         if (!is_intern(e))
     240     2146302 :                                 set_basecol(e);
     241             :                 }
     242             :         }
     243             :         return osq;
     244             : }
     245             : 
     246             : static sql_rel *
     247      102949 : rel_subquery_optname(sql_query *query, symbol *ast, list *refs)
     248             : {
     249      102949 :         mvc *sql = query->sql;
     250      102949 :         SelectNode *sn = (SelectNode *) ast;
     251      102949 :         exp_kind ek = {type_value, card_relation, TRUE};
     252      102949 :         sql_rel *sq = rel_subquery(query, ast, ek);
     253             : 
     254      102949 :         assert(ast->token == SQL_SELECT);
     255      102949 :         if (!sq)
     256             :                 return NULL;
     257             : 
     258      102926 :         return rel_table_optname(sql, sq, sn->name, refs);
     259             : }
     260             : 
     261             : static void
     262       10135 : rel_rename(mvc *sql, sql_rel *nrel, sql_alias *rname, sql_rel *brel)
     263             : {
     264       10135 :         assert(is_project(nrel->op));
     265       10135 :         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        9979 :         } else if (is_project(nrel->op) && nrel->exps) {
     283        9979 :                 node *ne = nrel->exps->h;
     284             : 
     285       41263 :                 for (; ne; ne = ne->next) {
     286       31284 :                         sql_exp *e = ne->data;
     287       31284 :                         char *name = NULL;
     288             : 
     289       31284 :                         if (!is_intern(e)) {
     290       31284 :                                 if (!exp_name(e))
     291          17 :                                         name = make_label(sql->sa, ++sql->label);
     292       31284 :                                 noninternexp_setname(sql, e, rname, name);
     293       31284 :                                 set_basecol(e);
     294             :                         }
     295             :                 }
     296        9979 :                 list_hash_clear(nrel->exps);
     297             :         }
     298       10135 : }
     299             : 
     300             : sql_rel *
     301        5936 : rel_with_query(sql_query *query, symbol *q )
     302             : {
     303        5936 :         mvc *sql = query->sql;
     304        5936 :         dnode *d = q->data.lval->h;
     305        5936 :         symbol *next = d->next->data.sym;
     306        5936 :         bool recursive = d->next->next->data.i_val;
     307        5936 :         sql_rel *rel;
     308             : 
     309        5936 :         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       15993 :         for (d = d->data.lval->h; d; d = d->next) {
     313       10076 :                 symbol *sym = d->data.sym;
     314       10076 :                 dnode *dn = sym->data.lval->h->next;
     315       10076 :                 sql_alias *rname = qname2alias(sql->sa, dn->data.lval);
     316       10076 :                 sql_rel *nrel, *base_rel = NULL;
     317       10076 :                 symbol *recursive_part = NULL;
     318       10076 :                 sql_rel_view *recursive_union = NULL;
     319       10076 :                 int recursive_distinct = 0;
     320             : 
     321       10076 :                 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       10073 :                 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       10073 :                 nrel = rel_semantic(query, sym);
     339       10073 :                 if (!nrel) {
     340          16 :                         stack_pop_frame(sql);
     341          16 :                         return NULL;
     342             :                 }
     343       10057 :                 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       10057 :                 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       10057 :                 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       10057 :                 rel_rename(sql, nrel, rname, base_rel);
     395             :         }
     396        5917 :         rel = rel_semantic(query, next);
     397        5917 :         stack_pop_frame(sql);
     398        5917 :         return rel;
     399             : }
     400             : 
     401             : static sql_rel *
     402       61060 : query_exp_optname(sql_query *query, symbol *q, list *refs)
     403             : {
     404       61060 :         mvc *sql = query->sql;
     405       61060 :         switch (q->token) {
     406         995 :         case SQL_WITH:
     407             :         {
     408         995 :                 sql_rel *tq = rel_with_query(query, q);
     409             : 
     410         995 :                 if (!tq)
     411             :                         return NULL;
     412         995 :                 if (q->data.lval->t->type == type_symbol)
     413         995 :                         return rel_table_optname(sql, tq, q->data.lval->t->data.sym, refs);
     414             :                 return tq;
     415             :         }
     416       60065 :         case SQL_JOIN:
     417             :         {
     418       60065 :                 sql_rel *tq = rel_joinquery(query, q, refs);
     419             : 
     420       60065 :                 if (!tq)
     421             :                         return NULL;
     422       60027 :                 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      589050 : bind_func_(mvc *sql, char *sname, char *fname, list *ops, sql_ftype type, bool private, bool *found, bool exact)
     432             : {
     433      589050 :         sql_subfunc *sf = NULL;
     434             : 
     435      589513 :         if (sql->forward && strcmp(fname, sql->forward->base.name) == 0 &&
     436         465 :             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      589048 :         sf = sql_bind_func_(sql, sname, fname, ops, type, private, exact, true);
     440      589071 :         if (found)
     441      588523 :                 *found |= sf != NULL;
     442      589071 :         if (sf && execute_priv(sql, sf->func))
     443             :                 return sf;
     444             :         return NULL;
     445             : }
     446             : 
     447             : static sql_subfunc *
     448      220253 : 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      220253 :         list *tl = sa_list(sql->sa);
     451      220253 :         assert(nr >= 1 && nr <= 2);
     452      220253 :         append(tl, t1);
     453      220253 :         if (nr == 2)
     454      184517 :                 append(tl, t2);
     455      220253 :         sql_subfunc *sf = NULL;
     456             : 
     457      220253 :         if (sql->forward) {
     458       22910 :                 if (execute_priv(sql, sql->forward) &&
     459       22910 :                     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      220253 :         sf = sql_bind_func_(sql, sname, fname, tl, type, private, exact, true);
     469      220253 :         if (found)
     470      220253 :                 *found |= sf != NULL;
     471      220253 :         if (sf && execute_priv(sql, sf->func))
     472             :                 return sf;
     473             :         return NULL;
     474             : }
     475             : 
     476             : static sql_subfunc *
     477      693715 : find_func(mvc *sql, char *sname, char *fname, int len, sql_ftype type, bool private, sql_subfunc *prev, bool *found)
     478             : {
     479      693715 :         sql_subfunc *sf = NULL;
     480             : 
     481      693715 :         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      693715 :         sf = sql_find_func(sql, sname, fname, len, type, private, prev);
     484      693773 :         if (found)
     485           0 :                 *found |= sf != NULL;
     486      693773 :         if (sf && execute_priv(sql, sf->func))
     487             :                 return sf;
     488             :         return NULL;
     489             : }
     490             : 
     491             : static sql_exp *
     492      806800 : exp_fix_scale(mvc *sql, sql_subtype *ct, sql_exp *e)
     493             : {
     494      806800 :         sql_subtype *et = exp_subtype(e);
     495             : 
     496      806866 :         if (ct->type->scale == SCALE_FIX && et->type->scale == SCALE_FIX) {
     497      139333 :                 int scale_diff = ((int) ct->scale - (int) et->scale);
     498             : 
     499      139333 :                 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        9833 : rel_get_count(sql_rel *rel)
     514             : {
     515       31641 :         if (!rel)
     516             :                 return 0;
     517       31637 :         prop *p = NULL;
     518       31637 :         if (rel->p && (p = find_prop(rel->p, PROP_COUNT)) != NULL)
     519        3106 :                 return p->value.lval;
     520       28531 :         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       28357 :         } else if(rel->l) {
     531       25643 :                 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      821173 : 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      821173 :         list *nexps = new_exp_list(sql->sa);
     543      821238 :         sql_subtype *atp = NULL, super, *res = !list_empty(sf->res) ? sf->res->h->data: NULL;
     544      821252 :         unsigned int digits = 0, scale = 0;
     545             : 
     546             :         /* find largest any type argument */
     547     2395488 :         for (node *n = exps->h, *m = sf->func->ops->h; n && m; n = n->next, m = m->next) {
     548     1574333 :                 sql_arg *a = m->data;
     549     1574333 :                 sql_exp *e = n->data;
     550     1574333 :                 sql_subtype *t = exp_subtype(e);
     551             : 
     552     1574236 :                 if (a->type.type->eclass == EC_ANY) {
     553      291464 :                         if (t && atp) {
     554      129028 :                                 supertype(&super, t, atp);
     555      129028 :                                 atp = &super;
     556      162436 :                         } else if (t) {
     557             :                                 atp = t;
     558             :                         }
     559             :                 }
     560     1574233 :                 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      821155 :         if (!atp && !list_empty(exps))
     568      656899 :                 atp = exp_subtype(exps->h->data);
     569             : 
     570      821264 :         if ((atp && atp->type->localtype == TYPE_void) || !atp) /* NULL */
     571       12057 :                 atp = sql_bind_localtype("str");
     572             : 
     573      821266 :         node *n, *m;
     574      821266 :         sql_arg *last = NULL;
     575     3969830 :         for (n = exps->h, m = sf->func->ops->h; n && ((sf->func->vararg && last) || m); n = n->next, m = m?m->next:NULL) {
     576     1574338 :                 sql_arg *a = m?m->data:last;
     577     1574338 :                 sql_exp *e = n->data;
     578     1574338 :                 sql_subtype *ntp = &a->type, *t = exp_subtype(e);
     579             : 
     580     1574256 :                 last = a;
     581     1574256 :                 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     1574219 :                 } else if (a->type.type->eclass == EC_ANY && atp) {
     586      291508 :                         ntp = sql_create_subtype(sql->sa, atp->type, atp->digits, atp->scale);
     587     1282711 :                 } else if (t && ntp->digits == 0 && EC_VARCHAR(a->type.type->eclass)) {
     588      534031 :                         ntp = sql_create_subtype(sql->sa, a->type.type, type_digits_to_char_digits(t), 0);
     589      748680 :                 } else if (t && ntp->digits > 0 && a->type.type->eclass == EC_NUM && t->type->eclass == EC_NUM) {
     590      401015 :                         ntp = sql_create_subtype(sql->sa, a->type.type, t->digits, 0);
     591      347665 :                 } 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      347665 :                 } else if (t && ntp->scale == 0 && ntp->type->eclass == EC_DEC) {
     597        4914 :                         ntp = sql_create_subtype(sql->sa, a->type.type, t->type->eclass == EC_NUM?bits2digits(t->digits):t->digits, t->scale);
     598      342751 :                 } else if (t->type == ntp->type) {
     599      340622 :                         ntp = t;
     600             :                 }
     601     1574283 :                 if (!(e = exp_check_type(sql, ntp, rel, e, type_equal)))
     602             :                         return NULL;
     603     1574227 :                 if (sf->func->fix_scale == SCALE_FIX) {
     604      592875 :                         ntp = sql_create_subtype(sql->sa, a->type.type->localtype?a->type.type:t?t->type:atp->type, digits, scale);
     605      592875 :                         e = exp_fix_scale(sql, ntp, e);
     606      981352 :                 } else if (sf->func->fix_scale == SCALE_EQ) {
     607      213938 :                         e = exp_fix_scale(sql, &a->type, e);
     608             :                 }
     609     1574300 :                 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     1574300 :                 append(nexps, e);
     614             :         }
     615             :         /* handle any extra arguments for rel_dump/analytic funcs */
     616      821432 :         for ( ; n; n = n->next)
     617         261 :                 append(nexps, n->data);
     618      821171 :         if (sf->func->fix_scale == SCALE_FIX || IS_ANALYTIC(sf->func)) {
     619      298995 :                 exps_scale_fix(sf, nexps, atp);
     620      522176 :         } else if (sf->func->fix_scale == MAX_BITS) {
     621      114593 :                 exps_max_bits(sf, nexps);
     622      407583 :         } else if (sf->func->fix_scale == SCALE_MUL) {
     623       25347 :                 exps_sum_scales(sf, nexps);
     624      382236 :         } else if (!internal && sf->func->fix_scale == SCALE_DIV) {
     625        2627 :                 if (!exps_scale_algebra(sql, sf, rel, nexps))
     626             :                         return NULL;
     627      379609 :         } else if (sf->func->fix_scale == DIGITS_ADD) {
     628      188944 :                 exps_digits_add(sf, nexps);
     629      190665 :         } else if (sf->func->fix_scale == INOUT) {
     630       19789 :                 exps_inout(sf, nexps);
     631      170876 :         } else if (is_sum_aggr(sf->func))
     632        9485 :                 exps_largest_int(sf, nexps, rel_get_count(rel));
     633             : 
     634             :         /* dirty hack */
     635      821169 :         if (sf->func->type != F_PROC && sf->func->type != F_UNION && sf->func->type != F_LOADER && res) {
     636      782573 :                 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          41 : file_loader_add_table_column_types(mvc *sql, sql_subfunc *f, list *exps, list *res_exps, char *tname)
     664             : {
     665          41 :         sql_exp *file = exps->h->data;
     666          41 :         if (!exp_is_atom(file))
     667             :                 return "Filename missing";
     668             : 
     669          41 :         atom *a = file->l;
     670          41 :         if (a->data.vtype != TYPE_str || !a->data.val.sval)
     671             :                 return "Filename missing";
     672             : 
     673          41 :         char *filename = a->data.val.sval;
     674          41 :         if (strcmp(filename, "") == 0)
     675             :                 return "Filename missing";
     676             : 
     677          39 :         char *ext = strrchr(filename, '.'), *ep = ext;
     678             : 
     679          39 :         if (ext) {
     680          36 :                 ext = ext + 1;
     681          36 :                 ext = mkLower(sa_strdup(sql->sa, ext));
     682             :         }
     683          36 :         if (!ext)
     684           3 :                 return "Filename extension missing";
     685             : 
     686          36 :         file_loader_t *fl = fl_find(ext);
     687          36 :         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          36 :         str err = fl->add_types(sql, f, filename, res_exps, tname);
     706          36 :         if (err)
     707             :                 return err;
     708          22 :         sql_subtype *st = sql_bind_localtype("str");
     709          22 :         sql_exp *ext_exp = exp_atom(sql->sa, atom_string(sql->sa, st, ext));
     710          22 :         if (!ext_exp)
     711             :                 return MAL_MALLOC_FAIL;
     712          22 :         append(exps, ext_exp);
     713          22 :         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          12 : rel_unnest_func(sql_query *query, list *exps, char *tname)
     754             : {
     755          12 :         if (list_empty(exps))
     756           0 :                 return sql_error(query->sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: unnest multiset missing");
     757          12 :         for( node *n = exps->h; n; n = n->next) {
     758          12 :                 sql_exp *e = n->data;
     759          12 :                 if (!e->freevar || e->type != e_column) {
     760           0 :                         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           0 :                         sql_rel *rp = rel_project(query->sql->sa, NULL, append(sa_list(query->sql->sa), e));
     763           0 :                         rp->card = CARD_MULTI;
     764           0 :                         sql_exp *el = exps_bind_column(e->f, MSEL_NAME, NULL, NULL, 1);
     765           0 :                         return rel_project(query->sql->sa, rp, append(sa_list(query->sql->sa), exp_ref(query->sql, el)));
     766             :                 }
     767          12 :                 prop *p = find_prop(e->p, PROP_NESTED);
     768          12 :                 if (p) {
     769          12 :                         sql_column *c = p->value.pval;
     770          12 :                         sql_table *st = mvc_bind_table(query->sql, c->t->s, c->storage_type);
     771          12 :                         if (!st)
     772           0 :                                 return sql_error(query->sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: unnest multiset table '%s' missing", (char*)c->storage_type);
     773          12 :                         sql_rel *bt = rel_basetable(query->sql, st, a_create(query->sql->sa, tname?tname:NULL));
     774          12 :                         if (!bt)
     775             :                                 return bt;
     776          12 :                         prop *p = prop_create(query->sql->sa, PROP_UNNEST, bt->p);
     777          12 :                         p->value.pval = e;
     778          12 :                         bt->p = p;
     779          12 :                         return bt;
     780             :                 }
     781           0 :                 sql_rel *r = query_fetch_outer(query, e->freevar-1);
     782           0 :                 if (r && !is_basetable(r->op)) {
     783           0 :                         sql_rel *rr = NULL;
     784           0 :                         if (rel_find_exp_and_corresponding_rel(r, e, false, &rr, NULL))
     785           0 :                                 r = rr;
     786             :                 }
     787           0 :                 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           0 :                         sql_subtype *t = exp_subtype(e);
     806           0 :                         reset_freevar(e);
     807           0 :                         if (t->multiset) {
     808           0 :                                 assert(e->f);
     809           0 :                                 list *exps = e->f, *nexps = sa_list(query->sql->sa);
     810           0 :                                 sql_alias *ta = a_create(query->sql->sa, tname?tname:exp_name(e));
     811           0 :                                 bool first = true;
     812           0 :                                 for(node *n = exps->h; n; n = n->next) {
     813           0 :                                         sql_exp *e = n->data;
     814           0 :                                         sql_exp *ne = exp_ref(query->sql, e);
     815           0 :                                         sql_subtype *tt = exp_subtype(ne);
     816             : 
     817           0 :                                         if (first)
     818           0 :                                                 tt->multiset = MS_VALUE;
     819           0 :                                         exp_setname(query->sql, ne, ta, exp_name(e));
     820           0 :                                         append(nexps, ne);
     821           0 :                                         first = false;
     822             :                                 }
     823           0 :                                 sql_rel *rp = rel_project(query->sql->sa, rel_dup(r), nexps);
     824           0 :                                 if (!rp)
     825             :                                         return rp;
     826           0 :                                 prop *p = prop_create(query->sql->sa, PROP_UNNEST, rp->p);
     827           0 :                                 p->value.pval = e;
     828           0 :                                 rp->p = p;
     829           0 :                                 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          41 : rel_file_loader(mvc *sql, list *exps, list *tl, char *tname)
     842             : {
     843          41 :         sql_subfunc *f = NULL;
     844          41 :         bool found = false;
     845             : 
     846          41 :         if ((f = bind_func_(sql, NULL, "file_loader", tl, F_UNION, true, &found, false))) {
     847          41 :                 list *nexps = exps;
     848          41 :                 if (list_empty(tl) || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false))) {
     849          41 :                         list *res_exps = sa_list(sql->sa);
     850          41 :                         if (list_length(exps) == 1 && f && f->func->varres && strlen(f->func->mod) == 0 && strlen(f->func->imp) == 0) {
     851          41 :                                 char *err = file_loader_add_table_column_types(sql, f, nexps, res_exps, tname);
     852          41 :                                 if (err)
     853          19 :                                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: file_loader function failed '%s'", err);
     854             :                         }
     855          22 :                         sql_exp *e = exp_op(sql->sa, nexps, f);
     856          22 :                         sql_rel *rel = rel_table_func(sql->sa, NULL, e, res_exps, TABLE_PROD_FUNC);
     857          22 :                         if (rel)
     858          22 :                                 rel = rel_project(sql->sa, rel, exps_alias(sql, res_exps));
     859          22 :                         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       11001 : find_table_function(mvc *sql, char *sname, char *fname, list *exps, list *tl, sql_ftype type)
     938             : {
     939       11001 :         bool found = false;
     940       11001 :         sql_subfunc *f = NULL;
     941             : 
     942       11001 :         assert(type == F_UNION || type == F_LOADER);
     943       11001 :         if ((f = bind_func_(sql, sname, fname, tl, type, false, &found, false))) {
     944       10978 :                 list *nexps = exps;
     945       10978 :                 if (list_empty(tl) || (nexps = check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1, false)))
     946       10978 :                         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       11107 : rel_named_table_function(sql_query *query, sql_rel *rel, symbol *ast, int lateral, list *refs)
     957             : {
     958       11107 :         mvc *sql = query->sql;
     959       11107 :         list *exps = NULL, *tl;
     960       11107 :         node *m;
     961       11107 :         exp_kind ek = {type_value, card_relation, TRUE};
     962       11107 :         sql_rel *sq = NULL, *outer = NULL;
     963       11107 :         sql_exp *e = NULL;
     964       11107 :         sql_subfunc *sf = NULL;
     965       11107 :         symbol *sym = ast->data.lval->h->data.sym, *subquery = NULL;
     966       11107 :         dnode *l = sym->data.lval->h, *n;
     967       11107 :         char *fname = qname_schema_object(l->data.lval);
     968       11107 :         char *sname = qname_schema(l->data.lval);
     969       11107 :         bool unnest = (!sname && strcmp(fname, "unnest") == 0);
     970             : 
     971       11095 :         if (unnest)
     972             :                 lateral = 1;
     973       11107 :         tl = sa_list(sql->sa);
     974       11107 :         exps = sa_list(sql->sa);
     975       11107 :         if (l->next)
     976       11107 :                 l = l->next; /* skip distinct */
     977       11107 :         if (l->next) { /* table call with subquery */
     978       11107 :                 int is_value = 1;
     979       11107 :                 if (l->next->type == type_symbol || l->next->type == type_list) {
     980       11107 :                         int count = 0;
     981             : 
     982       11107 :                         if (l->next->type == type_symbol)
     983             :                                 n = l->next;
     984             :                         else
     985       11107 :                                 n = l->next->data.lval?l->next->data.lval->h:NULL;
     986             : 
     987       13913 :                         for (dnode *m = n; m; m = m->next) {
     988        2806 :                                 if (m->type == type_symbol && m->data.sym->token == SQL_SELECT)
     989        2806 :                                         subquery = m->data.sym;
     990        2806 :                                 count++;
     991             :                         }
     992       11107 :                         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       11102 :                         if (subquery) {
     997          40 :                                 if (!(sq = rel_subquery(query, subquery, ek)))
     998             :                                         return NULL;
     999             :                                 is_value = 0;
    1000             :                         } else {
    1001       11062 :                                 exp_kind iek = {type_value, unnest?card_row:card_set, TRUE};
    1002       13807 :                                 for ( ; n; n = n->next) {
    1003        2751 :                                         sql_exp *e = rel_value_exp(query, &outer, n->data.sym, sql_sel | sql_from, iek);
    1004             : 
    1005        2751 :                                         if (!e)
    1006           6 :                                                 return NULL;
    1007        2745 :                                         append(exps, e);
    1008        2745 :                                         is_value &= exp_is_atom(e);
    1009             :                                 }
    1010       11056 :                                 if (unnest) {
    1011             :                                         is_value = 1;
    1012             :                                 } else {
    1013       11044 :                                         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       11095 :                 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       11095 :                 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       11042 :                         tl = exp_types(sql->sa, exps);
    1042             :                 }
    1043             :         }
    1044             : 
    1045       11095 :         rel = NULL;
    1046       11095 :         char *tname = NULL;
    1047       11095 :         if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym)
    1048        1246 :                 tname = ast->data.lval->t->data.sym->data.lval->h->data.sval;
    1049             :         else
    1050        9849 :                 tname = make_label(sql->sa, ++sql->label);
    1051       11095 :         sql_alias *ta = a_create(sql->sa, tname);
    1052             : 
    1053       11095 :         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         815 :         } else if (!sname && strcmp(fname, "file_loader") == 0) {
    1058          41 :                 rel = rel_file_loader(sql, exps, tl, tname);
    1059          41 :                 if (!rel)
    1060             :                         return NULL;
    1061       10982 :         } else if (unnest) {
    1062          12 :                 tname = NULL;
    1063          12 :                 if (ast->data.lval->t->type == type_symbol && ast->data.lval->t->data.sym)
    1064          12 :                         tname = ast->data.lval->t->data.sym->data.lval->h->data.sval;
    1065          12 :                 rel = rel_unnest_func(query, exps, tname);
    1066          12 :                 if (!rel)
    1067             :                         return NULL;
    1068       20916 :         } else if (!(e = find_table_function(sql, sname, fname, list_empty(exps) ? NULL : exps, tl, F_UNION)))
    1069             :                 return NULL;
    1070             : 
    1071       11035 :         if (!rel) {
    1072       10948 :                 rel = sq;
    1073             : 
    1074             :                 /* column or table function */
    1075       10948 :                 sf = e->f;
    1076       10948 :                 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       10948 :                 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       10948 :                 exps = new_exp_list(sql->sa);
    1090      107607 :                 for (m = sf->func->res->h; m; m = m->next) {
    1091       96659 :                         sql_arg *a = m->data;
    1092       96659 :                         sql_exp *e = exp_column(sql->sa, ta, a->name, &a->type, CARD_MULTI, 1, 0, 0);
    1093       96659 :                         e->alias.label = -(sql->nid++);
    1094             : 
    1095       96659 :                         set_basecol(e);
    1096       96659 :                         append(exps, e);
    1097             :                 }
    1098       21843 :                 rel = rel_table_func(sql->sa, rel, e, exps, (sq)?TABLE_FROM_RELATION:TABLE_PROD_FUNC);
    1099             :         }
    1100       11035 :         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          49 :                 rel = rel_table_optname(sql, rel, ast->data.lval->t->data.sym, refs);
    1102       10986 :         } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
    1103       10986 :                 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       10986 :                 list_append(refs, ta);
    1106             :         }
    1107             :         return rel;
    1108             : }
    1109             : 
    1110             : static sql_exp*
    1111        4212 : exp_tuples_set_supertype(mvc *sql, list *tuple_values, sql_exp *tuples)
    1112             : {
    1113        4212 :         assert(is_values(tuples));
    1114        4212 :         list *vals = exp_get_values(tuples);
    1115        4212 :         if (!vals || !vals->h)
    1116             :                 return NULL;
    1117             : 
    1118        4212 :         int tuple_width = list_length(tuple_values), i;
    1119        4212 :         sql_subtype *types = SA_NEW_ARRAY(sql->sa, sql_subtype, tuple_width);
    1120        4212 :         bool *has_type = SA_NEW_ARRAY(sql->sa, bool, tuple_width);
    1121        4212 :         node *n;
    1122             : 
    1123        4212 :         memset(has_type, 0, sizeof(bool)*tuple_width);
    1124       13723 :         for(n = tuple_values->h, i = 0; n; n = n->next, i++) {
    1125        9511 :                 sql_exp *e = n->data;
    1126        9511 :                 if (exp_subtype(e)) {
    1127        9509 :                         types[i] = *exp_subtype(e);
    1128        9509 :                         has_type[i] = 1;
    1129             :                 }
    1130             :         }
    1131             : 
    1132        8426 :         for (node *m = vals->h; m; m = m->next) {
    1133        4214 :                 sql_exp *tuple = m->data;
    1134        4214 :                 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        4214 :                         sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
    1158             : 
    1159       13729 :                         for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
    1160        9515 :                                 sql_subtype *tpe;
    1161        9515 :                                 sql_exp *e = n->data;
    1162             : 
    1163        9515 :                                 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        9515 :                                 tpe = exp_subtype(e);
    1170        9515 :                                 if (!tpe)
    1171             :                                         return NULL;
    1172        9515 :                                 if (has_type[i] && tpe) {
    1173        9513 :                                         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        8426 :         for (node *m = vals->h; m; m = m->next) {
    1183        4214 :                 sql_exp *tuple = m->data;
    1184        4214 :                 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        4214 :                         sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, tuple);
    1199             : 
    1200        4214 :                         list *nexps = sa_list(sql->sa);
    1201       13729 :                         for(n = tuple_relation->exps->h, i = 0; n; n = n->next, i++) {
    1202        9515 :                                 sql_exp *e = n->data;
    1203             : 
    1204        9515 :                                 e = exp_check_type(sql, types+i, NULL, e, type_equal);
    1205        9515 :                                 if (!e)
    1206             :                                         return NULL;
    1207        9515 :                                 append(nexps, e);
    1208             :                         }
    1209        4214 :                         tuple_relation->exps = nexps;
    1210             :                 }
    1211             :         }
    1212             :         return tuples;
    1213             : }
    1214             : 
    1215             : static int
    1216        9511 : rel_binop_check_types(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, int upcast)
    1217             : {
    1218        9511 :         sql_subtype *t1 = exp_subtype(ls), *t2 = exp_subtype(rs);
    1219             : 
    1220        9511 :         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        9511 :         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        4212 : tuples_check_types(mvc *sql, list *tuple_values, sql_exp *tuples)
    1235             : {
    1236        4212 :         list *tuples_list = exp_get_values(tuples);
    1237        4212 :         sql_exp *first_tuple = tuples_list->h->data;
    1238        4212 :         list *nvalues = sa_list(sql->sa);
    1239        4212 :         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        4212 :                 sql_rel *tuple_relation = exp_rel_get_rel(sql->sa, first_tuple);
    1254             : 
    1255        4212 :                 assert(list_length(tuple_values) == list_length(tuple_relation->exps));
    1256       13723 :                 for (node *n = tuple_values->h, *m = tuple_relation->exps->h; n && m; n = n->next, m = m->next) {
    1257        9511 :                         sql_exp *le = n->data, *re = m->data;
    1258             : 
    1259        9511 :                         if (rel_binop_check_types(sql, NULL, le, re, 0) < 0)
    1260             :                                 return NULL;
    1261        9511 :                         if ((le = exp_check_type(sql, exp_subtype(re), NULL, le, type_equal)) == NULL)
    1262             :                                 return NULL;
    1263        9511 :                         append(nvalues, le);
    1264             :                 }
    1265             :                 return nvalues;
    1266             :         }
    1267             :         return tuple_values;
    1268             : }
    1269             : 
    1270             : static list *
    1271          56 : row(sql_query *query, symbol *tuple)
    1272             : {
    1273          56 :         exp_kind ek = {type_value, card_value, TRUE};
    1274             : 
    1275          56 :         list *attrs = sa_list(query->sql->sa);
    1276         168 :         for (dnode *n = tuple->data.lval->h; n; n = n->next) {
    1277         112 :                 sql_rel *r = NULL;
    1278         112 :                 sql_exp *e = rel_value_exp(query, &r, n->data.sym, sql_sel | sql_values, ek);
    1279         112 :                 if (!e)
    1280           0 :                         return NULL;
    1281         112 :                 if (r)
    1282           0 :                         printf("found relation\n");
    1283         112 :                 list_append(attrs, e);
    1284             :         }
    1285             :         return attrs;
    1286             : }
    1287             : 
    1288             : static list *
    1289          56 : set_values_list(sql_query *query, symbol *values)
    1290             : {
    1291          56 :         dlist *rows = values->data.lval;
    1292          56 :         list *exps = sa_list(query->sql->sa);
    1293          56 :         exp_kind ek = {type_value, card_value, TRUE};
    1294             : 
    1295          56 :         if (!rows)
    1296             :                 return exps;
    1297         164 :         for (dnode *o = rows->h; o; o = o->next) {
    1298         108 :                 assert(o->type == type_symbol);
    1299         108 :                 sql_rel *r = NULL;
    1300         108 :                 sql_exp *e = rel_value_exp(query, &r, o->data.sym, sql_sel | sql_values, ek);
    1301         108 :                 if (!e)
    1302           0 :                         return NULL;
    1303         108 :                 if (r)
    1304           0 :                         printf("found relation\n");
    1305         108 :                 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        4051 : values_list(sql_query *query, symbol *tableref)
    1346             : {
    1347        4051 :         symbol *values = tableref;
    1348        4051 :         if (tableref->token == SQL_TABLE)
    1349        1408 :                 values = tableref->data.lval->h->data.sym;
    1350        4051 :         if (values->token == SQL_ROW)
    1351          56 :                 return row(query, values);
    1352        3995 :         if (values->token == SQL_SET)
    1353          56 :                 return set_values_list(query, values);
    1354             :         //return simple_values_list(query, values);
    1355        3939 :         mvc *sql = query->sql;
    1356        3939 :         dlist *rowlist = values->data.lval;
    1357        3939 :         node *m;
    1358        3939 :         list *exps = sa_list(sql->sa);
    1359        3938 :         exp_kind ek = {type_value, card_value, TRUE};
    1360             : 
    1361       15674 :         for (dnode *o = rowlist->h; o; o = o->next) {
    1362       11745 :                 dlist *values = o->data.lval;
    1363             : 
    1364       11745 :                 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       11742 :                         dnode *n;
    1368             : 
    1369       11742 :                         if (list_empty(exps)) {
    1370       12477 :                                 for (n = values->h; n; n = n->next) {
    1371        8538 :                                         sql_exp *vals = exp_values(sql->sa, sa_list(sql->sa));
    1372             : 
    1373        8538 :                                         exp_label(sql->sa, vals, ++sql->label);
    1374        8539 :                                         list_append(exps, vals);
    1375             :                                 }
    1376             :                         }
    1377       37172 :                         for (n = values->h, m = exps->h; n && m; n = n->next, m = m->next) {
    1378       25436 :                                 sql_exp *vals = m->data;
    1379       25436 :                                 list *vals_list = vals->f;
    1380       25436 :                                 sql_rel *r = NULL;
    1381       25436 :                                 sql_exp *e = rel_value_exp(query, &r, n->data.sym, sql_sel | sql_values, ek);
    1382       25436 :                                 if (!e)
    1383           7 :                                         return NULL;
    1384       25429 :                                 if (r) {
    1385           0 :                                         printf("found relation\n");
    1386             :                                 }
    1387       25429 :                                 list_append(vals_list, e);
    1388             :                         }
    1389             :                 }
    1390             :         }
    1391             : 
    1392             :         /* loop to check types and cardinality */
    1393        3929 :         unsigned int card = exps->h && list_length(((sql_exp*)exps->h->data)->f) > 1 ? CARD_MULTI : CARD_ATOM;
    1394       12451 :         for (m = exps->h; m; m = m->next) {
    1395        8525 :                 sql_exp *e = m->data;
    1396             : 
    1397        8525 :                 if (!(e = exp_values_set_supertype(sql, e, NULL)))
    1398             :                         return NULL;
    1399        8522 :                 e->card = card;
    1400        8522 :                 m->data = e;
    1401             :         }
    1402             :         return exps;
    1403             : }
    1404             : 
    1405             : static sql_exp *
    1406          93 : sql_exp_values(sql_query *query, symbol *values)
    1407             : {
    1408          93 :         list *exps = values_list(query, values);
    1409          93 :         if (!exps)
    1410             :                 return NULL;
    1411          92 :         sql_exp *e = exp_values(query->sql->sa, exps);
    1412          92 :         if (e && values->token == SQL_ROW)
    1413          53 :                 e->row = 1;
    1414             :         return e;
    1415             : }
    1416             : 
    1417             : static sql_rel *
    1418        3958 : rel_values(sql_query *query, symbol *tableref, list *refs)
    1419             : {
    1420        3958 :         list *exps = values_list(query, tableref);
    1421        3958 :         if (!exps)
    1422             :                 return NULL;
    1423        3946 :         sql_rel *r = rel_project(query->sql->sa, NULL, exps);
    1424        3946 :         r->nrcols = list_length(exps);
    1425        3946 :         r->card = exps_card(exps);
    1426             : 
    1427        3946 :         symbol *optname = NULL;
    1428        3946 :         if (tableref->token == SQL_TABLE)
    1429        1406 :                 optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
    1430        3946 :         return rel_table_optname(query->sql, r, optname, refs);
    1431             : }
    1432             : 
    1433             : static int
    1434      516620 : check_is_lateral(symbol *tableref)
    1435             : {
    1436      516620 :         if (tableref->token == SQL_NAME || tableref->token == SQL_TABLE ||
    1437             :                 tableref->token == SQL_VALUES) {
    1438      465627 :                 if (dlist_length(tableref->data.lval) == 3) {
    1439      465623 :                         if (tableref->data.lval->h->next->data.i_val)
    1440             :                                 return 1;
    1441             :                 }
    1442      465614 :                 if (tableref->data.lval->h->type == type_symbol && tableref->data.lval->h->data.sym->token == SQL_NOP) {
    1443       11088 :                         symbol *sym = tableref->data.lval->h->data.sym;
    1444       11088 :                         dlist *qname = sym->data.lval->h->data.lval;
    1445             :                         /* first is the qname */
    1446       11088 :                         if (dlist_length(qname) == 1 && strcmp(qname->h->data.sval, "unnest")==0)
    1447             :                                 return 1;
    1448             :                 }
    1449      465602 :                 return 0;
    1450             :         } else if (tableref->token == SQL_WITH) {
    1451         993 :                 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        2303 :                 SelectNode *sn = (SelectNode *) tableref;
    1456        2303 :                 return sn->lateral;
    1457             :         } else if (tableref->token == SQL_EXCEPT || tableref->token == SQL_INTERSECT ||
    1458             :                            tableref->token == SQL_UNION) {
    1459       11114 :                 if (dlist_length(tableref->data.lval) == 6)
    1460        9359 :                         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      707180 : table_ref(sql_query *query, symbol *tableref, int lateral, list *refs)
    1488             : {
    1489      707180 :         mvc *sql = query->sql;
    1490      707180 :         sql_alias *tname = NULL;
    1491      707180 :         sql_table *t = NULL;
    1492      707180 :         sql_rel *res = NULL;
    1493             : 
    1494      707180 :         if (tableref->token == SQL_NAME) {
    1495      486909 :                 dlist *name = tableref->data.lval->h->data.lval;
    1496      486909 :                 sql_rel *temp_table = NULL;
    1497      486909 :                 char *sname = qname_schema(name);
    1498      486923 :                 int allowed = 1;
    1499             : 
    1500      486923 :                 tname = qname2alias(sql->sa, name);
    1501             : 
    1502      486915 :                 if (dlist_length(name) > 2)
    1503           8 :                         return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: only a schema and table name expected");
    1504             : 
    1505      486911 :                 if (!sname)
    1506      110184 :                         temp_table = stack_find_rel_view(sql, tname->name);
    1507      110177 :                 if (!temp_table)
    1508      474000 :                         t = find_table_or_view_on_scope(sql, NULL, sname, tname->name, "SELECT", false);
    1509      486907 :                 if (!t && !temp_table)
    1510             :                         return NULL;
    1511      486795 :                 if (!temp_table && !table_privs(sql, t, PRIV_SELECT))
    1512      486784 :                         allowed = 0;
    1513             : 
    1514      486784 :                 if (tableref->data.lval->t->type == type_symbol && tableref->data.lval->t->data.sym) /* AS */
    1515      286862 :                         tname = a_create(sql->sa, tableref->data.lval->t->data.sym->data.lval->h->data.sval);
    1516      486784 :                 if (temp_table && !t) {
    1517       12905 :                         node *n;
    1518       12905 :                         int needed = !is_simple_project(temp_table->op);
    1519             : 
    1520       12905 :                         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       42289 :                                 for (n = temp_table->exps->h; n && !needed; n = n->next) {
    1525       29384 :                                         sql_exp *e = n->data;
    1526             : 
    1527       29384 :                                         if (!exp_relname(e) || !a_match(exp_relname(e), tname))
    1528             :                                                 needed = 1;
    1529             :                                 }
    1530             : 
    1531       12905 :                                 if (needed) {
    1532        5818 :                                         list *exps = rel_projections(sql, temp_table, NULL, 1, 1);
    1533             : 
    1534        5818 :                                         temp_table = rel_project(sql->sa, temp_table, exps);
    1535       18713 :                                         for (n = exps->h; n; n = n->next) {
    1536       12895 :                                                 sql_exp *e = n->data;
    1537             : 
    1538       12895 :                                                 noninternexp_setname(sql, e, tname, NULL);
    1539       12895 :                                                 set_basecol(e);
    1540             :                                         }
    1541        5818 :                                         list_hash_clear(exps);
    1542             :                                 }
    1543             :                         }
    1544       12905 :                         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       12905 :                         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      473879 :                 } else if (isView(t)) {
    1550             :                         /* instantiate base view */
    1551       72140 :                         node *n,*m;
    1552       72140 :                         sql_rel *rel;
    1553             : 
    1554       72140 :                         if (sql->emode == m_deps) {
    1555       25335 :                                 rel = rel_basetable(sql, t, tname);
    1556       25335 :                                 if (!allowed)
    1557           0 :                                         rel_base_disallow(rel);
    1558             :                         } else {
    1559             :                                 /* when recreating a view, the view itself can't be found */
    1560       46805 :                                 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       46804 :                                 rel = rel_parse(sql, t->s, t->query, m_instantiate);
    1563       46804 :                                 if (rel && sql->emode == m_deps)
    1564           0 :                                         rel = rel_unnest(sql, rel);
    1565             :                         }
    1566             : 
    1567       72137 :                         if (!rel)
    1568           2 :                                 return NULL;
    1569             :                         /* Rename columns of the rel_parse relation */
    1570       72137 :                         if (sql->emode != m_deps) {
    1571       46802 :                                 assert(is_project(rel->op));
    1572       46802 :                                 set_processed(rel);
    1573       46802 :                                 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       46802 :                                         rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 0, 0));
    1576       46802 :                                         set_processed(rel);
    1577             :                                 }
    1578      421152 :                                 for (n = ol_first_node(t->columns), m = rel->exps->h; n && m; n = n->next, m = m->next) {
    1579      374350 :                                         sql_column *c = n->data;
    1580      374350 :                                         sql_exp *e = m->data;
    1581             : 
    1582      374350 :                                         exp_setname(sql, e, tname, c->base.name);
    1583      374350 :                                         set_basecol(e);
    1584             :                                 }
    1585       46802 :                                 list_hash_clear(rel->exps);
    1586             :                         }
    1587       72137 :                         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       72121 :                         return rel;
    1590             :                 }
    1591      401739 :                 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      401725 :                 res = rel_basetable(sql, t, tname);
    1595      401745 :                 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      401714 :                 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      401702 :                 } else if (refs) { /* if this relation is under a FROM clause, check for duplicate names */
    1603      401697 :                         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      401690 :                         assert(tname);
    1606      401690 :                         list_append(refs, tname);
    1607             :                 }
    1608      401707 :                 return res;
    1609      220271 :         } else if (tableref->token == SQL_VALUES || (tableref->token == SQL_TABLE && tableref->data.lval->h->data.sym->token == SQL_VALUES)) {
    1610        1445 :                 return rel_values(query, tableref, refs);
    1611      218826 :         } else if (tableref->token == SQL_TABLE) {
    1612       11107 :                 return rel_named_table_function(query, NULL, tableref, lateral, refs);
    1613             :         } else if (tableref->token == SQL_SELECT) {
    1614      102949 :                 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       43710 :                 sql_rel *tq = rel_setquery(query, tableref);
    1618             : 
    1619       43710 :                 if (!tq)
    1620             :                         return NULL;
    1621             :                 /* look for lateral joins */
    1622       43703 :                 symbol *optname = tableref->data.lval->t->type == type_symbol ? tableref->data.lval->t->data.sym : NULL;
    1623       43703 :                 return rel_table_optname(sql, tq, optname, refs);
    1624             :         } else {
    1625       61060 :                 return query_exp_optname(query, tableref, refs);
    1626             :         }
    1627             : }
    1628             : 
    1629             : static sql_exp *
    1630      126270 : rel_exp_variable_on_scope(mvc *sql, const char *sname, const char *vname)
    1631             : {
    1632      126270 :         sql_subtype *tpe = NULL;
    1633      126270 :         sql_var *var = NULL;
    1634      126270 :         sql_arg *a = NULL;
    1635      126270 :         int level = 1;
    1636             : 
    1637      126270 :         if (find_variable_on_scope(sql, sname, vname, &var, &a, &tpe, &level, "SELECT")) {
    1638      122894 :                 if (var) /* if variable is known from the stack or a global var */
    1639       37926 :                         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       90026 :                 if (a) /* if variable is a parameter */
    1641       90026 :                         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        9259 : exps_get_exp(list *exps, int nth)
    1648             : {
    1649        9259 :         node *n = NULL;
    1650        9259 :         int i = 0;
    1651             : 
    1652        9259 :         if (exps)
    1653       27182 :                 for (n=exps->h, i=1; n && i<nth; n=n->next, i++)
    1654             :                         ;
    1655        9259 :         if (n && i == nth)
    1656        9256 :                 return n->data;
    1657             :         return NULL;
    1658             : }
    1659             : 
    1660             : static sql_rel *
    1661       31278 : rel_find_groupby(sql_rel *groupby)
    1662             : {
    1663       31278 :         if (groupby && !is_processed(groupby) && !is_base(groupby->op)) {
    1664       41048 :                 while(!is_processed(groupby) && !is_base(groupby->op)) {
    1665       33115 :                         if (is_groupby(groupby->op) || !groupby->l)
    1666             :                                 break;
    1667             :                         if (groupby->l)
    1668             :                                 groupby = groupby->l;
    1669             :                 }
    1670       31153 :                 if (groupby && is_groupby(groupby->op))
    1671       23220 :                         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        4837 : set_dependent_( sql_rel *r)
    1695             : {
    1696        4837 :         if (is_select(r->op))
    1697        3659 :                 r = r->l;
    1698        4837 :         if (r && is_join(r->op))
    1699        1240 :                 set_dependent(r);
    1700        4837 : }
    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     2426453 : rel_column_ref(sql_query *query, sql_rel **rel, symbol *column_r, int f)
    1770             : {
    1771     2426453 :         mvc *sql = query->sql;
    1772     2426453 :         sql_exp *exp = NULL;
    1773     2426453 :         dlist *l = NULL;
    1774     2426453 :         sql_rel *inner = rel?*rel:NULL, *outer = NULL;
    1775     2426453 :         int used_lower_after_processed = 0;
    1776             : 
    1777     2426453 :         assert((column_r->token == SQL_COLUMN || column_r->token == SQL_IDENT) && column_r->type == type_list);
    1778     2426453 :         l = column_r->data.lval;
    1779             : 
    1780     2426453 :         if (dlist_length(l) == 1) {
    1781     1123550 :                 const char *name = l->h->data.sval;
    1782     1123550 :                 if (!name)
    1783             :                         return NULL;
    1784             : 
    1785     1123550 :                 if (!exp && inner)
    1786     1026619 :                         if (!(exp = rel_bind_column(sql, inner, name, f, 0)) && sql->session->status == -ERR_AMBIGUOUS)
    1787             :                                 return NULL;
    1788     1123536 :                 if (!exp && inner && ((is_sql_aggr(f) && (is_groupby(inner->op) || is_select(inner->op))) ||
    1789       26702 :                                                      (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         258 :                         while (gp && is_select(gp->op))
    1793          27 :                                 gp = gp->l;
    1794         231 :                         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     1123536 :                 if (!exp && query && query_has_outer(query)) {
    1798         476 :                         int i;
    1799             : 
    1800         529 :                         for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
    1801         500 :                                 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         500 :                                 if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
    1810           0 :                                         exp = rel_project_add_exp(sql, outer, exp);
    1811         447 :                                 if (exp)
    1812             :                                         break;
    1813             :                         }
    1814         476 :                         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         471 :                         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         471 :                         if (exp && outer && !is_sql_aggr(f) && !is_sql_aggr(query_fetch_outer_state(query, i))) {
    1819         303 :                                 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         471 :                         if (exp) {
    1827         442 :                                 int of = query_fetch_outer_state(query, i);
    1828         442 :                                 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         405 :                                 } 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         348 :                                         exp->card = CARD_ATOM;
    1835         442 :                                 set_freevar(exp, i);
    1836         442 :                                 if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
    1837         151 :                                         set_outer(outer);
    1838             :                         }
    1839         471 :                         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     1123531 :                 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     1123529 :                 if (!exp) /* If no column was found, try a variable or parameter */
    1859      123215 :                         exp = rel_exp_variable_on_scope(sql, NULL, name);
    1860             : 
    1861      123215 :                 if (!exp) {
    1862        3376 :                         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     1120153 :                 if (!exp)
    1867        3329 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: identifier '%s' unknown", name);
    1868     1120153 :                 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     1120153 :                 if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp) && !inner->flag)
    1871       26403 :                         exp = rel_groupby_add_aggr(sql, inner, exp);
    1872     1302903 :         } else if (dlist_length(l) >= 2) {
    1873     1302903 :                 dnode *dn = l->h;
    1874     1302903 :                 sql_alias *ta = NULL;
    1875     2605827 :                 for(; dn->next; dn = dn->next) {
    1876     1302924 :                         sql_alias *nta = a_create(sql->sa, dn->data.sval);
    1877     1302924 :                         nta->parent = ta;
    1878     1302924 :                         ta = nta;
    1879             :                 }
    1880     1302903 :                 const char *cname = dn->data.sval;
    1881     1302903 :                 if (!cname || !ta)
    1882             :                         return NULL;
    1883             : 
    1884     1288171 :                 if (!exp && rel && inner)
    1885     1288036 :                         if (!(exp = rel_bind_column2(sql, inner, ta, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
    1886             :                                 return NULL;
    1887     1288169 :                 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     1288169 :                 if (!exp && query && query_has_outer(query)) {
    1896       12103 :                         int i;
    1897             : 
    1898       12313 :                         for (i=query_has_outer(query)-1; i>= 0 && !exp && (outer = query_fetch_outer(query,i)); i--) {
    1899       12312 :                                 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       12312 :                                 if (exp && is_simple_project(outer->op) && !rel_find_exp(outer, exp))
    1908           0 :                                         exp = rel_project_add_exp(sql, outer, exp);
    1909       12102 :                                 if (exp)
    1910             :                                         break;
    1911             :                         }
    1912       12103 :                         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       12097 :                         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       12097 :                         if (exp && outer && !is_sql_aggr(f)) {
    1917       11820 :                                 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       12097 :                         if (exp) {
    1925       12096 :                                 int of = query_fetch_outer_state(query, i);
    1926       12096 :                                 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       12032 :                                 } 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       11980 :                                         exp->card = CARD_ATOM;
    1933       12096 :                                 set_freevar(exp, i);
    1934       12096 :                                 if (!is_sql_where(of) && !is_sql_aggr(of) && !is_sql_aggr(f) && !outer->grouped)
    1935       10381 :                                         set_outer(outer);
    1936             :                         }
    1937       12097 :                         if (exp && outer && (is_select(outer->op) || is_join(outer->op)))
    1938        4794 :                                 set_dependent_(outer);
    1939             :                 }
    1940             : 
    1941             :                 /* some views are just in the stack, like before and after updates views */
    1942     1288163 :                 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     1288163 :                 if (!exp && ta) { /* If no column was found, try a global variable */
    1957       67902 :                         sql_var *var = NULL;
    1958       67902 :                         sql_subtype *tpe = NULL;
    1959       67902 :                         int level = 0;
    1960       67902 :                         sql_arg *a = NULL;
    1961             : 
    1962       67902 :                         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     1288163 :                 if (!exp) {
    1968       67892 :                         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       67839 :                         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "SELECT: no such column '%s.%s'", ta?ta->name:"", cname);
    1984     1220272 :                 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     1220272 :                 if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && !is_freevar(exp))
    1987       17733 :                         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     2340425 :         if (exp && !exp_is_atom(exp) && rel && !outer) {
    1992     2208044 :                 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     2208010 :                 query->prev = query->last_exp;
    2000     2208010 :                 query->last_exp = exp;
    2001     2208010 :                 query->last_state = f;
    2002     2208010 :                 query->last_rel = *rel;
    2003             :         }
    2004             :         return exp;
    2005             : }
    2006             : 
    2007             : int
    2008     1047409 : 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     1047409 :         sql_exp *ls = *L;
    2011     1047409 :         sql_exp *rs = *R;
    2012     1047409 :         sql_subtype *lt = exp_subtype(ls);
    2013     1047409 :         sql_subtype *rt = exp_subtype(rs);
    2014             : 
    2015     1047409 :         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     1047407 :         if (rt && (!lt || !lt->type))
    2020           7 :                  return rel_set_type_param(sql, rt, ll, ls, 0);
    2021     1047400 :         if (lt && (!rt || !rt->type))
    2022         648 :                  return rel_set_type_param(sql, lt, rr, rs, 0);
    2023             : 
    2024     1046752 :         if (rt && lt) {
    2025     1046752 :                 sql_subtype *i = lt;
    2026     1046752 :                 sql_subtype *r = rt;
    2027             : 
    2028     1046752 :                 if (subtype_cmp(lt, rt) != 0 || (tpe == type_equal_no_any && (lt->type->localtype==0 || rt->type->localtype==0))) {
    2029      280231 :                         sql_subtype super;
    2030             : 
    2031      280231 :                         cmp_supertype(&super, r, i);
    2032      280231 :                         if (scale_fixing) {
    2033             :                                 /* convert ls to super type */
    2034      280231 :                                 ls = exp_check_type(sql, &super, ll, ls, tpe);
    2035             :                                 /* convert rs to super type */
    2036      280231 :                                 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     1046752 :                 *L = ls;
    2047     1046752 :                 *R = rs;
    2048     1046752 :                 if (!ls || !rs)
    2049             :                         return -1;
    2050             :                 return 0;
    2051             :         }
    2052             :         return -1;
    2053             : }
    2054             : 
    2055             : static sql_rel *
    2056      104016 : push_select_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *ls, int f)
    2057             : {
    2058      104016 :         if (is_outerjoin(rel->op)) {
    2059        1195 :                 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        1157 :                 } 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        1152 :                 if (is_left(rel->op) && rel_find_exp(rel->r, ls)) {
    2067        1125 :                         rel->r = rel_push_select(sql, rel->r, ls, e, f);
    2068        1125 :                         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      102837 :         return rel_push_select(sql, rel, ls, e, f);
    2076             : }
    2077             : 
    2078             : static sql_rel *
    2079      211674 : push_join_exp(mvc *sql, sql_rel *rel, sql_exp *e, sql_exp *L, sql_exp *R, sql_exp *R2, int f)
    2080             : {
    2081      211674 :         sql_rel *r;
    2082      211674 :         if (/*is_semi(rel->op) ||*/ (is_outerjoin(rel->op) && !is_processed((rel)))) {
    2083       21477 :                 rel_join_add_exp(sql->sa, rel, e);
    2084       21477 :                 return rel;
    2085             :         }
    2086             :         /* push join into the given relation */
    2087      190197 :         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        4236 : rel_select_push_filter_exp_down(mvc *sql, sql_rel *rel, sql_exp *e, list *l, list *r, int ff)
    2095             : {
    2096        4236 :         sql_exp *ll;
    2097        4236 :         if (exps_card(r) <= CARD_ATOM && (exps_are_atoms(r) || exps_have_freevar(sql, r) || exps_have_freevar(sql, l))) {
    2098        4138 :                 if (exps_card(l) == exps_card(r) || rel->processed)  /* bin compare op */
    2099         127 :                         return rel_select(sql->sa, rel, e);
    2100        4011 :                 if ((ll = exps_find_one_multi_exp(l)))
    2101        4011 :                         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        4052 : rel_filter(mvc *sql, sql_rel *rel, list *l, list *r, char *sname, char *filter_op, int anti, int ff)
    2110             : {
    2111        4052 :         node *n;
    2112        4052 :         sql_exp *e = NULL;
    2113        4052 :         sql_subfunc *f = NULL;
    2114        4052 :         list *tl = sa_list(sql->sa);
    2115        4052 :         bool found = false;
    2116             : 
    2117        8104 :         for (n = l->h; n; n = n->next){
    2118        4052 :                 sql_exp *e = n->data;
    2119             : 
    2120        4052 :                 list_append(tl, exp_subtype(e));
    2121             :         }
    2122       16208 :         for (n = r->h; n; n = n->next){
    2123       12156 :                 sql_exp *e = n->data;
    2124             : 
    2125       12156 :                 list_append(tl, exp_subtype(e));
    2126             :         }
    2127             :         /* find filter function */
    2128        4052 :         f = bind_func_(sql, sname, filter_op, tl, F_FILT, false, &found, false);
    2129        4052 :         if (f) {
    2130        4052 :                 node *n,*m = f->func->ops->h;
    2131        4052 :                 list *nexps = sa_list(sql->sa);
    2132             : 
    2133        8104 :                 for(n=l->h; m && n; m = m->next, n = n->next) {
    2134        4052 :                         sql_arg *a = m->data;
    2135        4052 :                         sql_exp *e = n->data;
    2136             : 
    2137        4052 :                         e = exp_check_type(sql, &a->type, rel, e, type_equal);
    2138        4052 :                         if (!e)
    2139             :                                 return NULL;
    2140        4052 :                         list_append(nexps, e);
    2141             :                 }
    2142        4052 :                 l = nexps;
    2143        4052 :                 nexps = sa_list(sql->sa);
    2144       16208 :                 for(n=r->h; m && n; m = m->next, n = n->next) {
    2145       12156 :                         sql_arg *a = m->data;
    2146       12156 :                         sql_exp *e = n->data;
    2147             : 
    2148       12156 :                         e = exp_check_type(sql, &a->type, rel, e, type_equal);
    2149       12156 :                         if (!e)
    2150             :                                 return NULL;
    2151       12156 :                         list_append(nexps, e);
    2152             :                 }
    2153             :                 r = nexps;
    2154             :         }
    2155        4052 :         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        4052 :         e = exp_filter(sql->sa, l, r, f, anti);
    2159             : 
    2160        4052 :         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        8086 :         for (node *n=l->h; n; n = n->next) {
    2164        4043 :                 sql_exp *ls = n->data;
    2165             : 
    2166        4043 :                 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       16172 :         for (node *n=r->h; n; n = n->next) {
    2173       12129 :                 sql_exp *rs = n->data;
    2174             : 
    2175       12129 :                 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        4043 :         return rel_select_push_filter_exp_down(sql, rel, e, l, r, ff);
    2182             : }
    2183             : 
    2184             : static sql_rel *
    2185        4052 : 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        4052 :         list *l = sa_list(sql->sa);
    2188        4052 :         list *r = sa_list(sql->sa);
    2189             : 
    2190        4052 :         list_append(l, ls);
    2191        4052 :         list_append(r, r1);
    2192        4052 :         if (r2)
    2193        4052 :                 list_append(r, r2);
    2194        4052 :         if (r3)
    2195        4052 :                 list_append(r, r3);
    2196        4052 :         return rel_filter(sql, rel, l, r, "sys", filter_op, anti, f);
    2197             : }
    2198             : 
    2199             : static sql_rel *
    2200      383171 : 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      383171 :         if (!is_join(rel->op) && !is_select(rel->op))
    2203       87668 :                 return rel_select(sql->sa, rel, e);
    2204      379883 :         if ((rs->card <= CARD_ATOM || (rs2 && ls->card <= CARD_ATOM)) &&
    2205      168760 :                 (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       83829 :                 if (ls->card == rs->card || (rs2 && (ls->card == rs2->card || rs->card == rs2->card)) || rel->processed) /* bin compare op */
    2208        1016 :                         return rel_select(sql->sa, rel, e);
    2209             : 
    2210       82813 :                 return push_select_exp(sql, rel, e, ls, f);
    2211             :         } else { /* join */
    2212      211674 :                 return push_join_exp(sql, rel, e, ls, rs, rs2, f);
    2213             :         }
    2214             :         return rel;
    2215             : }
    2216             : 
    2217             : static sql_rel *
    2218      353658 : 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      353658 :         mvc *sql = query->sql;
    2221      353658 :         sql_exp *e = NULL;
    2222             : 
    2223      353658 :         if (quantifier || exp_is_rel(ls) || exp_is_rel(rs) || (rs2 && exp_is_rel(rs2))) {
    2224        3352 :                 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        3345 :                         assert(!symmetric);
    2230        3345 :                         if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    2231             :                                 return NULL;
    2232        3345 :                         e = exp_compare_func(sql, ls, rs, compare_func((comp_type)type, anti), quantifier);
    2233             :                 }
    2234        3352 :                 return rel_select(sql->sa, rel, e);
    2235      350306 :         } else if (!rs2) {
    2236      347384 :                 assert(!symmetric);
    2237      347384 :                 if (ls->card < rs->card) {
    2238        8825 :                         sql_exp *swap = ls;
    2239        8825 :                         ls = rs;
    2240        8825 :                         rs = swap;
    2241        8825 :                         type = (int)swap_compare((comp_type)type);
    2242             :                 }
    2243      347384 :                 if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0)
    2244             :                         return NULL;
    2245      347381 :                 e = exp_compare(sql->sa, ls, rs, type);
    2246      347381 :                 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      350303 :         if (anti)
    2256         837 :                 set_anti(e);
    2257             : 
    2258      350303 :         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      350303 :         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      350303 :         return rel_select_push_compare_exp_down(sql, rel, e, ls, rs, rs2, f);
    2269             : }
    2270             : 
    2271             : static sql_rel *
    2272      350729 : 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      350729 :         mvc *sql = query->sql;
    2275      350729 :         comp_type type = cmp_equal;
    2276             : 
    2277      350729 :         if (!ls || !rs)
    2278             :                 return NULL;
    2279             : 
    2280      350729 :         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      350729 :         type = compare_str2type(compare_op);
    2304      350729 :         assert(type != cmp_filter);
    2305      350729 :         return rel_compare_exp_(query, rel, ls, rs, NULL, type, need_not, quantifier, f, 0, is_semantics);
    2306             : }
    2307             : 
    2308             : static sql_rel *
    2309      350700 : 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      350700 :         mvc *sql = query->sql;
    2312      350700 :         sql_exp *rs = NULL, *ls;
    2313      350700 :         comp_type cmp_type = compare_str2type(compare_op);
    2314      350700 :         exp_kind ek = {type_value, card_column, FALSE};
    2315      350700 :         int need_not = 0;
    2316             : 
    2317      350700 :         if ((quantifier == 1 && cmp_type == cmp_equal) ||
    2318      350665 :             (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      350639 :         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      350639 :         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      350639 :         ls = rel_value_exp(query, &rel, lo, f|sql_farg, ek);
    2353      350639 :         if (!ls)
    2354             :                 return NULL;
    2355      350591 :         if (ls && rel && exp_has_freevar(sql, ls) && is_sql_sel(f))
    2356           0 :                 ls = rel_project_add_exp(sql, rel, ls);
    2357      350591 :         if (quantifier)
    2358          57 :                 ek.card = card_set;
    2359             : 
    2360      350591 :         rs = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
    2361      350591 :         if (!rs)
    2362             :                 return NULL;
    2363      350561 :         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      350561 :         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      350561 :         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      560582 : _rel_nop(mvc *sql, char *sname, char *fname, list *tl, sql_rel *rel, list *exps, exp_kind ek)
    2378             : {
    2379      560582 :         bool found = false;
    2380      560582 :         int table_func = (ek.card == card_relation);
    2381      560582 :         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      560582 :         sql_subfunc *f = bind_func_(sql, sname, fname, tl, type, false, &found, false);
    2385      560563 :         if (f && !(exps = check_arguments_and_find_largest_any_type(sql, rel, exps, f, table_func, false)))
    2386             :                 f = NULL;
    2387             : 
    2388      560307 :         if (f)
    2389      560307 :                 return exp_op(sql->sa, exps, f);
    2390         239 :         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        2111 : exp_exist(sql_query *query, sql_rel *rel, sql_exp *le, int exists)
    2397             : {
    2398        2111 :         mvc *sql = query->sql;
    2399        2111 :         sql_subfunc *exists_func = NULL;
    2400        2111 :         sql_subtype *t;
    2401        2111 :         sql_exp *res;
    2402             : 
    2403        2111 :         if (!exp_name(le))
    2404         753 :                 exp_label(sql->sa, le, ++sql->label);
    2405        2111 :         if (exp_is_rel(le)) { /* for the subquery case, propagate to the inner query */
    2406        2111 :                 sql_rel *r = exp_rel_get_rel(sql->sa, le);
    2407        2111 :                 if (is_project(r->op) && !list_empty(r->exps)) {
    2408        6278 :                         for (node *n = r->exps->h; n; n = n->next)
    2409        4167 :                                 if (!exp_subtype(n->data) && rel_set_type_param(sql, sql_bind_localtype("bit"), r, n->data, 0) < 0) /* workaround */
    2410             :                                         return NULL;
    2411        2111 :                         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        2111 :         t = exp_subtype(le);
    2416             : 
    2417        2172 :         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        2111 :         res = exp_unop(sql->sa, le, exists_func);
    2420        2111 :         set_has_no_nil(res);
    2421        2111 :         return res;
    2422             : }
    2423             : 
    2424             : static sql_exp *
    2425        1105 : rel_exists_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
    2426             : {
    2427        1105 :         exp_kind ek = {type_value, card_exists, FALSE};
    2428        1105 :         sql_exp *le, *e;
    2429             : 
    2430        1105 :         le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2431        1105 :         if (!le)
    2432             :                 return NULL;
    2433        1104 :         if (!(e = exp_exist(query, rel ? *rel : NULL, le, sc->token == SQL_EXISTS)))
    2434             :                 return NULL;
    2435             :         /* only freevar should have CARD_AGGR */
    2436        1104 :         e->card = CARD_ATOM;
    2437        1104 :         return e;
    2438             : }
    2439             : 
    2440             : static sql_rel *
    2441        1015 : rel_exists_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    2442             : {
    2443        1015 :         exp_kind ek = {type_value, card_exists, TRUE};
    2444        1015 :         mvc *sql = query->sql;
    2445        1015 :         sql_rel *sq = NULL;
    2446             : 
    2447        1015 :         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        1014 :         if (rel) {
    2450        1014 :                 query_processed(query);
    2451        1014 :                 query_push_outer(query, rel, f);
    2452             :         }
    2453        1014 :         sq = rel_subquery(query, sc->data.sym, ek);
    2454        1014 :         if (rel)
    2455        1014 :                 rel = query_pop_outer(query);
    2456        1014 :         assert(!is_sql_sel(f));
    2457        1014 :         if (sq) {
    2458        1007 :                 sql_exp *e = exp_rel(sql, sq);
    2459        1007 :                 if (!(e = exp_exist(query, rel, e, sc->token == SQL_EXISTS)))
    2460             :                         return NULL;
    2461             :                 /* only freevar should have CARD_AGGR */
    2462        1007 :                 e->card = CARD_ATOM;
    2463        1007 :                 rel = rel_select_add_exp(sql->sa, rel, e);
    2464        1007 :                 return rel;
    2465             :         }
    2466             :         return NULL;
    2467             : }
    2468             : 
    2469             : static int
    2470        8670 : is_project_true(sql_rel *r)
    2471             : {
    2472        8670 :         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       65230 : rel_in_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f)
    2482             : {
    2483       65230 :         mvc *sql = query->sql;
    2484       65230 :         exp_kind ek = {type_value, card_column, TRUE};
    2485       65230 :         dlist *dl = sc->data.lval;
    2486       65230 :         symbol *lo = NULL;
    2487       65230 :         dnode *n = dl->h->next, *dn = NULL;
    2488       65230 :         sql_exp *le = NULL, *re, *e = NULL;
    2489       65230 :         list *ll = sa_list(sql->sa);
    2490       65230 :         int is_tuple = 0, add_select = 0;
    2491             : 
    2492             :         /* complex case */
    2493       65230 :         if (dl->h->type == type_symbol && dl->h->data.sym->token == SQL_ROW) { /* (a,b..) in (.. ) */
    2494        4227 :                 lo = dl->h->data.sym;
    2495        4227 :                 dn = lo->data.lval->h;
    2496        4227 :                 lo = dn->data.sym;
    2497        4227 :                 dn = dn->next;
    2498             :         } else {
    2499       61003 :                 lo = dl->h->data.sym;
    2500             :         }
    2501      206310 :         for( ; lo; lo = dn?dn->data.sym:NULL, dn = dn?dn->next:NULL ) {
    2502       70544 :                 le = rel_value_exp(query, rel, lo, f|sql_farg, ek);
    2503       70544 :                 if (!le)
    2504             :                         return NULL;
    2505       70540 :                 append(ll, le);
    2506             :         }
    2507       65226 :         if (list_length(ll) == 1) {
    2508       60999 :                 le = ll->h->data;
    2509       60999 :                 ek.card = card_set;
    2510             :         } else {
    2511        4227 :                 le = exp_values(sql->sa, ll);
    2512        4227 :                 exp_label(sql->sa, le, ++sql->label);
    2513        4227 :                 ek.type = list_length(ll);
    2514        4227 :                 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       65226 :         if (n->type == type_list) {
    2523       65226 :                 sql_exp *values;
    2524       65226 :                 list *vals = sa_list(sql->sa);
    2525             : 
    2526       65226 :                 n = dl->h->next;
    2527       65226 :                 n = n->data.lval->h;
    2528             : 
    2529      319855 :                 for (; n; n = n->next) {
    2530      254669 :                         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      254669 :                                 assert(n->type == type_symbol);
    2543      254669 :                                 re = rel_value_exp(query, rel, n->data.sym, f|sql_farg, ek);
    2544             :                         }
    2545      254669 :                         if (!re)
    2546             :                                 return NULL;
    2547      254644 :                         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        4225 :                         if (is_tuple && exp_is_rel(re)) {
    2550        4225 :                                 sql_rel *r = exp_rel_get_rel(sql->sa, re);
    2551             : 
    2552        4225 :                                 if (!r)
    2553           0 :                                         return sql_error(sql, 02, SQLSTATE(42000) "Subquery missing");
    2554        4225 :                                 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        4216 :                                 re = exp_rel_label(sql, re);
    2557        4216 :                                 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      250415 :                         } else if (exp_is_rel(re)) {
    2560        8671 :                                 sql_rel *r = exp_rel_get_rel(sql->sa, re);
    2561        8671 :                                 add_select = 1;
    2562        8671 :                                 if (rel && *rel && is_join((*rel)->op))
    2563        4514 :                                         set_dependent((*rel));
    2564        8671 :                                 if (is_project(r->op) && is_project_true(r->l) && list_length(r->exps) == 1)
    2565          80 :                                         re = r->exps->h->data;
    2566      241744 :                         } 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      254629 :                         append(vals, re);
    2570             :                 }
    2571             : 
    2572       65186 :                 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       65186 :                 values = exp_values(sql->sa, vals);
    2576       65186 :                 exp_label(sql->sa, values, ++sql->label);
    2577       65186 :                 if (is_tuple) {
    2578        4212 :                         if (!(values = exp_tuples_set_supertype(sql, exp_get_values(le), values)))
    2579             :                                 return NULL;
    2580        4212 :                         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       60974 :                         sql_subtype super, *le_tpe = exp_subtype(le), *values_tpe = NULL;
    2584             : 
    2585      311388 :                         for (node *m = vals->h; m; m = m->next) { /* first get values supertype */
    2586      250414 :                                 sql_exp *e = m->data;
    2587      250414 :                                 sql_subtype *tpe = exp_subtype(e);
    2588             : 
    2589      250414 :                                 if (values_tpe && tpe) {
    2590      189437 :                                         cmp_supertype(&super, values_tpe, tpe);
    2591      189437 :                                         *values_tpe = super;
    2592       60977 :                                 } else if (!values_tpe && tpe) {
    2593       60970 :                                         super = *tpe;
    2594       60970 :                                         values_tpe = &super;
    2595             :                                 }
    2596             :                         }
    2597       60974 :                         if (!le_tpe)
    2598           2 :                                 le_tpe = values_tpe;
    2599       60974 :                         if (!values_tpe)
    2600           4 :                                 values_tpe = le_tpe;
    2601       60974 :                         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       60973 :                         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       60973 :                         if ((is_sql_where(f) || is_sql_having(f)) && !is_sql_farg(f) && !exp_has_rel(le) && exps_are_atoms(vals)) {
    2607       22682 :                                 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      108267 :                                         for (node *n = vals->h ; n ; n = n->next)
    2614       85697 :                                                 if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
    2615             :                                                         return NULL;
    2616       22570 :                                         if ((le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)) == NULL)
    2617             :                                                 return NULL;
    2618       29898 :                                         e = exp_in(sql->sa, le, vals, (sc->token == SQL_IN) ? cmp_in : cmp_notin);
    2619             :                                 }
    2620             :                         }
    2621       22682 :                         if (!e) { /* after computing supertype, check types for each IN value */
    2622      202895 :                                 for (node *n = vals->h ; n ; n = n->next)
    2623      164604 :                                         if ((n->data = exp_check_type(sql, &super, rel ? *rel : NULL, n->data, type_equal)) == NULL)
    2624             :                                                 return NULL;
    2625       38291 :                                 values->tpe = *exp_subtype(vals->h->data);
    2626       38291 :                                 if (!(le = exp_check_type(sql, &super, rel ? *rel : NULL, le, type_equal)))
    2627             :                                         return NULL;
    2628             :                         }
    2629             :                 }
    2630       60973 :                 if (!e) {
    2631       42503 :                         if (add_select && rel && *rel && !is_project((*rel)->op) && !is_select((*rel)->op) && !is_base((*rel)->op))
    2632        4513 :                                 *rel = rel_select(sql->sa, *rel, NULL);
    2633       42503 :                         if ((rel && *rel) || exp_has_rel(le) || exp_has_rel(values))
    2634       36845 :                                 e = exp_in_func(sql, le, values, (sc->token == SQL_IN), is_tuple);
    2635             :                         else
    2636        5658 :                                 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       32967 : rel_in_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    2644             : {
    2645       32967 :         mvc *sql = query->sql;
    2646       32967 :         sql_exp *e = rel_in_value_exp(query, &rel, sc, f);
    2647             : 
    2648       32967 :         assert(!is_sql_sel(f));
    2649       32967 :         if (!e || !rel)
    2650             :                 return NULL;
    2651             : 
    2652       32940 :         if (e->type == e_cmp) { /* it's a exp_in or cmp_equal of simple expressions, push down early on if possible */
    2653       22680 :                 sql_exp *ls = e->l;
    2654       22680 :                 bool rlist = (e->flag == cmp_in || e->flag == cmp_notin);
    2655       22680 :                 unsigned int rcard = rlist ? exps_card(e->r) : exp_card(e->r);
    2656       22680 :                 int r_is_atoms = rlist ? exps_are_atoms(e->r) : exp_is_atom(e->r);
    2657       22680 :                 int r_has_freevar = rlist ? exps_have_freevar(sql, e->r) : exp_has_freevar(sql, e->r);
    2658             : 
    2659       22680 :                 if (rcard <= CARD_ATOM && (r_is_atoms || r_has_freevar || exp_has_freevar(sql, ls))) {
    2660       22680 :                         if ((exp_card(ls) == rcard) || rel->processed) /* bin compare op */
    2661        5488 :                                 return rel_select(sql->sa, rel, e);
    2662             : 
    2663       17192 :                         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       10260 :         if (is_outerjoin(rel->op))
    2671          13 :                 return rel_select(sql->sa, rel, e);
    2672       10247 :         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      128071 : exp_is_null_no_value_opt(sql_exp *e)
    2706             : {
    2707      128071 :         if (!e)
    2708             :                 return false;
    2709      132014 :         while (is_convert(e->type))
    2710        3943 :                 e = e->l;
    2711      256115 :         return e->type == e_atom && e->l && atom_null(e->l);
    2712             : }
    2713             : 
    2714             : sql_exp *
    2715     2769615 : rel_logical_value_exp(sql_query *query, sql_rel **rel, symbol *sc, int f, exp_kind ek)
    2716             : {
    2717     2769615 :         mvc *sql = query->sql;
    2718             : 
    2719     2769615 :         if (!sc)
    2720             :                 return NULL;
    2721             : 
    2722     2769615 :         if (mvc_highwater(sql))
    2723         201 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    2724             : 
    2725     2769734 :         switch (sc->token) {
    2726       59882 :         case SQL_OR:
    2727             :         case SQL_AND:
    2728             :         {
    2729       59882 :                 symbol *lo = sc->data.lval->h->data.sym;
    2730       59882 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    2731       59882 :                 sql_exp *ls, *rs;
    2732             : 
    2733       59882 :                 if (!(ls = rel_value_exp(query, rel, lo, f|sql_farg, ek)))
    2734             :                         return NULL;
    2735       59881 :                 if (!(rs = rel_value_exp(query, rel, ro, f|sql_farg, ek)))
    2736             :                         return NULL;
    2737      103725 :                 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      127793 :         case SQL_COMPARE:
    2778             :         {
    2779      127793 :                 dnode *n = sc->data.lval->h;
    2780      127793 :                 symbol *lo = n->data.sym;
    2781      127793 :                 symbol *ro = n->next->next->data.sym;
    2782      127793 :                 char *compare_op = n->next->data.sval;
    2783      127793 :                 int quantifier = 0, need_not = 0;
    2784      127793 :                 sql_exp *rs = NULL, *ls;
    2785      127793 :                 comp_type cmp_type = compare_str2type(compare_op);
    2786      127793 :                 bool is_not_distinct_from = false;
    2787      127793 :                 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      127793 :                 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      127793 :                 if (quantifier == 3) {
    2799             :                                 is_not_distinct_from = true;
    2800             :                                 quantifier = 0;
    2801             :                 }
    2802      127778 :                 else if (quantifier == 4) {
    2803          13 :                                 is_distinct_from = true;
    2804          13 :                                 quantifier = 0;
    2805             :                 }
    2806             : 
    2807      127793 :                 if ((quantifier == 1 && cmp_type == cmp_equal) ||
    2808      127725 :                     (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      127697 :                 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      127697 :                 ls = rel_value_exp(query, rel, lo, f|sql_farg, ek);
    2828      127697 :                 if (!ls)
    2829             :                         return NULL;
    2830      127684 :                 if (quantifier)
    2831         139 :                         ek.card = card_set;
    2832             : 
    2833      127684 :                 rs = rel_value_exp(query, rel, ro, f|sql_farg, ek);
    2834      127684 :                 if (!rs)
    2835             :                         return NULL;
    2836             : 
    2837      127673 :                 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      127645 :                 if (rs->type == e_atom)
    2846      112263 :                         quantifier = 0;
    2847             : 
    2848      127645 :                 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      127645 :                 if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0)
    2856             :                         return NULL;
    2857      127642 :                 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      127635 :                 return exp_compare_func(sql, ls, rs, compare_func(cmp_type, need_not), quantifier);
    2861             :         }
    2862             :         /* Set Member ship */
    2863       32263 :         case SQL_IN:
    2864             :         case SQL_NOT_IN:
    2865       32263 :                 return rel_in_value_exp(query, rel, sc, f);
    2866        1105 :         case SQL_EXISTS:
    2867             :         case SQL_NOT_EXISTS:
    2868        1105 :                 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       15438 :         case SQL_IS_NULL:
    2938             :         case SQL_IS_NOT_NULL:
    2939             :         /* is (NOT) NULL */
    2940             :         {
    2941       15438 :                 sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2942             : 
    2943       15438 :                 if (!le)
    2944             :                         return NULL;
    2945       19790 :                 le = rel_unop_(sql, rel ? *rel : NULL, le, "sys", sc->token == SQL_IS_NULL ? "isnull" : "isnotnull", card_value);
    2946       15435 :                 if (!le)
    2947             :                         return NULL;
    2948       15435 :                 set_has_no_nil(le);
    2949       15435 :                 return le;
    2950             :         }
    2951       19500 :         case SQL_NOT: {
    2952       19500 :                 sql_exp *le = rel_value_exp(query, rel, sc->data.sym, f|sql_farg, ek);
    2953             : 
    2954       19500 :                 if (!le)
    2955             :                         return NULL;
    2956       19497 :                 return rel_unop_(sql, rel ? *rel : NULL, le, "sys", "not", card_value);
    2957             :         }
    2958             :         case SQL_ATOM: {
    2959     2491688 :                 AtomNode *an = (AtomNode *) sc;
    2960     2491688 :                 assert(an && an->a);
    2961     2491688 :                 return exp_atom(sql->sa, an->a);
    2962             :         }
    2963       21002 :         case SQL_IDENT:
    2964             :         case SQL_COLUMN:
    2965       21002 :                 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         318 :         default: {
    3000         318 :                 sql_exp *le = rel_value_exp(query, rel, sc, f|sql_farg, ek);
    3001         318 :                 sql_subtype bt;
    3002             : 
    3003         318 :                 if (!le)
    3004             :                         return NULL;
    3005         316 :                 sql_find_subtype(&bt, "boolean", 0, 0);
    3006         316 :                 if ((le = exp_check_type(sql, &bt, rel ? *rel : NULL, le, type_equal)) == NULL)
    3007             :                         return NULL;
    3008         316 :                 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      634210 : rel_logical_exp(sql_query *query, sql_rel *rel, symbol *sc, int f)
    3016             : {
    3017      634210 :         mvc *sql = query->sql;
    3018      634210 :         exp_kind ek = {type_value, card_column, TRUE};
    3019             : 
    3020      634210 :         if (!sc)
    3021             :                 return NULL;
    3022             : 
    3023      634210 :         if (mvc_highwater(sql))
    3024           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    3025             : 
    3026      634210 :         switch (sc->token) {
    3027       14563 :         case SQL_OR:
    3028             :         {
    3029       14563 :                 list *exps = NULL, *lexps = NULL, *rexps = NULL;
    3030       14563 :                 symbol *lo = sc->data.lval->h->data.sym;
    3031       14563 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    3032       14563 :                 sql_rel *lr, *rr;
    3033             : 
    3034       14563 :                 if (!rel)
    3035             :                         return NULL;
    3036             : 
    3037       14563 :                 lr = rel;
    3038       14563 :                 rr = rel_dup(lr);
    3039             : 
    3040       14563 :                 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       14519 :                         lr = rel_logical_exp(query, lr, lo, f | sql_or);
    3061       14519 :                         if (!lr)
    3062             :                                 return NULL;
    3063       14517 :                         rr = rel_logical_exp(query, rr, ro, f | sql_or);
    3064             :                 }
    3065             : 
    3066       14559 :                 if (!lr || !rr)
    3067             :                         return NULL;
    3068       14559 :                 return rel_or(sql, rel, lr, rr, exps, lexps, rexps);
    3069             :         }
    3070      194878 :         case SQL_AND:
    3071             :         {
    3072      194878 :                 symbol *lo = sc->data.lval->h->data.sym;
    3073      194878 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    3074      194878 :                 rel = rel_logical_exp(query, rel, lo, f);
    3075      194878 :                 if (!rel)
    3076             :                         return NULL;
    3077      194871 :                 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      350700 :         case SQL_COMPARE:
    3112             :         {
    3113      350700 :                 dnode *n = sc->data.lval->h;
    3114      350700 :                 symbol *lo = n->data.sym;
    3115      350700 :                 symbol *ro = n->next->next->data.sym;
    3116      350700 :                 char *compare_op = n->next->data.sval;
    3117      350700 :                 int quantifier = 0;
    3118      350700 :                 int is_semantics = 0;
    3119             : 
    3120      350700 :                 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      350700 :                 if (quantifier >= 3) {
    3125          10 :                         if (quantifier == 4)
    3126           6 :                                 compare_op = "<>";
    3127             :                         quantifier = 0;
    3128             :                         is_semantics = 1;
    3129             :                 }
    3130      350700 :                 return rel_compare(query, rel, sc, lo, ro, compare_op, f, ek, quantifier, is_semantics);
    3131             :         }
    3132             :         /* Set Member ship */
    3133       32967 :         case SQL_IN:
    3134             :         case SQL_NOT_IN:
    3135       32967 :                 return rel_in_exp(query, rel, sc, f);
    3136        1015 :         case SQL_EXISTS:
    3137             :         case SQL_NOT_EXISTS:
    3138        1015 :                 return rel_exists_exp(query, rel , sc, f);
    3139        4055 :         case SQL_LIKE:
    3140             :         case SQL_NOT_LIKE:
    3141             :         {
    3142        4055 :                 symbol *lo = sc->data.lval->h->data.sym;
    3143        4055 :                 symbol *ro = sc->data.lval->h->next->data.sym;
    3144        4055 :                 int insensitive = sc->data.lval->h->next->next->data.i_val;
    3145        4055 :                 int anti = (sc->token == SQL_NOT_LIKE) != (sc->data.lval->h->next->next->next->data.i_val != 0);
    3146        4055 :                 sql_subtype *st = sql_bind_localtype("str");
    3147        4055 :                 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        4055 :                 if (!le)
    3150             :                         return NULL;
    3151             : 
    3152        4053 :                 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        4053 :                 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        3508 :                         ee = exp_atom(sql->sa, atom_string(sql->sa, st, sa_strdup(sql->sa, "")));
    3162             :                 }
    3163        4053 :                 ro = ro->data.lval->h->data.sym;
    3164        4053 :                 re = rel_value_exp(query, &rel, ro, f|sql_farg, ek);
    3165        4053 :                 if (!re)
    3166             :                         return NULL;
    3167        4052 :                 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        4052 :                 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        4052 :                 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       10367 :         case SQL_IS_NULL:
    3203             :         case SQL_IS_NOT_NULL:
    3204             :         /* is (NOT) NULL */
    3205             :         {
    3206       10367 :                 sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
    3207       10367 :                 sql_subtype *t;
    3208             : 
    3209       10367 :                 if (!le)
    3210             :                         return NULL;
    3211       10363 :                 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       10362 :                 le = exp_compare(sql->sa, le, exp_atom(sql->sa, atom_general(sql->sa, t, NULL, 0)), cmp_equal);
    3214       10362 :                 if (sc->token == SQL_IS_NOT_NULL)
    3215        2605 :                         set_anti(le);
    3216       10362 :                 set_has_no_nil(le);
    3217       10362 :                 set_semantics(le);
    3218       10362 :                 return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
    3219             :         }
    3220       20875 :         case SQL_NOT: {
    3221       20875 :                 sql_exp *le = rel_value_exp(query, &rel, sc->data.sym, f|sql_farg, ek);
    3222       20875 :                 sql_subtype bt;
    3223             : 
    3224       20875 :                 sql_find_subtype(&bt, "boolean", 0, 0);
    3225       20875 :                 if (!le || !(le = exp_check_type(sql, &bt, rel, le, type_equal)))
    3226           1 :                         return NULL;
    3227       20874 :                 le = exp_compare(sql->sa, le, exp_atom_bool(sql->sa, 0), cmp_equal);
    3228       20874 :                 return rel_select_push_compare_exp_down(sql, rel, le, le->l, le->r, NULL, f);
    3229             :         }
    3230         625 :         case SQL_ATOM: {
    3231             :                 /* TRUE or FALSE */
    3232         625 :                 sql_rel *or = rel;
    3233         625 :                 AtomNode *an = (AtomNode *) sc;
    3234         625 :                 sql_exp *e = exp_atom(sql->sa, an->a);
    3235             : 
    3236         625 :                 if (e) {
    3237         625 :                         sql_subtype bt;
    3238             : 
    3239         625 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3240         625 :                         e = exp_check_type(sql, &bt, rel, e, type_equal);
    3241             :                 }
    3242         625 :                 if (!e || or != rel)
    3243           2 :                         return NULL;
    3244         623 :                 e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
    3245         623 :                 return rel_select_push_compare_exp_down(sql, rel, e, e->l, e->r, NULL, f);
    3246             :         }
    3247         716 :         case SQL_IDENT:
    3248             :         case SQL_COLUMN: {
    3249         716 :                 sql_rel *or = rel;
    3250         716 :                 sql_exp *e = rel_column_ref(query, &rel, sc, f);
    3251             : 
    3252         716 :                 if (e) {
    3253         713 :                         sql_subtype bt;
    3254             : 
    3255         713 :                         sql_find_subtype(&bt, "boolean", 0, 0);
    3256         713 :                         e = exp_check_type(sql, &bt, rel, e, type_equal);
    3257             :                 }
    3258         713 :                 if (!e || or != rel)
    3259           3 :                         return NULL;
    3260         713 :                 e = exp_compare(sql->sa, e, exp_atom_bool(sql->sa, 1), cmp_equal);
    3261         713 :                 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         503 :         default: {
    3312         503 :                 sql_exp *le = rel_value_exp(query, &rel, sc, f|sql_farg, ek);
    3313         503 :                 sql_subtype bt;
    3314             : 
    3315         503 :                 if (!le)
    3316             :                         return NULL;
    3317         479 :                 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         479 :                 if (le->flag == cmp_filter)
    3324         193 :                         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       35736 : rel_unop_(mvc *sql, sql_rel *rel, sql_exp *e, char *sname, char *fname, int card)
    3337             : {
    3338       35736 :         bool found = false;
    3339       35736 :         sql_subtype *t = exp_subtype(e);
    3340       35736 :         sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:
    3341             :                    ((card == card_relation)?F_UNION:F_FUNC));
    3342             : 
    3343       35736 :         sql_subfunc *f = bind_func(sql, sname, fname, t, NULL, 1, type, false, &found, false);
    3344       35736 :         if (f) {
    3345       35735 :                 sql_arg *a = f->func->ops->h->data;
    3346       35735 :                 t = &a->type;
    3347             :         }
    3348       35736 :         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       35736 :         if (f) {
    3359       35735 :                 if (check_card(card, f)) {
    3360       35735 :                         list *args = list_append(sa_list(sql->sa), e);
    3361       71470 :                         args = check_arguments_and_find_largest_any_type(sql, rel, args, f, card == card_relation && e->card > CARD_ATOM, false);
    3362       35735 :                         if (args)
    3363       35735 :                                 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      184517 : rel_binop_(mvc *sql, sql_rel *rel, sql_exp *l, sql_exp *r, char *sname, char *fname, int card, bool exact)
    3377             : {
    3378      184517 :         sql_subtype *t1 = exp_subtype(l), *t2 = exp_subtype(r);
    3379      184517 :         sql_ftype type = (card == card_loader)?F_LOADER:((card == card_none)?F_PROC:((card == card_relation)?F_UNION:F_FUNC));
    3380      184517 :         bool found = false;
    3381             : 
    3382      184517 :         if (card == card_loader)
    3383           0 :                 card = card_none;
    3384             : 
    3385      184517 :         if (is_commutative(sname, fname) && l->card < r->card) { /* move constants to the right if possible */
    3386             :                 sql_subtype *tmp = t1;
    3387      184517 :                 t1 = t2;
    3388      184517 :                 t2 = tmp;
    3389             :                 sql_exp *res = l;
    3390      184517 :                 l = r;
    3391      184517 :                 r = res;
    3392             :         }
    3393             :         /* swap complex types (intervals) to left side of +, * */
    3394      184517 :         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      184517 :                         t1 = t2;
    3399      184517 :                         t2 = tmp;
    3400             :                         sql_exp *res = l;
    3401      184517 :                         l = r;
    3402      184517 :                         r = res;
    3403             :                 }
    3404             :         }
    3405             : 
    3406      184517 :         sql_subfunc *f = bind_func(sql, sname, fname, t1, t2, 2, type, false, &found, exact);
    3407      184517 :         if (f && check_card(card,f)) {
    3408      184517 :                 t1 = exp_subtype(l);
    3409      184517 :                 t2 = exp_subtype(r);
    3410      184517 :                 list *args = list_append(list_append(sa_list(sql->sa), l), r);
    3411             : 
    3412      184517 :                 args = check_arguments_and_find_largest_any_type(sql, rel, args, f, 0, false);
    3413      184517 :                 if (args)
    3414      184517 :                                 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      593157 : rel_nop(sql_query *query, sql_rel **rel, symbol *se, int fs, exp_kind ek)
    3491             : {
    3492      593157 :         mvc *sql = query->sql;
    3493      593157 :         dnode *l = se->data.lval->h;
    3494      593157 :         dnode *ops = l->next->next->data.lval?l->next->next->data.lval->h:NULL;
    3495      593157 :         list *names = NULL;
    3496      593157 :         char *fname = NULL, *sname = NULL;;
    3497             : 
    3498      593157 :         if (l->type != type_int) {
    3499      587265 :                 int nargs = 0;
    3500      587265 :                 fname = qname_schema_object(l->data.lval);
    3501      587305 :                 sname = qname_schema(l->data.lval);
    3502             : 
    3503     1740238 :                 for (dnode *n = ops; n; n = n->next)
    3504     1152933 :                         nargs++;
    3505             : 
    3506             :                 /* first try aggregate */
    3507      587268 :                 if (find_func(sql, sname, fname, nargs, F_AGGR, false, NULL, NULL)) {
    3508       26581 :                         dnode *dn = l->next->next;
    3509       26581 :                         symbol *orderby = dn->next?dn->next->data.sym:NULL;
    3510       26581 :                         return _rel_aggr(query, rel, l->next->data.i_val, sname, fname, dn->data.lval->h, orderby, fs);
    3511             :                 }
    3512             :         }
    3513             : 
    3514      566628 :         int nr_args = 0;
    3515      566628 :         int split = (l->type == type_int && l->data.i_val == -1);
    3516      566628 :         list *exps = sa_list(sql->sa), *tl = sa_list(sql->sa);
    3517      566607 :         exp_kind iek = {type_value, card_column, FALSE};
    3518             : 
    3519      566607 :         if (split)
    3520           3 :                 names = sa_list(sql->sa);
    3521     1700137 :         for (; ops; ops = ops->next, nr_args++) {
    3522     1133672 :                 sql_exp *e = rel_value_exp(query, rel, ops->data.sym, fs|sql_farg, iek);
    3523     1133639 :                 if (!e)
    3524             :                         return NULL;
    3525     1133539 :                 if (split) {
    3526           5 :                         ops = ops->next;
    3527           5 :                         append(names, ops->data.sval);
    3528             :                 }
    3529     1133539 :                 append(exps, e);
    3530     1133524 :                 append(tl, exp_subtype(e));
    3531             :         }
    3532      566465 :         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      560557 :         if (nr_args == 2 && is_commutative(sname, fname)) {
    3576      124153 :                 sql_subtype *t1 = tl->h->data;
    3577      124153 :                 sql_subtype *t2 = tl->t->data;
    3578             : 
    3579      124153 :                 if (t1 && t2 && ((EC_INTERVAL(t1->type->eclass) && EC_TEMP(t2->type->eclass)) ||
    3580      124144 :            ((!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      560557 :         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      560556 :         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       46195 : _rel_aggr(sql_query *query, sql_rel **rel, int distinct, char *sname, char *aname, dnode *args, symbol *orderby, int f)
    3665             : {
    3666       46195 :         mvc *sql = query->sql;
    3667       46195 :         exp_kind ek = {type_value, card_column, FALSE};
    3668       46195 :         sql_subfunc *a = NULL;
    3669       46195 :         int no_nil = 0, group = 0, all_aggr = query_has_outer(query), i;
    3670       46195 :         unsigned int all_freevar = 0;
    3671       46195 :         sql_rel *groupby = rel ? *rel : NULL, *sel = NULL, *gr, *og = NULL, *res = groupby;
    3672       46195 :         sql_rel *subquery = NULL;
    3673       46195 :         list *exps = NULL, *ungrouped_cols = NULL;
    3674       46195 :         bool is_grouping = !strcmp(aname, "grouping"), has_args = false, found = false, used_rel = false;
    3675             : 
    3676       46195 :         if (!all_aggr) {
    3677       31120 :                 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       31116 :                 } 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       31108 :                 } 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       31107 :                 } 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       31104 :                 } 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       31100 :                 } 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       31099 :                 } 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       31095 :                 } 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       31095 :                 } 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       46170 :         exps = sa_list(sql->sa);
    3708       46170 :         if (args && args->data.sym) {
    3709       26669 :                 bool arguments_correlated = true, all_const = true;
    3710             : 
    3711       26669 :                 all_freevar = all_aggr?1:0;
    3712       62159 :                 for (i = 0; args && args->data.sym; args = args->next, i++) {
    3713       35550 :                         int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
    3714       27522 :                         sql_rel *gl = base?groupby:groupby->l, *ogl = gl; /* handle case of subqueries without correlation */
    3715       35550 :                         sql_exp *e = rel_value_exp(query, &gl, args->data.sym, (f | sql_aggr)& ~sql_farg, ek);
    3716       35550 :                         bool found_one_freevar = false;
    3717             : 
    3718       35550 :                         if (!e)
    3719          60 :                                 return NULL;
    3720       35496 :                         used_rel |= (rel_has_exp(gl, e, true) == 0);
    3721       35496 :                         has_args = true;
    3722       35496 :                         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       35491 :                         sql_subtype *t = exp_subtype(e);
    3733       35491 :                         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       35490 :                         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       35490 :                         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       35490 :                         exp_only_freevar(query, e, &arguments_correlated, &found_one_freevar, &ungrouped_cols);
    3748       35490 :                         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       35490 :                         all_const &= is_atom(e->type);
    3750       35490 :                         list_append(exps, e);
    3751             :                 }
    3752       26609 :                 if (all_const)
    3753         229 :                         all_freevar = 0;
    3754             :         }
    3755       46110 :         if (!all_freevar) {
    3756       45817 :                 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       45816 :                 } 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       45814 :                 } 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       45812 :                 } 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       45811 :                 } 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       45810 :                 } 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       45805 :                 } 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       46093 :         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       45800 :         } 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       46046 :         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       46046 :         if (!subquery && groupby && !is_processed(groupby) && !is_base(groupby->op)) {
    3900       30971 :                 og = groupby;
    3901       30971 :                 groupby = rel_find_groupby(groupby);
    3902       30971 :                 if (groupby)
    3903             :                         group = 1;
    3904             :                 else
    3905             :                         groupby = og;
    3906             :         }
    3907             : 
    3908        7925 :         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       46046 :         if (!subquery && groupby && groupby->op != op_groupby) {             /* implicit groupby */
    3914       21261 :                 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       21252 :                 res = groupby = rel_groupby(sql, groupby, NULL);
    3920             :         }
    3921       46037 :         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       46037 :         if ((!exps || exps_card(exps) > CARD_ATOM) && (!res || !groupby))
    3933             :                 return NULL;
    3934             : 
    3935       46037 :         list *obe = NULL;
    3936       46037 :         bool handled_order = true;
    3937       46037 :         if (args)
    3938             :                         return NULL;
    3939       46037 :         if (orderby) { /* handle order by */
    3940        4464 :                 int base = (!groupby || !is_project(groupby->op) || is_base(groupby->op) || is_processed(groupby));
    3941        4464 :                 sql_rel *gl = base?groupby:groupby->l;//, *ogl = gl; /* handle case of subqueries without correlation */
    3942        4464 :                 obe = rel_order_by(query, &gl, orderby, 0, f);
    3943        4464 :                 if (!obe)
    3944           0 :                         return NULL;
    3945        4464 :                 handled_order = false;
    3946             :         }
    3947             : 
    3948       46037 :         if (all_freevar) {
    3949         247 :                 query_update_outer(query, res, all_freevar-1);
    3950       45790 :         } else if (rel) {
    3951       45790 :                 *rel = res;
    3952       45790 :                 if (query->last_rel != res) {
    3953       41824 :                         query->last_rel = res;
    3954       41824 :                         query->last_state |= sql_aggr;
    3955             :                 }
    3956             :         }
    3957             : 
    3958       46037 :         if (!has_args) {        /* count(*) case */
    3959       19497 :                 obe = NULL; /* no errors, although the order by is useless */
    3960       19497 :                 sql_exp *e;
    3961             : 
    3962       19497 :                 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       19495 :                 a = sql_bind_func(sql, "sys", aname, sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    3967       19495 :                 e = exp_aggr(sql->sa, NULL, a, distinct, 0, groupby?groupby->card:CARD_ATOM, 0);
    3968             : 
    3969       19495 :                 if (!groupby)
    3970             :                         return e;
    3971       19495 :                 if (all_freevar)
    3972           0 :                         query_outer_used_exp(query, all_freevar-1, e, sql_aggr);
    3973       19495 :                 e = rel_groupby_add_aggr(sql, groupby, e);
    3974       19495 :                 if (!group && !all_freevar)
    3975             :                         return e;
    3976        3235 :                 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       26540 :         no_nil = 1;
    3987             : 
    3988       26540 :         gr = groupby;
    3989       26540 :         if (gr && gr->op == op_project && gr->l)
    3990             :                 gr = gr->l;
    3991             : 
    3992       26540 :         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       26431 :                 a = sql_bind_func_(sql, sname, aname, exp_types(sql->sa, exps), F_AGGR, false, false, true);
    4020       26431 :                 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       26540 :         if (a) {
    4036       26535 :                 found = true;
    4037       26535 :                 if (!execute_priv(sql, a->func))
    4038           0 :                         a = NULL;
    4039       26535 :                 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       26540 :         if (a) {
    4044       26535 :                 bool hasnil = have_nil(exps) || (strcmp(aname, "count") != 0 && (!groupby || list_empty(groupby->r))); /* for global case, the aggregate may return NULL */
    4045       26535 :                 sql_exp *e = exp_aggr(sql->sa, exps, a, distinct, no_nil, groupby?groupby->card:CARD_ATOM, hasnil);
    4046             : 
    4047       26535 :                 if (!obe && a->func->order_required && !handled_order) {
    4048             :                         /* TODO proper error on missing order by */
    4049             :                         return NULL;
    4050             :                 }
    4051        4464 :                 if (obe && !a->func->order_required && !a->func->opt_order)
    4052             :                         obe = NULL;
    4053        4464 :                 if (obe) /* add order by expressions */
    4054        4464 :                         e->r = append(sa_list(sql->sa), obe);
    4055       26535 :                 if (!groupby)
    4056             :                         return e;
    4057       26535 :                 if (all_freevar)
    4058         247 :                         query_outer_aggregated(query, all_freevar-1, e);
    4059       26535 :                 e = rel_groupby_add_aggr(sql, groupby, e);
    4060       26535 :                 if (!group && !all_freevar)
    4061             :                         return e;
    4062       19929 :                 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       19614 : rel_aggr(sql_query *query, sql_rel **rel, symbol *se, int f)
    4084             : {
    4085       19614 :         dlist *l = se->data.lval;
    4086       19614 :         dnode *d = l->h->next->next;
    4087       19614 :         symbol *orderby = d->next?d->next->data.sym:NULL;
    4088       19614 :         int distinct = l->h->next->data.i_val;
    4089       19614 :         char *aname = qname_schema_object(l->h->data.lval);
    4090       19614 :         char *sname = qname_schema(l->h->data.lval);
    4091             : 
    4092       19614 :         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      102418 : rel_case(sql_query *query, sql_rel **rel, symbol *opt_cond, dlist *when_search_list, symbol *opt_else, int f)
    4097             : {
    4098      102418 :         mvc *sql = query->sql;
    4099      102418 :         sql_subtype *tpe = NULL;
    4100      102418 :         list *conds = new_exp_list(sql->sa), *results = new_exp_list(sql->sa);
    4101      102418 :         sql_subtype *restype = NULL, *condtype = NULL, ctype, rtype, bt;
    4102      102418 :         sql_exp *res = NULL, *opt_cond_exp = NULL;
    4103      102418 :         exp_kind ek = {type_value, card_column, FALSE};
    4104             : 
    4105      102418 :         if (opt_cond) {
    4106        9631 :                 if (!(opt_cond_exp = rel_value_exp(query, rel, opt_cond, f, ek)))
    4107             :                         return NULL;
    4108        9630 :                 condtype = exp_subtype(opt_cond_exp);
    4109             :         }
    4110             : 
    4111      252896 :         for (dnode *dn = when_search_list->h; dn; dn = dn->next) {
    4112      150488 :                 sql_exp *cond = NULL, *result = NULL;
    4113      150488 :                 dlist *when = dn->data.sym->data.lval;
    4114             : 
    4115      150488 :                 if (opt_cond)
    4116       46418 :                         cond = rel_value_exp(query, rel, when->h->data.sym, f, ek);
    4117             :                 else
    4118      104070 :                         cond = rel_logical_value_exp(query, rel, when->h->data.sym, f, ek);
    4119      150488 :                 if (!cond)
    4120             :                         return NULL;
    4121      150482 :                 append(conds, cond);
    4122      150482 :                 tpe = exp_subtype(cond);
    4123      150482 :                 if (tpe && condtype) {
    4124       57695 :                         result_datatype(&ctype, condtype, tpe);
    4125       57695 :                         condtype = &ctype;
    4126       92787 :                 } else if (tpe) {
    4127       92785 :                         condtype = tpe;
    4128             :                 }
    4129             : 
    4130      150482 :                 if (!(result = rel_value_exp(query, rel, when->h->next->data.sym, f, ek)))
    4131             :                         return NULL;
    4132      150479 :                 append(results, result);
    4133      150479 :                 tpe = exp_subtype(result);
    4134      150479 :                 if (tpe && restype) {
    4135       48068 :                         result_datatype(&rtype, restype, tpe);
    4136       48068 :                         restype = &rtype;
    4137      102411 :                 } else if (tpe) {
    4138      102405 :                         restype = tpe;
    4139             :                 }
    4140             :         }
    4141      102408 :         if (opt_else) {
    4142       99790 :                 if (!(res = rel_value_exp(query, rel, opt_else, f, ek)))
    4143             :                         return NULL;
    4144             : 
    4145       99790 :                 tpe = exp_subtype(res);
    4146       99790 :                 if (tpe && restype) {
    4147       99785 :                         result_datatype(&rtype, restype, tpe);
    4148       99785 :                         restype = &rtype;
    4149           5 :                 } else if (tpe) {
    4150             :                         restype = tpe;
    4151             :                 }
    4152             : 
    4153       99788 :                 if (!restype)
    4154           2 :                         return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
    4155       99788 :                 if (restype->type->localtype == TYPE_void) /* NULL */
    4156           0 :                         restype = sql_bind_localtype("str");
    4157             : 
    4158       99788 :                 if (!(res = exp_check_type(sql, restype, rel ? *rel : NULL, res, type_equal)))
    4159             :                         return NULL;
    4160             :         } else {
    4161        2618 :                 if (!restype)
    4162           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "Result type missing");
    4163        2618 :                 if (restype->type->localtype == TYPE_void) /* NULL */
    4164           7 :                         restype = sql_bind_localtype("str");
    4165        2618 :                 res = exp_null(sql->sa, restype);
    4166             :         }
    4167             : 
    4168      102406 :         if (!condtype)
    4169           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "Condition type missing");
    4170      102406 :         if (condtype->type->localtype == TYPE_void) /* NULL */
    4171           0 :                 condtype = sql_bind_localtype("str");
    4172      102406 :         if (opt_cond_exp && !(opt_cond_exp = exp_check_type(sql, condtype, rel ? *rel : NULL, opt_cond_exp, type_equal)))
    4173             :                 return NULL;
    4174      102406 :         sql_find_subtype(&bt, "boolean", 0, 0);
    4175      102406 :         list *args = sa_list(sql->sa);
    4176      102406 :         if (opt_cond_exp)
    4177        9624 :                 append(args, opt_cond_exp);
    4178      252878 :         for (node *n = conds->h, *m = results->h; n && m; n = n->next, m = m->next) {
    4179      150473 :                 sql_exp *cond = n->data;
    4180      150473 :                 sql_exp *result = m->data;
    4181             : 
    4182      150473 :                 if (!(result = exp_check_type(sql, restype, rel ? *rel : NULL, result, type_equal)))
    4183             :                         return NULL;
    4184             : 
    4185      150473 :                 if (!(cond = exp_check_type(sql, condtype, rel ? *rel : NULL, cond, type_equal)))
    4186             :                         return NULL;
    4187      150472 :                 if (!opt_cond_exp && !(cond = exp_check_type(sql, &bt, rel ? *rel : NULL, cond, type_equal)))
    4188             :                         return NULL;
    4189      150472 :                 append(args, cond);
    4190      150472 :                 append(args, result);
    4191             :         }
    4192      102405 :         assert(res);
    4193      102405 :         list_append(args, res);
    4194      102405 :         list *types = sa_list(sql->sa);
    4195      102405 :         types = append(append(types, restype), restype);
    4196      195187 :         sql_subfunc *case_func = find_func(sql, NULL, opt_cond_exp?"casewhen":"case", list_length(types), F_FUNC, true, NULL, NULL);
    4197      102405 :         res = exp_op(sql->sa, args, case_func);
    4198      102405 :         ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(sql->sa, restype->type, restype->digits, restype->scale);
    4199      102405 :         return res;
    4200             : }
    4201             : 
    4202             : static sql_exp *
    4203        4066 : rel_complex_case(sql_query *query, sql_rel **rel, dlist *case_args, int f, str func)
    4204             : {
    4205        4066 :         exp_kind ek = {type_value, card_column, FALSE};
    4206        4066 :         list *args = sa_list(query->sql->sa);
    4207        4066 :         sql_subtype *restype = NULL, rtype;
    4208        4066 :         sql_exp *res;
    4209             : 
    4210             :         /* generate nested func calls */
    4211       12654 :         for(dnode *dn = case_args->h; dn; dn = dn->next) {
    4212        8601 :                 sql_exp *a = rel_value_exp(query, rel, dn->data.sym, f, ek);
    4213        8601 :                 if (!a)
    4214             :                         return NULL;
    4215        8588 :                 append(args, a);
    4216             :                 /* all arguments should have the same type */
    4217        8588 :                 sql_subtype *tpe = exp_subtype(a);
    4218        8588 :                 if (tpe && restype) {
    4219        4524 :                         result_datatype(&rtype, restype, tpe);
    4220        4524 :                         restype = &rtype;
    4221        4064 :                 } else if (tpe) {
    4222        4064 :                         restype = tpe;
    4223             :                 }
    4224             :         }
    4225        4053 :         if (!restype)
    4226           0 :                 return sql_error(query->sql, 02, SQLSTATE(42000) "Result type missing");
    4227        4053 :         if (restype->type->localtype == TYPE_void) /* NULL */
    4228           0 :                 restype = sql_bind_localtype("str");
    4229        4053 :         list *nargs = sa_list(query->sql->sa);
    4230       12626 :         for (node *m = args->h; m; m = m->next) {
    4231        8573 :                 sql_exp *result = m->data;
    4232             : 
    4233        8573 :                 if (!(result = exp_check_type(query->sql, restype, rel ? *rel : NULL, result, type_equal)))
    4234             :                         return NULL;
    4235        8573 :                 append(nargs, result);
    4236             :         }
    4237        4053 :         list *types = append(append(sa_list(query->sql->sa), restype), restype);
    4238        4053 :         sql_subfunc *fnc = find_func(query->sql, NULL, func, list_length(types), F_FUNC, true, NULL, NULL);
    4239        4053 :         res = exp_op(query->sql->sa, nargs, fnc);
    4240        4053 :         ((sql_subfunc*)res->f)->res->h->data = sql_create_subtype(query->sql->sa, restype->type, restype->digits, restype->scale);
    4241        4053 :         return res;
    4242             : }
    4243             : 
    4244             : static sql_exp *
    4245      106484 : rel_case_exp(sql_query *query, sql_rel **rel, symbol *se, int f)
    4246             : {
    4247      106484 :         dlist *l = se->data.lval;
    4248             : 
    4249      106484 :         if (se->token == SQL_COALESCE) {
    4250        3915 :                 return rel_complex_case(query, rel, l, f | sql_farg, "coalesce");
    4251      102569 :         } else if (se->token == SQL_NULLIF) {
    4252         151 :                 return rel_complex_case(query, rel, l, f | sql_farg, "nullif");
    4253      102418 :         } else if (l->h->type == type_list) {
    4254       92787 :                 dlist *when_search_list = l->h->data.lval;
    4255       92787 :                 symbol *opt_else = l->h->next->data.sym;
    4256             : 
    4257       92787 :                 return rel_case(query, rel, NULL, when_search_list, opt_else, f | sql_farg);
    4258             :         } else {
    4259        9631 :                 symbol *scalar_exp = l->h->data.sym;
    4260        9631 :                 dlist *when_value_list = l->h->next->data.lval;
    4261        9631 :                 symbol *opt_else = l->h->next->next->data.sym;
    4262             : 
    4263        9631 :                 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      176289 : rel_cast(sql_query *query, sql_rel **rel, symbol *se, int f)
    4271             : {
    4272      176289 :         mvc *sql = query->sql;
    4273      176289 :         dlist *dl = se->data.lval;
    4274      176289 :         symbol *s = dl->h->data.sym;
    4275      176289 :         sql_subtype *tpe = &dl->h->next->data.typeval;
    4276      176289 :         exp_kind ek = {type_value, card_column, FALSE};
    4277      176289 :         sql_exp *e = rel_value_exp(query, rel, s, f|sql_farg, ek);
    4278             : 
    4279      176289 :         if (!e)
    4280             :                 return NULL;
    4281             : 
    4282             :         /* strings may need to be truncated */
    4283      176273 :         if (EC_VARCHAR(tpe->type->eclass) && tpe->digits > 0) {
    4284       85770 :                 sql_subtype *et = exp_subtype(e);
    4285             :                 /* truncate only if the number of digits are smaller or from clob */
    4286       85770 :                 if (et && EC_VARCHAR(et->type->eclass) && (tpe->digits < et->digits || et->digits == 0)) {
    4287        2920 :                         sql_subfunc *c = sql_bind_func(sql, "sys", "truncate", et, sql_bind_localtype("int"), F_FUNC, true, true);
    4288        2920 :                         if (c)
    4289        2920 :                                 e = exp_binop(sql->sa, e, exp_atom_int(sql->sa, tpe->digits), c);
    4290             :                 }
    4291             :         }
    4292             : 
    4293      176273 :         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      176273 :         if (e)
    4325      176273 :                 e = exp_check_type(sql, tpe, rel ? *rel : NULL, e, type_cast);
    4326             : 
    4327      176273 :         if (e && e->type == e_convert)
    4328       49902 :                 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       36818 : rel_group_column(sql_query *query, sql_rel **rel, symbol *grp, dlist *selection, list *exps, int f)
    4417             : {
    4418       36818 :         sql_query *lquery = query_create(query->sql);
    4419       36818 :         mvc *sql = query->sql;
    4420       36818 :         exp_kind ek = {type_value, card_value, TRUE};
    4421       36818 :         sql_exp *e = rel_value_exp2(lquery, rel, grp, f, ek);
    4422             : 
    4423       36818 :         if (e && exp_is_atom(e)) {
    4424          35 :                 sql_subtype *tpe = exp_subtype(e);
    4425          35 :                 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       36799 :         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       13582 : rel_groupings(sql_query *query, sql_rel **rel, symbol *groupby, dlist *selection, int f, bool grouping_sets, list **sets)
    4544             : {
    4545       13582 :         mvc *sql = query->sql;
    4546       13582 :         list *exps = new_exp_list(sql->sa);
    4547             : 
    4548       13582 :         if (mvc_highwater(sql))
    4549           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    4550             : 
    4551       50307 :         for (dnode *o = groupby->data.lval->h; o; o = o->next) {
    4552       36745 :                 symbol *grouping = o->data.sym;
    4553       36745 :                 list *next_set = NULL;
    4554             : 
    4555       36745 :                 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       36706 :                         dlist *dl = grouping->data.lval;
    4562       36706 :                         if (dl) {
    4563       36680 :                                 list *set_cols = new_exp_list(sql->sa); /* columns and combination of columns to be used for the next set */
    4564             : 
    4565       73449 :                                 for (dnode *oo = dl->h; oo; oo = oo->next) {
    4566       36788 :                                         symbol *grp = oo->data.sym;
    4567       36788 :                                         list *next_tuple = new_exp_list(sql->sa); /* next tuple of columns */
    4568             : 
    4569       36788 :                                         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       36717 :                                                 sql_exp *e = rel_group_column(query, rel, grp, selection, exps, f);
    4582       36717 :                                                 if (!e)
    4583             :                                                         return NULL;
    4584       36698 :                                                 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       36698 :                                                 list_append(next_tuple, e);
    4591       36698 :                                                 list_append(exps, e);
    4592             :                                         }
    4593       36769 :                                         list_append(set_cols, next_tuple);
    4594             :                                 }
    4595       36661 :                                 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       36726 :                 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        2339 : rel_partition_groupings(sql_query *query, sql_rel **rel, symbol *partitionby, dlist *selection, int f)
    4620             : {
    4621        2339 :         mvc *sql = query->sql;
    4622        2339 :         dnode *o = partitionby->data.lval->h;
    4623        2339 :         list *exps = new_exp_list(sql->sa);
    4624             : 
    4625        7048 :         for (; o; o = o->next) {
    4626        2378 :                 symbol *grp = o->data.sym;
    4627        2378 :                 exp_kind ek = {type_value, card_value, TRUE};
    4628        2378 :                 sql_exp *e = rel_value_exp2(query, rel, grp, f, ek);
    4629             : 
    4630        2378 :                 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        2373 :                 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        2370 :                 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        2370 :                 if (e->card > CARD_AGGR)
    4671        2248 :                         e->card = CARD_AGGR;
    4672        2370 :                 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       71055 : rel_order_by_column_exp(sql_query *query, sql_rel **R, symbol *column_r, int needs_distinct, int f)
    4681             : {
    4682       71055 :         mvc *sql = query->sql;
    4683       71055 :         sql_rel *r = *R, *p = NULL;
    4684       71055 :         sql_exp *e = NULL, *found = NULL;
    4685       71055 :         exp_kind ek = {type_value, card_column, FALSE};
    4686             : 
    4687       71055 :         if (!r)
    4688             :                 return e;
    4689             : 
    4690       71055 :         if (is_simple_project(r->op) && r->l && is_processed(r)) {
    4691       70993 :                 p = r;
    4692       70993 :                 r = r->l;
    4693             :         }
    4694             : 
    4695       71055 :         e = rel_value_exp(query, &r, column_r, f, ek);
    4696             : 
    4697       71055 :         if (r && !p)
    4698          62 :                 *R = r;
    4699       70993 :         else if (r)
    4700       70993 :                 p->l = r;
    4701       71055 :         if (e && p) {
    4702       70966 :                 if (is_project(p->op) && (found = exps_any_match(p->exps, e))) { /* if one of the projections matches, return a reference to it */
    4703       60785 :                         e = exp_ref(sql, found);
    4704             :                 } else {
    4705       10181 :                         if (needs_distinct)
    4706           2 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: with DISTINCT ORDER BY expressions must appear in select list");
    4707       10179 :                         e = rel_project_add_exp(sql, p, e);
    4708       10179 :                         if (r) {
    4709      134593 :                                 for (node *n = p->exps->h ; n ; n = n->next) {
    4710      124416 :                                         sql_exp *ee = n->data;
    4711             : 
    4712      124416 :                                         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       70962 :                 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      118066 : simple_selection(symbol *sq)
    4741             : {
    4742      118066 :         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       47377 : rel_order_by(sql_query *query, sql_rel **R, symbol *orderby, int needs_distinct, int f)
    4754             : {
    4755       47377 :         mvc *sql = query->sql;
    4756       47377 :         sql_rel *rel = *R, *or = rel; /* the order by relation */
    4757       47377 :         list *exps = new_exp_list(sql->sa);
    4758             : 
    4759       47377 :         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       47371 :         dnode *o = orderby->data.lval->h;
    4772       47371 :         dlist *selection = NULL;
    4773             : 
    4774       47371 :         if (is_sql_orderby(f)) {
    4775       39854 :                 assert(is_project(rel->op));
    4776       39854 :                 rel = rel->l;
    4777             :         }
    4778             : 
    4779      165389 :         for (; o; o = o->next) {
    4780      118066 :                 symbol *order = o->data.sym;
    4781             : 
    4782      118066 :                 if (order->token == SQL_COLUMN || order->token == SQL_IDENT) {
    4783      118066 :                         symbol *col = order->data.lval->h->data.sym;
    4784      118066 :                         int direction = order->data.lval->h->next->data.i_val;
    4785      118066 :                         sql_exp *e = NULL;
    4786             : 
    4787      118066 :                         assert(order->data.lval->h->next->type == type_int);
    4788      118066 :                         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      118066 :                         if (col->token == SQL_COLUMN || col->token == SQL_IDENT || col->token == SQL_ATOM) {
    4798      117844 :                                 exp_kind ek = {type_value, card_column, FALSE};
    4799             : 
    4800      117844 :                                 e = rel_value_exp2(query, &rel, col, f, ek);
    4801             : 
    4802      117844 :                                 if (e && e->card <= CARD_ATOM) {
    4803        9376 :                                         sql_subtype *tpe = exp_subtype(e);
    4804             :                                         /* integer atom on the stack */
    4805        9376 :                                         if (!is_sql_window(f) && e->type == e_atom &&
    4806        9268 :                                             tpe->type->eclass == EC_NUM) {
    4807        9259 :                                                 atom *a = e->l;
    4808        9259 :                                                 int nr = (int)atom_get_int(a);
    4809             : 
    4810        9259 :                                                 e = exps_get_exp(rel->exps, nr);
    4811        9259 :                                                 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        9256 :                                                 e = exp_ref(sql, e);
    4814             :                                         }
    4815       37629 :                                 } 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      117841 :                                 if (e && !exp_name(e))
    4821          23 :                                         exp_label(sql->sa, e, ++sql->label);
    4822       47002 :                                 if (e && rel && is_project(rel->op)) {
    4823       39992 :                                         sql_exp *found = exps_find_exp(rel->exps, e);
    4824             : 
    4825       39992 :                                         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       39992 :                                         if (!is_freevar(e))
    4834       39975 :                                                 e = exp_ref(sql, e);
    4835             :                                 }
    4836             :                         }
    4837             : 
    4838      118063 :                         if (rel && !e && sql->session->status != -ERR_AMBIGUOUS) {
    4839             :                                 /* reset error */
    4840       71055 :                                 sql->session->status = 0;
    4841       71055 :                                 sql->errstr[0] = '\0';
    4842             : 
    4843       71055 :                                 e = rel_order_by_column_exp(query, &rel, col, needs_distinct, sql_sel | sql_orderby | (f & sql_group_totals) | (f & sql_window));
    4844             :                         }
    4845       71061 :                         if (!e)
    4846             :                                 return NULL;
    4847      118019 :                         if (!exp_subtype(e))
    4848           1 :                                 return sql_error(sql, 01, SQLSTATE(42000) "Cannot have a parameter (?) for order by column");
    4849      118018 :                         set_direction(e, direction);
    4850      118018 :                         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       47323 :         if (is_sql_orderby(f) && or != rel)
    4856       39813 :                 or->l = rel;
    4857       47323 :         if (is_sql_window(f))
    4858        3046 :                 *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       12839 : rel_rankop(sql_query *query, sql_rel **rel, symbol *se, int f)
    5042             : {
    5043       12839 :         mvc *sql = query->sql;
    5044       12839 :         node *n;
    5045       12839 :         dlist *l = se->data.lval, *window_specification = NULL;
    5046       12839 :         symbol *window_function = l->h->data.sym, *partition_by_clause = NULL, *order_by_clause = NULL, *frame_clause = NULL;
    5047       12839 :         char *aname = NULL, *sname = NULL, *window_ident = NULL;
    5048       12839 :         sql_subfunc *wf = NULL;
    5049       12839 :         sql_exp *in = NULL, *pe = NULL, *oe = NULL, *call = NULL, *start = NULL, *eend = NULL, *fstart = NULL, *fend = NULL, *ie = NULL;
    5050       12839 :         sql_rel *p;
    5051       12839 :         list *gbe = NULL, *obe = NULL, *args = NULL, *types = NULL, *fargs = NULL;
    5052       12839 :         dnode *dn = window_function->data.lval->h, *dargs = NULL;
    5053       12839 :         int distinct = 0, frame_type, pos, nf = f, nfargs = 0;
    5054       12839 :         bool is_nth_value, supports_frames = false, found = false;
    5055             : 
    5056       12839 :         frame_clear_visited_flag(sql); /* clear visited flags before iterating */
    5057             : 
    5058       12839 :         if (l->h->next->type == type_list) {
    5059       12823 :                 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       12838 :         window_ident = window_specification->h->data.sval;
    5070       12838 :         partition_by_clause = window_specification->h->next->data.sym;
    5071       12838 :         order_by_clause = window_specification->h->next->next->data.sym;
    5072       12838 :         frame_clause = window_specification->h->next->next->next->data.sym;
    5073             : 
    5074       12838 :         if (window_ident && !get_window_clauses(sql, window_ident, &partition_by_clause, &order_by_clause, &frame_clause))
    5075             :                 return NULL;
    5076             : 
    5077       12835 :         frame_type = frame_clause ? frame_clause->data.lval->h->next->next->data.i_val : FRAME_RANGE;
    5078       12835 :         aname = qname_schema_object(dn->data.lval);
    5079       12835 :         sname = qname_schema(dn->data.lval);
    5080             : 
    5081       12835 :         is_nth_value = !strcmp(aname, "nth_value");
    5082       12835 :         bool is_value = is_nth_value || !strcmp(aname, "first_value") || !strcmp(aname, "last_value");
    5083       12835 :         bool rank = false;
    5084       12835 :         if (strcmp(aname, "row_number") == 0 || strcmp(aname, "rank") == 0 || strcmp(aname, "dense_rank") == 0 ||
    5085        2935 :             strcmp(aname, "percent_rank") == 0 || strcmp(aname, "cume_dist") == 0 || strcmp(aname, "ntile") == 0 ||
    5086        2831 :             strcmp(aname, "lag") == 0 || strcmp(aname, "lead") == 0 || strcmp(aname, "fetch") == 0)
    5087       10076 :                 rank = true;
    5088       12835 :         supports_frames = (!rank || is_value);
    5089             : 
    5090       12835 :         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       12822 :         } 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       12820 :         } 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       12814 :         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       12814 :         if (window_function->token == SQL_NOP)
    5108       12708 :                 window_function->token = SQL_AGGR;
    5109       12814 :         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       12814 :         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       12814 :         p = *rel;
    5119             :         /* Partition By */
    5120       12814 :         if (partition_by_clause) {
    5121        2339 :                 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        2339 :                 if (!gbe)
    5123             :                         return NULL;
    5124        4698 :                 for (n = gbe->h ; n ; n = n->next) {
    5125        2367 :                         sql_exp *en = n->data;
    5126             : 
    5127        2367 :                         set_ascending(en);
    5128        2367 :                         set_nulls_first(en);
    5129             :                 }
    5130             :         }
    5131             : 
    5132             :         /* Order By */
    5133       12806 :         if (order_by_clause) {
    5134        3053 :                 obe = rel_order_by(query, &p, order_by_clause, 0, sql_window);
    5135        3053 :                 if (!obe)
    5136             :                         return NULL;
    5137             :         }
    5138             : 
    5139       12799 :         fargs = sa_list(sql->sa);
    5140       12799 :         if (rank) { /* rank function call */
    5141       10062 :                 dlist *dl = dn->next->next->data.lval;
    5142       10062 :                 bool is_lag = !strcmp(aname, "lag"), is_lead = !strcmp(aname, "lead"),
    5143       10062 :                          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       10062 :                 distinct = dn->next->data.i_val;
    5146       10062 :                 if (extra_input) { /* pass an input column for analytic functions that don't require it */
    5147        9991 :                         sql_subfunc *star = sql_bind_func(sql, "sys", "star", NULL, NULL, F_FUNC, true, true);
    5148        9991 :                         in = exp_op(sql->sa, NULL, star);
    5149        9991 :                         append(fargs, in);
    5150             :                 }
    5151       10062 :                 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        2737 :                 distinct = dn->next->data.i_val;
    5183        2737 :                 assert(dn->next->next->type == type_list);
    5184        2737 :                 dlist *dl = dn->next->next->data.lval;
    5185        9215 :                 for (dargs = dl?dl->h:NULL; dargs && dargs->data.sym ; dargs = dargs->next) {
    5186        3749 :                         exp_kind ek = {type_value, card_column, FALSE};
    5187        3749 :                         sql_subtype *empty = sql_bind_localtype("void"), *bte = sql_bind_localtype("bte");
    5188             : 
    5189        3749 :                         in = rel_value_exp2(query, &p, dargs->data.sym, f | sql_window | sql_farg, ek);
    5190        3749 :                         if (!in)
    5191           8 :                                 return NULL;
    5192        3742 :                         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        3741 :                         if (!exp_name(in))
    5197        2012 :                                 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        3741 :                         if (subtype_cmp(exp_subtype(in), empty) == 0)
    5201          53 :                                 in = exp_convert(sql, in, empty, bte);
    5202        3741 :                         if (!in)
    5203             :                                 return NULL;
    5204             : 
    5205        3741 :                         append(fargs, in);
    5206        3741 :                         in = exp_ref_save(sql, in);
    5207        3741 :                         nfargs++;
    5208             : 
    5209        3741 :                         if (!strcmp(aname, "count"))
    5210          86 :                                 append(fargs, exp_atom_bool(sql->sa, 1)); /* ignore nills */
    5211             :                 }
    5212             : 
    5213        2729 :                 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       12788 :         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       12784 :         if (gbe) {
    5230        2322 :                 sql_subtype *bt = sql_bind_localtype("bit");
    5231             : 
    5232        4679 :                 for( n = gbe->h; n; n = n->next) {
    5233        2358 :                         sql_subfunc *df;
    5234        2358 :                         sql_exp *e = n->data;
    5235             : 
    5236        2358 :                         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        2357 :                         e = exp_copy(sql, e);
    5240        2357 :                         args = sa_list(sql->sa);
    5241        2357 :                         if (pe) {
    5242          36 :                                 df = sql_bind_func(sql, "sys", "diff", bt, exp_subtype(e), F_ANALYTIC, true, true);
    5243          36 :                                 append(args, pe);
    5244             :                         } else {
    5245        2321 :                                 df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
    5246             :                         }
    5247        2357 :                         if (!df)
    5248           0 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: function 'diff' not found");
    5249        2357 :                         append(args, e);
    5250        2357 :                         pe = exp_op(sql->sa, args, df);
    5251             :                 }
    5252             :         } else {
    5253       10462 :                 pe = exp_atom_bool(sql->sa, 0);
    5254             :         }
    5255             : 
    5256             :         /* diff for orderby */
    5257       12783 :         if (obe) {
    5258        3044 :                 sql_subtype *bt = sql_bind_localtype("bit");
    5259             : 
    5260        6244 :                 for( n = obe->h; n; n = n->next) {
    5261        3200 :                         sql_subfunc *df;
    5262        3200 :                         sql_exp *e = n->data;
    5263             : 
    5264        3200 :                         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        3200 :                         e = exp_copy(sql, e);
    5268        3200 :                         args = sa_list(sql->sa);
    5269        3200 :                         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        3044 :                                 df = sql_bind_func(sql, "sys", "diff", exp_subtype(e), NULL, F_ANALYTIC, true, true);
    5274             :                         }
    5275        3200 :                         if (!df)
    5276           0 :                                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: function 'diff' not found");
    5277        3200 :                         append(args, e);
    5278        3200 :                         oe = exp_op(sql->sa, args, df);
    5279             :                 }
    5280             :         } else {
    5281        9739 :                 oe = exp_atom_bool(sql->sa, 0);
    5282             :         }
    5283             : 
    5284       12783 :         if (frame_clause || supports_frames) {
    5285        2726 :                 if (frame_type == FRAME_RANGE)
    5286        2415 :                         ie = obe ? (sql_exp*) obe->t->data : in;
    5287             :                 else
    5288         311 :                         ie = obe ? oe : in;
    5289             :         }
    5290       12783 :         assert(oe && pe);
    5291             : 
    5292       12783 :         types = exp_types(sql->sa, fargs);
    5293       12783 :         wf = bind_func_(sql, sname, aname, types, F_ANALYTIC, false, &found, false);
    5294       12783 :         if (wf && !list_empty(fargs) && !(fargs = check_arguments_and_find_largest_any_type(sql, NULL, fargs, wf, 0, false)))
    5295             :                 wf = NULL;
    5296       12779 :         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       12779 :         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       12369 :         } else if (supports_frames) { /* for analytic functions with no frame clause, we use the standard default values */
    5364        2314 :                 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        2206 :                         frame_type = list_empty(obe) ? FRAME_ALL : FRAME_UNBOUNDED_TILL_CURRENT_ROW;
    5376             :                 }
    5377             :         }
    5378             : 
    5379       12761 :         args = sa_list(sql->sa);
    5380       26925 :         for (node *n = fargs->h ; n ; n = n->next)
    5381       14164 :                 list_append(args, n->data);
    5382       12761 :         list_append(args, pe);
    5383       12761 :         list_append(args, oe);
    5384       12761 :         if (supports_frames) {
    5385        2706 :                 list_append(args, exp_atom_int(sql->sa, frame_type));
    5386        2706 :                 list_append(args, start ? start : exp_atom_oid(sql->sa, 1));
    5387        2706 :                 list_append(args, eend ? eend : exp_atom_oid(sql->sa, 1));
    5388             :         }
    5389       12761 :         call = exp_rank_op(sql->sa, list_empty(args) ? NULL : args, gbe, obe, wf);
    5390       12761 :         *rel = p;
    5391       12761 :         return call;
    5392             : }
    5393             : 
    5394             : sql_exp *
    5395     6132875 : rel_value_exp2(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
    5396             : {
    5397     6132875 :         mvc *sql = query->sql;
    5398     6132875 :         if (!se)
    5399             :                 return NULL;
    5400             : 
    5401     6132875 :         if (mvc_highwater(sql))
    5402          56 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    5403             : 
    5404     6132992 :         if (rel && *rel && (*rel)->card == CARD_AGGR) { /* group by expression case, handle it before */
    5405      137900 :                 sql_exp *exp = NULL;
    5406      137900 :                 if (!is_sql_aggr(f) && !is_sql_window(f))
    5407      137434 :                         exp = frame_get_groupby_expression(sql, se);
    5408      137900 :                 if (sql->errstr[0] != '\0')
    5409             :                         return NULL;
    5410      137900 :                 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     6132910 :         switch (se->token) {
    5426      593177 :         case SQL_NOP:
    5427      593177 :                 return rel_nop(query, rel, se, f, ek);
    5428       19614 :         case SQL_AGGR:
    5429       19614 :                 return rel_aggr(query, rel, se, f);
    5430       12839 :         case SQL_WINDOW:
    5431       12839 :                 return rel_rankop(query, rel, se, f);
    5432     2404735 :         case SQL_IDENT:
    5433             :         case SQL_COLUMN:
    5434     2404735 :                 return rel_column_ref(query, rel, se, f );
    5435        3055 :         case SQL_NAME: {
    5436        3055 :                 dlist *l = se->data.lval;
    5437        3055 :                 const char *sname = qname_schema(l);
    5438        3055 :                 const char *vname = qname_schema_object(l);
    5439        3055 :                 return rel_exp_variable_on_scope(sql, sname, vname);
    5440             :         }
    5441       51363 :         case SQL_VALUES:
    5442             :         case SQL_ROW:
    5443             :         case SQL_SET:
    5444             :         case SQL_WITH:
    5445             :         case SQL_SELECT: {
    5446       51363 :                 sql_rel *r = NULL;
    5447             : 
    5448       51363 :                 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       51359 :                 if (rel && *rel)
    5451       36980 :                         query_push_outer(query, *rel, f);
    5452       51359 :                 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         353 :                         if (ek.card <= card_row && !(rel && *rel)) {
    5456          93 :                                 sql_exp *e = sql_exp_values(query, se);
    5457          93 :                                 if (!e)
    5458             :                                         return NULL;
    5459          92 :                                 if (exp_is_atom(e)) /* single tuple */
    5460             :                                         return e;
    5461           1 :                                 r = rel_project(query->sql->sa, NULL, e->f);
    5462             :                         } else
    5463         259 :                                 r = rel_values(query, se, NULL);
    5464             :                 } else {
    5465           0 :                         assert(se->token == SQL_SELECT);
    5466       50971 :                         exp_kind nek = ek;
    5467       50971 :                         nek.aggr = is_sql_aggr(f);
    5468       50971 :                         if (is_sql_no_subquery(f))
    5469           3 :                                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery not allowed");
    5470             : 
    5471       50968 :                         r = rel_subquery(query, se, nek);
    5472       50968 :                         if (r)
    5473       50866 :                                 exps_label(sql, r->exps);
    5474             :                 }
    5475       51264 :                 if (rel && *rel) {
    5476       36977 :                         *rel = query_pop_outer(query);
    5477       36977 :                         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       36977 :                         } 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       36977 :                         } 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       51264 :                 if (!r)
    5486             :                         return NULL;
    5487       51160 :                 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       51127 :                 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       51127 :                 if (ek.type == type_value && list_length(r->exps) == 1 && !is_sql_psm(f)) /* for now don't rename multi attribute results */
    5492       38715 :                         r = rel_zero_or_one(sql, r, ek);
    5493       51127 :                 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      109527 :         case SQL_NULL:
    5514      109527 :                 return exp_null(sql->sa, sql_bind_localtype("void"));
    5515        1590 :         case SQL_NEXT:
    5516        1590 :                 return rel_next_value_for(sql, se);
    5517      176289 :         case SQL_CAST:
    5518      176289 :                 return rel_cast(query, rel, se, f);
    5519      106484 :         case SQL_CASE:
    5520             :         case SQL_COALESCE:
    5521             :         case SQL_NULLIF:
    5522      106484 :                 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     2652388 :         default:
    5535     2652388 :                 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     4668665 : rel_value_exp(sql_query *query, sql_rel **rel, symbol *se, int f, exp_kind ek)
    5581             : {
    5582     4668665 :         if (!se)
    5583             :                 return NULL;
    5584             : 
    5585     4668665 :         if (mvc_highwater(query->sql))
    5586           4 :                 return sql_error(query->sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    5587             : 
    5588     4668748 :         sql_exp *e = rel_value_exp2(query, rel, se, f, ek);
    5589     4668715 :         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     1356361 : column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
    5598             : {
    5599     1356361 :         dlist *l = column_e->data.lval;
    5600     1356361 :         exp_kind ek = {type_value, card_column, FALSE};
    5601     1356361 :         sql_exp *ve;
    5602             : 
    5603     1356361 :         if (f == sql_sel && rel && *rel && (*rel)->card < CARD_AGGR)
    5604       83235 :                 ek.card = card_value;
    5605     1356361 :         ve = rel_value_exp(query, rel, l->h->data.sym, f, ek);
    5606     1356396 :         if (!ve)
    5607             :                 return NULL;
    5608             :         /* AS name */
    5609     1340523 :         if (ve && l->h->next->data.sval)
    5610      513555 :                 exp_setname(query->sql, ve, NULL, l->h->next->data.sval);
    5611             :         return ve;
    5612             : }
    5613             : 
    5614             : static int
    5615      880678 : exp_is_not_intern(sql_exp *e)
    5616             : {
    5617      880678 :         return is_intern(e)?-1:0;
    5618             : }
    5619             : 
    5620             : static void
    5621      130635 : rel_remove_internal_exp(sql_rel *rel)
    5622             : {
    5623      130635 :         if (rel->exps) {
    5624      130635 :                 list *n_exps = list_select(rel->exps, rel, (fcmp)&exp_is_not_intern, (fdup)NULL);
    5625             : 
    5626      130635 :                 rel->exps = n_exps;
    5627             :         }
    5628      130635 : }
    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       59386 : rel_table_exp(sql_query *query, sql_rel **rel, symbol *column_e, bool single_exp )
    5675             : {
    5676       59386 :         mvc *sql = query->sql;
    5677       59386 :         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       59386 :         char *tname = NULL;
    5689       59386 :         if (column_e->token == SQL_TABLE) {
    5690       43524 :                 tname = column_e->data.lval->h->data.sval;
    5691       15862 :         } else if (column_e->token == SQL_COLUMN && column_e->data.lval->h->type == type_symbol) {
    5692       15862 :                 symbol *sym = column_e->data.lval->h->data.sym;
    5693       15862 :                 if (sym->token == SQL_COLUMN)
    5694       14849 :                         tname = sym->data.lval->h->data.sval;
    5695             :                 else
    5696             :                         return NULL;
    5697             :         } else {
    5698             :                 return NULL;
    5699             :         }
    5700             : 
    5701       58373 :         list *exps = NULL;
    5702       58373 :         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       58373 :         if (project) {
    5706       67861 :                 while (is_groupby(project->op) || is_select(project->op)) {
    5707        9488 :                         if (is_groupby(project->op))
    5708          37 :                                 groupby = project;
    5709        9488 :                         if (project->l)
    5710        9488 :                                 project = project->l;
    5711             :                 }
    5712             :                 assert(project);
    5713             :         }
    5714             : 
    5715       58373 :         if (project->op == op_project && project->l && project == *rel && !tname && !rel_is_ref(project) && !need_distinct(project) && single_exp) {
    5716         520 :                 sql_rel *l = project->l;
    5717         520 :                 if (!l || !is_project(l->op) || list_length(project->exps) == list_length(l->exps)) {
    5718         513 :                         rel_remove_internal_exp(*rel);
    5719         513 :                         exps = project->exps;
    5720         513 :                         *rel = project->l;
    5721             :                 }
    5722             :         }
    5723       58373 :         if ((exps || (exps = rel_table_projections(sql, project, tname, 0)) != NULL) && !list_empty(exps)) {
    5724       58272 :                 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       58272 :                 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       58265 :                 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     1399889 : rel_column_exp(sql_query *query, sql_rel **rel, symbol *column_e, int f)
    5747             : {
    5748     1399889 :         if (column_e->token == SQL_COLUMN || column_e->token == SQL_IDENT)
    5749     1356367 :                 return column_exp(query, rel, column_e, f);
    5750             :         return NULL;
    5751             : }
    5752             : 
    5753             : static sql_rel*
    5754      380320 : rel_where_groupby_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, int *group_totals)
    5755             : {
    5756      380320 :         mvc *sql = query->sql;
    5757             : 
    5758      380320 :         if (sn->where) {
    5759      150361 :                 rel = rel_logical_exp(query, rel, sn->where, sql_where);
    5760      150361 :                 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      380246 :         query_processed(query);
    5767             : 
    5768      380244 :         if (rel && sn->groupby) {
    5769       13551 :                 list *gbe = NULL, *sets = NULL;
    5770       13551 :                 int all = 0;
    5771       13551 :                 if (sn->groupby->data.lval == NULL) { /* ALL */
    5772             :                         all = 1;
    5773             :                 } else {
    5774       50062 :                         for (dnode *o = sn->groupby->data.lval->h; o ; o = o->next) {
    5775       36638 :                                 symbol *grouping = o->data.sym;
    5776       36638 :                                 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       13543 :                         gbe = rel_groupings(query, &rel, sn->groupby, sn->selection, sql_sel | sql_groupby | *group_totals, false, &sets);
    5782       13543 :                         if (!gbe)
    5783          20 :                                 return NULL;
    5784             :                 }
    5785       13531 :                 rel = rel_groupby(sql, rel, gbe);
    5786       13531 :                 if (rel && all)
    5787           8 :                         rel->flag = 2;
    5788       13531 :                 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      380224 :         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      380224 :         query_processed(query);
    5801      380259 :         return rel;
    5802             : }
    5803             : 
    5804             : static sql_rel*
    5805      379091 : rel_having_limits_nodes(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek, int group_totals)
    5806             : {
    5807      379091 :         mvc *sql = query->sql;
    5808      379091 :         sql_rel *inner = NULL;
    5809      379091 :         int single_value = 1;
    5810             : 
    5811      379091 :         if (is_project(rel->op) && rel->l) {
    5812      379091 :                 inner = rel->l;
    5813      379091 :                 single_value = 0;
    5814             :         }
    5815             : 
    5816      379091 :         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      379050 :         if (sn->qualify) {
    5828           0 :                 if (!(rel = rel_logical_exp(query, rel, sn->qualify, sql_qualify)))
    5829             :                         return NULL;
    5830             :         }
    5831             : 
    5832      379050 :         if (rel && sn->distinct)
    5833        1039 :                 rel = rel_distinct(rel);
    5834             : 
    5835      379050 :         if (rel && sn->orderby) {
    5836       39860 :                 list *obe = NULL;
    5837       39860 :                 sql_rel *sel = NULL, *l = rel->l;
    5838             : 
    5839             :                 /* project( select ) */
    5840       39860 :                 if (sn->having && is_select(l->op)) {
    5841          52 :                         sel = l;
    5842          52 :                         rel->l = l->l;
    5843             :                 }
    5844       39860 :                 rel = rel_orderby(sql, rel);
    5845       39860 :                 set_processed(rel);
    5846       39860 :                 obe = rel_order_by(query, &rel, sn->orderby, sn->distinct, sql_orderby | group_totals);
    5847       39860 :                 if (!obe)
    5848             :                         return NULL;
    5849       39819 :                 rel->r = obe;
    5850       39819 :                 if (sel) {
    5851          51 :                         sql_rel *o = rel, *p = o->l;
    5852          51 :                         p->l = sel;
    5853             :                 }
    5854             :         }
    5855      379009 :         if (!rel)
    5856             :                 return NULL;
    5857             : 
    5858      379009 :         if (sn->limit || sn->offset) {
    5859       16743 :                 sql_subtype *lng = sql_bind_localtype("lng");
    5860       16729 :                 list *exps = new_exp_list(sql->sa);
    5861             : 
    5862       16729 :                 if (sn->limit) {
    5863       16703 :                         sql_exp *l = rel_value_exp(query, NULL, sn->limit, 0, ek);
    5864             : 
    5865       16703 :                         if (!l || !(l=exp_check_type(sql, lng, NULL, l, type_equal)))
    5866           0 :                                 return NULL;
    5867       16701 :                         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       16701 :                         list_append(exps, l);
    5873             :                 } else
    5874          26 :                         list_append(exps, exp_atom(sql->sa, atom_general(sql->sa, lng, NULL, 0)));
    5875       16726 :                 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       16726 :                 rel = rel_topn(sql->sa, rel, exps);
    5882             :         }
    5883             : 
    5884      378991 :         if (sn->sample || sn->seed) {
    5885          22 :                 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      378992 :         if (!sn->having && inner && is_groupby(inner->op))
    5909       33016 :                 set_processed(inner);
    5910      378992 :         if (rel)
    5911      378992 :                 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      380332 : rel_select_exp(sql_query *query, sql_rel *rel, SelectNode *sn, exp_kind ek)
    5982             : {
    5983      380332 :         mvc *sql = query->sql;
    5984      380332 :         sql_rel *inner = NULL;
    5985      380332 :         int group_totals = 0;
    5986      380332 :         list *pexps = NULL;
    5987             : 
    5988      380332 :         assert(sn->s.token == SQL_SELECT);
    5989      380332 :         if (!sn->selection)
    5990           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "SELECT: the selection or from part is missing");
    5991             : 
    5992      380332 :         if (!rel)
    5993       72918 :                 rel = rel_project_exp(sql, exp_atom_bool(sql->sa, 1));
    5994      380364 :         rel = rel_where_groupby_nodes(query, rel, sn, &group_totals);
    5995      380357 :         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      380260 :         inner = rel;
    5999      380260 :         pexps = sa_list(sql->sa);
    6000     1778993 :         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     1399887 :                 list *te = NULL;
    6007     2799731 :                 sql_exp *ce = rel_column_exp(query, &inner, n->data.sym, sql_sel | group_totals | (ek.aggr?sql_aggr:0));
    6008             : 
    6009     1399902 :                 if (ce) {
    6010     1340517 :                         if (inner && inner->flag && is_groupby(inner->op)) {
    6011          62 :                                 int found = 0;
    6012          62 :                                 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          62 :                                 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          81 :                                         for(node *n = gbe->h; n && !found; n = n->next) {
    6028          44 :                                                 sql_exp *e = n->data;
    6029          44 :                                                 if (is_atom(e->type) && a_no_name(&e->alias)) {
    6030          29 :                                                         atom *a = e->l;
    6031          29 :                                                         int nr = (int)atom_get_int(a);
    6032          29 :                                                         if (nr == (list_length(pexps) + 1)) {
    6033          27 :                                                                 n->data = ce;
    6034          27 :                                                                 ce = exp_ref(sql, ce);
    6035          27 :                                                                 ce->card = CARD_AGGR;
    6036          27 :                                                                 list_append(inner->exps, ce);
    6037          27 :                                                                 ce = exp_ref(sql, ce);
    6038          27 :                                                                 found = 1;
    6039             :                                                         }
    6040             :                                                 }
    6041             :                                         }
    6042             :                                 }
    6043             :                         }
    6044     1340517 :                         pexps = append(pexps, ce);
    6045     1340496 :                         rel = inner;
    6046     1340496 :                         continue;
    6047             :                 } else {
    6048       63952 :                         te = rel_table_exp(query, &rel, n->data.sym, !list_length(pexps) && !n->next);
    6049             :                 }
    6050       59388 :                 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       58265 :                 pexps = list_merge(pexps, te, (fdup)NULL);
    6060             :         }
    6061      379106 :         if (rel && is_groupby(rel->op) && rel->flag) {
    6062          34 :                 list *gbe = rel->r;
    6063          34 :                 if (!list_empty(gbe)) {
    6064          68 :                         for (node *n=gbe->h; n; n = n->next) {
    6065          37 :                                 sql_exp *e = n->data;
    6066          37 :                                 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          36 :                                 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      379103 :         if (rel && is_groupby(rel->op) && (!sn->groupby || rel->flag) && !is_processed(rel)) {
    6077       43628 :                 for (node *n=pexps->h; n; n = n->next) {
    6078       22282 :                         sql_exp *ce = n->data;
    6079       22282 :                         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       21346 :                 set_processed(rel);
    6086             :         }
    6087      379103 :         rel = rel_project(sql->sa, rel, pexps);
    6088             : 
    6089      379129 :         rel = rel_having_limits_nodes(query, rel, sn, ek, group_totals);
    6090      379129 :         return rel;
    6091             : }
    6092             : 
    6093             : static sql_rel*
    6094      130074 : rel_unique_names(mvc *sql, sql_rel *rel)
    6095             : {
    6096      130074 :         list *l;
    6097             : 
    6098      130074 :         if (!is_project(rel->op))
    6099             :                 return rel;
    6100      130074 :         l = sa_list(sql->sa);
    6101     1008386 :         for (node *n = rel->exps->h; n; n = n->next) {
    6102      878312 :                 sql_exp *e = n->data;
    6103      878312 :                 const char *name = exp_name(e);
    6104             : 
    6105             :                 /* If there are two identical expression names, there will be ambiguity */
    6106      878312 :                 if (!name || exps_bind_column(l, name, NULL, NULL, 0))
    6107       59145 :                         exp_label(sql->sa, e, ++sql->label);
    6108      878312 :                 append(l,e);
    6109             :         }
    6110      130074 :         rel->exps = l;
    6111      130074 :         return rel;
    6112             : }
    6113             : 
    6114             : static sql_rel *
    6115      380683 : rel_query(sql_query *query, symbol *sq, exp_kind ek)
    6116             : {
    6117      380683 :         mvc *sql = query->sql;
    6118      380683 :         sql_rel *res = NULL;
    6119      380683 :         SelectNode *sn = NULL;
    6120             : 
    6121      380683 :         if (sq->token != SQL_SELECT)
    6122          22 :                 return table_ref(query, sq, 0, NULL);
    6123             : 
    6124             :         /* select ... into is currently not handled here ! */
    6125      380661 :         sn = (SelectNode *) sq;
    6126      380661 :         if (sn->into)
    6127             :                 return NULL;
    6128             : 
    6129      380661 :         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      380658 :         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      380657 :         if (sn->from) {
    6147      307721 :                 dlist *fl = sn->from->data.lval;
    6148      307721 :                 sql_rel *fnd = NULL;
    6149      307721 :                 list *refs = new_exp_list(sql->sa); /* Keep list of relation names in order to test for duplicates */
    6150             : 
    6151      764238 :                 for (dnode *n = fl->h; n ; n = n->next) {
    6152      456822 :                         int lateral = check_is_lateral(n->data.sym);
    6153             : 
    6154             :                         /* just used current expression */
    6155      456823 :                         if (lateral && res)
    6156          34 :                                 query_push_outer(query, res, sql_from);
    6157      456823 :                         fnd = table_ref(query, n->data.sym, lateral, refs);
    6158      456832 :                         if (lateral && res)
    6159          34 :                                 res = query_pop_outer(query);
    6160      456832 :                         if (!fnd)
    6161             :                                 break;
    6162      456520 :                         if (res) {
    6163      149092 :                                 res = rel_crossproduct(sql->sa, res, fnd, op_join);
    6164      149092 :                                 if (lateral)
    6165          34 :                                         set_dependent(res);
    6166             :                         } else {
    6167             :                                 res = fnd;
    6168             :                         }
    6169             :                 }
    6170      307728 :                 if (!fnd) {
    6171         312 :                         if (res)
    6172          12 :                                 rel_destroy(res);
    6173         312 :                         return NULL;
    6174             :                 }
    6175       72936 :         } else if (!query_has_outer(query) || !res) {/* only on top level query */
    6176       72921 :                 return rel_select_exp(query, NULL, sn, ek);
    6177             :         }
    6178             : 
    6179      307416 :         sql_rel *rel = NULL;
    6180      307416 :         if (res)
    6181      307416 :                 rel = rel_select_exp(query, res, sn, ek);
    6182      307409 :         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       62576 : 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       62576 :         assert(op == op_munion);
    6297             : 
    6298       62576 :         mvc *sql = query->sql;
    6299       62576 :         sql_rel *rel;
    6300             : 
    6301       62576 :         if (outer && !cols)
    6302           0 :                         return sql_error(sql, 02, SQLSTATE(42000) "UNION: OUTER needs to be combined with CORRESPONDING [ BY ( column list ) ]");
    6303       62576 :         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       62555 :                 list *ls, *rs;
    6307             : 
    6308       62555 :                 l = rel_unique_names(sql, l);
    6309       62555 :                 r = rel_unique_names(sql, r);
    6310       62555 :                 ls = rel_projections(sql, l, NULL, 0, 1);
    6311       62555 :                 rs = rel_projections(sql, r, NULL, 0, 1);
    6312       62555 :                 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       62576 :         if (rel) {
    6318       62570 :                 rel_setop_n_ary_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 1), false);
    6319       62570 :                 set_processed(rel);
    6320             :         }
    6321             : 
    6322             :         return rel;
    6323             : 
    6324             : }
    6325             : 
    6326             : static sql_rel *
    6327       65073 : rel_setquery(sql_query *query, symbol *q)
    6328             : {
    6329       65073 :         mvc *sql = query->sql;
    6330       65073 :         sql_rel *res = NULL;
    6331       65073 :         dnode *n = q->data.lval->h;
    6332       65073 :         symbol *tab_ref1 = n->data.sym;
    6333       65073 :         int distinct = n->next->data.i_val;
    6334       65073 :         dlist *corresponding = n->next->next->data.lval;
    6335       65073 :         symbol *tab_ref2 = n->next->next->next->data.sym;
    6336       65073 :         sql_rel *t1, *t2;
    6337             : 
    6338       65073 :         assert(n->next->type == type_int);
    6339       65073 :         t1 = table_ref(query, tab_ref1, 0, NULL);
    6340       65073 :         if (!t1)
    6341             :                 return NULL;
    6342       65069 :         t2 = table_ref(query, tab_ref2, 0, NULL);
    6343       65069 :         if (!t2)
    6344             :                 return NULL;
    6345             : 
    6346       65061 :         rel_remove_internal_exp(t1);
    6347       65061 :         rel_remove_internal_exp(t2);
    6348       65061 :         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       65060 :         if ( q->token == SQL_UNION) {
    6361       62576 :                 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       62576 :                 if (t1 && distinct)
    6365        3505 :                         t1 = rel_distinct(t1);
    6366       62576 :                 if (t2 && distinct)
    6367        3505 :                         t2 = rel_distinct(t2);
    6368             :                 // TODO: this has to be fixed
    6369             :                 /*res = rel_setquery_(query, t1, t2, corresponding, op_union, outer);*/
    6370       62576 :                 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       65060 :         if (res) {
    6376       65051 :                 set_processed(res);
    6377       65051 :                 if (distinct)
    6378        5863 :                         res = rel_distinct(res);
    6379             :         }
    6380             :         return res;
    6381             : }
    6382             : 
    6383             : static sql_rel *
    6384       60065 : rel_joinquery_(sql_query *query, symbol *tab1, int natural, jt jointype, symbol *tab2, symbol *js, list *refs)
    6385             : {
    6386       60065 :         mvc *sql = query->sql;
    6387       60065 :         operator_type op = op_join;
    6388       60065 :         sql_rel *t1 = NULL, *t2 = NULL, *inner, *rel = NULL;
    6389       60065 :         int l_nil = 0, r_nil = 0, lateral = 0;
    6390             : 
    6391       60065 :         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       60065 :         lateral = (op == op_join || op == op_left) && check_is_lateral(tab2);
    6409       60065 :         t1 = table_ref(query, tab1, 0, refs);
    6410       60065 :         if (t1) {
    6411       60060 :                 if (!lateral) {
    6412       60025 :                         t2 = table_ref(query, tab2, 0, refs);
    6413             :                 } else {
    6414          35 :                         query_processed(query);
    6415          35 :                         query_push_outer(query, t1, sql_from);
    6416          35 :                         t2 = table_ref(query, tab2, 0, refs);
    6417          35 :                         t1 = query_pop_outer(query);
    6418             :                 }
    6419             :         }
    6420       60065 :         if (!t1 || !t2)
    6421             :                 return NULL;
    6422             : 
    6423       60044 :         query_processed(query);
    6424       60044 :         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       60044 :         inner = rel = rel_crossproduct(sql->sa, t1, t2, op);
    6429       60044 :         if (!rel)
    6430             :                 return NULL;
    6431       60044 :         if (lateral)
    6432          34 :                 set_dependent(rel);
    6433             : 
    6434       60044 :         assert(jointype != jt_cross || (!natural && !js)); /* there are no natural cross joins, or cross joins with conditions */
    6435       60044 :         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       60044 :         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       60044 :         if (js && js->token != SQL_USING) {  /* On sql_logical_exp */
    6441       59867 :                 rel = rel_logical_exp(query, rel, js, sql_where | sql_join);
    6442         177 :         } 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         153 :         } 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       60044 :         if (!rel)
    6519             :                 return NULL;
    6520       60027 :         if (inner && is_outerjoin(inner->op))
    6521       21134 :                 set_processed(inner);
    6522       60027 :         set_processed(rel);
    6523       60027 :         query_processed(query);
    6524       60027 :         return rel;
    6525             : }
    6526             : 
    6527             : static sql_rel *
    6528       60065 : rel_joinquery(sql_query *query, symbol *q, list *refs)
    6529             : {
    6530       60065 :         dnode *n = q->data.lval->h;
    6531       60065 :         symbol *tab_ref1 = n->data.sym;
    6532       60065 :         int natural = n->next->data.i_val;
    6533       60065 :         jt jointype = (jt) n->next->next->data.i_val;
    6534       60065 :         symbol *tab_ref2 = n->next->next->next->data.sym;
    6535       60065 :         symbol *joinspec = n->next->next->next->next->data.sym;
    6536             : 
    6537       60065 :         assert(n->next->type == type_int);
    6538       60065 :         assert(n->next->next->type == type_int);
    6539       60065 :         return rel_joinquery_(query, tab_ref1, natural, jointype, tab_ref2, joinspec, refs);
    6540             : }
    6541             : 
    6542             : sql_rel *
    6543      380640 : rel_subquery(sql_query *query, symbol *sq, exp_kind ek)
    6544             : {
    6545      380640 :         mvc *sql = query->sql;
    6546             : 
    6547      380640 :         query_processed(query);
    6548      380640 :         if (!stack_push_frame(sql, NULL))
    6549           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    6550      380702 :         sql_rel *rel = rel_query(query, sq, ek);
    6551      380647 :         stack_pop_frame(sql);
    6552      380715 :         if (!query_has_outer(query))
    6553      341717 :                 query_processed(query);
    6554      380700 :         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      241410 : rel_selects(sql_query *query, symbol *s)
    6561             : {
    6562      241410 :         mvc *sql = query->sql;
    6563      241410 :         sql_rel *ret = NULL;
    6564             : 
    6565      241410 :         switch (s->token) {
    6566        4522 :         case SQL_WITH:
    6567        4522 :                 ret = rel_with_query(query, s);
    6568        4522 :                 sql->type = Q_TABLE;
    6569        4522 :                 break;
    6570        2254 :         case SQL_VALUES:
    6571        2254 :                 ret = rel_values(query, s, NULL);
    6572        2253 :                 sql->type = Q_TABLE;
    6573        2253 :                 break;
    6574      213482 :         case SQL_SELECT: {
    6575      213482 :                 exp_kind ek = {type_value, card_relation, TRUE};
    6576      213482 :                 SelectNode *sn = (SelectNode *) s;
    6577             : 
    6578      213482 :                 if (sn->into) {
    6579           1 :                         sql->type = Q_SCHEMA;
    6580           1 :                         ret = rel_select_with_into(query, s);
    6581             :                 } else {
    6582      213481 :                         ret = rel_subquery(query, s, ek);
    6583      213541 :                         sql->type = Q_TABLE;
    6584             :                 }
    6585      213538 :         }       break;
    6586           0 :         case SQL_JOIN:
    6587           0 :                 ret = rel_joinquery(query, s, NULL);
    6588           0 :                 sql->type = Q_TABLE;
    6589           0 :                 break;
    6590       21152 :         case SQL_UNION:
    6591             :         case SQL_EXCEPT:
    6592             :         case SQL_INTERSECT:
    6593       21152 :                 ret = rel_setquery(query, s);
    6594       21152 :                 sql->type = Q_TABLE;
    6595       21152 :                 break;
    6596             :         default:
    6597             :                 return NULL;
    6598             :         }
    6599      241465 :         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       78507 : schema_selects(sql_query *query, sql_schema *schema, symbol *s)
    6606             : {
    6607       78507 :         mvc *sql = query->sql;
    6608       78507 :         sql_rel *res;
    6609       78507 :         sql_schema *os = cur_schema(sql);
    6610             : 
    6611       78507 :         sql->session->schema = schema;
    6612       78507 :         res = rel_selects(query, s);
    6613       78507 :         sql->session->schema = os;
    6614       78507 :         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