LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3284 3582 91.7 %
Date: 2021-10-13 02:24:04 Functions: 111 112 99.1 %

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

Generated by: LCOV version 1.14