LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3744 4118 90.9 %
Date: 2024-04-25 20:03:45 Functions: 115 116 99.1 %

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

Generated by: LCOV version 1.14