LCOV - code coverage report
Current view: top level - sql/server - rel_select.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3735 4075 91.7 %
Date: 2024-11-13 22:44:48 Functions: 116 117 99.1 %

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

Generated by: LCOV version 1.14