LCOV - code coverage report
Current view: top level - sql/backends/monet5 - rel_bin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3216 3526 91.2 %
Date: 2021-10-13 02:24:04 Functions: 112 115 97.4 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : 
      11             : #include "rel_bin.h"
      12             : #include "rel_rel.h"
      13             : #include "rel_basetable.h"
      14             : #include "rel_exp.h"
      15             : #include "rel_psm.h"
      16             : #include "rel_prop.h"
      17             : #include "rel_select.h"
      18             : #include "rel_updates.h"
      19             : #include "rel_unnest.h"
      20             : #include "rel_optimizer.h"
      21             : #include "rel_predicates.h"
      22             : #include "sql_env.h"
      23             : #include "sql_optimizer.h"
      24             : #include "sql_gencode.h"
      25             : #include "mal_builder.h"
      26             : #include "opt_prelude.h"
      27             : 
      28             : static stmt * exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, int reduce, int push);
      29             : static stmt * rel_bin(backend *be, sql_rel *rel);
      30             : static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
      31             : 
      32             : static stmt *check_types(backend *be, sql_subtype *fromtype, stmt *s, check_type tpe);
      33             : 
      34             : static void
      35       36180 : clean_mal_statements(backend *be, int oldstop, int oldvtop, int oldvid)
      36             : {
      37       36180 :         MSresetInstructions(be->mb, oldstop);
      38       36180 :         freeVariables(be->client, be->mb, NULL, oldvtop, oldvid);
      39       36180 : }
      40             : 
      41             : static int
      42         207 : add_to_rowcount_accumulator(backend *be, int nr)
      43             : {
      44         207 :         int prev = be->rowcount;
      45         207 :         InstrPtr q = newStmt(be->mb, calcRef, plusRef);
      46             : 
      47         207 :         getArg(q, 0) = be->rowcount = newTmpVariable(be->mb, TYPE_lng);
      48         207 :         q = pushArgument(be->mb, q, prev);
      49         207 :         q = pushArgument(be->mb, q, nr);
      50             : 
      51         207 :         return getDestVar(q);
      52             : }
      53             : 
      54             : static stmt *
      55       10844 : stmt_selectnil( backend *be, stmt *col)
      56             : {
      57       10844 :         sql_subtype *t = tail_type(col);
      58       10844 :         return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL)), cmp_equal, NULL, 0, 1);
      59             : }
      60             : 
      61             : static stmt *
      62        4059 : sql_unop_(backend *be, const char *fname, stmt *rs)
      63             : {
      64        4059 :         mvc *sql = be->mvc;
      65             :         sql_subtype *rt = NULL;
      66             :         sql_subfunc *f = NULL;
      67             : 
      68        4059 :         rt = tail_type(rs);
      69        4059 :         f = sql_bind_func(sql, "sys", fname, rt, NULL, F_FUNC);
      70             :         /* try to find the function without a type, and convert
      71             :          * the value to the type needed by this function!
      72             :          */
      73        4059 :         if (!f && (f = sql_find_func(sql, "sys", fname, 1, F_FUNC, NULL)) != NULL) {
      74           0 :                 sql_arg *a = f->func->ops->h->data;
      75             : 
      76           0 :                 sql->session->status = 0;
      77           0 :                 sql->errstr[0] = '\0';
      78           0 :                 rs = check_types(be, &a->type, rs, type_equal);
      79           0 :                 if (!rs)
      80             :                         f = NULL;
      81             :         }
      82        4059 :         if (f) {
      83             :                 /*
      84             :                 if (f->func->res.scale == INOUT) {
      85             :                         f->res.digits = rt->digits;
      86             :                         f->res.scale = rt->scale;
      87             :                 }
      88             :                 */
      89        4059 :                 return stmt_unop(be, rs, NULL, f);
      90           0 :         } else if (rs) {
      91           0 :                 char *type = tail_type(rs)->type->base.name;
      92             : 
      93           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such unary operator '%s(%s)'", fname, type);
      94             :         }
      95             :         return NULL;
      96             : }
      97             : 
      98             : static stmt *
      99             : refs_find_rel(list *refs, sql_rel *rel)
     100             : {
     101             :         node *n;
     102             : 
     103       46708 :         for(n=refs->h; n; n = n->next->next) {
     104       30204 :                 sql_rel *ref = n->data;
     105       30204 :                 stmt *s = n->next->data;
     106             : 
     107       30204 :                 if (rel == ref)
     108             :                         return s;
     109             :         }
     110             :         return NULL;
     111             : }
     112             : 
     113             : static void
     114             : refs_update_stmt(list *refs, sql_rel *rel, stmt *s)
     115             : {
     116             :         node *n;
     117             : 
     118       10481 :         for(n=refs->h; n; n = n->next->next) {
     119       10481 :                 sql_rel *ref = n->data;
     120             : 
     121       10481 :                 if (rel == ref) {
     122        7506 :                         n->next->data = s;
     123        7506 :                         break;
     124             :                 }
     125             :         }
     126             : }
     127             : 
     128             : 
     129             : static void
     130           0 : print_stmtlist(sql_allocator *sa, stmt *l)
     131             : {
     132             :         node *n;
     133           0 :         if (l) {
     134           0 :                 for (n = l->op4.lval->h; n; n = n->next) {
     135           0 :                         const char *rnme = table_name(sa, n->data);
     136           0 :                         const char *nme = column_name(sa, n->data);
     137             : 
     138           0 :                         TRC_INFO(SQL_EXECUTION, "%s.%s\n", rnme ? rnme : "(null!)", nme ? nme : "(null!)");
     139             :                 }
     140             :         }
     141           0 : }
     142             : 
     143             : static stmt *
     144     1397636 : list_find_column(backend *be, list *l, const char *rname, const char *name )
     145             : {
     146             :         stmt *res = NULL;
     147             :         node *n;
     148             : 
     149     1397636 :         if (!l)
     150             :                 return NULL;
     151     1397636 :         if (!l->ht && list_length(l) > HASH_MIN_SIZE) {
     152      205763 :                 l->ht = hash_new(l->sa, MAX(list_length(l), l->expected_cnt), (fkeyvalue)&stmt_key);
     153      205763 :                 if (l->ht == NULL)
     154             :                         return NULL;
     155             : 
     156     3506808 :                 for (n = l->h; n; n = n->next) {
     157     3301045 :                         const char *nme = column_name(be->mvc->sa, n->data);
     158     3301045 :                         if (nme) {
     159     3301045 :                                 int key = hash_key(nme);
     160             : 
     161     3301045 :                                 if (hash_add(l->ht, key, n->data) == NULL)
     162             :                                         return NULL;
     163             :                         }
     164             :                 }
     165             :         }
     166     1397636 :         if (l->ht) {
     167      969040 :                 int key = hash_key(name);
     168      969040 :                 sql_hash_e *e = l->ht->buckets[key&(l->ht->size-1)];
     169             : 
     170      969040 :                 if (rname) {
     171     1276739 :                         for (; e; e = e->chain) {
     172     1243297 :                                 stmt *s = e->value;
     173     1243297 :                                 const char *rnme = table_name(be->mvc->sa, s);
     174     1243297 :                                 const char *nme = column_name(be->mvc->sa, s);
     175             : 
     176     1243297 :                                 if (rnme && strcmp(rnme, rname) == 0 &&
     177     1008407 :                                     strcmp(nme, name) == 0) {
     178             :                                         res = s;
     179             :                                         break;
     180             :                                 }
     181             :                         }
     182             :                 } else {
     183       33281 :                         for (; e; e = e->chain) {
     184       32826 :                                 stmt *s = e->value;
     185       32826 :                                 const char *rnme = table_name(be->mvc->sa, s);
     186       32826 :                                 const char *nme = column_name(be->mvc->sa, s);
     187             : 
     188       32826 :                                 if (!rnme && nme && strcmp(nme, name) == 0) {
     189             :                                         res = s;
     190             :                                         break;
     191             :                                 }
     192             :                         }
     193             :                 }
     194      969040 :                 if (!res)
     195             :                         return NULL;
     196      935143 :                 return res;
     197             :         }
     198      428596 :         if (rname) {
     199      734232 :                 for (n = l->h; n; n = n->next) {
     200      702635 :                         const char *rnme = table_name(be->mvc->sa, n->data);
     201      702635 :                         const char *nme = column_name(be->mvc->sa, n->data);
     202             : 
     203      702635 :                         if (rnme && strcmp(rnme, rname) == 0 &&
     204      594235 :                                     strcmp(nme, name) == 0) {
     205      391275 :                                 res = n->data;
     206      391275 :                                 break;
     207             :                         }
     208             :                 }
     209             :         } else {
     210       11294 :                 for (n = l->h; n; n = n->next) {
     211        9332 :                         const char *rnme = table_name(be->mvc->sa, n->data);
     212        9332 :                         const char *nme = column_name(be->mvc->sa, n->data);
     213             : 
     214        9332 :                         if (!rnme && nme && strcmp(nme, name) == 0) {
     215        3762 :                                 res = n->data;
     216        3762 :                                 break;
     217             :                         }
     218             :                 }
     219             :         }
     220      428596 :         if (!res)
     221       33559 :                 return NULL;
     222             :         return res;
     223             : }
     224             : 
     225             : static stmt *
     226             : bin_find_column( backend *be, stmt *sub, const char *rname, const char *name )
     227             : {
     228     1358637 :         return list_find_column( be, sub->op4.lval, rname, name);
     229             : }
     230             : 
     231             : static list *
     232             : bin_find_columns( backend *be, stmt *sub, const char *name )
     233             : {
     234             :         node *n;
     235             :         list *l = sa_list(be->mvc->sa);
     236             : 
     237             :         for (n = sub->op4.lval->h; n; n = n->next) {
     238             :                 const char *nme = column_name(be->mvc->sa, n->data);
     239             : 
     240             :                 if (strcmp(nme, name) == 0)
     241             :                         append(l, n->data);
     242             :         }
     243             :         if (list_length(l))
     244             :                 return l;
     245             :         return NULL;
     246             : }
     247             : 
     248     2541657 : static stmt *column(backend *be, stmt *val )
     249             : {
     250     2541657 :         if (val->nrcols == 0)
     251        8843 :                 return const_column(be, val);
     252             :         return val;
     253             : }
     254             : 
     255      266334 : static stmt *create_const_column(backend *be, stmt *val )
     256             : {
     257      266334 :         if (val->nrcols == 0)
     258         298 :                 val = const_column(be, val);
     259      266334 :         return stmt_append(be, stmt_temp(be, tail_type(val)), val);
     260             : }
     261             : 
     262             : static int
     263      569403 : statment_score(stmt *c)
     264             : {
     265      569403 :         sql_subtype *t = tail_type(c);
     266             :         int score = 0;
     267             : 
     268      569403 :         if (c->nrcols != 0) /* no need to create an extra intermediate */
     269             :                 score += 200;
     270             : 
     271      569403 :         if (!t)
     272             :                 return score;
     273      569403 :         switch (ATOMstorage(t->type->localtype)) { /* give preference to smaller types */
     274       39780 :                 case TYPE_bte:
     275       39780 :                         score += 150 - 8;
     276       39780 :                         break;
     277       59417 :                 case TYPE_sht:
     278       59417 :                         score += 150 - 16;
     279       59417 :                         break;
     280      273002 :                 case TYPE_int:
     281      273002 :                         score += 150 - 32;
     282      273002 :                         break;
     283       36436 :                 case TYPE_void:
     284             :                 case TYPE_lng:
     285       36436 :                         score += 150 - 64;
     286       36436 :                         break;
     287        1866 :                 case TYPE_uuid:
     288             : #ifdef HAVE_HGE
     289             :                 case TYPE_hge:
     290             : #endif
     291        1866 :                         score += 150 - 128;
     292        1866 :                         break;
     293        2730 :                 case TYPE_flt:
     294        2730 :                         score += 75 - 24;
     295        2730 :                         break;
     296        5182 :                 case TYPE_dbl:
     297        5182 :                         score += 75 - 53;
     298        5182 :                         break;
     299             :                 default:
     300             :                         break;
     301             :         }
     302             :         return score;
     303             : }
     304             : 
     305             : static stmt *
     306      100348 : bin_find_smallest_column(backend *be, stmt *sub)
     307             : {
     308      100348 :         stmt *res = sub->op4.lval->h->data;
     309      100348 :         int best_score = statment_score(sub->op4.lval->h->data);
     310             : 
     311      100350 :         if (sub->op4.lval->h->next)
     312      548372 :                 for (node *n = sub->op4.lval->h->next ; n ; n = n->next) {
     313      469053 :                         stmt *c = n->data;
     314      469053 :                         int next_score = statment_score(c);
     315             : 
     316      469053 :                         if (next_score > best_score) {
     317             :                                 res = c;
     318             :                                 best_score = next_score;
     319             :                         }
     320             :                 }
     321      100350 :         if (res->nrcols == 0)
     322           3 :                 return const_column(be, res);
     323             :         return res;
     324             : }
     325             : 
     326             : static stmt *
     327      323864 : row2cols(backend *be, stmt *sub)
     328             : {
     329      323864 :         if (sub->nrcols == 0 && sub->key) {
     330             :                 node *n;
     331        3757 :                 list *l = sa_list(be->mvc->sa);
     332             : 
     333       11767 :                 for (n = sub->op4.lval->h; n; n = n->next) {
     334        8010 :                         stmt *sc = n->data;
     335        8010 :                         const char *cname = column_name(be->mvc->sa, sc);
     336        8010 :                         const char *tname = table_name(be->mvc->sa, sc);
     337             : 
     338        8010 :                         sc = column(be, sc);
     339        8010 :                         list_append(l, stmt_alias(be, sc, tname, cname));
     340             :                 }
     341        3757 :                 sub = stmt_list(be, l);
     342             :         }
     343      323864 :         return sub;
     344             : }
     345             : 
     346             : static stmt*
     347          65 : distinct_value_list(backend *be, list *vals, stmt **last_null_value, int depth, int push)
     348             : {
     349          65 :         list *l = sa_list(be->mvc->sa);
     350             :         stmt *s;
     351             : 
     352             :         /* create bat append values */
     353        1887 :         for (node *n = vals->h; n; n = n->next) {
     354        1822 :                 sql_exp *e = n->data;
     355        1822 :                 stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, depth, 0, push);
     356             : 
     357        1822 :                 if (exp_is_null(e))
     358           0 :                         *last_null_value = i;
     359             : 
     360        1822 :                 if (!i)
     361             :                         return NULL;
     362             : 
     363        1822 :                 list_append(l, i);
     364             :         }
     365          65 :         s = stmt_append_bulk(be, stmt_temp(be, exp_subtype(vals->h->data)), l);
     366             :         /* Probably faster to filter out the values directly in the underlying list of atoms.
     367             :            But for now use groupby to filter out duplicate values. */
     368          65 :         stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
     369          65 :         stmt* ext = stmt_result(be, groupby, 1);
     370             : 
     371          65 :         return stmt_project(be, ext, s);
     372             : }
     373             : 
     374             : static stmt *
     375        1872 : stmt_selectnonil( backend *be, stmt *col, stmt *s )
     376             : {
     377        1872 :         sql_subtype *t = tail_type(col);
     378        1872 :         return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL)), cmp_equal, s, 1, 1);
     379             : }
     380             : 
     381             : static int
     382       14203 : is_tid_chain(stmt *cand)
     383             : {
     384       18802 :         while(cand && cand->type != st_tid && cand->cand) {
     385             :                 cand = cand->cand;
     386             :         }
     387       14203 :         if (cand && cand->type == st_tid)
     388       12486 :                 return 1;
     389             :         return 0;
     390             : }
     391             : 
     392             : static stmt *
     393      912587 : subrel_project( backend *be, stmt *s, list *refs, sql_rel *rel)
     394             : {
     395      912587 :         if (!s || s->type != st_list || !s->cand)
     396             :                 return s;
     397             : 
     398      184479 :         list *l = sa_list(be->mvc->sa);
     399      184479 :         stmt *cand = s->cand;
     400      184479 :         if (!l)
     401             :                 return NULL;
     402      797337 :         for(node *n = s->op4.lval->h; n; n = n->next) {
     403      612858 :                 stmt *c = n->data;
     404             : 
     405      612858 :                 assert(c->type == st_alias || (c->type == st_join && c->flag == cmp_project) || c->type == st_bat || c->type == st_idxbat || c->type == st_single);
     406      612858 :                 if (c->type != st_alias) {
     407      564424 :                         c = stmt_project(be, cand, c);
     408       48434 :                 } else if (c->op1->type == st_mirror && is_tid_chain(cand)) { /* alias with mirror (ie full row ids) */
     409       12486 :                         c = stmt_alias(be, cand, c->tname, c->cname);
     410             :                 } else { /* st_alias */
     411             :                         stmt *s = c->op1;
     412       35948 :                         if (s->nrcols == 0)
     413           0 :                                 s = stmt_const(be, cand, s);
     414             :                         else
     415       35948 :                                 s = stmt_project(be, cand, s);
     416       35948 :                         c = stmt_alias(be, s, c->tname, c->cname);
     417             :                 }
     418      612858 :                 append(l, c);
     419             :         }
     420      184479 :         s = stmt_list(be, l);
     421      184479 :         if (rel && rel_is_ref(rel))
     422             :                 refs_update_stmt(refs, rel, s);
     423             :         return s;
     424             : }
     425             : 
     426             : static stmt *
     427       15524 : handle_in_exps(backend *be, sql_exp *ce, list *nl, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, bool in, int depth, int reduce, int push)
     428             : {
     429       15524 :         mvc *sql = be->mvc;
     430             :         node *n;
     431       15524 :         stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     432             : 
     433       15524 :         if(!c)
     434             :                 return NULL;
     435             : 
     436       15524 :         if (reduce && c->nrcols == 0)
     437          28 :                 c = stmt_const(be, bin_find_smallest_column(be, left), c);
     438             : 
     439       15524 :         if (c->nrcols == 0 || depth || !reduce) {
     440           2 :                 sql_subtype *bt = sql_bind_localtype("bit");
     441             :                 sql_subfunc *cmp = (in)
     442           2 :                         ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC)
     443           2 :                         :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC);
     444           2 :                 sql_subfunc *a = (in)?sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC)
     445           2 :                                      :sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC);
     446             : 
     447           6 :                 for( n = nl->h; n; n = n->next) {
     448           4 :                         sql_exp *e = n->data;
     449           4 :                         stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     450           4 :                         if(!i)
     451             :                                 return NULL;
     452             : 
     453           4 :                         i = stmt_binop(be, c, i, NULL, cmp);
     454           4 :                         if (s)
     455           2 :                                 s = stmt_binop(be, s, i, NULL, a);
     456             :                         else
     457             :                                 s = i;
     458             :                 }
     459           2 :                 if (sel && !(depth || !reduce))
     460           0 :                         s = stmt_uselect(be,
     461             :                                 stmt_const(be, bin_find_smallest_column(be, left), s),
     462             :                                 stmt_bool(be, 1), cmp_equal, sel, 0, 0);
     463       15522 :         } else if (list_length(nl) < 16) {
     464       15457 :                 comp_type cmp = (in)?cmp_equal:cmp_notequal;
     465             : 
     466       15457 :                 if (!in)
     467             :                         s = sel;
     468       85973 :                 for( n = nl->h; n; n = n->next) {
     469       70516 :                         sql_exp *e = n->data;
     470       70516 :                         stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     471       70516 :                         if(!i)
     472             :                                 return NULL;
     473             : 
     474       70516 :                         if (in) {
     475       48523 :                                 i = stmt_uselect(be, c, i, cmp, sel, 0, 0);
     476       48523 :                                 if (s)
     477       39447 :                                         s = stmt_tunion(be, s, i);
     478             :                                 else
     479             :                                         s = i;
     480             :                         } else {
     481       21993 :                                 s = stmt_uselect(be, c, i, cmp, s, 0, 0);
     482             :                         }
     483             :                 }
     484             :         } else {
     485             :                 /* TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
     486             :                    For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
     487             :                    make sure that this behavior is replicated by the sql optimizer and not handle_in_exps. */
     488             : 
     489          65 :                 stmt* last_null_value = NULL;  /* CORNER CASE ALERT: See description below. */
     490             : 
     491             :                 /* The actual in-value-list should not contain duplicates to ensure that final join results are unique. */
     492          65 :                 s = distinct_value_list(be, nl, &last_null_value, depth+1, push);
     493          65 :                 if (!s)
     494           0 :                         return NULL;
     495             : 
     496          65 :                 if (last_null_value) {
     497             :                         /* The actual in-value-list should not contain null values. */
     498           0 :                         s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
     499             :                 }
     500             : 
     501          65 :                 if (in) {
     502          65 :                         s = stmt_semijoin(be, c, s, sel, NULL, 0, false);
     503             :                 } else {
     504           0 :                         if (last_null_value) {
     505             :                                 /* CORNER CASE ALERT:
     506             :                                    In case of a not-in-expression with the associated in-value-list containing a null value,
     507             :                                    the entire in-predicate is forced to always return false, i.e. an empty candidate list.
     508             :                                    This is similar to postgres behavior.
     509             :                                    TODO: However I do not think this behavior is in accordance with SQL standard 2003.
     510             : 
     511             :                                    Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
     512             :                                    list* singleton_bat = sa_list(sql->sa);
     513             :                                    list_append(singleton_bat, null_value); */
     514           0 :                                 s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0, 0);
     515             :                         } else {
     516             :                                 /* BACK TO HAPPY FLOW:
     517             :                                    Make sure that null values are never returned. */
     518             :                                 stmt* non_nulls;
     519           0 :                                 non_nulls = stmt_selectnonil(be, c, sel);
     520           0 :                                 s = stmt_tdiff(be, stmt_project(be, non_nulls, c), s, NULL);
     521           0 :                                 s = stmt_project(be, s, non_nulls);
     522             :                         }
     523             :                 }
     524             :         }
     525             :         return s;
     526             : }
     527             : 
     528             : static stmt *
     529        7363 : value_list(backend *be, list *vals, stmt *left, stmt *sel)
     530             : {
     531        7363 :         sql_subtype *type = exp_subtype(vals->h->data);
     532             :         list *l;
     533             : 
     534        7363 :         if (!type)
     535           0 :                 return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
     536             :         /* create bat append values */
     537        7363 :         l = sa_list(be->mvc->sa);
     538      343937 :         for (node *n = vals->h; n; n = n->next) {
     539      336767 :                 sql_exp *e = n->data;
     540      336767 :                 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     541             : 
     542      336767 :                 if (!i)
     543             :                         return NULL;
     544             : 
     545      336767 :                 if (list_length(vals) == 1)
     546         193 :                         return i;
     547      336574 :                 list_append(l, i);
     548             :         }
     549        7170 :         return stmt_append_bulk(be, stmt_temp(be, type), l);
     550             : }
     551             : 
     552             : static stmt *
     553         259 : exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
     554             : {
     555         259 :         mvc *sql = be->mvc;
     556             :         node *n;
     557         259 :         list *nl = sa_list(sql->sa);
     558             : 
     559         570 :         for( n = exps->h; n; n = n->next) {
     560         311 :                 sql_exp *e = n->data;
     561         311 :                 stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0, 0);
     562         311 :                 if(!i)
     563             :                         return NULL;
     564             : 
     565         311 :                 if (n->next && i->type == st_table) /* relational statement */
     566           3 :                         l = i->op1;
     567             :                 else
     568         308 :                         append(nl, i);
     569             :         }
     570         259 :         return stmt_list(be, nl);
     571             : }
     572             : 
     573             : static stmt *
     574        1586 : exp_count_no_nil_arg( sql_exp *e, stmt *ext, sql_exp *ae, stmt *as )
     575             : {
     576             :         /* small optimization, ie use candidates directly on count(*) */
     577        1586 :         if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
     578             :                 /* skip alias statements */
     579        1683 :                 while (as->type == st_alias)
     580         301 :                         as = as->op1;
     581             :                 /* use candidate */
     582        1382 :                 if (as && as->type == st_join && as->flag == cmp_project) {
     583        1282 :                         if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
     584             :                                 as = as->op1;
     585             :                 }
     586             :         }
     587        1586 :         return as;
     588             : }
     589             : 
     590             : static stmt *
     591       14305 : exp_bin_or(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, bool reduce, int push)
     592             : {
     593       14305 :         sql_subtype *bt = sql_bind_localtype("bit");
     594       14305 :         list *l = e->l;
     595             :         node *n;
     596             :         stmt *sel1 = NULL, *sel2 = NULL, *s = NULL;
     597       14305 :         int anti = is_anti(e);
     598             : 
     599             :         sel1 = sel;
     600             :         sel2 = sel;
     601       30149 :         for( n = l->h; n; n = n->next ) {
     602       15844 :                 sql_exp *c = n->data;
     603       15844 :                 stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
     604             : 
     605             :                 /* propagate the anti flag */
     606       15844 :                 if (anti)
     607          55 :                         set_anti(c);
     608       15844 :                 s = exp_bin(be, c, left, right, grp, ext, cnt, sin, depth, reduce, push);
     609       15844 :                 if (!s)
     610             :                         return s;
     611             : 
     612       15844 :                 if (!sin && sel1 && sel1->nrcols == 0 && s->nrcols == 0) {
     613           0 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC);
     614           0 :                         assert(f);
     615           0 :                         s = stmt_binop(be, sel1, s, sin, f);
     616       15844 :                 } else if (sel1 && (sel1->nrcols == 0 || s->nrcols == 0)) {
     617           4 :                         stmt *predicate = bin_find_smallest_column(be, left);
     618             : 
     619           4 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
     620           4 :                         if (s->nrcols == 0)
     621           4 :                                 s = stmt_uselect(be, predicate, s, cmp_equal, sel1, anti, is_semantics(c));
     622             :                         else
     623           0 :                                 s = stmt_uselect(be, predicate, sel1, cmp_equal, s, anti, is_semantics(c));
     624             :                 }
     625             :                 sel1 = s;
     626             :         }
     627       14305 :         l = e->r;
     628       31008 :         for( n = l->h; n; n = n->next ) {
     629       16703 :                 sql_exp *c = n->data;
     630       16703 :                 stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
     631             : 
     632             :                 /* propagate the anti flag */
     633       16703 :                 if (anti)
     634          55 :                         set_anti(c);
     635       16703 :                 s = exp_bin(be, c, left, right, grp, ext, cnt, sin, depth, reduce, push);
     636       16703 :                 if (!s)
     637             :                         return s;
     638             : 
     639       16703 :                 if (!sin && sel2 && sel2->nrcols == 0 && s->nrcols == 0) {
     640           0 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC);
     641           0 :                         assert(f);
     642           0 :                         s = stmt_binop(be, sel2, s, sin, f);
     643       16703 :                 } else if (sel2 && (sel2->nrcols == 0 || s->nrcols == 0)) {
     644           6 :                         stmt *predicate = bin_find_smallest_column(be, left);
     645             : 
     646           6 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
     647           6 :                         if (s->nrcols == 0)
     648           6 :                                 s = stmt_uselect(be, predicate, s, cmp_equal, sel2, anti, 0);
     649             :                         else
     650           0 :                                 s = stmt_uselect(be, predicate, sel2, cmp_equal, s, anti, 0);
     651             :                 }
     652             :                 sel2 = s;
     653             :         }
     654       14305 :         if (sel1->nrcols == 0 && sel2->nrcols == 0) {
     655           0 :                 sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC);
     656           0 :                 assert(f);
     657           0 :                 return stmt_binop(be, sel1, sel2, NULL, f);
     658             :         }
     659       14305 :         if (sel1->nrcols == 0) {
     660           0 :                 stmt *predicate = bin_find_smallest_column(be, left);
     661             : 
     662           0 :                 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
     663           0 :                 sel1 = stmt_uselect(be, predicate, sel1, cmp_equal, NULL, 0/*anti*/, 0);
     664             :         }
     665       14305 :         if (sel2->nrcols == 0) {
     666          72 :                 stmt *predicate = bin_find_smallest_column(be, left);
     667             : 
     668          72 :                 predicate = stmt_const(be, predicate, stmt_bool(be, 1));
     669          72 :                 sel2 = stmt_uselect(be, predicate, sel2, cmp_equal, NULL, 0/*anti*/, 0);
     670             :         }
     671       14305 :         if (anti)
     672          55 :                 return stmt_project(be, stmt_tinter(be, sel1, sel2, false), sel1);
     673       14250 :         return stmt_tunion(be, sel1, sel2);
     674             : }
     675             : 
     676             : static stmt *
     677       13076 : exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
     678             : {
     679             :         stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
     680       13076 :         int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
     681             :         char name[16], *nme = NULL;
     682       13076 :         sql_subtype *bt = sql_bind_localtype("bit");
     683       13076 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC);
     684       13076 :         sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC);
     685       13076 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC);
     686             : 
     687       13076 :         if (single_value) {
     688             :                 /* var_x = nil; */
     689          86 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
     690          86 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
     691             :         }
     692             : 
     693       13076 :         list *exps = fe->l;
     694             : 
     695             :         /*
     696             :          * left - isel: calls down need id's from the range of left
     697             :          * res  - rsel: updates to res need id's in the range from res
     698             :          */
     699       57220 :         for (node *en = exps->h; en; en = en->next) {
     700       44144 :                 sql_exp *e = en->data;
     701             : 
     702       44144 :                 next_cond = next_cond && en->next; /* last else is only a value */
     703             : 
     704             :                 stmt *nsel = rsel;
     705       44144 :                 if (!single_value) {
     706       43776 :                         if (/*!next_cond &&*/ rsel && isel) {
     707             :                                 /* back into left range */
     708        6658 :                                 nsel = stmt_project(be, rsel, isel);
     709       37118 :                         } else if (isel && !rsel)
     710             :                                 nsel = isel;
     711             :                 }
     712       44144 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
     713             : 
     714       44144 :                 if (!es)
     715             :                         return NULL;
     716       44144 :                 if (!single_value) {
     717             :                         /* create result */
     718       43776 :                         if (!res) {
     719             :                                 stmt *l = isel;
     720       12990 :                                 if (!l)
     721        9678 :                                         l = bin_find_smallest_column(be, left);
     722       12990 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL)));
     723             :                                 ires = l;
     724       12990 :                                 if (res)
     725       12990 :                                         res->cand = isel;
     726       30786 :                         } else if (res && !next_cond) { /* use result to update column */
     727             :                                 stmt *val = es;
     728             :                                 stmt *pos = rsel;
     729             : 
     730       28383 :                                 if (val->nrcols == 0)
     731       12477 :                                         val = stmt_const(be, pos, val);
     732       15906 :                                 else if (!val->cand && nsel)
     733         300 :                                         val = stmt_project(be, nsel, val);
     734       28383 :                                 res = stmt_replace(be, res, pos, val);
     735             : 
     736       28383 :                                 assert(cond);
     737             : 
     738       28383 :                                 if (en->next) {
     739             :                                         /* osel - rsel */
     740       15393 :                                         if (!osel)
     741       12990 :                                                 osel = stmt_mirror(be, ires);
     742       15393 :                                         stmt *d = stmt_tdiff(be, osel, rsel, NULL);
     743       15393 :                                         osel = rsel = stmt_project(be, d, osel);
     744             :                                 }
     745             :                         }
     746       43776 :                         if (next_cond) {
     747             :                                 ncond = cond = es;
     748       15393 :                                 if (!ncond->nrcols) {
     749          65 :                                         if (osel) {
     750          22 :                                                 ncond = stmt_const(be, nsel, ncond);
     751          22 :                                                 ncond->cand = nsel;
     752          43 :                                         } else if (isel) {
     753           7 :                                                 ncond = stmt_const(be, isel, ncond);
     754           7 :                                                 ncond->cand = isel;
     755             :                                         } else
     756          36 :                                                 ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
     757             :                                 }
     758       15393 :                                 if (isel && !ncond->cand) {
     759          10 :                                         ncond = stmt_project(be, nsel, ncond);
     760          10 :                                         ncond->cand = nsel;
     761             :                                 }
     762       25079 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
     763       15393 :                                 if (rsel && ncond->cand)
     764        2395 :                                         rsel = stmt_project(be, s, rsel);
     765             :                                 else
     766             :                                         rsel = s;
     767             :                         }
     768             :                 } else {
     769         368 :                         if (!res) {
     770             :                                 /* if_barrier ... */
     771         141 :                                 assert(next_cond);
     772             :                                 if (next_cond) {
     773         141 :                                         if (cond) {
     774          55 :                                                 ncond = stmt_binop(be, cond, es, nsel, and);
     775             :                                         } else {
     776             :                                                 ncond = es;
     777             :                                         }
     778             :                                         cond = es;
     779             :                                 }
     780             :                         } else {
     781             :                                 /* var_x = s */
     782         227 :                                 (void)stmt_assign(be, NULL, nme, es, 2);
     783             :                                 /* endif_barrier */
     784         227 :                                 (void)stmt_control_end(be, res);
     785             :                                 res = NULL;
     786             : 
     787         227 :                                 if (en->next) {
     788         141 :                                         cond = stmt_unop(be, cond, nsel, not);
     789             : 
     790         141 :                                         sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC);
     791         141 :                                         cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
     792         141 :                                         if (ocond)
     793          55 :                                                 cond = stmt_binop(be, ocond, cond, nsel, and);
     794             :                                         ocond = cond;
     795         141 :                                         if (!en->next->next)
     796             :                                                 ncond = cond;
     797             :                                 }
     798             :                         }
     799         368 :                         if (ncond && (next_cond || (en->next && !en->next->next))) {
     800             :                                 /* if_barrier ... */
     801         227 :                                 res = stmt_cond(be, ncond, NULL, 0, 0);
     802             :                         }
     803             :                 }
     804       44144 :                 next_cond = !next_cond;
     805             :         }
     806       13076 :         if (single_value)
     807          86 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
     808             :         return res;
     809             : }
     810             : 
     811             : static stmt *
     812        1800 : exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
     813             : {
     814             :         stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
     815        1800 :         int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
     816             :         char name[16], *nme = NULL;
     817        1800 :         sql_subtype *bt = sql_bind_localtype("bit");
     818        1800 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC);
     819        1800 :         sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC);
     820        1800 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC);
     821             :         sql_subfunc *cmp;
     822             : 
     823        1800 :         if (single_value) {
     824             :                 /* var_x = nil; */
     825         205 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
     826         205 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
     827             :         }
     828             : 
     829        1800 :         list *exps = fe->l;
     830        1800 :         node *en = exps->h;
     831        1800 :         sql_exp *e = en->data;
     832             : 
     833        1800 :         stmt *nsel = !single_value?isel:NULL;
     834        1800 :         stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
     835        1800 :         if (!case_when)
     836             :                 return NULL;
     837        1800 :         cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e), exp_subtype(e), F_FUNC);
     838        1800 :         if (!cmp)
     839             :                 return NULL;
     840        1800 :         if (!single_value && !case_when->nrcols) {
     841             :                 stmt *l = isel;
     842          66 :                 if (!l)
     843          53 :                         l = bin_find_smallest_column(be, left);
     844          66 :                 case_when = stmt_const(be, l, case_when);
     845          66 :                 if (case_when)
     846          66 :                         case_when->cand = isel;
     847             :         }
     848        1800 :         if (!single_value && isel && !case_when->cand) {
     849          14 :                 case_when = stmt_project(be, isel, case_when);
     850          14 :                 case_when->cand = isel;
     851             :         }
     852             : 
     853             :         /*
     854             :          * left - isel: calls down need id's from the range of left
     855             :          * res  - rsel: updates to res need id's in the range from res
     856             :          */
     857       15638 :         for (en = en->next; en; en = en->next) {
     858       13838 :                 sql_exp *e = en->data;
     859             : 
     860       13838 :                 next_cond = next_cond && en->next; /* last else is only a value */
     861             : 
     862             :                 stmt *nsel = rsel;
     863       13838 :                 if (!single_value) {
     864       12687 :                         if (/*!next_cond &&*/ rsel && isel) {
     865             :                                 /* back into left range */
     866         170 :                                 nsel = stmt_project(be, rsel, isel);
     867       12517 :                         } else if (isel && !rsel)
     868             :                                 nsel = isel;
     869             :                 }
     870       13838 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
     871             : 
     872       13838 :                 if (!es)
     873             :                         return NULL;
     874       13838 :                 if (next_cond) {
     875             :                         stmt *l = case_when;
     876        6019 :                         if (!single_value) {
     877        5546 :                                 if (rsel && isel) {
     878          56 :                                         assert(l->cand == isel);
     879          56 :                                         l = stmt_project(be, rsel, l);
     880          56 :                                         l->cand = nsel;
     881             :                                 }
     882             : 
     883        5546 :                                 if (es->cand && !l->cand) {
     884        3179 :                                         assert(es->cand == rsel);
     885        3179 :                                         l = stmt_project(be, es->cand, l);
     886        3179 :                                         l->cand = es->cand;
     887        2367 :                                 } else if (nsel && !es->cand) {
     888         800 :                                         es = stmt_project(be, nsel, es);
     889         800 :                                         es->cand = nsel;
     890         800 :                                         if (!l->cand) {
     891         716 :                                                 l = stmt_project(be, nsel, l);
     892         716 :                                                 l->cand = nsel;
     893             :                                         }
     894             :                                 }
     895        5546 :                                 assert(l->cand == es->cand);
     896             :                         }
     897        6019 :                         es = stmt_binop(be, l, es, NULL, cmp);
     898             :                 }
     899       13838 :                 if (!single_value) {
     900             :                         /* create result */
     901       12687 :                         if (!res) {
     902             :                                 stmt *l = isel;
     903        1595 :                                 if (!l)
     904        1566 :                                         l = bin_find_smallest_column(be, left);
     905        1595 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL)));
     906             :                                 ires = l;
     907        1595 :                                 if (res)
     908        1595 :                                         res->cand = isel;
     909       11092 :                         } else if (res && !next_cond) { /* use result to update column */
     910             :                                 stmt *val = es;
     911             :                                 stmt *pos = rsel;
     912             : 
     913        7141 :                                 if (val->nrcols == 0)
     914        6948 :                                         val = stmt_const(be, pos, val);
     915         193 :                                 else if (!val->cand && nsel)
     916          50 :                                         val = stmt_project(be, nsel, val);
     917        7141 :                                 res = stmt_replace(be, res, pos, val);
     918             : 
     919        7141 :                                 assert(cond);
     920             : 
     921        7141 :                                 if (en->next) {
     922             :                                         /* osel - rsel */
     923        5546 :                                         if (!osel)
     924        1595 :                                                 osel = stmt_mirror(be, ires);
     925        5546 :                                         stmt *d = stmt_tdiff(be, osel, rsel, NULL);
     926        5546 :                                         osel = rsel = stmt_project(be, d, osel);
     927             :                                 }
     928             :                         }
     929       12687 :                         if (next_cond) {
     930             :                                 ncond = cond = es;
     931        5546 :                                 if (!ncond->nrcols) {
     932           0 :                                         if (osel) {
     933           0 :                                                 ncond = stmt_const(be, nsel, ncond);
     934           0 :                                                 ncond->cand = nsel;
     935           0 :                                         } else if (isel) {
     936           0 :                                                 ncond = stmt_const(be, isel, ncond);
     937           0 :                                                 ncond->cand = isel;
     938             :                                         } else
     939           0 :                                                 ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
     940             :                                 }
     941        5546 :                                 if (isel && !ncond->cand)
     942           0 :                                         ncond = stmt_project(be, nsel, ncond);
     943        7112 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
     944        5546 :                                 if (rsel && ncond->cand)
     945        3951 :                                         rsel = stmt_project(be, s, rsel);
     946             :                                 else
     947             :                                         rsel = s;
     948             :                         }
     949             :                 } else {
     950        1151 :                         if (!res) {
     951             :                                 /* if_barrier ... */
     952         473 :                                 assert(next_cond);
     953             :                                 if (next_cond) {
     954         473 :                                         if (cond) {
     955         268 :                                                 ncond = stmt_binop(be, cond, es, nsel, and);
     956             :                                         } else {
     957             :                                                 ncond = es;
     958             :                                         }
     959             :                                         cond = es;
     960             :                                 }
     961             :                         } else {
     962             :                                 /* var_x = s */
     963         678 :                                 (void)stmt_assign(be, NULL, nme, es, 2);
     964             :                                 /* endif_barrier */
     965         678 :                                 (void)stmt_control_end(be, res);
     966             :                                 res = NULL;
     967             : 
     968         678 :                                 if (en->next) {
     969         473 :                                         cond = stmt_unop(be, cond, nsel, not);
     970             : 
     971         473 :                                         sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC);
     972         473 :                                         cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
     973         473 :                                         if (ocond)
     974         268 :                                                 cond = stmt_binop(be, ocond, cond, nsel, and);
     975             :                                         ocond = cond;
     976         473 :                                         if (!en->next->next)
     977             :                                                 ncond = cond;
     978             :                                 }
     979             :                         }
     980        1151 :                         if (ncond && (next_cond || (en->next && !en->next->next))) {
     981             :                                 /* if_barrier ... */
     982         678 :                                 res = stmt_cond(be, ncond, NULL, 0, 0);
     983             :                         }
     984             :                 }
     985       13838 :                 next_cond = !next_cond;
     986             :         }
     987        1800 :         if (single_value)
     988         205 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
     989             :         return res;
     990             : }
     991             : 
     992             : static stmt*
     993         444 : exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
     994             : {
     995             :         stmt *res = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL;
     996         444 :         int single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
     997             :         char name[16], *nme = NULL;
     998         444 :         sql_subtype *bt = sql_bind_localtype("bit");
     999         444 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC);
    1000         444 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC);
    1001             : 
    1002         444 :         if (single_value) {
    1003             :                 /* var_x = nil; */
    1004          42 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
    1005          42 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
    1006             :         }
    1007             : 
    1008         444 :         list *exps = fe->l;
    1009        1789 :         for (node *en = exps->h; en; en = en->next) {
    1010        1345 :                 sql_exp *e = en->data;
    1011             : 
    1012             :                 stmt *nsel = rsel;
    1013        1345 :                 if (!single_value) {
    1014        1218 :                         if (/*!next_cond &&*/ rsel && isel) {
    1015             :                                 /* back into left range */
    1016          75 :                                 nsel = stmt_project(be, rsel, isel);
    1017        1143 :                         } else if (isel && !rsel)
    1018             :                                 nsel = isel;
    1019             :                 }
    1020        1345 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
    1021             : 
    1022        1345 :                 if (!es)
    1023             :                         return NULL;
    1024             :                 /* create result */
    1025        1345 :                 if (!single_value) {
    1026        1218 :                         if (!res) {
    1027             :                                 stmt *l = isel;
    1028         402 :                                 if (!l)
    1029         357 :                                         l = bin_find_smallest_column(be, left);
    1030         402 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL)));
    1031         402 :                                 if (res)
    1032         402 :                                         res->cand = isel;
    1033             :                         }
    1034        1218 :                         if (res) {
    1035             :                                 stmt *val = es;
    1036             :                                 stmt *pos = rsel;
    1037             : 
    1038        1218 :                                 if (en->next) {
    1039         816 :                                         sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC);
    1040         816 :                                         ncond = stmt_unop(be, es, NULL, a);
    1041         816 :                                         if (ncond->nrcols == 0) {
    1042         132 :                                                 stmt *l = bin_find_smallest_column(be, left);
    1043         132 :                                                 if (nsel && l)
    1044          76 :                                                         l = stmt_project(be, nsel, l);
    1045         132 :                                                 ncond = stmt_const(be, l, ncond);
    1046         132 :                                                 if (nsel)
    1047          76 :                                                         ncond->cand = nsel;
    1048         684 :                                         } else if (!ncond->cand && nsel)
    1049         351 :                                                 ncond = stmt_project(be, nsel, ncond);
    1050         816 :                                         stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0);
    1051         816 :                                         if (!val->cand && nsel)
    1052         427 :                                                 val = stmt_project(be, nsel, val);
    1053         816 :                                         val = stmt_project(be, s, val);
    1054         816 :                                         if (osel)
    1055         414 :                                                 rsel = stmt_project(be, s, osel);
    1056             :                                         else
    1057             :                                                 rsel = s;
    1058             :                                         pos = rsel;
    1059         816 :                                         val->cand = pos;
    1060             :                                 }
    1061        1218 :                                 if (val->nrcols == 0)
    1062         129 :                                         val = stmt_const(be, pos, val);
    1063        1089 :                                 else if (!val->cand && nsel)
    1064         157 :                                         val = stmt_project(be, nsel, val);
    1065             : 
    1066        1218 :                                 res = stmt_replace(be, res, pos, val);
    1067             :                         }
    1068        1218 :                         if (en->next) { /* handled then part */
    1069         816 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0);
    1070         816 :                                 if (osel)
    1071         414 :                                         rsel = stmt_project(be, s, osel);
    1072             :                                 else
    1073             :                                         rsel = s;
    1074             :                                 osel = rsel;
    1075             :                         }
    1076             :                 } else {
    1077             :                         stmt *cond = ocond;
    1078         127 :                         if (en->next) {
    1079          85 :                                 sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC);
    1080          85 :                                 ncond = stmt_unop(be, es, nsel, a);
    1081             : 
    1082          85 :                                 if (ocond)
    1083          43 :                                         cond = stmt_binop(be, ocond, ncond, nsel, and);
    1084             :                                 else
    1085             :                                         cond = ncond;
    1086             :                         }
    1087             : 
    1088             :                         /* if_barrier ... */
    1089         127 :                         stmt *b = stmt_cond(be, cond, NULL, 0, 0);
    1090             :                         /* var_x = s */
    1091         127 :                         (void)stmt_assign(be, NULL, nme, es, 2);
    1092             :                         /* endif_barrier */
    1093         127 :                         (void)stmt_control_end(be, b);
    1094             : 
    1095         127 :                         cond = stmt_unop(be, ncond, nsel, not);
    1096         127 :                         if (ocond)
    1097          85 :                                 ocond = stmt_binop(be, cond, ocond, nsel, and);
    1098             :                         else
    1099             :                                 ocond = cond;
    1100             :                 }
    1101             :         }
    1102         444 :         if (single_value)
    1103          42 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
    1104             :         return res;
    1105             : }
    1106             : 
    1107             : stmt *
    1108     4087610 : exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt *ext, stmt *cnt, stmt *sel, int depth, int reduce, int push)
    1109             : {
    1110     4087610 :         mvc *sql = be->mvc;
    1111             :         stmt *s = NULL;
    1112             : 
    1113     4087610 :         if (THRhighwater())
    1114           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1115             : 
    1116     4087610 :         if (!e) {
    1117           0 :                 assert(0);
    1118             :                 return NULL;
    1119             :         }
    1120             : 
    1121     4087610 :         switch(e->type) {
    1122        5557 :         case e_psm:
    1123        5557 :                 if (e->flag & PSM_SET) {
    1124         577 :                         stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1125         577 :                         if(!r)
    1126             :                                 return NULL;
    1127         577 :                         if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
    1128           2 :                                 r = stmt_fetch(be, r);
    1129         577 :                         return stmt_assign(be, exp_relname(e), exp_name(e), r, GET_PSM_LEVEL(e->flag));
    1130        4980 :                 } else if (e->flag & PSM_VAR) {
    1131         142 :                         if (e->f)
    1132          20 :                                 return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
    1133             :                         else
    1134         122 :                                 return stmt_var(be, exp_relname(e), exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
    1135        4838 :                 } else if (e->flag & PSM_RETURN) {
    1136         591 :                         sql_exp *l = e->l;
    1137         591 :                         stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1138             : 
    1139         591 :                         if (!r)
    1140             :                                 return NULL;
    1141             :                         /* handle table returning functions */
    1142         591 :                         if (l->type == e_psm && l->flag & PSM_REL) {
    1143         203 :                                 stmt *lst = r->op1;
    1144         245 :                                 if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
    1145             :                                         node *n;
    1146          42 :                                         list *l = sa_list(sql->sa);
    1147             : 
    1148          89 :                                         for(n=lst->op4.lval->h; n; n = n->next)
    1149          47 :                                                 list_append(l, const_column(be, (stmt*)n->data));
    1150          42 :                                         r = stmt_list(be, l);
    1151         161 :                                 } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */
    1152          26 :                                         sql_rel *ll = (sql_rel*) l->l;
    1153          26 :                                         r = lst->op4.lval->h->data;
    1154          26 :                                         if (!r->aggr && lastexp(ll)->card > CARD_ATOM) /* if the cardinality is atom, no fetch call needed */
    1155           0 :                                                 r = stmt_fetch(be, r);
    1156             :                                 }
    1157         203 :                                 if (r->type == st_list)
    1158          42 :                                         r = stmt_table(be, r, 1);
    1159             :                         }
    1160         591 :                         return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
    1161        4247 :                 } else if (e->flag & PSM_WHILE) {
    1162             :                         /* while is a if - block true with leave statement
    1163             :                          * needed because the condition needs to be inside this outer block */
    1164          13 :                         stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
    1165          13 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1166             :                         stmt *wstmt;
    1167             : 
    1168          13 :                         if(!cond)
    1169             :                                 return NULL;
    1170          13 :                         wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
    1171             : 
    1172          13 :                         if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
    1173             :                                 return NULL;
    1174          13 :                         (void)stmt_control_end(be, wstmt);
    1175          13 :                         return stmt_control_end(be, ifstmt);
    1176        4234 :                 } else if (e->flag & PSM_IF) {
    1177         225 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1178             :                         stmt *ifstmt, *res;
    1179             : 
    1180         225 :                         if(!cond)
    1181             :                                 return NULL;
    1182         225 :                         ifstmt = stmt_cond(be, cond, NULL, 0, 0);
    1183         225 :                         if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
    1184             :                                 return NULL;
    1185         225 :                         res = stmt_control_end(be, ifstmt);
    1186         225 :                         if (e->f) {
    1187          21 :                                 stmt *elsestmt = stmt_cond(be, cond, NULL, 0, 1);
    1188             : 
    1189          21 :                                 if (!exp_list(be, e->f, left, right, grp, ext, cnt, sel))
    1190             :                                         return NULL;
    1191          21 :                                 res = stmt_control_end(be, elsestmt);
    1192             :                         }
    1193         225 :                         return res;
    1194        4009 :                 } else if (e->flag & PSM_REL) {
    1195        3609 :                         sql_rel *rel = e->l;
    1196        3609 :                         stmt *r = rel_bin(be, rel);
    1197             : 
    1198        3609 :                         if (!r)
    1199             :                                 return NULL;
    1200         469 :                         if (is_modify(rel->op) || is_ddl(rel->op))
    1201             :                                 return r;
    1202         297 :                         return stmt_table(be, r, 1);
    1203         400 :                 } else if (e->flag & PSM_EXCEPTION) {
    1204         400 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1205         400 :                         if (!cond)
    1206             :                                 return NULL;
    1207         400 :                         return stmt_exception(be, cond, (const char *) e->r, 0);
    1208             :                 }
    1209             :                 break;
    1210     2204012 :         case e_atom: {
    1211     2204012 :                 if (e->l) {                  /* literals */
    1212             :                         atom *a = e->l;
    1213     2193792 :                         s = stmt_atom(be, atom_dup(sql->sa, a));
    1214       10220 :                 } else if (e->r) {           /* parameters and declared variables */
    1215             :                         sql_var_name *vname = (sql_var_name*) e->r;
    1216        2334 :                         assert(vname->name);
    1217        2334 :                         s = stmt_var(be, vname->sname ? sa_strdup(sql->sa, vname->sname) : NULL, sa_strdup(sql->sa, vname->name), e->tpe.type?&e->tpe:NULL, 0, e->flag);
    1218        7886 :                 } else if (e->f) {           /* values */
    1219        7363 :                         s = value_list(be, e->f, left, sel);
    1220             :                 } else {                        /* arguments */
    1221         523 :                         s = stmt_varnr(be, e->flag, e->tpe.type?&e->tpe:NULL);
    1222             :                 }
    1223             :         }       break;
    1224      153392 :         case e_convert: {
    1225             :                 /* if input is type any NULL or column of nulls, change type */
    1226      153392 :                 list *tps = e->r;
    1227      153392 :                 sql_subtype *from = tps->h->data;
    1228      153392 :                 sql_subtype *to = tps->h->next->data;
    1229             :                 stmt *l;
    1230             : 
    1231      153392 :                 if (from->type->localtype == 0) {
    1232         555 :                         l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
    1233         555 :                         if (l)
    1234         554 :                                 l = stmt_atom(be, atom_general(sql->sa, to, NULL));
    1235             :                 } else {
    1236      152837 :                         l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
    1237             :                 }
    1238      153392 :                 if (!l)
    1239             :                         return NULL;
    1240      162846 :                 s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, from, to);
    1241      151457 :         }       break;
    1242      161037 :         case e_func: {
    1243             :                 node *en;
    1244      161037 :                 list *l = sa_list(sql->sa), *exps = e->l;
    1245      161037 :                 sql_subfunc *f = e->f;
    1246             :                 stmt *rows = NULL;
    1247      161037 :                 int push_cands = can_push_cands(sel, f);
    1248             : 
    1249      161037 :                 if (f->func->side_effect && left && left->nrcols > 0) {
    1250             :                         sql_subfunc *f1 = NULL;
    1251             :                         /* we cannot assume all SQL functions with no arguments have a correspondent with one argument, so attempt to find it. 'rand' function is the exception */
    1252         111 :                         if (list_empty(exps) && (strcmp(f->func->base.name, "rand") == 0 || (f1 = sql_find_func(sql, f->func->s ? f->func->s->base.name : NULL, f->func->base.name, 1, f->func->type, NULL)))) {
    1253             :                                 if (f1)
    1254             :                                         f = f1;
    1255          26 :                                 list_append(l, stmt_const(be, bin_find_smallest_column(be, left),
    1256          13 :                                                                                   stmt_atom(be, atom_general(sql->sa, f1 ? &(((sql_arg*)f1->func->ops->h->data)->type) : sql_bind_localtype("int"), NULL))));
    1257          98 :                         } else if (exps_card(exps) < CARD_MULTI) {
    1258          82 :                                 rows = bin_find_smallest_column(be, left);
    1259             :                         }
    1260         111 :                         sql->session->status = 0; /* if the function was not found clean the error */
    1261         111 :                         sql->errstr[0] = '\0';
    1262             :                 }
    1263      161037 :                 assert(!e->r);
    1264      161037 :                 if (strcmp(sql_func_mod(f->func), "") == 0 && strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "star") == 0)
    1265         373 :                         return left->op4.lval->h->data;
    1266      160664 :                 else if (!list_empty(exps)) {
    1267             :                         unsigned nrcols = 0;
    1268             : 
    1269      155141 :                         if (strcmp(sql_func_mod(f->func), "") == 0 && strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "case") == 0)
    1270       13076 :                                 return exp2bin_case(be, e, left, right, sel, depth);
    1271      142065 :                         if (strcmp(sql_func_mod(f->func), "") == 0 && strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "casewhen") == 0)
    1272        1800 :                                 return exp2bin_casewhen(be, e, left, right, sel, depth);
    1273      140265 :                         if (strcmp(sql_func_mod(f->func), "") == 0 && strcmp(sql_func_imp(f->func), "") == 0 && strcmp(f->func->base.name, "coalesce") == 0)
    1274         444 :                                 return exp2bin_coalesce(be, e, left, right, sel, depth);
    1275             : 
    1276      139821 :                         assert(list_length(exps) == list_length(f->func->ops) || f->func->type == F_ANALYTIC || f->func->type == F_LOADER || f->func->vararg || f->func->varres);
    1277      398746 :                         for (en = exps->h; en; en = en->next) {
    1278      272553 :                                 sql_exp *e = en->data;
    1279      500731 :                                 stmt *es = exp_bin(be, e, left, right, grp, ext, cnt, (push_cands)?sel:NULL, depth+1, 0, push);
    1280             : 
    1281      272553 :                                 if (!es)
    1282             :                                         return NULL;
    1283      258925 :                                 if (rows && en == exps->h && f->func->type != F_LOADER)
    1284          76 :                                         es = stmt_const(be, rows, es);
    1285      258849 :                                 else if (f->func->type == F_ANALYTIC && es->nrcols == 0) {
    1286        7442 :                                         if (en == exps->h && left->nrcols)
    1287         226 :                                                 es = stmt_const(be, bin_find_smallest_column(be, left), es); /* ensure the first argument is a column */
    1288        7442 :                                         if (!f->func->s && !strcmp(f->func->base.name, "window_bound")
    1289        3365 :                                                 && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next && left->nrcols)
    1290          30 :                                                 es = stmt_const(be, bin_find_smallest_column(be, left), es);
    1291             :                                 }
    1292             :                                 if (es->nrcols > nrcols)
    1293             :                                         nrcols = es->nrcols;
    1294      258925 :                                 list_append(l, es);
    1295             :                         }
    1296             :                 }
    1297      131716 :                 if (!(s = stmt_Nop(be, stmt_list(be, l), sel, f)))
    1298           2 :                         return NULL;
    1299             :         }       break;
    1300       12221 :         case e_aggr: {
    1301       12221 :                 list *attr = e->l;
    1302             :                 stmt *as = NULL;
    1303       12221 :                 sql_subfunc *a = e->f;
    1304             : 
    1305       12221 :                 assert(sel == NULL);
    1306       18669 :                 if (attr && attr->h) {
    1307             :                         node *en;
    1308        6449 :                         list *l = sa_list(sql->sa);
    1309             : 
    1310       13550 :                         for (en = attr->h; en; en = en->next) {
    1311        7102 :                                 sql_exp *at = en->data;
    1312             : 
    1313        7102 :                                 as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
    1314             : 
    1315        7102 :                                 if (as && as->nrcols <= 0 && left)
    1316         239 :                                         as = stmt_const(be, bin_find_smallest_column(be, left), as);
    1317        7102 :                                 if (en == attr->h && !en->next && exp_aggr_is_count(e))
    1318         204 :                                         as = exp_count_no_nil_arg(e, ext, at, as);
    1319             :                                 /* insert single value into a column */
    1320        7102 :                                 if (as && as->nrcols <= 0 && !left)
    1321           3 :                                         as = const_column(be, as);
    1322             : 
    1323        7102 :                                 if (!as)
    1324             :                                         return NULL;
    1325        7101 :                                 append(l, as);
    1326             :                         }
    1327        6448 :                         if (need_distinct(e) && (grp || list_length(l) > 1)){
    1328          49 :                                 list *nl = sa_list(sql->sa);
    1329             :                                 stmt *ngrp = grp;
    1330             :                                 stmt *next = ext;
    1331             :                                 stmt *ncnt = cnt;
    1332         100 :                                 for (en = l->h; en; en = en->next) {
    1333          51 :                                         stmt *as = en->data;
    1334          51 :                                         stmt *g = stmt_group(be, as, ngrp, next, ncnt, 1);
    1335          51 :                                         ngrp = stmt_result(be, g, 0);
    1336          51 :                                         next = stmt_result(be, g, 1);
    1337          51 :                                         ncnt = stmt_result(be, g, 2);
    1338             :                                 }
    1339         100 :                                 for (en = l->h; en; en = en->next) {
    1340          51 :                                         stmt *as = en->data;
    1341          51 :                                         append(nl, stmt_project(be, next, as));
    1342             :                                 }
    1343          49 :                                 if (grp)
    1344          48 :                                         grp = stmt_project(be, next, grp);
    1345             :                                 l = nl;
    1346        6399 :                         } else if (need_distinct(e)) {
    1347          65 :                                 stmt *a = l->h->data;
    1348          65 :                                 stmt *u = stmt_unique(be, a);
    1349          65 :                                 l = sa_list(sql->sa);
    1350          65 :                                 append(l, stmt_project(be, u, a));
    1351             :                         }
    1352        6448 :                         as = stmt_list(be, l);
    1353             :                 } else {
    1354             :                         /* count(*) may need the default group (relation) and
    1355             :                            and/or an attribute to count */
    1356        5772 :                         if (grp) {
    1357             :                                 as = grp;
    1358        1380 :                         } else if (left) {
    1359        1380 :                                 as = bin_find_smallest_column(be, left);
    1360        1382 :                                 as = exp_count_no_nil_arg(e, ext, NULL, as);
    1361             :                         } else {
    1362             :                                 /* create dummy single value in a column */
    1363           0 :                                 as = stmt_atom_lng(be, 0);
    1364           0 :                                 as = const_column(be, as);
    1365             :                         }
    1366             :                 }
    1367       12221 :                 s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e) );
    1368       12220 :                 if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
    1369           0 :                         s->flag |= OUTER_ZERO;
    1370             :         }       break;
    1371     1318089 :         case e_column: {
    1372     1318089 :                 if (right) /* check relation names */
    1373       66589 :                         s = bin_find_column(be, right, e->l, e->r);
    1374     1318089 :                 if (!s && left)
    1375     1262301 :                         s = bin_find_column(be, left, e->l, e->r);
    1376     1318089 :                 if (s && grp)
    1377        1686 :                         s = stmt_project(be, ext, s);
    1378     1318089 :                 if (!s && right) {
    1379           0 :                         TRC_CRITICAL(SQL_EXECUTION, "Could not find %s.%s\n", (char*)e->l, (char*)e->r);
    1380           0 :                         print_stmtlist(sql->sa, left);
    1381           0 :                         print_stmtlist(sql->sa, right);
    1382             :                         if (!s) {
    1383           0 :                                 TRC_ERROR(SQL_EXECUTION, "Query: '%s'\n", be->client->query);
    1384             :                         }
    1385           0 :                         assert(s);
    1386             :                         return NULL;
    1387             :                 }
    1388             :         }       break;
    1389      233302 :         case e_cmp: {
    1390             :                 stmt *l = NULL, *r = NULL, *r2 = NULL;
    1391             :                 int swapped = 0, is_select = 0, oldvtop, oldstop, oldvid;
    1392      233302 :                 sql_exp *re = e->r, *re2 = e->f;
    1393             : 
    1394             :                 /* general predicate, select and join */
    1395      233302 :                 if (e->flag == cmp_filter) {
    1396             :                         list *args;
    1397             :                         list *ops;
    1398             :                         node *n;
    1399             :                         int first = 1;
    1400             : 
    1401         443 :                         ops = sa_list(sql->sa);
    1402         443 :                         args = e->l;
    1403         886 :                         for( n = args->h; n; n = n->next ) {
    1404         443 :                                 oldvtop = be->mb->vtop;
    1405         443 :                                 oldstop = be->mb->stop;
    1406         443 :                                 oldvid = be->mb->vid;
    1407             :                                 s = NULL;
    1408         443 :                                 if (!swapped)
    1409         443 :                                         s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    1410         443 :                                 if (!s && (first || swapped)) {
    1411           4 :                                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    1412           4 :                                         s = exp_bin(be, n->data, right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    1413             :                                         swapped = 1;
    1414             :                                 }
    1415         443 :                                 if (!s)
    1416             :                                         return s;
    1417         443 :                                 if (s->nrcols == 0 && first)
    1418          67 :                                         s = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), s);
    1419         443 :                                 list_append(ops, s);
    1420             :                                 first = 0;
    1421             :                         }
    1422         443 :                         l = stmt_list(be, ops);
    1423         443 :                         ops = sa_list(sql->sa);
    1424         443 :                         args = e->r;
    1425        1772 :                         for( n = args->h; n; n = n->next ) {
    1426        1377 :                                 s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    1427        1329 :                                 if (!s)
    1428             :                                         return s;
    1429        1329 :                                 list_append(ops, s);
    1430             :                         }
    1431         443 :                         r = stmt_list(be, ops);
    1432             : 
    1433         443 :                         if (left && right && (exps_card(e->r) != CARD_ATOM || !exps_are_atoms(e->r))) {
    1434          20 :                                 sql_subfunc *f = e->f;
    1435          40 :                                 for (node *n = l->op4.lval->h ; n ; n = n->next)
    1436          20 :                                         n->data = column(be, n->data);
    1437          80 :                                 for (node *n = r->op4.lval->h ; n ; n = n->next)
    1438          60 :                                         n->data = column(be, n->data);
    1439          20 :                                 return stmt_genjoin(be, l, r, f, is_anti(e), swapped);
    1440             :                         }
    1441         423 :                         assert(!swapped);
    1442         423 :                         s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
    1443         423 :                         return s;
    1444             :                 }
    1445      232859 :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    1446       15524 :                         return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), depth, reduce, push);
    1447      217335 :                 if (e->flag == cmp_or && (!right || right->nrcols == 1))
    1448       14305 :                         return exp_bin_or(be, e, left, right, grp, ext, cnt, sel, depth, reduce, push);
    1449      203030 :                 if (e->flag == cmp_or && right) {  /* join */
    1450           0 :                         assert(0);
    1451             :                 }
    1452             : 
    1453             :                 /* mark use of join indices */
    1454      203030 :                 if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
    1455         653 :                         be->join_idx++;
    1456             : 
    1457      203030 :                 oldvtop = be->mb->vtop;
    1458      203030 :                 oldstop = be->mb->stop;
    1459      203030 :                 oldvid = be->mb->vid;
    1460             :                 if (!l) {
    1461      405842 :                         l = exp_bin(be, e->l, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1462             :                         swapped = 0;
    1463             :                 }
    1464      203030 :                 if (!l && right) {
    1465       21088 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    1466       21088 :                         l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1467             :                         swapped = 1;
    1468             :                 }
    1469             : 
    1470      203030 :                 oldvtop = be->mb->vtop;
    1471      203030 :                 oldstop = be->mb->stop;
    1472      203030 :                 oldvid = be->mb->vid;
    1473      203030 :                 if (swapped || !right || !reduce)
    1474      120528 :                         r = exp_bin(be, re, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1475             :                 else
    1476       82502 :                         r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1477      203030 :                 if (!r && !swapped) {
    1478           0 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    1479           0 :                         r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1480             :                         is_select = 1;
    1481             :                 }
    1482      203030 :                 if (!r && swapped) {
    1483           0 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    1484           0 :                         r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1485             :                         is_select = 1;
    1486             :                 }
    1487      203030 :                 if (re2 && (swapped || !right || !reduce))
    1488        5079 :                         r2 = exp_bin(be, re2, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1489      197951 :                 else if (re2)
    1490          58 :                         r2 = exp_bin(be, re2, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    1491             : 
    1492      203030 :                 if (!l || !r || (re2 && !r2))
    1493             :                         return NULL;
    1494             : 
    1495             :                 (void)is_select;
    1496      203030 :                 if (reduce && left && right) {
    1497      103590 :                         if (l->nrcols == 0)
    1498           0 :                                 l = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), l);
    1499      103590 :                         if (r->nrcols == 0)
    1500           6 :                                 r = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r);
    1501      103590 :                         if (r2 && r2->nrcols == 0)
    1502           6 :                                 r2 = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r2);
    1503      103590 :                         if (r2) {
    1504          59 :                                 s = stmt_join2(be, l, r, r2, (comp_type)e->flag, is_anti(e), is_symmetric(e), swapped);
    1505      103531 :                         } else if (swapped) {
    1506       21087 :                                 s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag), 0, is_semantics(e), false);
    1507             :                         } else {
    1508       82444 :                                 s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag, 0, is_semantics(e), false);
    1509             :                         }
    1510             :                 } else {
    1511       99440 :                         if (r2) { /* handle all cases in stmt_uselect, reducing, non reducing, scalar etc */
    1512        5078 :                                 if (l->nrcols == 0 && ((sel && sel->nrcols > 0) || r->nrcols > 0 || r2->nrcols > 0 || reduce))
    1513          53 :                                         l = left ? stmt_const(be, bin_find_smallest_column(be, left), l) : column(be, l);
    1514        5078 :                                 s = stmt_uselect2(be, l, r, r2, (comp_type)e->flag, sel, is_anti(e), is_symmetric(e), reduce);
    1515             :                         } else {
    1516             :                                 /* value compare or select */
    1517       94362 :                                 if ((!reduce || (l->nrcols == 0 && r->nrcols == 0)) && (e->flag == mark_in || e->flag == mark_notin)) {
    1518           7 :                                         int in_flag = e->flag==mark_in?1:0;
    1519           7 :                                         if (is_anti(e))
    1520           0 :                                                 in_flag = !in_flag;
    1521           7 :                                         sql_subfunc *f = sql_bind_func(sql, "sys", in_flag?"=":"<>", tail_type(l), tail_type(l), F_FUNC);
    1522           7 :                                         assert(f);
    1523           7 :                                         s = stmt_binop(be, l, r, sel, f);
    1524           7 :                                         if (l->cand)
    1525           0 :                                                 s->cand = l->cand;
    1526           7 :                                         if (r->cand)
    1527           0 :                                                 s->cand = r->cand;
    1528       94355 :                                 } else if (!reduce || (l->nrcols == 0 && r->nrcols == 0)) {
    1529         594 :                                         sql_subfunc *f = sql_bind_func(sql, "sys", compare_func((comp_type)e->flag, is_anti(e)),
    1530             :                                                                                                    tail_type(l), tail_type(l), F_FUNC);
    1531         594 :                                         assert(f);
    1532         594 :                                         if (is_semantics(e)) {
    1533          71 :                                                 if (exp_is_null(e->l) && exp_is_null(e->r)) {
    1534           0 :                                                         s = stmt_bool(be, !is_anti(e));
    1535             :                                                 } else {
    1536          71 :                                                         list *args = sa_list(sql->sa);
    1537             :                                                         /* add nil semantics bit */
    1538          71 :                                                         list_append(args, l);
    1539          71 :                                                         list_append(args, r);
    1540          71 :                                                         list_append(args, stmt_bool(be, 1));
    1541          71 :                                                         s = stmt_Nop(be, stmt_list(be, args), sel, f);
    1542             :                                                 }
    1543             :                                         } else {
    1544         523 :                                                 s = stmt_binop(be, l, r, sel, f);
    1545             :                                         }
    1546         594 :                                         if (l->cand)
    1547           0 :                                                 s->cand = l->cand;
    1548         594 :                                         if (r->cand)
    1549           0 :                                                 s->cand = r->cand;
    1550             :                                 } else {
    1551             :                                         /* this can still be a join (as relational algebra and single value subquery results still means joins */
    1552       93761 :                                         s = stmt_uselect(be, l, r, (comp_type)e->flag, sel, is_anti(e), is_semantics(e));
    1553             :                                 }
    1554             :                         }
    1555             :                 }
    1556             :          }      break;
    1557             :         default:
    1558             :                 ;
    1559             :         }
    1560             :         return s;
    1561             : }
    1562             : 
    1563             : static stmt *
    1564      522176 : stmt_col( backend *be, sql_column *c, stmt *del, int part)
    1565             : {
    1566      522176 :         stmt *sc = stmt_bat(be, c, RDONLY, part);
    1567             : 
    1568      522176 :         if (isTable(c->t) && c->t->access != TABLE_READONLY &&
    1569      495600 :            (!isNew(c) || !isNew(c->t) /* alter */) &&
    1570      482554 :            (c->t->persistence == SQL_PERSIST || c->t->s) /*&& !c->t->commit_action*/) {
    1571      482554 :                 stmt *u = stmt_bat(be, c, RD_UPD_ID, part);
    1572      482553 :                 sc = stmt_project_delta(be, sc, u);
    1573      482554 :                 if (del)
    1574       16392 :                         sc = stmt_project(be, del, sc);
    1575       39622 :         } else if (del) { /* always handle the deletes */
    1576        5944 :                 sc = stmt_project(be, del, sc);
    1577             :         }
    1578      522176 :         return sc;
    1579             : }
    1580             : 
    1581             : static stmt *
    1582        3699 : stmt_idx( backend *be, sql_idx *i, stmt *del, int part)
    1583             : {
    1584        3699 :         stmt *sc = stmt_idxbat(be, i, RDONLY, part);
    1585             : 
    1586        3699 :         if (isTable(i->t) && i->t->access != TABLE_READONLY &&
    1587        3699 :            (!isNew(i) || !isNew(i->t) /* alter */) &&
    1588        2980 :            (i->t->persistence == SQL_PERSIST || i->t->s) /*&& !i->t->commit_action*/) {
    1589        2980 :                 stmt *u = stmt_idxbat(be, i, RD_UPD_ID, part);
    1590        2980 :                 sc = stmt_project_delta(be, sc, u);
    1591        2980 :                 if (del)
    1592         304 :                         sc = stmt_project(be, del, sc);
    1593         719 :         } else if (del) { /* always handle the deletes */
    1594         608 :                 sc = stmt_project(be, del, sc);
    1595             :         }
    1596        3699 :         return sc;
    1597             : }
    1598             : 
    1599             : static int
    1600           0 : stmt_set_type_param(mvc *sql, sql_subtype *type, stmt *param)
    1601             : {
    1602           0 :         if (!type || !param || param->type != st_var)
    1603             :                 return -1;
    1604             : 
    1605           0 :         if (set_type_param(sql, type, param->flag) == 0) {
    1606           0 :                 param->op4.typeval = *type;
    1607           0 :                 return 0;
    1608             :         }
    1609             :         return -1;
    1610             : }
    1611             : 
    1612             : /* check_types tries to match the t type with the type of s if they don't
    1613             :  * match s is converted. Returns NULL on failure.
    1614             :  */
    1615             : static stmt *
    1616        4161 : check_types(backend *be, sql_subtype *t, stmt *s, check_type tpe)
    1617             : {
    1618        4161 :         mvc *sql = be->mvc;
    1619             :         int c, err = 0;
    1620        4161 :         sql_subtype *fromtype = tail_type(s);
    1621             : 
    1622        4161 :         if ((!fromtype || !fromtype->type) && stmt_set_type_param(sql, t, s) == 0)
    1623             :                 return s;
    1624        4161 :         if (!fromtype)
    1625           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "statement has no type information");
    1626             : 
    1627        4161 :         if (fromtype && subtype_cmp(t, fromtype) != 0) {
    1628           1 :                 if (EC_INTERVAL(fromtype->type->eclass) && (t->type->eclass == EC_NUM || t->type->eclass == EC_POS) && t->digits < fromtype->digits) {
    1629             :                         err = 1; /* conversion from interval to num depends on the number of digits */
    1630             :                 } else {
    1631           1 :                         c = sql_type_convert(fromtype->type->eclass, t->type->eclass);
    1632           1 :                         if (!c || (c == 2 && tpe == type_set) || (c == 3 && tpe != type_cast)) {
    1633             :                                 err = 1;
    1634             :                         } else {
    1635           1 :                                 s = stmt_convert(be, s, NULL, fromtype, t);
    1636             :                         }
    1637             :                 }
    1638             :         }
    1639             :         if (err) {
    1640           0 :                 stmt *res = sql_error(sql, 03, SQLSTATE(42000) "types %s(%u,%u) (%s) and %s(%u,%u) (%s) are not equal",
    1641             :                         fromtype->type->base.name,
    1642             :                         fromtype->digits,
    1643             :                         fromtype->scale,
    1644           0 :                         fromtype->type->impl,
    1645             :                         t->type->base.name,
    1646             :                         t->digits,
    1647             :                         t->scale,
    1648           0 :                         t->type->impl
    1649             :                 );
    1650           0 :                 return res;
    1651             :         }
    1652             :         return s;
    1653             : }
    1654             : 
    1655             : static stmt *
    1656        4059 : sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
    1657             : {
    1658        4059 :         mvc *sql = be->mvc;
    1659        4059 :         list *sl = sa_list(sql->sa);
    1660        4059 :         list *tl = sa_list(sql->sa);
    1661             :         sql_subfunc *f = NULL;
    1662             : 
    1663        4059 :         list_append(sl, a1);
    1664        4059 :         list_append(tl, tail_type(a1));
    1665        4059 :         list_append(sl, a2);
    1666        4059 :         list_append(tl, tail_type(a2));
    1667        4059 :         list_append(sl, a3);
    1668        4059 :         list_append(tl, tail_type(a3));
    1669        4059 :         if (a4) {
    1670           0 :                 list_append(sl, a4);
    1671           0 :                 list_append(tl, tail_type(a4));
    1672             :         }
    1673             : 
    1674        4059 :         if ((f = sql_bind_func_(sql, "sys", fname, tl, F_FUNC)))
    1675        4059 :                 return stmt_Nop(be, stmt_list(be, sl), NULL, f);
    1676           0 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such operator '%s'", fname);
    1677             : }
    1678             : 
    1679             : static stmt *
    1680          10 : parse_value(backend *be, sql_schema *s, char *query, sql_subtype *tpe, char emode)
    1681             : {
    1682          10 :         sql_exp *e = rel_parse_val(be->mvc, s, query, tpe, emode, NULL);
    1683          10 :         if (e)
    1684          10 :                 return exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    1685           0 :         return sql_error(be->mvc, 02, SQLSTATE(HY001) MAL_MALLOC_FAIL);
    1686             : }
    1687             : 
    1688             : static stmt *
    1689     1504306 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    1690             : {
    1691     1504306 :         const char *name = exp_name(exp);
    1692     1504307 :         const char *rname = exp_relname(exp);
    1693             :         stmt *o = s;
    1694             : 
    1695     1504307 :         if (!name && exp_is_atom(exp))
    1696          27 :                 name = sa_strdup(be->mvc->sa, "single_value");
    1697     1504307 :         assert(name);
    1698     1504307 :         s = stmt_alias(be, s, rname, name);
    1699     1504306 :         if (o->flag & OUTER_ZERO)
    1700          73 :                 s->flag |= OUTER_ZERO;
    1701     1504306 :         return s;
    1702             : }
    1703             : 
    1704             : static stmt *
    1705        1007 : rel2bin_sql_table(backend *be, sql_table *t, list *aliases)
    1706             : {
    1707        1007 :         mvc *sql = be->mvc;
    1708        1007 :         list *l = sa_list(sql->sa);
    1709             :         node *n;
    1710        1007 :         stmt *dels = stmt_tid(be, t, 0);
    1711             : 
    1712        1007 :         if (aliases) {
    1713       14962 :                 for (n = aliases->h; n; n = n->next) {
    1714       13955 :                         sql_exp *e = n->data;
    1715       13955 :                         if (e->type != e_column)
    1716         107 :                                 continue;
    1717             :                         assert(e->type == e_column);
    1718       13848 :                         char *name = e->r;
    1719       13848 :                         if (name[0] == '%') {
    1720        1001 :                                 if (strcmp(name, TID)==0) {
    1721             :                                         /* tid function  sql.tid(t) */
    1722        1001 :                                         const char *rnme = t->base.name;
    1723             : 
    1724        1001 :                                         stmt *sc = dels?dels:stmt_tid(be, t, 0);
    1725        1001 :                                         sc = stmt_alias(be, sc, rnme, TID);
    1726        1001 :                                         list_append(l, sc);
    1727             :                                 } else {
    1728           0 :                                         node *m = ol_find_name(t->idxs, name+1);
    1729           0 :                                         if (!m)
    1730           0 :                                                 assert(0);
    1731           0 :                                         sql_idx *i = m->data;
    1732           0 :                                         stmt *sc = stmt_idx(be, i, dels, dels->partition);
    1733           0 :                                         const char *rnme = t->base.name;
    1734             : 
    1735             :                                         /* index names are prefixed, to make them independent */
    1736           0 :                                         sc = stmt_alias(be, sc, rnme, sa_strconcat(sql->sa, "%", i->base.name));
    1737           0 :                                         list_append(l, sc);
    1738             :                                 }
    1739             :                         } else {
    1740       12847 :                                 node *m = ol_find_name(t->columns, name);
    1741       12847 :                                 if (!m)
    1742           0 :                                         assert(0);
    1743       12847 :                                 sql_column *c = m->data;
    1744       12847 :                                 stmt *sc = stmt_col(be, c, dels, dels->partition);
    1745       12847 :                                 list_append(l, sc);
    1746             :                         }
    1747             :                 }
    1748             :         } else {
    1749           0 :                 for (n = ol_first_node(t->columns); n; n = n->next) {
    1750           0 :                         sql_column *c = n->data;
    1751           0 :                         stmt *sc = stmt_col(be, c, dels, dels->partition);
    1752             : 
    1753           0 :                         list_append(l, sc);
    1754             :                 }
    1755             :                 /* TID column */
    1756           0 :                 if (ol_first_node(t->columns)) {
    1757             :                         /* tid function  sql.tid(t) */
    1758           0 :                         const char *rnme = t->base.name;
    1759             : 
    1760           0 :                         stmt *sc = dels?dels:stmt_tid(be, t, 0);
    1761           0 :                         sc = stmt_alias(be, sc, rnme, TID);
    1762           0 :                         list_append(l, sc);
    1763             :                 }
    1764           0 :                 if (t->idxs) {
    1765           0 :                         for (n = ol_first_node(t->idxs); n; n = n->next) {
    1766           0 :                                 sql_idx *i = n->data;
    1767           0 :                                 stmt *sc = stmt_idx(be, i, dels, dels->partition);
    1768           0 :                                 const char *rnme = t->base.name;
    1769             : 
    1770             :                                 /* index names are prefixed, to make them independent */
    1771           0 :                                 sc = stmt_alias(be, sc, rnme, sa_strconcat(sql->sa, "%", i->base.name));
    1772           0 :                                 list_append(l, sc);
    1773             :                         }
    1774             :                 }
    1775             :         }
    1776        1007 :         return stmt_list(be, l);
    1777             : }
    1778             : 
    1779             : static stmt *
    1780      167793 : rel2bin_basetable(backend *be, sql_rel *rel)
    1781             : {
    1782      167793 :         mvc *sql = be->mvc;
    1783      167793 :         sql_table *t = rel->l;
    1784             :         sql_column *fcol = NULL;
    1785             :         sql_idx *fi = NULL;
    1786      167793 :         list *l = sa_list(sql->sa);
    1787      167793 :         stmt *dels = stmt_tid(be, t, rel->flag == REL_PARTITION), *col = NULL;
    1788             :         node *en;
    1789             : 
    1790             :         /* add aliases */
    1791      167793 :         assert(rel->exps);
    1792      335606 :         for( en = rel->exps->h; en && !col; en = en->next ) {
    1793      167813 :                 sql_exp *exp = en->data;
    1794      167813 :                 const char *oname = exp->r;
    1795             : 
    1796      167813 :                 if (is_func(exp->type) || (oname[0] == '%' && strcmp(oname, TID) == 0))
    1797        2383 :                         continue;
    1798      165430 :                 if (oname[0] == '%') {
    1799          60 :                         sql_idx *i = find_sql_idx(t, oname+1);
    1800             : 
    1801             :                         /* do not include empty indices in the plan */
    1802          60 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
    1803           0 :                                 continue;
    1804             :                         fi = i;
    1805          60 :                         col = stmt_idx(be, i, NULL/*dels*/, dels->partition);
    1806             :                 } else {
    1807      165370 :                         sql_column *c = find_sql_column(t, oname);
    1808             : 
    1809             :                         fcol = c;
    1810      165370 :                         col = stmt_col(be, c, NULL/*dels*/, dels->partition);
    1811             :                 }
    1812             :         }
    1813      685772 :         for( en = rel->exps->h; en; en = en->next ) {
    1814      517979 :                 sql_exp *exp = en->data;
    1815      517979 :                 const char *rname = exp_relname(exp)?exp_relname(exp):exp->l;
    1816      517979 :                 const char *oname = exp->r;
    1817             :                 stmt *s = NULL;
    1818             : 
    1819      517979 :                 assert(!is_func(exp->type));
    1820      533331 :                 if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    1821             :                         /* tid function  sql.tid(t) */
    1822       15352 :                         const char *rnme = t->base.name;
    1823             : 
    1824       15352 :                         if (col)
    1825       12989 :                                 s = stmt_mirror(be, col);
    1826             :                         else {
    1827        2363 :                                 s = dels?dels:stmt_tid(be, t, 0);
    1828             :                                 dels = NULL;
    1829             :                         }
    1830       15352 :                         s = stmt_alias(be, s, rnme, TID);
    1831      502627 :                 } else if (oname[0] == '%') {
    1832        2787 :                         sql_idx *i = find_sql_idx(t, oname+1);
    1833             : 
    1834             :                         /* do not include empty indices in the plan */
    1835        2787 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
    1836           0 :                                 continue;
    1837        2787 :                         s = (i == fi) ? col : stmt_idx(be, i, NULL/*dels*/, dels->partition);
    1838             :                 } else {
    1839      499840 :                         sql_column *c = find_sql_column(t, oname);
    1840             : 
    1841      499840 :                         s = (c == fcol) ? col : stmt_col(be, c, NULL/*dels*/, dels->partition);
    1842             :                 }
    1843      517979 :                 s->tname = rname;
    1844      517979 :                 s->cname = exp_name(exp);
    1845      517979 :                 list_append(l, s);
    1846             :         }
    1847      167793 :         stmt *res = stmt_list(be, l);
    1848      167793 :         if (res && dels)
    1849      165430 :                 res->cand = dels;
    1850      167793 :         return res;
    1851             : }
    1852             : 
    1853             : static int
    1854          21 : alias_cmp( stmt *s, const char *nme )
    1855             : {
    1856          21 :         return strcmp(s->cname, nme);
    1857             : }
    1858             : 
    1859             : static list* exps2bin_args(backend *be, list *exps, list *args);
    1860             : 
    1861             : static list *
    1862        1738 : exp2bin_args(backend *be, sql_exp *e, list *args)
    1863             : {
    1864        1830 :         mvc *sql = be->mvc;
    1865             : 
    1866        1830 :         if (THRhighwater())
    1867           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1868             : 
    1869        1830 :         if (!e || !args)
    1870             :                 return args;
    1871        1830 :         switch(e->type){
    1872             :         case e_column:
    1873             :         case e_psm:
    1874             :                 return args;
    1875          64 :         case e_cmp:
    1876          64 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    1877           6 :                         args = exps2bin_args(be, e->l, args);
    1878           6 :                         args = exps2bin_args(be, e->r, args);
    1879          58 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    1880           1 :                         args = exp2bin_args(be, e->l, args);
    1881           1 :                         args = exps2bin_args(be, e->r, args);
    1882             :                 } else {
    1883          57 :                         args = exp2bin_args(be, e->l, args);
    1884          57 :                         args = exp2bin_args(be, e->r, args);
    1885          57 :                         if (e->f)
    1886             :                                 args = exp2bin_args(be, e->f, args);
    1887             :                 }
    1888             :                 return args;
    1889          76 :         case e_convert:
    1890          76 :                 if (e->l)
    1891             :                         return exp2bin_args(be, e->l, args);
    1892             :                 break;
    1893         124 :         case e_aggr:
    1894             :         case e_func:
    1895         124 :                 if (e->l)
    1896          93 :                         return exps2bin_args(be, e->l, args);
    1897             :                 break;
    1898         266 :         case e_atom:
    1899         266 :                 if (e->l) {
    1900             :                         return args;
    1901          22 :                 } else if (e->f) {
    1902           0 :                         return exps2bin_args(be, e->f, args);
    1903          22 :                 } else if (e->r) {
    1904             :                         sql_var_name *vname = (sql_var_name*) e->r;
    1905          22 :                         const char *nme = sql_escape_ident(sql->sa, vname->name);
    1906             :                         char *buf = NULL;
    1907             : 
    1908          22 :                         if (vname->sname) { /* Global variable */
    1909           3 :                                 const char *sname = sql_escape_ident(sql->sa, vname->sname);
    1910           3 :                                 if (!nme || !sname || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(sname) + strlen(nme) + 6)))
    1911           0 :                                         return NULL;
    1912           3 :                                 stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(buf, "0\""), sname), "\"\""), nme), "\""); /* escape variable name */
    1913             :                         } else { /* Parameter or local variable */
    1914             :                                 char levelstr[16];
    1915          19 :                                 snprintf(levelstr, sizeof(levelstr), "%u", e->flag);
    1916          19 :                                 if (!nme || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(nme) + 3)))
    1917           0 :                                         return NULL;
    1918          19 :                                 stpcpy(stpcpy(stpcpy(stpcpy(buf, levelstr), "\""), nme), "\""); /* escape variable name */
    1919             :                         }
    1920          22 :                         if (!list_find(args, buf, (fcmp)&alias_cmp)) {
    1921          22 :                                 stmt *s = stmt_var(be, vname->sname, vname->name, &e->tpe, 0, e->flag);
    1922             : 
    1923          22 :                                 s = stmt_alias(be, s, NULL, sa_strdup(sql->sa, buf));
    1924          22 :                                 list_append(args, s);
    1925             :                         }
    1926             :                 }
    1927             :         }
    1928             :         return args;
    1929             : }
    1930             : 
    1931             : static list *
    1932         309 : exps2bin_args(backend *be, list *exps, list *args)
    1933             : {
    1934             :         node *n;
    1935             : 
    1936         309 :         if (!exps)
    1937             :                 return args;
    1938        1932 :         for (n = exps->h; n; n = n->next)
    1939        1623 :                 args = exp2bin_args(be, n->data, args);
    1940             :         return args;
    1941             : }
    1942             : 
    1943             : static list *
    1944         127 : rel2bin_args(backend *be, sql_rel *rel, list *args)
    1945             : {
    1946         330 :         if (THRhighwater())
    1947           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1948             : 
    1949         330 :         if (!rel || !args)
    1950             :                 return args;
    1951         330 :         switch(rel->op) {
    1952             :         case op_basetable:
    1953             :         case op_table:
    1954             :                 break;
    1955           2 :         case op_join:
    1956             :         case op_left:
    1957             :         case op_right:
    1958             :         case op_full:
    1959             : 
    1960             :         case op_semi:
    1961             :         case op_anti:
    1962             : 
    1963             :         case op_union:
    1964             :         case op_inter:
    1965             :         case op_except:
    1966             :         case op_merge:
    1967           2 :                 args = rel2bin_args(be, rel->l, args);
    1968           2 :                 args = rel2bin_args(be, rel->r, args);
    1969           2 :                 break;
    1970          37 :         case op_groupby:
    1971          37 :                 if (rel->r)
    1972           2 :                         args = exps2bin_args(be, rel->r, args);
    1973             :                 /* fall through */
    1974             :         case op_project:
    1975             :         case op_select:
    1976             :         case op_topn:
    1977             :         case op_sample:
    1978         201 :                 if (rel->exps)
    1979         201 :                         args = exps2bin_args(be, rel->exps, args);
    1980         201 :                 args = rel2bin_args(be, rel->l, args);
    1981         201 :                 break;
    1982           0 :         case op_ddl:
    1983           0 :                 args = rel2bin_args(be, rel->l, args);
    1984           0 :                 if (rel->r)
    1985             :                         args = rel2bin_args(be, rel->r, args);
    1986             :                 break;
    1987           0 :         case op_insert:
    1988             :         case op_update:
    1989             :         case op_delete:
    1990             :         case op_truncate:
    1991           0 :                 args = rel2bin_args(be, rel->r, args);
    1992           0 :                 break;
    1993             :         }
    1994             :         return args;
    1995             : }
    1996             : 
    1997             : typedef struct trigger_input {
    1998             :         sql_table *t;
    1999             :         stmt *tids;
    2000             :         stmt **updates;
    2001             :         int type; /* insert 1, update 2, delete 3, truncate 4 */
    2002             :         const char *on;
    2003             :         const char *nn;
    2004             : } trigger_input;
    2005             : 
    2006             : static stmt *
    2007        6347 : rel2bin_table(backend *be, sql_rel *rel, list *refs)
    2008             : {
    2009        6347 :         mvc *sql = be->mvc;
    2010             :         list *l;
    2011             :         stmt *sub = NULL, *osub = NULL;
    2012             :         node *en, *n;
    2013        6347 :         sql_exp *op = rel->r;
    2014             : 
    2015        6347 :         if (rel->flag == TRIGGER_WRAPPER) {
    2016           9 :                 trigger_input *ti = rel->l;
    2017           9 :                 l = sa_list(sql->sa);
    2018             : 
    2019          26 :                 for(n = ol_first_node(ti->t->columns); n; n = n->next) {
    2020          17 :                         sql_column *c = n->data;
    2021             : 
    2022          17 :                         if (ti->type == 2) { /* updates */
    2023           4 :                                 stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
    2024           4 :                                 append(l, stmt_alias(be, s, ti->on, c->base.name));
    2025             :                         }
    2026          17 :                         if (ti->updates && ti->updates[c->colnr]) {
    2027          15 :                                 append(l, stmt_alias(be, ti->updates[c->colnr], ti->nn, c->base.name));
    2028             :                         } else {
    2029           2 :                                 stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
    2030           2 :                                 append(l, stmt_alias(be, s, ti->nn, c->base.name));
    2031           2 :                                 assert(ti->type != 1);
    2032             :                         }
    2033             :                 }
    2034           9 :                 sub = stmt_list(be, l);
    2035           9 :                 return sub;
    2036        6338 :         } else if (op) {
    2037             :                 int i;
    2038        6213 :                 sql_subfunc *f = op->f;
    2039             :                 stmt *psub = NULL;
    2040             :                 list *ops = NULL;
    2041             :                 stmt *ids = NULL;
    2042             : 
    2043        6213 :                 if (rel->l) { /* first construct the sub relation */
    2044             :                         sql_rel *l = rel->l;
    2045         346 :                         if (l->op == op_ddl) {
    2046           0 :                                 sql_table *t = rel_ddl_table_get(l);
    2047             : 
    2048           0 :                                 if (t)
    2049           0 :                                         sub = rel2bin_sql_table(be, t, NULL);
    2050             :                         } else {
    2051         346 :                                 sub = subrel_bin(be, rel->l, refs);
    2052             :                         }
    2053         346 :                         sub = subrel_project(be, sub, refs, rel->l);
    2054         346 :                         if (!sub)
    2055             :                                 return NULL;
    2056             :                 }
    2057             : 
    2058        6213 :                 assert(f);
    2059        6213 :                 if (f->func->res && list_length(f->func->res) + 1 == list_length(rel->exps) && !f->func->varres) {
    2060             :                         /* add inputs in correct order ie loop through args of f and pass column */
    2061           8 :                         list *exps = op->l;
    2062           8 :                         ops = sa_list(be->mvc->sa);
    2063           8 :                         if (exps) {
    2064          24 :                                 for (node *en = exps->h; en; en = en->next) {
    2065          16 :                                         sql_exp *e = en->data;
    2066             : 
    2067             :                                         /* find column */
    2068          16 :                                         stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    2069          16 :                                         if (!s)
    2070             :                                                 return NULL;
    2071          16 :                                         if (en->next)
    2072           8 :                                                 append(ops, s);
    2073             :                                         else /* last added exp is the ids (todo use name base lookup !!) */
    2074             :                                                 ids = s;
    2075             :                                 }
    2076             :                         }
    2077             :                 } else {
    2078        6205 :                         psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0); /* table function */
    2079        6205 :                         if (!psub)
    2080             :                                 return NULL;
    2081             :                 }
    2082        6213 :                 l = sa_list(sql->sa);
    2083        6213 :                 if (f->func->res) {
    2084        6188 :                         if (f->func->varres) {
    2085       10837 :                                 for(i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++ ) {
    2086        9809 :                                         sql_exp *exp = en->data;
    2087        9809 :                                         sql_subtype *st = n->data;
    2088        9809 :                                         const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
    2089        9809 :                                         stmt *s = stmt_rs_column(be, psub, i, st);
    2090             : 
    2091        9809 :                                         s = stmt_alias(be, s, rnme, exp_name(exp));
    2092        9809 :                                         list_append(l, s);
    2093             :                                 }
    2094             :                         } else {
    2095        5160 :                                 node *m = rel->exps->h;
    2096             :                                 int i = 0;
    2097             : 
    2098             :                                 /* correlated table returning function */
    2099        5160 :                                 if (list_length(f->func->res) + 1 == list_length(rel->exps)) {
    2100             :                                         /* use a simple nested loop solution for this case, ie
    2101             :                                          * output a table of (input) row-ids, the output of the table producing function
    2102             :                                          */
    2103             :                                         /* make sure the input for sql.unionfunc are bats */
    2104           8 :                                         if (ids)
    2105           8 :                                                 ids = column(be, ids);
    2106           8 :                                         if (ops)
    2107          16 :                                                 for (node *en = ops->h; en; en = en->next)
    2108           8 :                                                         en->data = column(be, (stmt *) en->data);
    2109             : 
    2110           8 :                                         int narg = 3 + list_length(rel->exps);
    2111           8 :                                         if (ops)
    2112           8 :                                                 narg += list_length(ops);
    2113           8 :                                         InstrPtr q = newStmtArgs(be->mb, sqlRef, "unionfunc", narg);
    2114             :                                         /* Generate output rowid column and output of function f */
    2115          24 :                                         for(i=0; m; m = m->next, i++) {
    2116          16 :                                                 sql_exp *e = m->data;
    2117          16 :                                                 int type = exp_subtype(e)->type->localtype;
    2118             : 
    2119          16 :                                                 type = newBatType(type);
    2120          16 :                                                 if (i)
    2121           8 :                                                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
    2122             :                                                 else
    2123           8 :                                                         getArg(q, 0) = newTmpVariable(be->mb, type);
    2124             :                                         }
    2125           8 :                                         str mod = sql_func_mod(f->func);
    2126           8 :                                         str fcn = sql_func_imp(f->func);
    2127           8 :                                         q = pushStr(be->mb, q, mod);
    2128           8 :                                         q = pushStr(be->mb, q, fcn);
    2129           8 :                                         if (backend_create_func(be, f->func, NULL, ops) < 0)
    2130             :                                                 return NULL;
    2131           8 :                                         psub = stmt_direct_func(be, q);
    2132             : 
    2133           8 :                                         if (ids) /* push input rowids column */
    2134           8 :                                                 q = pushArgument(be->mb, q, ids->nr);
    2135             : 
    2136             :                                         /* add inputs in correct order ie loop through args of f and pass column */
    2137           8 :                                         if (ops) {
    2138          16 :                                                 for (node *en = ops->h; en; en = en->next) {
    2139           8 :                                                         stmt *op = en->data;
    2140             : 
    2141           8 :                                                         q = pushArgument(be->mb, q, op->nr);
    2142             :                                                 }
    2143             :                                         }
    2144             : 
    2145             :                                         /* name output of dependent columns, output of function is handled the same as without correlation */
    2146           8 :                                         int len = list_length(rel->exps)-list_length(f->func->res);
    2147           8 :                                         assert(len== 1);
    2148          16 :                                         for(i=0, m=rel->exps->h; m && i<len; m = m->next, i++ ) {
    2149           8 :                                                 sql_exp *exp = m->data;
    2150           8 :                                                 stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp));
    2151             : 
    2152           8 :                                                 s = stmt_alias(be, s, exp->l, exp->r);
    2153           8 :                                                 list_append(l, s);
    2154             :                                         }
    2155             :                                 }
    2156       19824 :                                 for(n = f->func->res->h; n && m; n = n->next, m = m->next, i++ ) {
    2157       14664 :                                         sql_arg *a = n->data;
    2158       14664 :                                         sql_exp *exp = m->data;
    2159       14664 :                                         stmt *s = stmt_rs_column(be, psub, i, &a->type);
    2160       14664 :                                         const char *rnme = exp_relname(exp)?exp_relname(exp):exp_find_rel_name(op);
    2161             : 
    2162       14664 :                                         s = stmt_alias(be, s, rnme, a->name);
    2163       14664 :                                         list_append(l, s);
    2164             :                                 }
    2165             :                         }
    2166             :                 }
    2167        6213 :                 assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
    2168        6213 :                 sub = stmt_list(be, l);
    2169         125 :         } else if (rel->l) { /* handle sub query via function */
    2170             :                 int i;
    2171             :                 char name[16], *nme;
    2172             :                 sql_rel *fr;
    2173             : 
    2174         125 :                 nme = number2name(name, sizeof(name), ++be->remote);
    2175             : 
    2176         125 :                 l = rel2bin_args(be, rel->l, sa_list(sql->sa));
    2177         125 :                 if (!l)
    2178           0 :                         return NULL;
    2179         125 :                 sub = stmt_list(be, l);
    2180         125 :                 if (!(sub = stmt_func(be, sub, sa_strdup(sql->sa, nme), rel->l, 0)))
    2181             :                         return NULL;
    2182         125 :                 fr = rel->l = sub->op4.rel; /* rel->l may get rewritten */
    2183         125 :                 l = sa_list(sql->sa);
    2184        1397 :                 for(i = 0, n = rel->exps->h; n; n = n->next, i++ ) {
    2185        1272 :                         sql_exp *c = n->data;
    2186        1272 :                         stmt *s = stmt_rs_column(be, sub, i, exp_subtype(c));
    2187        1272 :                         const char *nme = exp_name(c);
    2188        1272 :                         const char *rnme = exp_relname(c);
    2189             : 
    2190        1272 :                         s = stmt_alias(be, s, rnme, nme);
    2191        1272 :                         if (fr->card <= CARD_ATOM) /* single value, get result from bat */
    2192          29 :                                 s = stmt_fetch(be, s);
    2193        1272 :                         list_append(l, s);
    2194             :                 }
    2195         125 :                 sub = stmt_list(be, l);
    2196             :         }
    2197        6338 :         if (!sub) {
    2198           0 :                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2199             :                 return NULL;
    2200             :         }
    2201        6338 :         l = sa_list(sql->sa);
    2202       32091 :         for( en = rel->exps->h; en; en = en->next ) {
    2203       25753 :                 sql_exp *exp = en->data;
    2204       25753 :                 const char *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
    2205       25753 :                 stmt *s = bin_find_column(be, sub, exp->l, exp->r);
    2206             : 
    2207       25753 :                 if (!s) {
    2208           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2209             :                         return NULL;
    2210             :                 }
    2211       25753 :                 if (sub && sub->nrcols >= 1 && s->nrcols == 0)
    2212           0 :                         s = stmt_const(be, bin_find_smallest_column(be, sub), s);
    2213       25753 :                 s = stmt_alias(be, s, rnme, exp_name(exp));
    2214       25753 :                 list_append(l, s);
    2215             :         }
    2216             :         if (osub && osub->nrcols)
    2217             :                 list_merge(l, osub->op4.lval, NULL);
    2218        6338 :         sub = stmt_list(be, l);
    2219        6338 :         return sub;
    2220             : }
    2221             : 
    2222             : static stmt *
    2223          77 : rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en )
    2224             : {
    2225          77 :         mvc *sql = be->mvc;
    2226             :         node *n;
    2227          77 :         sql_subtype *it = sql_bind_localtype("int");
    2228          77 :         sql_subtype *lng = sql_bind_localtype("lng");
    2229             :         stmt *h = NULL;
    2230          77 :         stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
    2231          77 :         sql_exp *e = en->data;
    2232          77 :         sql_exp *l = e->l;
    2233          77 :         stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    2234             :         int swap_exp = 0, swap_rel = 0, semantics = 0;
    2235             : 
    2236          77 :         if (!idx) {
    2237             :                 swap_exp = 1;
    2238          26 :                 l = e->r;
    2239          26 :                 idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    2240             :         }
    2241          77 :         if (!idx && right) {
    2242             :                 swap_exp = 0;
    2243             :                 swap_rel = 1;
    2244          24 :                 l = e->l;
    2245          24 :                 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    2246             :         }
    2247          77 :         if (!idx && right) {
    2248             :                 swap_exp = 1;
    2249             :                 swap_rel = 1;
    2250           0 :                 l = e->r;
    2251           0 :                 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    2252             :         }
    2253          77 :         if (!idx)
    2254             :                 return NULL;
    2255             :         /* should be in key order! */
    2256         276 :         for( en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next ) {
    2257         201 :                 sql_exp *e = en->data;
    2258             :                 stmt *s = NULL;
    2259             : 
    2260         201 :                 if (e->type == e_cmp && e->flag == cmp_equal) {
    2261         201 :                         sql_exp *ee = (swap_exp)?e->l:e->r;
    2262         201 :                         if (swap_rel)
    2263          49 :                                 s = exp_bin(be, ee, left, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    2264             :                         else
    2265         152 :                                 s = exp_bin(be, ee, right, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    2266             :                 }
    2267             : 
    2268         201 :                 if (!s)
    2269           2 :                         return NULL;
    2270         199 :                 if (h) {
    2271         124 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, lng, 3, lng, it, tail_type(s));
    2272             : 
    2273         124 :                         h = stmt_Nop(be, stmt_list(be, list_append( list_append(
    2274             :                                 list_append(sa_list(sql->sa), h), bits), s)), NULL, xor);
    2275             :                         semantics = 1;
    2276             :                 } else {
    2277          75 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, lng, 1, tail_type(s));
    2278             : 
    2279          75 :                         h = stmt_unop(be, s, NULL, hf);
    2280             :                 }
    2281             :         }
    2282          75 :         if (h && h->nrcols) {
    2283          75 :                 if (!swap_rel) {
    2284          51 :                         return stmt_join(be, idx, h, 0, cmp_equal, 0, semantics, false);
    2285             :                 } else {
    2286          24 :                         return stmt_join(be, h, idx, 0, cmp_equal, 0, semantics, false);
    2287             :                 }
    2288             :         } else {
    2289           0 :                 return stmt_uselect(be, idx, h, cmp_equal, NULL, 0, semantics);
    2290             :         }
    2291             : }
    2292             : 
    2293             : static stmt *
    2294        6674 : join_hash_key( backend *be, list *l )
    2295             : {
    2296        6674 :         mvc *sql = be->mvc;
    2297             :         node *m;
    2298             :         sql_subtype *it, *lng;
    2299             :         stmt *h = NULL;
    2300        6674 :         stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
    2301             : 
    2302        6674 :         it = sql_bind_localtype("int");
    2303        6674 :         lng = sql_bind_localtype("lng");
    2304       21194 :         for (m = l->h; m; m = m->next) {
    2305       14520 :                 stmt *s = m->data;
    2306             : 
    2307       14520 :                 if (h) {
    2308        7846 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, lng, 3, lng, it, tail_type(s));
    2309             : 
    2310        7846 :                         h = stmt_Nop(be, stmt_list(be, list_append( list_append( list_append(sa_list(sql->sa), h), bits), s )), NULL, xor);
    2311             :                 } else {
    2312        6674 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, lng, 1, tail_type(s));
    2313        6674 :                         h = stmt_unop(be, s, NULL, hf);
    2314             :                 }
    2315             :         }
    2316        6674 :         return h;
    2317             : }
    2318             : 
    2319             : static stmt *
    2320        5967 : releqjoin( backend *be, list *l1, list *l2, list *exps, int used_hash, int need_left, int is_semantics )
    2321             : {
    2322        5967 :         mvc *sql = be->mvc;
    2323        5967 :         node *n1 = l1->h, *n2 = l2->h, *n3 = NULL;
    2324             :         stmt *l, *r, *res;
    2325             :         sql_exp *e;
    2326             : 
    2327        5967 :         if (exps)
    2328        3227 :                 n3 = exps->h;
    2329        5967 :         if (list_length(l1) <= 1) {
    2330        2320 :                 l = l1->h->data;
    2331        2320 :                 r = l2->h->data;
    2332        2320 :                 if (!is_semantics && exps) {
    2333           0 :                         e = n3->data;
    2334           0 :                         is_semantics = is_semantics(e);
    2335             :                 }
    2336        2320 :                 r =  stmt_join(be, l, r, 0, cmp_equal, need_left, is_semantics, false);
    2337        2320 :                 return r;
    2338             :         }
    2339        3647 :         if (used_hash) {
    2340         310 :                 l = n1->data;
    2341         310 :                 r = n2->data;
    2342         310 :                 n1 = n1->next;
    2343         310 :                 n2 = n2->next;
    2344         310 :                 n3 = n3?n3->next:NULL;
    2345         310 :                 res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
    2346             :         } else { /* need hash */
    2347        3337 :                 l = join_hash_key(be, l1);
    2348        3337 :                 r = join_hash_key(be, l2);
    2349        3337 :                 res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
    2350             :         }
    2351        3647 :         l = stmt_result(be, res, 0);
    2352        3647 :         r = stmt_result(be, res, 1);
    2353       19627 :         for (; n1 && n2; n1 = n1->next, n2 = n2->next, n3 = n3?n3->next:NULL) {
    2354             :                 int semantics = is_semantics;
    2355        7990 :                 stmt *ld = n1->data;
    2356        7990 :                 stmt *rd = n2->data;
    2357        7990 :                 stmt *le = stmt_project(be, l, ld );
    2358        7990 :                 stmt *re = stmt_project(be, r, rd );
    2359             :                 /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
    2360             :                 sql_subfunc *f = NULL;
    2361             :                 stmt * cmp;
    2362             :                 list *ops;
    2363             : 
    2364        7990 :                 f = sql_bind_func(sql, "sys", "=", tail_type(le), tail_type(le), F_FUNC);
    2365        7990 :                 assert(f);
    2366             : 
    2367        7990 :                 ops = sa_list(be->mvc->sa);
    2368        7990 :                 list_append(ops, le);
    2369        7990 :                 list_append(ops, re);
    2370        7990 :                 if (!semantics && exps) {
    2371        6830 :                         e = n3->data;
    2372        6830 :                         semantics = is_semantics(e);
    2373             :                 }
    2374        7990 :                 if (semantics)
    2375        3477 :                         list_append(ops, stmt_bool(be, 1));
    2376        7990 :                 cmp = stmt_Nop(be, stmt_list(be, ops), NULL, f);
    2377        7990 :                 cmp = stmt_uselect(be, cmp, stmt_bool(be, 1), cmp_equal, NULL, 0, 0);
    2378        7990 :                 l = stmt_project(be, cmp, l );
    2379        7990 :                 r = stmt_project(be, cmp, r );
    2380             :         }
    2381        3647 :         res = stmt_join(be, l, r, 0, cmp_joined, 0, 0, false);
    2382        3647 :         return res;
    2383             : }
    2384             : 
    2385             : static void
    2386      102076 : split_join_exps(sql_rel *rel, list *joinable, list *not_joinable)
    2387             : {
    2388      102076 :         if (!list_empty(rel->exps)) {
    2389      209351 :                 for (node *n = rel->exps->h; n; n = n->next) {
    2390      107275 :                         sql_exp *e = n->data;
    2391             :                         int can_join = 0;
    2392             : 
    2393             :                         /* we can handle thetajoins, rangejoins and filter joins (like) */
    2394             :                         /* ToDo how about atom expressions? */
    2395      107275 :                         if (e->type == e_cmp) {
    2396      107270 :                                 int flag = e->flag;
    2397             :                                 /* check if its a select or join expression, ie use only expressions of one relation left and of the other right (than join) */
    2398      107270 :                                 if (flag < cmp_filter || flag == mark_in || flag == mark_notin) { /* theta and range joins */
    2399             :                                         /* join or select ? */
    2400      107210 :                                         sql_exp *l = e->l, *r = e->r, *f = e->f;
    2401             : 
    2402      107210 :                                         if (f) {
    2403          99 :                                                 int ll = rel_find_exp(rel->l, l) != NULL;
    2404          99 :                                                 int rl = rel_find_exp(rel->r, l) != NULL;
    2405          99 :                                                 int lr = rel_find_exp(rel->l, r) != NULL;
    2406          99 :                                                 int rr = rel_find_exp(rel->r, r) != NULL;
    2407          99 :                                                 int lf = rel_find_exp(rel->l, f) != NULL;
    2408          99 :                                                 int rf = rel_find_exp(rel->r, f) != NULL;
    2409             :                                                 int nrcr1 = 0, nrcr2 = 0, nrcl1 = 0, nrcl2 = 0;
    2410             : 
    2411          99 :                                                 if ((ll && !rl &&
    2412          90 :                                                    ((rr && !lr) || (nrcr1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
    2413          82 :                                                    ((rf && !lf) || (nrcr2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcr1+nrcr2) <= 1) ||
    2414          17 :                                                     (rl && !ll &&
    2415           9 :                                                    ((lr && !rr) || (nrcl1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
    2416           8 :                                                    ((lf && !rf) || (nrcl2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcl1+nrcl2) <= 1)) {
    2417             :                                                         can_join = 1;
    2418             :                                                 }
    2419             :                                         } else {
    2420             :                                                 int ll = 0, lr = 0, rl = 0, rr = 0;
    2421             : 
    2422      107111 :                                                 if (l->card != CARD_ATOM || !exp_is_atom(l)) {
    2423      107101 :                                                         ll |= rel_find_exp(rel->l, l) != NULL;
    2424      107101 :                                                         rl |= rel_find_exp(rel->r, l) != NULL;
    2425             :                                                 }
    2426      107111 :                                                 if (r->card != CARD_ATOM || !exp_is_atom(r)) {
    2427      107013 :                                                         lr |= rel_find_exp(rel->l, r) != NULL;
    2428      107013 :                                                         rr |= rel_find_exp(rel->r, r) != NULL;
    2429             :                                                 }
    2430      107111 :                                                 if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
    2431             :                                                         can_join = 1;
    2432             :                                         }
    2433          60 :                                 } else if (flag == cmp_filter) {
    2434          30 :                                         list *l = e->l, *r = e->r;
    2435             :                                         int ll = 0, lr = 0, rl = 0, rr = 0;
    2436             : 
    2437          60 :                                         for (node *n = l->h ; n ; n = n->next) {
    2438          30 :                                                 sql_exp *ee = n->data;
    2439             : 
    2440          30 :                                                 if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
    2441          28 :                                                         ll |= rel_find_exp(rel->l, ee) != NULL;
    2442          28 :                                                         rl |= rel_find_exp(rel->r, ee) != NULL;
    2443             :                                                 }
    2444             :                                         }
    2445         120 :                                         for (node *n = r->h ; n ; n = n->next) {
    2446          90 :                                                 sql_exp *ee = n->data;
    2447             : 
    2448          90 :                                                 if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
    2449          30 :                                                         lr |= rel_find_exp(rel->l, ee) != NULL;
    2450          30 :                                                         rr |= rel_find_exp(rel->r, ee) != NULL;
    2451             :                                                 }
    2452             :                                         }
    2453          30 :                                         if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
    2454             :                                                 can_join = 1;
    2455             :                                 }
    2456             :                         }
    2457             :                         if (can_join) {
    2458      107094 :                                 append(joinable, e);
    2459             :                         } else {
    2460         181 :                                 append(not_joinable, e);
    2461             :                         }
    2462             :                 }
    2463             :         }
    2464      102076 : }
    2465             : 
    2466             : #define is_equi_exp_(e) ((e)->flag == cmp_equal || (e)->flag == mark_in)
    2467             : 
    2468             : static list *
    2469      101943 : get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
    2470             : {
    2471      101943 :         list *new_exps = sa_list(sql->sa);
    2472             : 
    2473      209037 :         for( node *n = exps->h; n; n = n->next ) {
    2474      107094 :                 sql_exp *e = n->data;
    2475             : 
    2476      107094 :                 assert(e->type == e_cmp && e->flag != cmp_in && e->flag != cmp_notin && e->flag != cmp_or);
    2477      107094 :                 if (is_equi_exp_(e))
    2478      102584 :                         list_append(new_exps, e);
    2479             :                 else
    2480        4510 :                         *equality_only = 0;
    2481             :         }
    2482      209037 :         for( node *n = exps->h; n; n = n->next ) {
    2483      107094 :                 sql_exp *e = n->data;
    2484             : 
    2485      107094 :                 if (!is_equi_exp_(e))
    2486        4510 :                         list_append(new_exps, e);
    2487             :         }
    2488      101943 :         return new_exps;
    2489             : }
    2490             : 
    2491             : static stmt *
    2492      112836 : rel2bin_join(backend *be, sql_rel *rel, list *refs)
    2493             : {
    2494      112836 :         mvc *sql = be->mvc;
    2495             :         list *l, *sexps = NULL, *l2 = NULL;
    2496             :         node *en = NULL, *n;
    2497             :         stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *ld = NULL, *rd = NULL, *res;
    2498      112836 :         int need_left = (rel->flag & LEFT_JOIN);
    2499             : 
    2500      112836 :         if (rel->l) /* first construct the left sub relation */
    2501      112836 :                 left = subrel_bin(be, rel->l, refs);
    2502      112836 :         if (rel->r) /* first construct the right sub relation */
    2503      112836 :                 right = subrel_bin(be, rel->r, refs);
    2504      112836 :         left = subrel_project(be, left, refs, rel->l);
    2505      112836 :         right = subrel_project(be, right, refs, rel->r);
    2506      112836 :         if (!left || !right)
    2507             :                 return NULL;
    2508      112836 :         left = row2cols(be, left);
    2509      112836 :         right = row2cols(be, right);
    2510             :         /*
    2511             :          * split in 2 steps,
    2512             :          *      first cheap join(s) (equality or idx)
    2513             :          *      second selects/filters
    2514             :          */
    2515      112836 :         if (!list_empty(rel->exps)) {
    2516       99415 :                 list *jexps = sa_list(sql->sa);
    2517       99415 :                 sexps = sa_list(sql->sa);
    2518             : 
    2519       99415 :                 split_join_exps(rel, jexps, sexps);
    2520       99415 :                 if (list_empty(jexps)) { /* cross product and continue after project */
    2521         126 :                         stmt *l = bin_find_smallest_column(be, left);
    2522         126 :                         stmt *r = bin_find_smallest_column(be, right);
    2523         126 :                         join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    2524             :                 }
    2525             : 
    2526         126 :                 if (join) {
    2527         126 :                         en = jexps->h;
    2528             :                 } else {
    2529       99289 :                         list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
    2530       99289 :                         int used_hash = 0, idx = 0, equality_only = 1;
    2531             : 
    2532             :                         (void) equality_only;
    2533       99289 :                         jexps = get_equi_joins_first(sql, jexps, &equality_only);
    2534             :                         /* generate a relational join (releqjoin) which does a multi attribute (equi) join */
    2535      199734 :                         for( en = jexps->h; en; en = en->next ) {
    2536      102764 :                                 int join_idx = be->join_idx;
    2537      102764 :                                 sql_exp *e = en->data;
    2538             :                                 stmt *s = NULL;
    2539             :                                 prop *p;
    2540             : 
    2541             :                                 /* stop search for equi joins on first non equi */
    2542      102764 :                                 if (list_length(lje) && (idx || e->type != e_cmp || e->flag != cmp_equal))
    2543             :                                         break;
    2544             : 
    2545             :                                 /* handle possible index lookups, expressions are in index order! */
    2546      201980 :                                 if (!join &&
    2547       99289 :                                         (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
    2548          75 :                                         sql_idx *i = p->value;
    2549             : 
    2550          75 :                                         join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
    2551          75 :                                         if (s) {
    2552          75 :                                                 list_append(lje, s->op1);
    2553          75 :                                                 list_append(rje, s->op2);
    2554          75 :                                                 list_append(exps, NULL);
    2555             :                                                 used_hash = 1;
    2556             :                                         }
    2557             :                                 }
    2558             : 
    2559      102691 :                                 s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
    2560      102691 :                                 if (!s) {
    2561           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2562           0 :                                         return NULL;
    2563             :                                 }
    2564      102691 :                                 if (join_idx != be->join_idx)
    2565             :                                         idx = 1;
    2566      102691 :                                 assert(s->type == st_join || s->type == st_join2 || s->type == st_joinN);
    2567      102691 :                                 if (!join)
    2568             :                                         join = s;
    2569      102691 :                                 if (e->flag != cmp_equal) { /* only collect equi joins */
    2570        2246 :                                         en = en->next;
    2571        2246 :                                         break;
    2572             :                                 }
    2573      100445 :                                 list_append(lje, s->op1);
    2574      100445 :                                 list_append(rje, s->op2);
    2575      100445 :                                 list_append(exps, e);
    2576             :                         }
    2577       99289 :                         if (list_length(lje) > 1) {
    2578        3112 :                                 join = releqjoin(be, lje, rje, exps, used_hash, need_left, 0);
    2579       96177 :                         } else if (!join || need_left) {
    2580         630 :                                 sql_exp *e = exps->h->data;
    2581         630 :                                 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, need_left, is_semantics(e), false);
    2582             :                         }
    2583             :                 }
    2584             :         } else {
    2585       13421 :                 stmt *l = bin_find_smallest_column(be, left);
    2586       13421 :                 stmt *r = bin_find_smallest_column(be, right);
    2587       13421 :                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, is_single(rel));
    2588             :         }
    2589      112836 :         jl = stmt_result(be, join, 0);
    2590      112836 :         jr = stmt_result(be, join, 1);
    2591      112836 :         if (en || (sexps && list_length(sexps))) {
    2592             :                 stmt *sub, *sel = NULL;
    2593             :                 list *nl;
    2594             : 
    2595             :                 /* construct relation */
    2596        1281 :                 nl = sa_list(sql->sa);
    2597             : 
    2598             :                 /* first project using equi-joins */
    2599        4442 :                 for( n = left->op4.lval->h; n; n = n->next ) {
    2600        3161 :                         stmt *c = n->data;
    2601        3161 :                         const char *rnme = table_name(sql->sa, c);
    2602        3161 :                         const char *nme = column_name(sql->sa, c);
    2603        3161 :                         stmt *s = stmt_project(be, jl, column(be, c) );
    2604             : 
    2605        3161 :                         s = stmt_alias(be, s, rnme, nme);
    2606        3161 :                         list_append(nl, s);
    2607             :                 }
    2608        4158 :                 for( n = right->op4.lval->h; n; n = n->next ) {
    2609        2877 :                         stmt *c = n->data;
    2610        2877 :                         const char *rnme = table_name(sql->sa, c);
    2611        2877 :                         const char *nme = column_name(sql->sa, c);
    2612        2877 :                         stmt *s = stmt_project(be, jr, column(be, c) );
    2613             : 
    2614        2877 :                         s = stmt_alias(be, s, rnme, nme);
    2615        2877 :                         list_append(nl, s);
    2616             :                 }
    2617        1281 :                 sub = stmt_list(be, nl);
    2618             : 
    2619             :                 /* continue with non equi-joins */
    2620        3682 :                 while(sexps) {
    2621        2401 :                         if (!en) {
    2622        1281 :                                 en = sexps->h;
    2623             :                                 sexps = NULL;
    2624             :                         }
    2625        3707 :                         for( ; en; en = en->next ) {
    2626        1306 :                                 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    2627             : 
    2628        1306 :                                 if (!s) {
    2629           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2630             :                                         return NULL;
    2631             :                                 }
    2632        1306 :                                 if (s->nrcols == 0) {
    2633           7 :                                         stmt *l = bin_find_smallest_column(be, sub);
    2634           7 :                                         s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
    2635             :                                 }
    2636             :                                 sel = s;
    2637             :                         }
    2638             :                 }
    2639             :                 /* recreate join output */
    2640        1281 :                 jl = stmt_project(be, sel, jl);
    2641        1281 :                 jr = stmt_project(be, sel, jr);
    2642             :         }
    2643             : 
    2644             :         /* construct relation */
    2645      112836 :         l = sa_list(sql->sa);
    2646             : 
    2647      112836 :         if (rel->op == op_left || rel->op == op_full || is_single(rel)) {
    2648             :                 /* we need to add the missing oid's */
    2649       26553 :                 stmt *l = ld = stmt_mirror(be, bin_find_smallest_column(be, left));
    2650       26553 :                 if (rel->op == op_left || rel->op == op_full)
    2651       21554 :                         ld = stmt_tdiff(be, ld, jl, NULL);
    2652       26553 :                 if (is_single(rel) && !list_empty(rel->exps)) {
    2653         268 :                         join = stmt_semijoin(be, l, jl, NULL, NULL, 0, true);
    2654         268 :                         jl = stmt_result(be, join, 0);
    2655         268 :                         jr = stmt_project(be, stmt_result(be, join, 1), jr);
    2656             :                 }
    2657             :         }
    2658      112836 :         if (rel->op == op_right || rel->op == op_full) {
    2659             :                 /* we need to add the missing oid's */
    2660         184 :                 rd = stmt_mirror(be, bin_find_smallest_column(be, right));
    2661         184 :                 rd = stmt_tdiff(be, rd, jr, NULL);
    2662             :         }
    2663             : 
    2664      112836 :         if (rel->op == op_left) { /* used for merge statments, this will be cleaned out on the pushcands branch :) */
    2665       21490 :                 l2 = sa_list(sql->sa);
    2666       21490 :                 list_append(l2, left);
    2667       21490 :                 list_append(l2, right);
    2668       21490 :                 list_append(l2, jl);
    2669       21490 :                 list_append(l2, jr);
    2670       21490 :                 list_append(l2, ld);
    2671             :         }
    2672             : 
    2673     2260569 :         for( n = left->op4.lval->h; n; n = n->next ) {
    2674     2147733 :                 stmt *c = n->data;
    2675     2147733 :                 const char *rnme = table_name(sql->sa, c);
    2676     2147733 :                 const char *nme = column_name(sql->sa, c);
    2677     2147733 :                 stmt *s = stmt_project(be, jl, column(be, c) );
    2678             : 
    2679             :                 /* as append isn't save, we append to a new copy */
    2680     2147733 :                 if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
    2681      158553 :                         s = create_const_column(be, s);
    2682     2147733 :                 if (rel->op == op_left || rel->op == op_full)
    2683      158234 :                         s = stmt_append(be, s, stmt_project(be, ld, c));
    2684     2147733 :                 if (rel->op == op_right || rel->op == op_full)
    2685         432 :                         s = stmt_append(be, s, stmt_const(be, rd, (c->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(sql->sa, tail_type(c), NULL))));
    2686             : 
    2687     2147733 :                 s = stmt_alias(be, s, rnme, nme);
    2688     2147733 :                 list_append(l, s);
    2689             :         }
    2690      411915 :         for( n = right->op4.lval->h; n; n = n->next ) {
    2691      299079 :                 stmt *c = n->data;
    2692      299079 :                 const char *rnme = table_name(sql->sa, c);
    2693      299079 :                 const char *nme = column_name(sql->sa, c);
    2694      299079 :                 stmt *s = stmt_project(be, jr, column(be, c) );
    2695             : 
    2696             :                 /* as append isn't save, we append to a new copy */
    2697      299079 :                 if (rel->op == op_left || rel->op == op_full || rel->op == op_right)
    2698       41613 :                         s = create_const_column(be, s);
    2699      299079 :                 if (rel->op == op_left || rel->op == op_full)
    2700       41260 :                         s = stmt_append(be, s, stmt_const(be, ld, (c->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(sql->sa, tail_type(c), NULL))));
    2701      299079 :                 if (rel->op == op_right || rel->op == op_full)
    2702         456 :                         s = stmt_append(be, s, stmt_project(be, rd, c));
    2703             : 
    2704      299079 :                 s = stmt_alias(be, s, rnme, nme);
    2705      299079 :                 list_append(l, s);
    2706             :         }
    2707      112836 :         res = stmt_list(be, l);
    2708      112836 :         res->extra = l2; /* used for merge statments, this will be cleaned out on the pushcands branch :) */
    2709      112836 :         return res;
    2710             : }
    2711             : 
    2712             : static int
    2713             : exp_is_mark(sql_exp *e)
    2714             : {
    2715        2050 :         if (e->type == e_cmp && (e->flag == mark_in || e->flag == mark_notin))
    2716             :                 return 1;
    2717             :         return 0;
    2718             : }
    2719             : 
    2720             : static stmt *
    2721        2050 : rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
    2722             : {
    2723        2050 :         mvc *sql = be->mvc;
    2724             :         list *l, *jexps = NULL, *mexps = NULL;
    2725             :         node *en = NULL, *n;
    2726             :         stmt *left = NULL, *right = NULL, *join = NULL;
    2727             : 
    2728        2050 :         if (rel->l) /* first construct the left sub relation */
    2729        2050 :                 left = subrel_bin(be, rel->l, refs);
    2730        2050 :         if (rel->r) /* first construct the right sub relation */
    2731        2050 :                 right = subrel_bin(be, rel->r, refs);
    2732        2050 :         left = subrel_project(be, left, refs, rel->l);
    2733        2050 :         right = subrel_project(be, right, refs, rel->r);
    2734        2050 :         if (!left || !right)
    2735             :                 return NULL;
    2736        2050 :         left = row2cols(be, left);
    2737        2050 :         right = row2cols(be, right);
    2738             : 
    2739        2050 :         if (rel->exps) {
    2740        2050 :                 jexps = sa_list(sql->sa);
    2741        2050 :                 mexps = sa_list(sql->sa);
    2742             : 
    2743        4100 :                 for( en = rel->exps->h; en; en = en->next ) {
    2744        2050 :                         sql_exp *e = en->data;
    2745             : 
    2746        2050 :                         assert(e->type == e_cmp);
    2747             :                         if (exp_is_mark(e))
    2748        2050 :                                 append(mexps, e);
    2749             :                         else
    2750           0 :                                 append(jexps, e);
    2751             :                 }
    2752             :         }
    2753             :         /* handle join-ing conditions first */
    2754        2050 :         if (!list_empty(jexps)) {
    2755           0 :                 if (list_empty(mexps))
    2756             :                         mexps = jexps;
    2757             :         }
    2758             :         /* handle mark conditions second */
    2759        2050 :         if (!list_empty(mexps)) {
    2760        2050 :                 assert(list_length(mexps) == 1);
    2761        4100 :                 for( en = mexps->h; en; en = en->next ) {
    2762        2050 :                         sql_exp *e = en->data;
    2763        2050 :                         stmt *ls = exp_bin(be, e->l, left, right, NULL, NULL, NULL, NULL, 1, 0, 0), *rs;
    2764        2050 :                         if (!ls)
    2765             :                                 return NULL;
    2766             : 
    2767        2050 :                         if (!(rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0)))
    2768             :                                 return NULL;
    2769             : 
    2770        2050 :                         if (ls->nrcols == 0)
    2771           5 :                                 ls = stmt_const(be, bin_find_smallest_column(be, left), ls);
    2772        2050 :                         if (rs->nrcols == 0)
    2773           0 :                                 rs = stmt_const(be, bin_find_smallest_column(be, right), rs);
    2774        2050 :                         join = stmt_tdiff2(be, ls, rs, NULL);
    2775             :                 }
    2776             :         }
    2777             : 
    2778             :         /* construct relation */
    2779        2050 :         l = sa_list(sql->sa);
    2780             : 
    2781             :         /* project all the left columns */
    2782       17665 :         for( n = left->op4.lval->h; n; n = n->next ) {
    2783       15615 :                 stmt *c = n->data;
    2784       15615 :                 const char *rnme = table_name(sql->sa, c);
    2785       15615 :                 const char *nme = column_name(sql->sa, c);
    2786       15615 :                 stmt *s = stmt_project(be, join, column(be, c));
    2787             : 
    2788       15615 :                 s = stmt_alias(be, s, rnme, nme);
    2789       15615 :                 list_append(l, s);
    2790             :         }
    2791        2050 :         return stmt_list(be, l);
    2792             : }
    2793             : 
    2794             : static stmt *
    2795        4769 : rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
    2796             : {
    2797        4769 :         mvc *sql = be->mvc;
    2798             :         list *l, *sexps = NULL;
    2799             :         node *en = NULL, *n;
    2800             :         stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c, *lcand = NULL;
    2801             :         int semijoin_only = 0, l_is_base = 0;
    2802             : 
    2803        4769 :         if (rel->op == op_anti && list_length(rel->exps) == 1 && ((sql_exp*)rel->exps->h->data)->flag == mark_notin)
    2804        2050 :                 return rel2bin_antijoin(be, rel, refs);
    2805             : 
    2806        2719 :         if (rel->l) { /* first construct the left sub relation */
    2807             :                 sql_rel *l = rel->l;
    2808        2719 :                 l_is_base = is_basetable(l->op);
    2809        2719 :                 left = subrel_bin(be, l, refs);
    2810             :         }
    2811        2719 :         if (rel->r) /* first construct the right sub relation */
    2812        2719 :                 right = subrel_bin(be, rel->r, refs);
    2813        2719 :         if (!left || !right)
    2814             :                 return NULL;
    2815        2719 :         left = row2cols(be, left);
    2816        2719 :         right = row2cols(be, right);
    2817             :         /*
    2818             :          * split in 2 steps,
    2819             :          *      first cheap join(s) (equality or idx)
    2820             :          *      second selects/filters
    2821             :          */
    2822        2719 :         if (!list_empty(rel->exps)) {
    2823        2661 :                 list *jexps = sa_list(sql->sa);
    2824        2661 :                 sexps = sa_list(sql->sa);
    2825             : 
    2826        2661 :                 split_join_exps(rel, jexps, sexps);
    2827        2661 :                 if (list_empty(jexps)) { /* cross product and continue after project */
    2828           7 :                         right = subrel_project(be, right, refs, rel->r);
    2829           7 :                         stmt *l = bin_find_smallest_column(be, left);
    2830           7 :                         stmt *r = bin_find_smallest_column(be, right);
    2831           7 :                         join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    2832           7 :                         lcand = left->cand;
    2833             :                 }
    2834             : 
    2835        2661 :                 if (join) {
    2836           7 :                         en = jexps->h;
    2837             :                 } else {
    2838        2654 :                         list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
    2839        2654 :                         int idx = 0, equality_only = 1;
    2840             : 
    2841        2654 :                         jexps = get_equi_joins_first(sql, jexps, &equality_only);
    2842        2654 :                         if (!equality_only || list_length(jexps) > 1 || exp_has_func((sql_exp*)jexps->h->data))
    2843        1218 :                                 left = subrel_project(be, left, refs, rel->l);
    2844        2654 :                         right = subrel_project(be, right, refs, rel->r);
    2845             : 
    2846        5509 :                         for( en = jexps->h; en; en = en->next ) {
    2847        3245 :                                 int join_idx = be->join_idx;
    2848        3245 :                                 sql_exp *e = en->data;
    2849             :                                 stmt *s = NULL;
    2850             : 
    2851             :                                 /* only handle simple joins here */
    2852        3245 :                                 if ((exp_has_func(e) && e->flag != cmp_filter) || e->flag == cmp_or || (e->f && is_anti(e))) {
    2853           0 :                                         if (!join && !list_length(lje)) {
    2854           0 :                                                 stmt *l = bin_find_smallest_column(be, left);
    2855           0 :                                                 stmt *r = bin_find_smallest_column(be, right);
    2856           0 :                                                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    2857             :                                         }
    2858             :                                         break;
    2859             :                                 }
    2860        3245 :                                 if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
    2861         201 :                                 (join && e->flag == cmp_filter)))
    2862             :                                         break;
    2863             : 
    2864        2855 :                                 if (equality_only) {
    2865        1936 :                                         int oldvtop = be->mb->vtop, oldstop = be->mb->stop, oldvid = be->mb->vid, swap = 0;
    2866        1936 :                                         stmt *r, *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    2867             : 
    2868        1936 :                                         if (!l) {
    2869             :                                                 swap = 1;
    2870         264 :                                                 clean_mal_statements(be, oldstop, oldvtop, oldvid);
    2871         264 :                                                 l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    2872             :                                         }
    2873        1936 :                                         r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0);
    2874             : 
    2875        1936 :                                         if (swap) {
    2876             :                                                 stmt *t = l;
    2877             :                                                 l = r;
    2878             :                                                 r = t;
    2879             :                                         }
    2880             : 
    2881        1936 :                                         if (!l || !r)
    2882           0 :                                                 return NULL;
    2883        1936 :                                         if (be->no_mitosis && list_length(jexps) == 1 && list_empty(sexps) && rel->op == op_semi && !is_anti(e) && is_equi_exp_(e)) {
    2884           0 :                                                 join = stmt_semijoin(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_semantics(e), false);
    2885             :                                                 semijoin_only = 1;
    2886             :                                                 en = NULL;
    2887           0 :                                                 break;
    2888             :                                         } else
    2889        1936 :                                                 s = stmt_join_cand(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false);
    2890        1936 :                                         lcand = left->cand;
    2891             :                                 } else {
    2892         919 :                                         s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
    2893             :                                 }
    2894        2855 :                                 if (!s) {
    2895           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2896             :                                         return NULL;
    2897             :                                 }
    2898        2855 :                                 if (join_idx != be->join_idx)
    2899             :                                         idx = 1;
    2900             :                                 /* stop on first non equality join */
    2901        2855 :                                 if (!join) {
    2902        2654 :                                         if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
    2903           0 :                                                 if (!en->next && (s->type == st_uselect || s->type == st_uselect2))
    2904             :                                                         join = s;
    2905             :                                                 else
    2906             :                                                         break;
    2907             :                                         }
    2908             :                                         join = s;
    2909         201 :                                 } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
    2910             :                                         /* handle select expressions */
    2911             :                                         break;
    2912             :                                 }
    2913        2855 :                                 if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
    2914        2855 :                                         list_append(lje, s->op1);
    2915        2855 :                                         list_append(rje, s->op2);
    2916        2855 :                                         list_append(exps, e);
    2917             :                                 }
    2918             :                         }
    2919        2654 :                         if (list_length(lje) > 1) {
    2920         115 :                                 join = releqjoin(be, lje, rje, exps, 0 /* use hash */, 0, 0);
    2921        2539 :                         } else if (!join && list_length(lje) == list_length(rje) && list_length(lje)) {
    2922           0 :                                 sql_exp *e = exps->h->data;
    2923           0 :                                 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, 0, is_semantics(e), false);
    2924        2539 :                         } else if (!join) {
    2925           0 :                                 stmt *l = bin_find_smallest_column(be, left);
    2926           0 :                                 stmt *r = bin_find_smallest_column(be, right);
    2927           0 :                                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    2928             :                         }
    2929             :                 }
    2930             :         } else {
    2931          58 :                 right = subrel_project(be, right, refs, rel->r);
    2932          58 :                 stmt *l = bin_find_smallest_column(be, left);
    2933          58 :                 stmt *r = bin_find_smallest_column(be, right);
    2934          58 :                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    2935          58 :                 lcand = left->cand;
    2936             :         }
    2937        2719 :         jl = stmt_result(be, join, 0);
    2938        2719 :         if (en || (sexps && list_length(sexps))) {
    2939             :                 stmt *sub, *sel = NULL;
    2940             :                 list *nl;
    2941             : 
    2942         397 :                 jr = stmt_result(be, join, 1);
    2943             :                 /* construct relation */
    2944         397 :                 nl = sa_list(sql->sa);
    2945             : 
    2946             :                 /* first project after equi-joins */
    2947        5558 :                 for( n = left->op4.lval->h; n; n = n->next ) {
    2948        5161 :                         stmt *c = n->data;
    2949        5161 :                         const char *rnme = table_name(sql->sa, c);
    2950        5161 :                         const char *nme = column_name(sql->sa, c);
    2951        5161 :                         stmt *s = stmt_project(be, jl, column(be, c) );
    2952             : 
    2953        5161 :                         s = stmt_alias(be, s, rnme, nme);
    2954        5161 :                         list_append(nl, s);
    2955             :                 }
    2956        1222 :                 for( n = right->op4.lval->h; n; n = n->next ) {
    2957         825 :                         stmt *c = n->data;
    2958         825 :                         const char *rnme = table_name(sql->sa, c);
    2959         825 :                         const char *nme = column_name(sql->sa, c);
    2960         825 :                         stmt *s = stmt_project(be, jr, column(be, c) );
    2961             : 
    2962         825 :                         s = stmt_alias(be, s, rnme, nme);
    2963         825 :                         list_append(nl, s);
    2964             :                 }
    2965         397 :                 sub = stmt_list(be, nl);
    2966             : 
    2967             :                 /* continue with non equi-joins */
    2968        1184 :                 while(sexps) {
    2969         787 :                         if (!en) {
    2970         397 :                                 en = sexps->h;
    2971             :                                 sexps = NULL;
    2972             :                         }
    2973        1210 :                         for( ; en; en = en->next ) {
    2974         423 :                                 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    2975             : 
    2976         423 :                                 if (!s) {
    2977           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    2978             :                                         return NULL;
    2979             :                                 }
    2980         423 :                                 if (s->nrcols == 0) {
    2981           0 :                                         stmt *l = bin_find_smallest_column(be, sub);
    2982           0 :                                         s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
    2983             :                                 }
    2984             :                                 sel = s;
    2985             :                         }
    2986             :                 }
    2987             :                 /* recreate join output */
    2988         397 :                 jl = stmt_project(be, sel, jl);
    2989             :         }
    2990             : 
    2991             :         /* construct relation */
    2992        2719 :         l = sa_list(sql->sa);
    2993             : 
    2994             :         /* We did a full join, thats too much.
    2995             :            Reduce this using difference and intersect */
    2996        2719 :         if (!semijoin_only) {
    2997        2719 :                 c = stmt_mirror(be, bin_find_smallest_column(be, left));
    2998        2719 :                 if (rel->op == op_anti) {
    2999         286 :                         join = stmt_tdiff(be, c, jl, lcand);
    3000             :                 } else {
    3001        2433 :                         if (lcand)
    3002        1106 :                                 join = stmt_semijoin(be, c, jl, lcand, NULL/*right->cand*/, 0, false);
    3003             :                         else
    3004        1327 :                                 join = stmt_tinter(be, c, jl, false);
    3005             :                 }
    3006             :         }
    3007             : 
    3008             :         /* project all the left columns */
    3009       19349 :         for( n = left->op4.lval->h; n; n = n->next ) {
    3010       16630 :                 stmt *c = n->data, *s;
    3011       16630 :                 const char *rnme = table_name(sql->sa, c);
    3012       16630 :                 const char *nme = column_name(sql->sa, c);
    3013             : 
    3014       16630 :                 if (semijoin_only && l_is_base && nme[0] == '%' && strcmp(nme, TID) == 0)
    3015             :                         s = join;
    3016             :                 else
    3017       16630 :                         s = stmt_project(be, join, column(be, c));
    3018             : 
    3019       16630 :                 s = stmt_alias(be, s, rnme, nme);
    3020       16630 :                 list_append(l, s);
    3021             :         }
    3022        2719 :         return stmt_list(be, l);
    3023             : }
    3024             : 
    3025             : static stmt *
    3026        1931 : rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
    3027             : {
    3028        1931 :         mvc *sql = be->mvc;
    3029             :         node *n;
    3030             :         stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
    3031        1931 :         list *rl = sa_list(sql->sa), *tids;
    3032             : 
    3033             :         /* single values are unique */
    3034        1931 :         if (s->key && s->nrcols == 0)
    3035             :                 return s;
    3036             : 
    3037             :         /* Use 'all' tid columns */
    3038             :         if (/* DISABLES CODE */ (0) && (tids = bin_find_columns(be, s, TID)) != NULL) {
    3039             :                 for (n = tids->h; n; n = n->next) {
    3040             :                         stmt *t = n->data;
    3041             : 
    3042             :                         g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
    3043             :                         grp = stmt_result(be, g, 0);
    3044             :                         ext = stmt_result(be, g, 1);
    3045             :                         cnt = stmt_result(be, g, 2);
    3046             :                 }
    3047             :         } else {
    3048        5959 :                 for (n = s->op4.lval->h; n; n = n->next) {
    3049        4036 :                         stmt *t = n->data;
    3050             : 
    3051        4036 :                         g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
    3052        4036 :                         grp = stmt_result(be, g, 0);
    3053        4036 :                         ext = stmt_result(be, g, 1);
    3054        4036 :                         cnt = stmt_result(be, g, 2);
    3055             :                 }
    3056             :         }
    3057        1923 :         if (!ext)
    3058             :                 return NULL;
    3059             : 
    3060        5959 :         for (n = s->op4.lval->h; n; n = n->next) {
    3061        4036 :                 stmt *t = n->data;
    3062             : 
    3063        4036 :                 list_append(rl, stmt_project(be, ext, t));
    3064             :         }
    3065             : 
    3066        1923 :         if (distinct)
    3067           0 :                 *distinct = ext;
    3068        1923 :         s = stmt_list(be, rl);
    3069        1923 :         return s;
    3070             : }
    3071             : 
    3072             : static stmt *
    3073           8 : rel2bin_single(backend *be, stmt *s)
    3074             : {
    3075           8 :         if (s->key && s->nrcols == 0)
    3076             :                 return s;
    3077             : 
    3078           8 :         mvc *sql = be->mvc;
    3079           8 :         list *rl = sa_list(sql->sa);
    3080             : 
    3081          16 :         for (node *n = s->op4.lval->h; n; n = n->next) {
    3082           8 :                 stmt *t = n->data;
    3083           8 :                 const char *rnme = table_name(sql->sa, t);
    3084           8 :                 const char *nme = column_name(sql->sa, t);
    3085           8 :                 sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", tail_type(t), NULL, F_AGGR);
    3086             : 
    3087           8 :                 t = stmt_aggr(be, t, NULL, NULL, zero_or_one, 1, 0, 1);
    3088           8 :                 t = stmt_alias(be, t, rnme, nme);
    3089           8 :                 list_append(rl, t);
    3090             :         }
    3091           8 :         s = stmt_list(be, rl);
    3092           8 :         return s;
    3093             : }
    3094             : 
    3095             : static stmt *
    3096       15693 : rel_rename(backend *be, sql_rel *rel, stmt *sub)
    3097             : {
    3098       15693 :         mvc *sql = be->mvc;
    3099             : 
    3100             :         (void) sql;
    3101       15693 :         if (rel->exps) {
    3102             :                 node *en, *n;
    3103       15693 :                 list *l = sa_list(be->mvc->sa);
    3104             : 
    3105       84771 :                 for( en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next ) {
    3106       69078 :                         sql_exp *exp = en->data;
    3107       69078 :                         stmt *s = n->data;
    3108             : 
    3109       69078 :                         if (!s) {
    3110           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3111             :                                 return NULL;
    3112             :                         }
    3113       69078 :                         s = stmt_rename(be, exp, s);
    3114       69078 :                         list_append(l, s);
    3115             :                 }
    3116       15693 :                 sub = stmt_list(be, l);
    3117             :         }
    3118             :         return sub;
    3119             : }
    3120             : 
    3121             : static stmt *
    3122       13239 : rel2bin_union(backend *be, sql_rel *rel, list *refs)
    3123             : {
    3124       13239 :         mvc *sql = be->mvc;
    3125             :         list *l;
    3126             :         node *n, *m;
    3127             :         stmt *left = NULL, *right = NULL, *sub;
    3128             : 
    3129       13239 :         if (rel->l) /* first construct the left sub relation */
    3130       13239 :                 left = subrel_bin(be, rel->l, refs);
    3131       13239 :         if (rel->r) /* first construct the right sub relation */
    3132       13239 :                 right = subrel_bin(be, rel->r, refs);
    3133       13239 :         left = subrel_project(be, left, refs, rel->l);
    3134       13239 :         right = subrel_project(be, right, refs, rel->r);
    3135       13239 :         if (!left || !right)
    3136             :                 return NULL;
    3137             : 
    3138             :         /* construct relation */
    3139       13239 :         l = sa_list(sql->sa);
    3140       79407 :         for( n = left->op4.lval->h, m = right->op4.lval->h; n && m;
    3141       66168 :                  n = n->next, m = m->next ) {
    3142       66168 :                 stmt *c1 = n->data;
    3143       66168 :                 stmt *c2 = m->data;
    3144       66168 :                 const char *rnme = table_name(sql->sa, c1);
    3145       66168 :                 const char *nme = column_name(sql->sa, c1);
    3146             :                 stmt *s;
    3147             : 
    3148       66168 :                 s = stmt_append(be, create_const_column(be, c1), c2);
    3149       66168 :                 s = stmt_alias(be, s, rnme, nme);
    3150       66168 :                 list_append(l, s);
    3151             :         }
    3152       13239 :         sub = stmt_list(be, l);
    3153             : 
    3154       13239 :         sub = rel_rename(be, rel, sub);
    3155       13239 :         if (need_distinct(rel))
    3156        1923 :                 sub = rel2bin_distinct(be, sub, NULL);
    3157       13239 :         if (is_single(rel))
    3158           8 :                 sub = rel2bin_single(be, sub);
    3159             :         return sub;
    3160             : }
    3161             : 
    3162             : static stmt *
    3163        2059 : rel2bin_except(backend *be, sql_rel *rel, list *refs)
    3164             : {
    3165        2059 :         mvc *sql = be->mvc;
    3166        2059 :         sql_subtype *lng = sql_bind_localtype("lng");
    3167             :         list *stmts;
    3168             :         node *n, *m;
    3169             :         stmt *left = NULL, *right = NULL, *sub;
    3170             :         sql_subfunc *min;
    3171             : 
    3172             :         stmt *lg = NULL, *rg = NULL;
    3173             :         stmt *lgrp = NULL, *rgrp = NULL;
    3174             :         stmt *lext = NULL, *rext = NULL, *next = NULL;
    3175             :         stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
    3176             :         stmt *s, *lm, *rm;
    3177        2059 :         list *lje = sa_list(sql->sa);
    3178        2059 :         list *rje = sa_list(sql->sa);
    3179             : 
    3180        2059 :         if (rel->l) /* first construct the left sub relation */
    3181        2059 :                 left = subrel_bin(be, rel->l, refs);
    3182        2059 :         if (rel->r) /* first construct the right sub relation */
    3183        2059 :                 right = subrel_bin(be, rel->r, refs);
    3184        2059 :         if (!left || !right)
    3185             :                 return NULL;
    3186        2059 :         left = subrel_project(be, left, refs, rel->l);
    3187        2059 :         right = subrel_project(be, right, refs, rel->r);
    3188        2059 :         left = row2cols(be, left);
    3189        2059 :         right = row2cols(be, right);
    3190             : 
    3191             :         /*
    3192             :          * The multi column except is handled using group by's and
    3193             :          * group size counts on both sides of the intersect. We then
    3194             :          * return for each group of L with min(L.count,R.count),
    3195             :          * number of rows.
    3196             :          */
    3197        4453 :         for (n = left->op4.lval->h; n; n = n->next) {
    3198        2394 :                 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
    3199        2394 :                 lgrp = stmt_result(be, lg, 0);
    3200        2394 :                 lext = stmt_result(be, lg, 1);
    3201        2394 :                 lcnt = stmt_result(be, lg, 2);
    3202             :         }
    3203        4453 :         for (n = right->op4.lval->h; n; n = n->next) {
    3204        2394 :                 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
    3205        2394 :                 rgrp = stmt_result(be, rg, 0);
    3206        2394 :                 rext = stmt_result(be, rg, 1);
    3207        2394 :                 rcnt = stmt_result(be, rg, 2);
    3208             :         }
    3209             : 
    3210        2059 :         if (!lg || !rg)
    3211             :                 return NULL;
    3212             : 
    3213        2059 :         if (need_distinct(rel)) {
    3214        1935 :                 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
    3215        1935 :                 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
    3216             :         }
    3217             : 
    3218             :         /* now find the matching groups */
    3219        4453 :         for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
    3220        2394 :                 stmt *l = column(be, n->data);
    3221        2394 :                 stmt *r = column(be, m->data);
    3222             : 
    3223        2394 :                 l = stmt_project(be, lext, l);
    3224        2394 :                 r = stmt_project(be, rext, r);
    3225        2394 :                 list_append(lje, l);
    3226        2394 :                 list_append(rje, r);
    3227             :         }
    3228        2059 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
    3229        2059 :         lm = stmt_result(be, s, 0);
    3230        2059 :         rm = stmt_result(be, s, 1);
    3231             : 
    3232        2059 :         s = stmt_mirror(be, lext);
    3233        2059 :         s = stmt_tdiff(be, s, lm, NULL);
    3234             : 
    3235             :         /* first we find those missing in R */
    3236        2059 :         next = stmt_project(be, s, lext);
    3237        2059 :         ncnt = stmt_project(be, s, lcnt);
    3238        2059 :         zero = stmt_const(be, s, stmt_atom_lng(be, 0));
    3239             : 
    3240             :         /* ext, lcount, rcount */
    3241        2059 :         lext = stmt_project(be, lm, lext);
    3242        2059 :         lcnt = stmt_project(be, lm, lcnt);
    3243        2059 :         rcnt = stmt_project(be, rm, rcnt);
    3244             : 
    3245             :         /* append those missing in L */
    3246        2059 :         lext = stmt_append(be, lext, next);
    3247        2059 :         lcnt = stmt_append(be, lcnt, ncnt);
    3248        2059 :         rcnt = stmt_append(be, rcnt, zero);
    3249             : 
    3250        2059 :         min = sql_bind_func(sql, "sys", "sql_sub", lng, lng, F_FUNC);
    3251        2059 :         s = stmt_binop(be, lcnt, rcnt, NULL, min); /* use count */
    3252             : 
    3253             :         /* now we have gid,cnt, blowup to full groupsizes */
    3254        2059 :         s = stmt_gen_group(be, lext, s);
    3255             : 
    3256             :         /* project columns of left hand expression */
    3257        2059 :         stmts = sa_list(sql->sa);
    3258        4453 :         for (n = left->op4.lval->h; n; n = n->next) {
    3259        2394 :                 stmt *c1 = column(be, n->data);
    3260             :                 const char *rnme = NULL;
    3261        2394 :                 const char *nme = column_name(sql->sa, c1);
    3262             : 
    3263             :                 /* retain name via the stmt_alias */
    3264        2394 :                 c1 = stmt_project(be, s, c1);
    3265             : 
    3266        2394 :                 rnme = table_name(sql->sa, c1);
    3267        2394 :                 c1 = stmt_alias(be, c1, rnme, nme);
    3268        2394 :                 list_append(stmts, c1);
    3269             :         }
    3270        2059 :         sub = stmt_list(be, stmts);
    3271        2059 :         return rel_rename(be, rel, sub);
    3272             : }
    3273             : 
    3274             : static stmt *
    3275         395 : rel2bin_inter(backend *be, sql_rel *rel, list *refs)
    3276             : {
    3277         395 :         mvc *sql = be->mvc;
    3278         395 :         sql_subtype *lng = sql_bind_localtype("lng");
    3279             :         list *stmts;
    3280             :         node *n, *m;
    3281             :         stmt *left = NULL, *right = NULL, *sub;
    3282             :         sql_subfunc *min;
    3283             : 
    3284             :         stmt *lg = NULL, *rg = NULL;
    3285             :         stmt *lgrp = NULL, *rgrp = NULL;
    3286             :         stmt *lext = NULL, *rext = NULL;
    3287             :         stmt *lcnt = NULL, *rcnt = NULL;
    3288             :         stmt *s, *lm, *rm;
    3289         395 :         list *lje = sa_list(sql->sa);
    3290         395 :         list *rje = sa_list(sql->sa);
    3291             : 
    3292         395 :         if (rel->l) /* first construct the left sub relation */
    3293         395 :                 left = subrel_bin(be, rel->l, refs);
    3294         395 :         if (rel->r) /* first construct the right sub relation */
    3295         395 :                 right = subrel_bin(be, rel->r, refs);
    3296         395 :         left = subrel_project(be, left, refs, rel->l);
    3297         395 :         right = subrel_project(be, right, refs, rel->r);
    3298         395 :         if (!left || !right)
    3299             :                 return NULL;
    3300         395 :         left = row2cols(be, left);
    3301             : 
    3302             :         /*
    3303             :          * The multi column intersect is handled using group by's and
    3304             :          * group size counts on both sides of the intersect. We then
    3305             :          * return for each group of L with min(L.count,R.count),
    3306             :          * number of rows.
    3307             :          */
    3308         913 :         for (n = left->op4.lval->h; n; n = n->next) {
    3309         518 :                 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
    3310         518 :                 lgrp = stmt_result(be, lg, 0);
    3311         518 :                 lext = stmt_result(be, lg, 1);
    3312         518 :                 lcnt = stmt_result(be, lg, 2);
    3313             :         }
    3314         913 :         for (n = right->op4.lval->h; n; n = n->next) {
    3315         518 :                 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
    3316         518 :                 rgrp = stmt_result(be, rg, 0);
    3317         518 :                 rext = stmt_result(be, rg, 1);
    3318         518 :                 rcnt = stmt_result(be, rg, 2);
    3319             :         }
    3320             : 
    3321         395 :         if (!lg || !rg)
    3322             :                 return NULL;
    3323             : 
    3324         395 :         if (need_distinct(rel)) {
    3325         359 :                 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
    3326         359 :                 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
    3327             :         }
    3328             : 
    3329             :         /* now find the matching groups */
    3330         913 :         for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
    3331         518 :                 stmt *l = column(be, n->data);
    3332         518 :                 stmt *r = column(be, m->data);
    3333             : 
    3334         518 :                 l = stmt_project(be, lext, l);
    3335         518 :                 r = stmt_project(be, rext, r);
    3336         518 :                 list_append(lje, l);
    3337         518 :                 list_append(rje, r);
    3338             :         }
    3339         395 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /* is_semantics */);
    3340         395 :         lm = stmt_result(be, s, 0);
    3341         395 :         rm = stmt_result(be, s, 1);
    3342             : 
    3343             :         /* ext, lcount, rcount */
    3344         395 :         lext = stmt_project(be, lm, lext);
    3345         395 :         lcnt = stmt_project(be, lm, lcnt);
    3346         395 :         rcnt = stmt_project(be, rm, rcnt);
    3347             : 
    3348         395 :         min = sql_bind_func(sql, "sys", "sql_min", lng, lng, F_FUNC);
    3349         395 :         s = stmt_binop(be, lcnt, rcnt, NULL, min);
    3350             : 
    3351             :         /* now we have gid,cnt, blowup to full groupsizes */
    3352         395 :         s = stmt_gen_group(be, lext, s);
    3353             : 
    3354             :         /* project columns of left hand expression */
    3355         395 :         stmts = sa_list(sql->sa);
    3356         913 :         for (n = left->op4.lval->h; n; n = n->next) {
    3357         518 :                 stmt *c1 = column(be, n->data);
    3358             :                 const char *rnme = NULL;
    3359         518 :                 const char *nme = column_name(sql->sa, c1);
    3360             : 
    3361             :                 /* retain name via the stmt_alias */
    3362         518 :                 c1 = stmt_project(be, s, c1);
    3363             : 
    3364         518 :                 rnme = table_name(sql->sa, c1);
    3365         518 :                 c1 = stmt_alias(be, c1, rnme, nme);
    3366         518 :                 list_append(stmts, c1);
    3367             :         }
    3368         395 :         sub = stmt_list(be, stmts);
    3369         395 :         return rel_rename(be, rel, sub);
    3370             : }
    3371             : 
    3372             : static stmt *
    3373       15132 : sql_reorder(backend *be, stmt *order, stmt *s)
    3374             : {
    3375       15132 :         list *l = sa_list(be->mvc->sa);
    3376             :         node *n;
    3377             : 
    3378       74450 :         for (n = s->op4.lval->h; n; n = n->next) {
    3379       59318 :                 stmt *sc = n->data;
    3380       59318 :                 const char *cname = column_name(be->mvc->sa, sc);
    3381       59318 :                 const char *tname = table_name(be->mvc->sa, sc);
    3382             : 
    3383       59318 :                 sc = stmt_project(be, order, sc);
    3384       59318 :                 sc = stmt_alias(be, sc, tname, cname );
    3385       59318 :                 list_append(l, sc);
    3386             :         }
    3387       15132 :         return stmt_list(be, l);
    3388             : }
    3389             : 
    3390             : static sql_exp*
    3391        1109 : topn_limit(sql_rel *rel)
    3392             : {
    3393        1109 :         if (rel->exps) {
    3394        1109 :                 sql_exp *limit = rel->exps->h->data;
    3395        1109 :                 if (exp_is_null(limit)) /* If the limit is NULL, ignore the value */
    3396             :                         return NULL;
    3397        1092 :                 return limit;
    3398             :         }
    3399             :         return NULL;
    3400             : }
    3401             : 
    3402             : static sql_exp*
    3403        1109 : topn_offset( sql_rel *rel )
    3404             : {
    3405        1109 :         if (rel->exps && list_length(rel->exps) > 1) {
    3406          56 :                 sql_exp *offset = rel->exps->h->next->data;
    3407             : 
    3408          56 :                 return offset;
    3409             :         }
    3410             :         return NULL;
    3411             : }
    3412             : 
    3413             : static stmt *
    3414      283500 : rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
    3415             : {
    3416      283500 :         mvc *sql = be->mvc;
    3417             :         list *pl;
    3418             :         node *en, *n;
    3419             :         stmt *sub = NULL, *psub = NULL;
    3420             :         stmt *l = NULL;
    3421             : 
    3422      283500 :         if (topn) {
    3423         329 :                 sql_exp *le = topn_limit(topn);
    3424         329 :                 sql_exp *oe = topn_offset(topn);
    3425             : 
    3426         329 :                 if (!le) { /* Don't push only offset */
    3427             :                         topn = NULL;
    3428             :                 } else {
    3429         325 :                         l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3430         325 :                         if(!l)
    3431             :                                 return NULL;
    3432         325 :                         if (oe) {
    3433          14 :                                 sql_subtype *lng = sql_bind_localtype("lng");
    3434          14 :                                 sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, lng, 2, lng, lng);
    3435          14 :                                 stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3436          14 :                                 if(!o)
    3437             :                                         return NULL;
    3438          14 :                                 l = stmt_binop(be, l, o, NULL, add);
    3439             :                         }
    3440             :                 }
    3441             :         }
    3442             : 
    3443      283500 :         if (!rel->exps)
    3444           0 :                 return stmt_none(be);
    3445             : 
    3446      283500 :         if (rel->l) { /* first construct the sub relation */
    3447             :                 sql_rel *l = rel->l;
    3448      184702 :                 if (l->op == op_ddl) {
    3449        1007 :                         sql_table *t = rel_ddl_table_get(l);
    3450             : 
    3451        1007 :                         if (t)
    3452        1007 :                                 sub = rel2bin_sql_table(be, t, rel->exps);
    3453             :                 } else {
    3454      183695 :                         sub = subrel_bin(be, rel->l, refs);
    3455             :                 }
    3456      184702 :                 sub = subrel_project(be, sub, refs, rel->l);
    3457      184702 :                 if (!sub)
    3458             :                         return NULL;
    3459             :         }
    3460             : 
    3461      283500 :         pl = sa_list(sql->sa);
    3462      283500 :         if (sub)
    3463      184702 :                 pl->expected_cnt = list_length(sub->op4.lval);
    3464      283500 :         psub = stmt_list(be, pl);
    3465     1686982 :         for( en = rel->exps->h; en; en = en->next ) {
    3466     1403483 :                 sql_exp *exp = en->data;
    3467     1403483 :                 int oldvtop = be->mb->vtop, oldstop = be->mb->stop, oldvid = be->mb->vid;
    3468     1403483 :                 stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL, 0, 0, 0);
    3469             : 
    3470     1403483 :                 if (!s) { /* try with own projection as well, but first clean leftover statements */
    3471       14068 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    3472       14068 :                         s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    3473             :                 }
    3474     1403483 :                 if (!s) /* error */
    3475             :                         return NULL;
    3476             :                 /* single value with limit */
    3477     1403482 :                 if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
    3478         104 :                         s = const_column(be, s);
    3479     1403378 :                 else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
    3480       28381 :                         s = stmt_const(be, bin_find_smallest_column(be, sub), s);
    3481             : 
    3482     1403482 :                 if (!exp_name(exp))
    3483       72929 :                         exp_label(sql->sa, exp, ++sql->label);
    3484     1403481 :                 s = stmt_rename(be, exp, s);
    3485     1403481 :                 column_name(sql->sa, s); /* save column name */
    3486     1403481 :                 list_append(pl, s);
    3487             :         }
    3488      283499 :         stmt_set_nrcols(psub);
    3489             : 
    3490             :         /* In case of a topn
    3491             :                 if both order by and distinct: then get first order by col
    3492             :                 do topn on it. Project all again! Then rest
    3493             :         */
    3494      283499 :         if (topn && rel->r) {
    3495         312 :                 list *oexps = rel->r, *npl = sa_list(sql->sa);
    3496             :                 /* distinct, topn returns atleast N (unique groups) */
    3497         312 :                 int distinct = need_distinct(rel);
    3498             :                 stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
    3499             : 
    3500        1100 :                 for (n=oexps->h; n; n = n->next) {
    3501         788 :                         sql_exp *orderbycole = n->data;
    3502         788 :                         int last = (n->next == NULL);
    3503             : 
    3504         788 :                         stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    3505             : 
    3506         788 :                         if (!orderbycolstmt)
    3507             :                                 return NULL;
    3508             : 
    3509             :                         /* handle constants */
    3510         788 :                         if (orderbycolstmt->nrcols == 0 && !last) /* no need to sort on constant */
    3511           0 :                                 continue;
    3512         788 :                         orderbycolstmt = column(be, orderbycolstmt);
    3513         788 :                         if (!limit) {   /* topn based on a single column */
    3514         312 :                                 limit = stmt_limit(be, orderbycolstmt, NULL, NULL, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
    3515             :                         } else {        /* topn based on 2 columns */
    3516         476 :                                 limit = stmt_limit(be, orderbycolstmt, lpiv, lgid, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), last, 1);
    3517             :                         }
    3518         788 :                         if (!limit)
    3519             :                                 return NULL;
    3520             :                         lpiv = limit;
    3521         788 :                         if (!last) {
    3522         476 :                                 lpiv = stmt_result(be, limit, 0);
    3523         476 :                                 lgid = stmt_result(be, limit, 1);
    3524             :                         }
    3525             :                 }
    3526             : 
    3527             :                 limit = lpiv;
    3528        1931 :                 for ( n=pl->h ; n; n = n->next)
    3529        1619 :                         list_append(npl, stmt_project(be, limit, column(be, n->data)));
    3530         312 :                 psub = stmt_list(be, npl);
    3531             : 
    3532             :                 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
    3533         312 :                 pl = sub->op4.lval;
    3534         312 :                 npl = sa_list(sql->sa);
    3535        2077 :                 for ( n=pl->h ; n; n = n->next) {
    3536        1765 :                         list_append(npl, stmt_project(be, limit, column(be, n->data)));
    3537             :                 }
    3538         312 :                 sub = stmt_list(be, npl);
    3539             :         }
    3540      283499 :         if (need_distinct(rel)) {
    3541           8 :                 stmt *distinct = NULL;
    3542           8 :                 psub = rel2bin_distinct(be, psub, &distinct);
    3543             :                 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
    3544           8 :                 if (sub && distinct) {
    3545           0 :                         list *npl = sa_list(sql->sa);
    3546             : 
    3547           0 :                         pl = sub->op4.lval;
    3548           0 :                         for ( n=pl->h ; n; n = n->next)
    3549           0 :                                 list_append(npl, stmt_project(be, distinct, column(be, n->data)));
    3550           0 :                         sub = stmt_list(be, npl);
    3551             :                 }
    3552             :         }
    3553      283499 :         if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
    3554             :                 list *oexps = rel->r;
    3555             :                 stmt *orderby_ids = NULL, *orderby_grp = NULL;
    3556             : 
    3557       47363 :                 for (en = oexps->h; en; en = en->next) {
    3558             :                         stmt *orderby = NULL;
    3559       32204 :                         sql_exp *orderbycole = en->data;
    3560       32204 :                         stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    3561             : 
    3562       32204 :                         if (!orderbycolstmt) {
    3563           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3564             :                                 return NULL;
    3565             :                         }
    3566             :                         /* single values don't need sorting */
    3567       32204 :                         if (orderbycolstmt->nrcols == 0)
    3568          43 :                                 continue;
    3569       32161 :                         if (orderby_ids)
    3570       17029 :                                 orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
    3571             :                         else
    3572       15132 :                                 orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
    3573       32161 :                         orderby_ids = stmt_result(be, orderby, 1);
    3574       32161 :                         orderby_grp = stmt_result(be, orderby, 2);
    3575             :                 }
    3576       15159 :                 if (orderby_ids)
    3577       15132 :                         psub = sql_reorder(be, orderby_ids, psub);
    3578             :         }
    3579             :         return psub;
    3580             : }
    3581             : 
    3582             : static stmt *
    3583           0 : rel2bin_predicate(backend *be)
    3584             : {
    3585           0 :         return const_column(be, stmt_bool(be, 1));
    3586             : }
    3587             : 
    3588             : static stmt *
    3589       84141 : rel2bin_select(backend *be, sql_rel *rel, list *refs)
    3590             : {
    3591       84141 :         mvc *sql = be->mvc;
    3592             :         node *en;
    3593             :         stmt *sub = NULL, *sel = NULL;
    3594             :         stmt *predicate = NULL;
    3595             : 
    3596       84141 :         if (rel->l) { /* first construct the sub relation */
    3597       84141 :                 sub = subrel_bin(be, rel->l, refs);
    3598       84141 :                 if (!sub)
    3599             :                         return NULL;
    3600       84141 :                 sel = sub->cand;
    3601       84141 :                 sub = row2cols(be, sub);
    3602             :         }
    3603       84141 :         if (!sub && !predicate)
    3604           0 :                 predicate = rel2bin_predicate(be);
    3605       84141 :         if (list_empty(rel->exps)) {
    3606        1398 :                 if (sub)
    3607             :                         return sub;
    3608           0 :                 if (predicate)
    3609             :                         return predicate;
    3610           0 :                 assert(0);
    3611             :         }
    3612       82743 :         en = rel->exps->h;
    3613       82743 :         if (!sub && predicate) {
    3614           0 :                 list *l = sa_list(sql->sa);
    3615             :                 assert(predicate);
    3616           0 :                 append(l, predicate);
    3617           0 :                 sub = stmt_list(be, l);
    3618             :         }
    3619             :         /* handle possible index lookups */
    3620             :         /* expressions are in index order ! */
    3621       82743 :         if (sub && en) {
    3622       82743 :                 sql_exp *e = en->data;
    3623             :                 prop *p;
    3624             : 
    3625       82743 :                 if ((p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
    3626           2 :                         sql_idx *i = p->value;
    3627             : 
    3628           2 :                         sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, en);
    3629             :                 }
    3630             :         }
    3631      178661 :         for( en = rel->exps->h; en; en = en->next ) {
    3632       95918 :                 sql_exp *e = en->data;
    3633       95918 :                 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    3634             : 
    3635       95918 :                 if (!s) {
    3636           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3637             :                         return NULL;
    3638             :                 }
    3639       95918 :                 if (s->nrcols == 0){
    3640        1234 :                         if (!predicate && sub)
    3641        1210 :                                 predicate = stmt_const(be, bin_find_smallest_column(be, sub), stmt_bool(be, 1));
    3642        1234 :                         if (e->type != e_cmp) {
    3643         717 :                                 sql_subtype *bt = sql_bind_localtype("bit");
    3644             : 
    3645         717 :                                 s = stmt_convert(be, s, NULL, exp_subtype(e), bt);
    3646             :                         }
    3647        1234 :                         sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0, 0);
    3648       94684 :                 } else if (e->type != e_cmp) {
    3649           0 :                         sel = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
    3650             :                 } else {
    3651             :                         sel = s;
    3652             :                 }
    3653             :         }
    3654             : 
    3655       82743 :         if (sub && sel) {
    3656       82743 :                 sub = stmt_list(be, sub->op4.lval); /* protect against references */
    3657       82743 :                 sub->cand = sel;
    3658             :         }
    3659             :         return sub;
    3660             : }
    3661             : 
    3662             : static stmt *
    3663       15582 : rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
    3664             : {
    3665       15582 :         mvc *sql = be->mvc;
    3666       15582 :         list *l, *aggrs, *gbexps = sa_list(sql->sa);
    3667             :         node *n, *en;
    3668             :         stmt *sub = NULL, *cursub;
    3669             :         stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
    3670             : 
    3671       15582 :         if (rel->l) { /* first construct the sub relation */
    3672       15582 :                 sub = subrel_bin(be, rel->l, refs);
    3673       15582 :                 sub = subrel_project(be, sub, refs, rel->l);
    3674       15582 :                 if (!sub)
    3675             :                         return NULL;
    3676             :         }
    3677             : 
    3678       15582 :         if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
    3679         349 :                 list *newl = sa_list(sql->sa);
    3680             :                 node *n;
    3681             : 
    3682         792 :                 for(n=sub->op4.lval->h; n; n = n->next) {
    3683         443 :                         const char *cname = column_name(sql->sa, n->data);
    3684         443 :                         const char *tname = table_name(sql->sa, n->data);
    3685         443 :                         stmt *s = column(be, n->data);
    3686             : 
    3687         443 :                         s = stmt_alias(be, s, tname, cname );
    3688         443 :                         append(newl, s);
    3689             :                 }
    3690         349 :                 sub = stmt_list(be, newl);
    3691             :         }
    3692             : 
    3693             :         /* groupby columns */
    3694             : 
    3695             :         /* Keep groupby columns, sub that they can be lookup in the aggr list */
    3696       15582 :         if (rel->r) {
    3697             :                 list *exps = rel->r;
    3698             : 
    3699       30849 :                 for( en = exps->h; en; en = en->next ) {
    3700       18735 :                         sql_exp *e = en->data;
    3701       18735 :                         stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3702             : 
    3703       18735 :                         if (!gbcol) {
    3704           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3705             :                                 return NULL;
    3706             :                         }
    3707       18735 :                         if (!gbcol->nrcols)
    3708          23 :                                 gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
    3709       18735 :                         groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
    3710       18735 :                         grp = stmt_result(be, groupby, 0);
    3711       18735 :                         ext = stmt_result(be, groupby, 1);
    3712       18735 :                         cnt = stmt_result(be, groupby, 2);
    3713       18735 :                         gbcol = stmt_alias(be, gbcol, exp_find_rel_name(e), exp_name(e));
    3714       18735 :                         list_append(gbexps, gbcol);
    3715             :                 }
    3716             :         }
    3717             :         /* now aggregate */
    3718       15582 :         l = sa_list(sql->sa);
    3719       15581 :         aggrs = rel->exps;
    3720       15581 :         cursub = stmt_list(be, l);
    3721       47328 :         for( n = aggrs->h; n; n = n->next ) {
    3722       31746 :                 sql_exp *aggrexp = n->data;
    3723             :                 stmt *aggrstmt = NULL;
    3724             :                 int oldvtop, oldstop, oldvid;
    3725             : 
    3726             :                 /* first look in the current aggr list (l) and group by column list */
    3727       31746 :                 if (l && !aggrstmt && aggrexp->type == e_column)
    3728       19508 :                         aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
    3729       31746 :                 if (gbexps && !aggrstmt && aggrexp->type == e_column) {
    3730       19491 :                         aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
    3731       19491 :                         if (aggrstmt && groupby) {
    3732       17803 :                                 aggrstmt = stmt_project(be, ext, aggrstmt);
    3733       17803 :                                 if (list_length(gbexps) == 1)
    3734        7297 :                                         aggrstmt->key = 1;
    3735             :                         }
    3736             :                 }
    3737             : 
    3738       31746 :                 oldvtop = be->mb->vtop;
    3739       31746 :                 oldstop = be->mb->stop;
    3740       31746 :                 oldvid = be->mb->vid;
    3741       31746 :                 if (!aggrstmt)
    3742       13926 :                         aggrstmt = exp_bin(be, aggrexp, sub, NULL, grp, ext, cnt, NULL, 0, 0, 0);
    3743             :                 /* maybe the aggr uses intermediate results of this group by,
    3744             :                    therefore we pass the group by columns too
    3745             :                  */
    3746       31747 :                 if (!aggrstmt) {
    3747           1 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    3748           1 :                         aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL, 0, 0, 0);
    3749             :                 }
    3750       31747 :                 if (!aggrstmt) {
    3751           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3752             :                         return NULL;
    3753             :                 }
    3754             : 
    3755       31747 :                 if (!aggrstmt->nrcols && ext && ext->nrcols)
    3756          10 :                         aggrstmt = stmt_const(be, ext, aggrstmt);
    3757             : 
    3758       31747 :                 aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
    3759       31747 :                 list_append(l, aggrstmt);
    3760             :         }
    3761       15582 :         stmt_set_nrcols(cursub);
    3762       15582 :         return cursub;
    3763             : }
    3764             : 
    3765             : static stmt *
    3766         780 : rel2bin_topn(backend *be, sql_rel *rel, list *refs)
    3767             : {
    3768         780 :         mvc *sql = be->mvc;
    3769             :         sql_exp *oe = NULL, *le = NULL;
    3770             :         stmt *sub = NULL, *l = NULL, *o = NULL;
    3771             :         node *n;
    3772             : 
    3773         780 :         if (rel->l) { /* first construct the sub relation */
    3774             :                 sql_rel *rl = rel->l;
    3775             : 
    3776         780 :                 if (rl->op == op_project) {
    3777         329 :                         sub = rel2bin_project(be, rl, refs, rel);
    3778             :                 } else {
    3779         451 :                         sub = subrel_bin(be, rl, refs);
    3780             :                 }
    3781         780 :                 sub = subrel_project(be, sub, refs, rl);
    3782             :         }
    3783         780 :         if (!sub)
    3784           0 :                 return NULL;
    3785             : 
    3786         780 :         le = topn_limit(rel);
    3787         780 :         oe = topn_offset(rel);
    3788             : 
    3789         780 :         n = sub->op4.lval->h;
    3790         780 :         if (n) {
    3791         780 :                 stmt *limit = NULL, *sc = n->data;
    3792         780 :                 const char *cname = column_name(sql->sa, sc);
    3793         780 :                 const char *tname = table_name(sql->sa, sc);
    3794         780 :                 list *newl = sa_list(sql->sa);
    3795         780 :                 int oldvtop = be->mb->vtop, oldstop = be->mb->stop, oldvid = be->mb->vid;
    3796             : 
    3797         780 :                 if (le)
    3798         767 :                         l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3799         767 :                 if (!l) {
    3800          13 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    3801          13 :                         l = stmt_atom_lng_nil(be);
    3802             :                 }
    3803             : 
    3804         780 :                 oldvtop = be->mb->vtop;
    3805         780 :                 oldstop = be->mb->stop;
    3806         780 :                 oldvid = be->mb->vid;
    3807         780 :                 if (oe)
    3808          38 :                         o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3809          38 :                 if (!o) {
    3810         742 :                         clean_mal_statements(be, oldstop, oldvtop, oldvid);
    3811         742 :                         o = stmt_atom_lng(be, 0);
    3812             :                 }
    3813         780 :                 if (!l || !o)
    3814             :                         return NULL;
    3815             : 
    3816         780 :                 sc = column(be, sc);
    3817         780 :                 limit = stmt_limit(be, stmt_alias(be, sc, tname, cname), NULL, NULL, o, l, 0,0,0,0,0);
    3818             : 
    3819        5403 :                 for ( ; n; n = n->next) {
    3820        4623 :                         stmt *sc = n->data;
    3821        4623 :                         const char *cname = column_name(sql->sa, sc);
    3822        4623 :                         const char *tname = table_name(sql->sa, sc);
    3823             : 
    3824        4623 :                         sc = column(be, sc);
    3825        4623 :                         sc = stmt_project(be, limit, sc);
    3826        4623 :                         list_append(newl, stmt_alias(be, sc, tname, cname));
    3827             :                 }
    3828         780 :                 sub = stmt_list(be, newl);
    3829             :         }
    3830             :         return sub;
    3831             : }
    3832             : 
    3833             : static stmt *
    3834          21 : rel2bin_sample(backend *be, sql_rel *rel, list *refs)
    3835             : {
    3836          21 :         mvc *sql = be->mvc;
    3837             :         list *newl;
    3838             :         stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
    3839             :         node *n;
    3840             : 
    3841          21 :         if (rel->l) /* first construct the sub relation */
    3842          21 :                 sub = subrel_bin(be, rel->l, refs);
    3843          21 :         sub = subrel_project(be, sub, refs, rel->l);
    3844          21 :         if (!sub)
    3845             :                 return NULL;
    3846             : 
    3847          21 :         n = sub->op4.lval->h;
    3848          21 :         newl = sa_list(sql->sa);
    3849             : 
    3850          21 :         if (n) {
    3851          21 :                 stmt *sc = n->data;
    3852          21 :                 const char *cname = column_name(sql->sa, sc);
    3853          21 :                 const char *tname = table_name(sql->sa, sc);
    3854             : 
    3855          21 :                  if (!(sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0)))
    3856             :                         return NULL;
    3857             : 
    3858          21 :                 if (rel->exps->cnt == 2) {
    3859          12 :                         seed = exp_bin(be, rel->exps->h->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3860          12 :                         if (!seed)
    3861             :                                 return NULL;
    3862             :                 }
    3863             : 
    3864          21 :                 sc = column(be, sc);
    3865          21 :                 sample = stmt_sample(be, stmt_alias(be, sc, tname, cname),sample_size, seed);
    3866             : 
    3867          45 :                 for ( ; n; n = n->next) {
    3868          24 :                         stmt *sc = n->data;
    3869          24 :                         const char *cname = column_name(sql->sa, sc);
    3870          24 :                         const char *tname = table_name(sql->sa, sc);
    3871             : 
    3872          24 :                         sc = column(be, sc);
    3873          24 :                         sc = stmt_project(be, sample, sc);
    3874          24 :                         list_append(newl, stmt_alias(be, sc, tname, cname));
    3875             :                 }
    3876             :         }
    3877          21 :         sub = stmt_list(be, newl);
    3878          21 :         return sub;
    3879             : }
    3880             : 
    3881             : static stmt *
    3882        3592 : sql_parse(backend *be, sql_schema *s, const char *query, char mode)
    3883             : {
    3884        3592 :         sql_rel *rel = rel_parse(be->mvc, s, query, mode);
    3885             :         stmt *sq = NULL;
    3886             : 
    3887        3592 :         if ((rel = sql_processrelation(be->mvc, rel, 1, 1)))
    3888        3590 :                 sq = rel_bin(be, rel);
    3889        3592 :         return sq;
    3890             : }
    3891             : 
    3892             : static stmt *
    3893        7554 : insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
    3894             : {
    3895        7554 :         mvc *sql = be->mvc;
    3896             : /* pkey's cannot have NULLs, ukeys however can
    3897             :    current implementation switches on 'NOT NULL' on primary key columns */
    3898             : 
    3899             :         char *msg = NULL;
    3900             :         stmt *res;
    3901             : 
    3902        7554 :         sql_subtype *lng = sql_bind_localtype("lng");
    3903        7554 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    3904        7554 :         sql_subtype *bt = sql_bind_localtype("bit");
    3905        7554 :         stmt *dels = stmt_tid(be, k->t, 0);
    3906        7554 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    3907             : 
    3908        7554 :         if (list_length(k->columns) > 1) {
    3909             :                 node *m;
    3910         798 :                 stmt *s = list_fetch(inserts, 0), *ins = s;
    3911             :                 sql_subfunc *sum;
    3912             :                 stmt *ssum = NULL;
    3913             :                 stmt *col = NULL;
    3914             : 
    3915             :                 s = ins;
    3916             :                 /* 1st stage: find out if original contains same values */
    3917         798 :                 if (/*s->key &&*/ s->nrcols == 0) {
    3918             :                         s = NULL;
    3919         576 :                         if (k->idx && hash_index(k->idx->type))
    3920         576 :                                 s = stmt_uselect(be, stmt_idx(be, k->idx, dels, dels->partition), idx_inserts, cmp_equal, s, 0, 1 /* is_semantics*/);
    3921        2119 :                         for (m = k->columns->h; m; m = m->next) {
    3922        1543 :                                 sql_kc *c = m->data;
    3923        1543 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    3924             : 
    3925             :                                 /* foreach column add predicate */
    3926        1543 :                                 if (add_column_predicate(be, c->c) != LOG_OK)
    3927           0 :                                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3928             : 
    3929        1543 :                                 col = stmt_col(be, c->c, dels, dels->partition);
    3930        1640 :                                 if ((k->type == ukey) && stmt_has_null(col)) {
    3931          97 :                                         stmt *nn = stmt_selectnonil(be, col, s);
    3932          97 :                                         s = stmt_uselect( be, col, cs, cmp_equal, nn, 0, 0);
    3933             :                                 } else {
    3934        1446 :                                         s = stmt_uselect( be, col, cs, cmp_equal, s, 0, 0);
    3935             :                                 }
    3936             :                         }
    3937             :                 } else {
    3938         222 :                         list *lje = sa_list(sql->sa);
    3939         222 :                         list *rje = sa_list(sql->sa);
    3940         222 :                         if (k->idx && hash_index(k->idx->type)) {
    3941         222 :                                 list_append(lje, stmt_idx(be, k->idx, dels, dels->partition));
    3942         222 :                                 list_append(rje, idx_inserts);
    3943             :                         }
    3944         713 :                         for (m = k->columns->h; m; m = m->next) {
    3945         491 :                                 sql_kc *c = m->data;
    3946         491 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    3947             : 
    3948             :                                 /* foreach column add predicate */
    3949         491 :                                 if (add_column_predicate(be, c->c) != LOG_OK)
    3950           0 :                                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3951             : 
    3952         491 :                                 col = stmt_col(be, c->c, dels, dels->partition);
    3953         491 :                                 list_append(lje, col);
    3954         491 :                                 list_append(rje, cs);
    3955             :                         }
    3956         222 :                         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
    3957         222 :                         s = stmt_result(be, s, 0);
    3958             :                 }
    3959         798 :                 s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    3960             : 
    3961             :                 /* 2nd stage: find out if inserted are unique */
    3962         798 :                 if ((!idx_inserts && ins->nrcols) || (idx_inserts && idx_inserts->nrcols)) {      /* insert columns not atoms */
    3963         222 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, bt, 2, bt, bt);
    3964             :                         stmt *orderby_ids = NULL, *orderby_grp = NULL;
    3965             :                         stmt *sel = NULL;
    3966             : 
    3967             :                         /* remove any nils as in stmt_order NULL = NULL, instead of NULL != NULL */
    3968         222 :                         if (k->type == ukey) {
    3969         141 :                                 for (m = k->columns->h; m; m = m->next) {
    3970          97 :                                         sql_kc *c = m->data;
    3971          97 :                                         stmt *cs = list_fetch(inserts, c->c->colnr);
    3972             : 
    3973          97 :                                         if (stmt_has_null(cs))
    3974          97 :                                                 sel = stmt_selectnonil(be, cs, sel);
    3975             :                                 }
    3976             :                         }
    3977             :                         /* implementation uses sort key check */
    3978         713 :                         for (m = k->columns->h; m; m = m->next) {
    3979         491 :                                 sql_kc *c = m->data;
    3980             :                                 stmt *orderby;
    3981         491 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    3982             : 
    3983         491 :                                 if (sel)
    3984          97 :                                         cs = stmt_project(be, sel, cs);
    3985         491 :                                 if (orderby_grp)
    3986         269 :                                         orderby = stmt_reorder(be, cs, 1, 0, orderby_ids, orderby_grp);
    3987             :                                 else
    3988         222 :                                         orderby = stmt_order(be, cs, 1, 0);
    3989         491 :                                 orderby_ids = stmt_result(be, orderby, 1);
    3990         491 :                                 orderby_grp = stmt_result(be, orderby, 2);
    3991             :                         }
    3992             : 
    3993         222 :                         if (!orderby_grp || !orderby_ids)
    3994             :                                 return NULL;
    3995             : 
    3996         222 :                         sum = sql_bind_func(sql, "sys", "not_unique", tail_type(orderby_grp), NULL, F_AGGR);
    3997         222 :                         ssum = stmt_aggr(be, orderby_grp, NULL, NULL, sum, 1, 0, 1);
    3998             :                         /* combine results */
    3999         222 :                         s = stmt_binop(be, s, ssum, NULL, or);
    4000             :                 }
    4001             : 
    4002         798 :                 if (k->type == pkey) {
    4003         324 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4004             :                 } else {
    4005         474 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4006             :                 }
    4007         798 :                 res = stmt_exception(be, s, msg, 00001);
    4008             :         } else {                /* single column key */
    4009        6756 :                 sql_kc *c = k->columns->h->data;
    4010        6756 :                 stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
    4011             : 
    4012             :                 /* add predicate for this column */
    4013        6756 :                 if (add_column_predicate(be, c->c) != LOG_OK)
    4014           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4015             : 
    4016        6756 :                 s = stmt_col(be, c->c, dels, dels->partition);
    4017        6756 :                 if ((k->type == ukey) && stmt_has_null(s)) {
    4018         179 :                         stmt *nn = stmt_selectnonil(be, s, NULL);
    4019         179 :                         s = stmt_project(be, nn, s);
    4020             :                 }
    4021        6756 :                 if (h->nrcols) {
    4022        3864 :                         s = stmt_join(be, s, h, 0, cmp_equal, 0, 0, false);
    4023             :                         /* s should be empty */
    4024        3864 :                         s = stmt_result(be, s, 0);
    4025        3864 :                         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    4026             :                 } else {
    4027        2892 :                         s = stmt_uselect(be, s, h, cmp_equal, NULL, 0, 0);
    4028             :                         /* s should be empty */
    4029        2892 :                         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    4030             :                 }
    4031             :                 /* s should be empty */
    4032        6756 :                 s = stmt_binop(be, s, stmt_atom_lng(be, 0), NULL, ne);
    4033             : 
    4034             :                 /* 2e stage: find out if inserts are unique */
    4035        6756 :                 if (h->nrcols) {     /* insert multiple atoms */
    4036             :                         sql_subfunc *sum;
    4037             :                         stmt *count_sum = NULL;
    4038        3864 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, bt, 2, bt, bt);
    4039             :                         stmt *ssum, *ss;
    4040             : 
    4041        3864 :                         stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
    4042             : 
    4043             :                         /* inserted vaules may be null */
    4044        3864 :                         if ((k->type == ukey) && stmt_has_null(ins)) {
    4045        1457 :                                 stmt *nn = stmt_selectnonil(be, ins, NULL);
    4046        1457 :                                 ins = stmt_project(be, nn, ins);
    4047             :                         }
    4048             : 
    4049        3864 :                         g = stmt_group(be, ins, NULL, NULL, NULL, 1);
    4050        3864 :                         ss = stmt_result(be, g, 2); /* use count */
    4051             :                         /* (count(ss) <> sum(ss)) */
    4052        3864 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR);
    4053        3864 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    4054        3864 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    4055        3864 :                         count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
    4056             : 
    4057             :                         /* combine results */
    4058        3864 :                         s = stmt_binop(be, s, count_sum, NULL, or);
    4059             :                 }
    4060        6756 :                 if (k->type == pkey) {
    4061        5165 :                         msg = sa_message( sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4062             :                 } else {
    4063        1591 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4064             :                 }
    4065        6756 :                 res = stmt_exception(be, s, msg, 00001);
    4066             :         }
    4067             :         return res;
    4068             : }
    4069             : 
    4070             : static stmt *
    4071         779 : insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
    4072             : {
    4073         779 :         mvc *sql = be->mvc;
    4074             :         char *msg = NULL;
    4075         779 :         stmt *cs = list_fetch(inserts, 0), *s = cs;
    4076         779 :         sql_subtype *lng = sql_bind_localtype("lng");
    4077         779 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    4078         779 :         sql_subtype *bt = sql_bind_localtype("bit");
    4079         779 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    4080             : 
    4081        1593 :         for (node *m = k->columns->h; m; m = m->next) {
    4082         814 :                 sql_kc *c = m->data;
    4083             : 
    4084             :                 /* foreach column add predicate */
    4085         814 :                 if (add_column_predicate(be, c->c) != LOG_OK)
    4086           0 :                         return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4087             :         }
    4088             : 
    4089         779 :         if (pin && list_length(pin->op4.lval))
    4090         779 :                 s = pin->op4.lval->h->data;
    4091         779 :         if (s->key && s->nrcols == 0) {
    4092         742 :                 s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 1), NULL, ne);
    4093             :         } else {
    4094             :                 /* releqjoin.count <> inserts[col1].count */
    4095          37 :                 s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 0, 1), stmt_aggr(be, column(be, s), NULL, NULL, cnt, 1, 0, 1), NULL, ne);
    4096             :         }
    4097             : 
    4098             :         /* s should be empty */
    4099         779 :         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4100         779 :         return stmt_exception(be, s, msg, 00001);
    4101             : }
    4102             : 
    4103             : static stmt *
    4104        8333 : sql_insert_key(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
    4105             : {
    4106             :         /* int insert = 1;
    4107             :          * while insert and has u/pkey and not defered then
    4108             :          *      if u/pkey values exist then
    4109             :          *              insert = 0
    4110             :          * while insert and has fkey and not defered then
    4111             :          *      find id of corresponding u/pkey
    4112             :          *      if (!found)
    4113             :          *              insert = 0
    4114             :          * if insert
    4115             :          *      insert values
    4116             :          *      insert fkey/pkey index
    4117             :          */
    4118        8333 :         if (k->type == pkey || k->type == ukey) {
    4119        7554 :                 return insert_check_ukey(be, inserts, k, idx_inserts );
    4120             :         } else {                /* foreign keys */
    4121         779 :                 return insert_check_fkey(be, inserts, k, idx_inserts, pin );
    4122             :         }
    4123             : }
    4124             : 
    4125             : static int
    4126        3166 : sql_stack_add_inserted( mvc *sql, const char *name, sql_table *t, stmt **updates)
    4127             : {
    4128             :         /* Put single relation of updates and old values on to the stack */
    4129             :         sql_rel *r = NULL;
    4130             :         node *n;
    4131        3166 :         list *exps = sa_list(sql->sa);
    4132        3166 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    4133             : 
    4134        3166 :         ti->t = t;
    4135        3166 :         ti->tids = NULL;
    4136        3166 :         ti->updates = updates;
    4137        3166 :         ti->type = 1;
    4138        3166 :         ti->nn = name;
    4139        9499 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    4140        6333 :                 sql_column *c = n->data;
    4141        6333 :                 sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    4142             : 
    4143        6333 :                 append(exps, ne);
    4144             :         }
    4145        3166 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    4146        3166 :         r->l = ti;
    4147             : 
    4148        3166 :         return stack_push_rel_view(sql, name, r) ? 1 : 0;
    4149             : }
    4150             : 
    4151             : static int
    4152      135330 : sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
    4153             : {
    4154      135330 :         mvc *sql = be->mvc;
    4155             :         node *n;
    4156             :         int res = 1;
    4157             : 
    4158      135330 :         if (!ol_length(t->triggers))
    4159             :                 return res;
    4160             : 
    4161        3416 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    4162        3348 :                 sql_trigger *trigger = n->data;
    4163             : 
    4164        3348 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    4165             :                         return 0;
    4166        3348 :                 if (trigger->event == 0 && trigger->time == time) {
    4167        3166 :                         const char *n = trigger->new_name;
    4168             : 
    4169             :                         /* add name for the 'inserted' to the stack */
    4170        3166 :                         if (!n) n = "new";
    4171             : 
    4172        3166 :                         if(!sql_stack_add_inserted(sql, n, t, updates)) {
    4173           0 :                                 stack_pop_frame(sql);
    4174           0 :                                 return 0;
    4175             :                         }
    4176        3166 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    4177        3142 :                                 stack_pop_frame(sql);
    4178        3142 :                                 return 0;
    4179             :                         }
    4180             :                 }
    4181         206 :                 stack_pop_frame(sql);
    4182             :         }
    4183             :         return res;
    4184             : }
    4185             : 
    4186             : static sql_table *
    4187       69236 : sql_insert_check_null(backend *be, sql_table *t, list *inserts)
    4188             : {
    4189       69236 :         mvc *sql = be->mvc;
    4190             :         node *m, *n;
    4191       69236 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    4192             : 
    4193      581767 :         for (n = ol_first_node(t->columns), m = inserts->h; n && m;
    4194      512531 :                 n = n->next, m = m->next) {
    4195      512531 :                 stmt *i = m->data;
    4196      512531 :                 sql_column *c = n->data;
    4197             : 
    4198      512531 :                 if (!c->null) {
    4199             :                         stmt *s = i;
    4200             :                         char *msg = NULL;
    4201             : 
    4202             :                         /* foreach column add predicate */
    4203       18442 :                         if (add_column_predicate(be, c) != LOG_OK)
    4204           0 :                                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4205             : 
    4206       18442 :                         if (!(s->key && s->nrcols == 0)) {
    4207        9716 :                                 s = stmt_selectnil(be, column(be, i));
    4208        9716 :                                 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    4209             :                         } else {
    4210        8726 :                                 sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC);
    4211             : 
    4212        8726 :                                 s = stmt_unop(be, i, NULL, isnil);
    4213             :                         }
    4214       18442 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
    4215       18442 :                         (void)stmt_exception(be, s, msg, 00001);
    4216             :                 }
    4217             :         }
    4218             :         return t; /* return something to say it succeeded */
    4219             : }
    4220             : 
    4221             : static stmt **
    4222       73044 : table_update_stmts(mvc *sql, sql_table *t, int *Len)
    4223             : {
    4224       73044 :         *Len = ol_length(t->columns);
    4225       73044 :         return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
    4226             : }
    4227             : 
    4228             : static stmt *
    4229       69236 : rel2bin_insert(backend *be, sql_rel *rel, list *refs)
    4230             : {
    4231       69236 :         mvc *sql = be->mvc;
    4232             :         list *l;
    4233             :         stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL;
    4234       69236 :         int idx_ins = 0, constraint = 1, len = 0;
    4235             :         node *n, *m, *idx_m = NULL;
    4236       69236 :         sql_rel *tr = rel->l, *prel = rel->r;
    4237             :         sql_table *t = NULL;
    4238             : 
    4239       69236 :         if ((rel->flag&UPD_NO_CONSTRAINT))
    4240             :                 constraint = 0;
    4241       69236 :         if ((rel->flag&UPD_COMP)) {  /* special case ! */
    4242             :                 idx_ins = 1;
    4243             :                 prel = rel->l;
    4244             :                 rel = rel->r;
    4245        6106 :                 tr = rel->l;
    4246             :         }
    4247             : 
    4248       69236 :         if (tr->op == op_basetable) {
    4249       69177 :                 t = tr->l;
    4250             :         } else {
    4251          59 :                 ddl = subrel_bin(be, tr, refs);
    4252          59 :                 ddl = subrel_project(be, ddl, refs, NULL);
    4253          59 :                 if (!ddl)
    4254             :                         return NULL;
    4255          59 :                 t = rel_ddl_table_get(tr);
    4256             :         }
    4257             : 
    4258       69236 :         if (rel->r) /* first construct the inserts relation */
    4259       69236 :                 inserts = subrel_bin(be, rel->r, refs);
    4260       69236 :         inserts = subrel_project(be, inserts, refs, rel->r);
    4261             : 
    4262       69236 :         if (!inserts)
    4263             :                 return NULL;
    4264             : 
    4265       69236 :         if (idx_ins)
    4266             :                 pin = refs_find_rel(refs, prel);
    4267             : 
    4268       69236 :         if (constraint && !sql_insert_check_null(be, t, inserts->op4.lval))
    4269             :                 return NULL;
    4270             : 
    4271       69236 :         l = sa_list(sql->sa);
    4272             : 
    4273       69236 :         updates = table_update_stmts(sql, t, &len);
    4274      581767 :         for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
    4275      512531 :                 sql_column *c = n->data;
    4276             : 
    4277      512531 :                 updates[c->colnr] = m->data;
    4278             :         }
    4279             : 
    4280             : /* before */
    4281       69236 :         if (!sql_insert_triggers(be, t, updates, 0))
    4282        3142 :                 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    4283             : 
    4284       66094 :         insert = inserts->op4.lval->h->data;
    4285       66094 :         if (insert->nrcols == 0) {
    4286       61579 :                 cnt = stmt_atom_lng(be, 1);
    4287             :         } else {
    4288        4515 :                 cnt = stmt_aggr(be, insert, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    4289             :         }
    4290             :         insert = NULL;
    4291             : 
    4292       66094 :         if (t->idxs) {
    4293             :                 idx_m = m;
    4294       75905 :                 for (n = ol_first_node(t->idxs); n && m; n = n->next) {
    4295        9811 :                         stmt *is = m->data;
    4296        9811 :                         sql_idx *i = n->data;
    4297             : 
    4298        9811 :                     if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    4299           4 :                                 continue;
    4300        9807 :                         if (hash_index(i->type) && list_length(i->columns) <= 1)
    4301             :                                 is = NULL;
    4302        9807 :                         if (i->key && constraint) {
    4303        8333 :                                 stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
    4304             : 
    4305        8333 :                                 list_append(l, ckeys);
    4306             :                         }
    4307        9807 :                         if (!insert)
    4308             :                                 insert = is;
    4309             :                         /* If the index doesn't hold delta structures, don't update the 'm' variable */
    4310        9807 :                         m = m->next;
    4311             :                 }
    4312             :         }
    4313             : 
    4314       66094 :         if (t->s) /* only not declared tables, need this */
    4315       66076 :                 pos = stmt_claim(be, t, cnt);
    4316             : 
    4317       66094 :         if (t->idxs)
    4318       75905 :         for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next) {
    4319        9811 :                 stmt *is = m->data;
    4320        9811 :                 sql_idx *i = n->data;
    4321             : 
    4322        9811 :                 if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    4323           4 :                         continue;
    4324        9807 :                 if (hash_index(i->type) && list_length(i->columns) <= 1)
    4325             :                         is = NULL;
    4326        2193 :                 if (is)
    4327        2193 :                         is = stmt_append_idx(be, i, pos, is);
    4328             :                 /* If the index doesn't hold delta structures, don't update the 'm' variable */
    4329        9807 :                 m = m->next;
    4330             :         }
    4331             : 
    4332       66094 :         int mvc_var = be->mvc_var;
    4333      572341 :         for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
    4334             : 
    4335      506247 :                 stmt *ins = m->data;
    4336      506247 :                 sql_column *c = n->data;
    4337             : 
    4338      506247 :                 insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
    4339      506247 :                 append(l,insert);
    4340             :         }
    4341       66094 :         be->mvc_var = mvc_var;
    4342       66094 :         if (!insert)
    4343             :                 return NULL;
    4344             : 
    4345       66094 :         if (!sql_insert_triggers(be, t, updates, 1))
    4346           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    4347             :         /* update predicate list */
    4348       66094 :         if (rel->r && !rel_predicates(be, rel->r))
    4349             :                 return NULL;
    4350       66094 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK)
    4351           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    4352             : 
    4353       66094 :         if (ddl) {
    4354             :                 ret = ddl;
    4355          59 :                 list_prepend(l, ddl);
    4356          59 :                 return stmt_list(be, l);
    4357             :         } else {
    4358             :                 ret = cnt;
    4359       66035 :                 if (!be->silent) {
    4360             :                         /* if there are multiple update statements, update total count, otherwise use the the current count */
    4361       65965 :                         be->rowcount = be->rowcount ? add_to_rowcount_accumulator(be, ret->nr) : ret->nr;
    4362             :                 }
    4363       66035 :                 return ret;
    4364             :         }
    4365             : }
    4366             : 
    4367             : static int
    4368        1176 : is_idx_updated(sql_idx * i, stmt **updates)
    4369             : {
    4370             :         int update = 0;
    4371             :         node *m;
    4372             : 
    4373        2280 :         for (m = i->columns->h; m; m = m->next) {
    4374        1305 :                 sql_kc *ic = m->data;
    4375             : 
    4376        1305 :                 if (updates[ic->c->colnr]) {
    4377             :                         update = 1;
    4378             :                         break;
    4379             :                 }
    4380             :         }
    4381        1176 :         return update;
    4382             : }
    4383             : 
    4384             : static int
    4385             : first_updated_col(stmt **updates, int cnt)
    4386             : {
    4387             :         int i;
    4388             : 
    4389       32380 :         for (i = 0; i < cnt; i++) {
    4390       31486 :                 if (updates[i])
    4391             :                         return i;
    4392             :         }
    4393             :         return -1;
    4394             : }
    4395             : 
    4396             : static stmt *
    4397         195 : update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *u_tids, stmt *idx_updates, int updcol)
    4398             : {
    4399         195 :         mvc *sql = be->mvc;
    4400             :         char *msg = NULL;
    4401             :         stmt *res = NULL;
    4402             : 
    4403         195 :         sql_subtype *lng = sql_bind_localtype("lng");
    4404         195 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    4405         195 :         sql_subtype *bt = sql_bind_localtype("bit");
    4406             :         sql_subfunc *ne;
    4407             : 
    4408         195 :         ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    4409         195 :         if (list_length(k->columns) > 1) {
    4410          47 :                 stmt *dels = stmt_tid(be, k->t, 0);
    4411             :                 node *m;
    4412             :                 stmt *s = NULL;
    4413             : 
    4414             :                 /* 1st stage: find out if original (without the updated)
    4415             :                         do not contain the same values as the updated values.
    4416             :                         This is done using a relation join and a count (which
    4417             :                         should be zero)
    4418             :                 */
    4419          47 :                 if (!isNew(k)) {
    4420          11 :                         stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
    4421          11 :                         list *lje = sa_list(sql->sa);
    4422          11 :                         list *rje = sa_list(sql->sa);
    4423             : 
    4424          11 :                         if (k->idx && hash_index(k->idx->type)) {
    4425          11 :                                 list_append(lje, stmt_idx(be, k->idx, nu_tids, nu_tids->partition));
    4426          11 :                                 list_append(rje, idx_updates);
    4427             :                         }
    4428          33 :                         for (m = k->columns->h; m; m = m->next) {
    4429          22 :                                 sql_kc *c = m->data;
    4430             :                                 stmt *upd;
    4431             : 
    4432          22 :                                 assert(updates);
    4433          22 :                                 if (updates[c->c->colnr]) {
    4434             :                                         upd = updates[c->c->colnr];
    4435             :                                 } else {
    4436           8 :                                         upd = stmt_col(be, c->c, u_tids, u_tids->partition);
    4437             :                                 }
    4438          22 :                                 list_append(lje, stmt_col(be, c->c, nu_tids, nu_tids->partition));
    4439          22 :                                 list_append(rje, upd);
    4440             :                         }
    4441          11 :                         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
    4442          11 :                         s = stmt_result(be, s, 0);
    4443          11 :                         s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    4444             :                 }
    4445             : 
    4446             :                 /* 2e stage: find out if the updated are unique */
    4447          47 :                 if (!updates || updates[updcol]->nrcols) {   /* update columns not atoms */
    4448             :                         sql_subfunc *sum;
    4449             :                         stmt *count_sum = NULL, *ssum;
    4450             :                         stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
    4451             :                         stmt *cand = NULL;
    4452             :                         stmt *ss;
    4453          47 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, bt, 2, bt, bt);
    4454             : 
    4455             :                         /* also take the hopefully unique hash keys, to reduce
    4456             :                            (re)group costs */
    4457          47 :                         if (k->idx && hash_index(k->idx->type)) {
    4458          47 :                                 g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
    4459          47 :                                 grp = stmt_result(be, g, 0);
    4460          47 :                                 ext = stmt_result(be, g, 1);
    4461          47 :                                 Cnt = stmt_result(be, g, 2);
    4462             : 
    4463             :                                 /* continue only with groups with a cnt > 1 */
    4464          47 :                                 cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0, 0);
    4465             :                                 /* project cand on ext and Cnt */
    4466          47 :                                 Cnt = stmt_project(be, cand, Cnt);
    4467          47 :                                 ext = stmt_project(be, cand, ext);
    4468             : 
    4469             :                                 /* join groups with extend to retrieve all oid's of the original
    4470             :                                  * bat that belong to a group with Cnt >1 */
    4471          47 :                                 g = stmt_join(be, grp, ext, 0, cmp_equal, 0, 0, false);
    4472          47 :                                 cand = stmt_result(be, g, 0);
    4473          47 :                                 grp = stmt_project(be, cand, grp);
    4474             :                         }
    4475             : 
    4476         151 :                         for (m = k->columns->h; m; m = m->next) {
    4477         104 :                                 sql_kc *c = m->data;
    4478             :                                 stmt *upd;
    4479             : 
    4480         104 :                                 if (updates && updates[c->c->colnr]) {
    4481             :                                         upd = updates[c->c->colnr];
    4482             :                                 } else {
    4483          90 :                                         upd = stmt_col(be, c->c, dels, dels->partition);
    4484             :                                 }
    4485             : 
    4486             :                                 /* apply cand list first */
    4487         104 :                                 if (cand)
    4488         104 :                                         upd = stmt_project(be, cand, upd);
    4489             : 
    4490             :                                 /* remove nulls */
    4491         104 :                                 if ((k->type == ukey) && stmt_has_null(upd)) {
    4492          29 :                                         stmt *nn = stmt_selectnonil(be, upd, NULL);
    4493          29 :                                         upd = stmt_project(be, nn, upd);
    4494          29 :                                         if (grp)
    4495          29 :                                                 grp = stmt_project(be, nn, grp);
    4496          29 :                                         if (cand)
    4497          29 :                                                 cand = stmt_project(be, nn, cand);
    4498             :                                 }
    4499             : 
    4500             :                                 /* apply group by on groups with Cnt > 1 */
    4501         104 :                                 g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
    4502         104 :                                 grp = stmt_result(be, g, 0);
    4503         104 :                                 ext = stmt_result(be, g, 1);
    4504         104 :                                 Cnt = stmt_result(be, g, 2);
    4505             :                         }
    4506             :                         ss = Cnt; /* use count */
    4507             :                         /* (count(ss) <> sum(ss)) */
    4508          47 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR);
    4509          47 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    4510          47 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    4511          47 :                         count_sum = stmt_binop(be, stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), check_types(be, lng, ssum, type_equal), NULL, ne);
    4512             : 
    4513             :                         /* combine results */
    4514          47 :                         if (s)
    4515          11 :                                 s = stmt_binop(be, s, count_sum, NULL, or);
    4516             :                         else
    4517             :                                 s = count_sum;
    4518             :                 }
    4519             : 
    4520          47 :                 if (k->type == pkey) {
    4521          31 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4522             :                 } else {
    4523          16 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4524             :                 }
    4525          47 :                 res = stmt_exception(be, s, msg, 00001);
    4526             :         } else {                /* single column key */
    4527         148 :                 stmt *dels = stmt_tid(be, k->t, 0);
    4528         148 :                 sql_kc *c = k->columns->h->data;
    4529             :                 stmt *s = NULL, *h = NULL, *o;
    4530             : 
    4531             :                 /* s should be empty */
    4532         148 :                 if (!isNew(k)) {
    4533          63 :                         stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
    4534          63 :                         assert (updates);
    4535             : 
    4536          63 :                         h = updates[c->c->colnr];
    4537          63 :                         o = stmt_col(be, c->c, nu_tids, nu_tids->partition);
    4538          63 :                         s = stmt_join(be, o, h, 0, cmp_equal, 0, 0, false);
    4539          63 :                         s = stmt_result(be, s, 0);
    4540          63 :                         s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    4541             :                 }
    4542             : 
    4543             :                 /* 2e stage: find out if updated are unique */
    4544          63 :                 if (!h || h->nrcols) {       /* update columns not atoms */
    4545             :                         sql_subfunc *sum;
    4546             :                         stmt *count_sum = NULL;
    4547         148 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, bt, 2, bt, bt);
    4548             :                         stmt *ssum, *ss;
    4549             :                         stmt *upd;
    4550             :                         stmt *g;
    4551             : 
    4552         148 :                         if (updates) {
    4553          64 :                                 upd = updates[c->c->colnr];
    4554             :                         } else {
    4555          84 :                                 upd = stmt_col(be, c->c, dels, dels->partition);
    4556             :                         }
    4557             : 
    4558             :                         /* remove nulls */
    4559         148 :                         if ((k->type == ukey) && stmt_has_null(upd)) {
    4560          13 :                                 stmt *nn = stmt_selectnonil(be, upd, NULL);
    4561          13 :                                 upd = stmt_project(be, nn, upd);
    4562             :                         }
    4563             : 
    4564         148 :                         g = stmt_group(be, upd, NULL, NULL, NULL, 1);
    4565         148 :                         ss = stmt_result(be, g, 2); /* use count */
    4566             : 
    4567             :                         /* (count(ss) <> sum(ss)) */
    4568         148 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR);
    4569         148 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    4570         148 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    4571         148 :                         count_sum = stmt_binop(be, check_types(be, tail_type(ssum), stmt_aggr(be, ss, NULL, NULL, cnt, 1, 0, 1), type_equal), ssum, NULL, ne);
    4572             : 
    4573             :                         /* combine results */
    4574         148 :                         if (s)
    4575          63 :                                 s = stmt_binop(be, s, count_sum, NULL, or);
    4576             :                         else
    4577             :                                 s = count_sum;
    4578             :                 }
    4579             : 
    4580         148 :                 if (k->type == pkey) {
    4581         133 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4582             :                 } else {
    4583          15 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4584             :                 }
    4585         148 :                 res = stmt_exception(be, s, msg, 00001);
    4586             :         }
    4587         195 :         return res;
    4588             : }
    4589             : 
    4590             : /*
    4591             :          A referential constraint is satisfied if one of the following con-
    4592             :          ditions is true, depending on the <match option> specified in the
    4593             :          <referential constraint definition>:
    4594             : 
    4595             :          -  If no <match type> was specified then, for each row R1 of the
    4596             :             referencing table, either at least one of the values of the
    4597             :             referencing columns in R1 shall be a null value, or the value of
    4598             :             each referencing column in R1 shall be equal to the value of the
    4599             :             corresponding referenced column in some row of the referenced
    4600             :             table.
    4601             : 
    4602             :          -  If MATCH FULL was specified then, for each row R1 of the refer-
    4603             :             encing table, either the value of every referencing column in R1
    4604             :             shall be a null value, or the value of every referencing column
    4605             :             in R1 shall not be null and there shall be some row R2 of the
    4606             :             referenced table such that the value of each referencing col-
    4607             :             umn in R1 is equal to the value of the corresponding referenced
    4608             :             column in R2.
    4609             : 
    4610             :          -  If MATCH PARTIAL was specified then, for each row R1 of the
    4611             :             referencing table, there shall be some row R2 of the refer-
    4612             :             enced table such that the value of each referencing column in
    4613             :             R1 is either null or is equal to the value of the corresponding
    4614             :             referenced column in R2.
    4615             : */
    4616             : 
    4617             : static stmt *
    4618         694 : update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
    4619             : {
    4620         694 :         mvc *sql = be->mvc;
    4621             :         char *msg = NULL;
    4622             :         stmt *s, *cur, *null = NULL, *cntnulls;
    4623         694 :         sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
    4624         694 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    4625         694 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    4626         694 :         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, bt, 2, bt, bt);
    4627             :         node *m;
    4628             : 
    4629         694 :         if (!idx_updates)
    4630             :                 return NULL;
    4631             :         /* releqjoin.count <> updates[updcol].count */
    4632         694 :         if (pup && list_length(pup->op4.lval)) {
    4633         651 :                 cur = pup->op4.lval->h->data;
    4634          43 :         } else if (updates) {
    4635          43 :                 cur = updates[updcol];
    4636             :         } else {
    4637             :                 sql_kc *c = k->columns->h->data;
    4638           0 :                 stmt *dels = stmt_tid(be, k->t, 0);
    4639           0 :                 assert(0);
    4640             :                 cur = stmt_col(be, c->c, dels, dels->partition);
    4641             :         }
    4642         694 :         s = stmt_binop(be, stmt_aggr(be, idx_updates, NULL, NULL, cnt, 1, 0, 1), stmt_aggr(be, cur, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
    4643             : 
    4644        1409 :         for (m = k->columns->h; m; m = m->next) {
    4645         715 :                 sql_kc *c = m->data;
    4646             : 
    4647             :                 /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
    4648             :                 /* Currently only the default MATCH SIMPLE is supported */
    4649         715 :                 if (c->c->null) {
    4650             :                         stmt *upd, *nn;
    4651             : 
    4652         303 :                         if (updates && updates[c->c->colnr]) {
    4653             :                                 upd = updates[c->c->colnr];
    4654             :                         } else { /* created idx/key using alter */
    4655         270 :                                 upd = stmt_col(be, c->c, tids, tids->partition);
    4656             :                         }
    4657         303 :                         nn = stmt_selectnil(be, upd);
    4658         303 :                         if (null)
    4659           9 :                                 null = stmt_tunion(be, null, nn);
    4660             :                         else
    4661             :                                 null = nn;
    4662             :                 }
    4663             :         }
    4664         694 :         if (null) {
    4665         294 :                 cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
    4666             :         } else {
    4667         400 :                 cntnulls = stmt_atom_lng(be, 0);
    4668             :         }
    4669         694 :         s = stmt_binop(be, s,
    4670             :                 stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls, NULL, ne), NULL, or);
    4671             : 
    4672             :         /* s should be empty */
    4673         694 :         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4674         694 :         return stmt_exception(be, s, msg, 00001);
    4675             : }
    4676             : 
    4677             : static stmt *
    4678          10 : join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
    4679             : {
    4680          10 :         mvc *sql = be->mvc;
    4681          10 :         sql_trans *tr = sql->session->tr;
    4682             :         char *msg = NULL;
    4683             :         int nulls = 0;
    4684             :         node *m, *o;
    4685          10 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    4686          10 :         stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
    4687             :         stmt *null = NULL, *rows;
    4688          10 :         sql_subtype *lng = sql_bind_localtype("lng");
    4689          10 :         sql_subtype *bt = sql_bind_localtype("bit");
    4690          10 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    4691          10 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    4692          10 :         list *lje = sa_list(sql->sa);
    4693          10 :         list *rje = sa_list(sql->sa);
    4694             : 
    4695          10 :         fdels = stmt_tid(be, k->idx->t, 0);
    4696          10 :         rows = stmt_idx(be, k->idx, fdels, fdels->partition);
    4697             : 
    4698          10 :         rows = stmt_join(be, rows, tids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    4699          10 :         rows = stmt_result(be, rows, 0);
    4700             : 
    4701          22 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    4702          12 :                 sql_kc *fc = m->data;
    4703          12 :                 sql_kc *c = o->data;
    4704             :                 stmt *upd, *col;
    4705             : 
    4706          12 :                 if (updates[c->c->colnr]) {
    4707             :                         upd = updates[c->c->colnr];
    4708             :                 } else {
    4709           2 :                         upd = stmt_project(be, tids, stmt_col(be, c->c, dels, dels->partition));
    4710             :                 }
    4711          12 :                 if (c->c->null) { /* new nulls (MATCH SIMPLE) */
    4712           3 :                         stmt *nn = stmt_selectnil(be, upd);
    4713           3 :                         if (null)
    4714           1 :                                 null = stmt_tunion(be, null, nn);
    4715             :                         else
    4716             :                                 null = nn;
    4717             :                         nulls = 1;
    4718             :                 }
    4719          12 :                 col = stmt_col(be, fc->c, rows, rows->partition);
    4720          12 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    4721           0 :                         return NULL;
    4722          12 :                 list_append(lje, upd);
    4723          12 :                 list_append(rje, col);
    4724             :         }
    4725          10 :         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
    4726          10 :         s = stmt_result(be, s, 0);
    4727             : 
    4728             :         /* add missing nulls */
    4729          10 :         cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    4730          10 :         if (nulls) {
    4731           2 :                 sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, lng, 2, lng, lng);
    4732           2 :                 cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), NULL, add);
    4733             :         }
    4734             : 
    4735             :         /* releqjoin.count <> updates[updcol].count */
    4736          10 :         s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
    4737             : 
    4738             :         /* s should be empty */
    4739          10 :         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    4740          10 :         return stmt_exception(be, s, msg, 00001);
    4741             : }
    4742             : 
    4743             : static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
    4744             : 
    4745             : static stmt*
    4746          11 : sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
    4747             : {
    4748          11 :         mvc *sql = be->mvc;
    4749          11 :         sql_trans *tr = sql->session->tr;
    4750             :         list *l = NULL;
    4751          11 :         int len = 0;
    4752             :         node *m, *o;
    4753          11 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    4754             :         stmt **new_updates;
    4755          11 :         sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
    4756             : 
    4757          11 :         new_updates = table_update_stmts(sql, t, &len);
    4758          24 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    4759          13 :                 sql_kc *fc = m->data;
    4760             :                 stmt *upd = NULL;
    4761             : 
    4762          13 :                 if (action == ACT_SET_DEFAULT) {
    4763           4 :                         if (fc->c->def) {
    4764           4 :                                 stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
    4765           4 :                                 if (!sq)
    4766             :                                         return NULL;
    4767             :                                 upd = sq;
    4768             :                         } else {
    4769           0 :                                 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
    4770             :                         }
    4771             :                 } else {
    4772           9 :                         upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
    4773             :                 }
    4774             : 
    4775          13 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    4776           0 :                         return NULL;
    4777             : 
    4778          13 :                 if (upd->nrcols <= 0)
    4779          13 :                         upd = stmt_const(be, ftids, upd);
    4780             : 
    4781          13 :                 new_updates[fc->c->colnr] = upd;
    4782             :         }
    4783          11 :         if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
    4784             :                 return NULL;
    4785          11 :         return stmt_list(be, l);
    4786             : }
    4787             : 
    4788             : static stmt*
    4789          32 : sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
    4790             : {
    4791          32 :         mvc *sql = be->mvc;
    4792          32 :         sql_trans *tr = sql->session->tr;
    4793             :         list *l = NULL;
    4794          32 :         int len = 0;
    4795             :         node *m, *o;
    4796          32 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    4797             :         stmt **new_updates;
    4798             :         stmt *rows;
    4799          32 :         sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
    4800             :         stmt *ftids, *upd_ids;
    4801             : 
    4802          32 :         ftids = stmt_tid(be, k->idx->t, 0);
    4803          32 :         rows = stmt_idx(be, k->idx, ftids, ftids->partition);
    4804             : 
    4805          32 :         rows = stmt_join(be, rows, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    4806          32 :         upd_ids = stmt_result(be, rows, 1);
    4807          32 :         rows = stmt_result(be, rows, 0);
    4808          32 :         rows = stmt_project(be, rows, ftids);
    4809             : 
    4810          32 :         new_updates = table_update_stmts(sql, t, &len);
    4811          64 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    4812          32 :                 sql_kc *fc = m->data;
    4813          32 :                 sql_kc *c = o->data;
    4814             :                 stmt *upd = NULL;
    4815             : 
    4816          32 :                 if (!updates[c->c->colnr]) {
    4817           0 :                         continue;
    4818          32 :                 } else if (action == ACT_CASCADE) {
    4819             :                         upd = updates[c->c->colnr];
    4820          16 :                 } else if (action == ACT_SET_DEFAULT) {
    4821           6 :                         if (fc->c->def) {
    4822           6 :                                 stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
    4823           6 :                                 if (!sq)
    4824             :                                         return NULL;
    4825             :                                 upd = sq;
    4826             :                         } else {
    4827           0 :                                 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
    4828             :                         }
    4829          10 :                 } else if (action == ACT_SET_NULL) {
    4830          10 :                         upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL));
    4831             :                 }
    4832             : 
    4833          32 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    4834           0 :                         return NULL;
    4835             : 
    4836          32 :                 if (upd->nrcols <= 0)
    4837          16 :                         upd = stmt_const(be, upd_ids, upd);
    4838             :                 else
    4839          16 :                         upd = stmt_project(be, upd_ids, upd);
    4840             : 
    4841          32 :                 new_updates[fc->c->colnr] = upd;
    4842             :         }
    4843             : 
    4844          32 :         if ((l = sql_update(be, t, rows, new_updates)) == NULL)
    4845             :                 return NULL;
    4846          32 :         return stmt_list(be, l);
    4847             : }
    4848             : 
    4849             : static int
    4850          75 : cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
    4851             : {
    4852             :         /* now iterate over all keys */
    4853          75 :         sql_trans *tr = be->mvc->session->tr;
    4854          75 :         list *keys = sql_trans_get_dependencies(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    4855          75 :         if (keys) {
    4856         125 :                 for (node *n = keys->h; n; n = n->next->next) {
    4857          50 :                         sqlid fkey_id = *(sqlid*)n->data;
    4858          50 :                         sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    4859             :                         sql_key *fk = (sql_key*)b;
    4860             :                         sql_fkey *rk = (sql_fkey*)b;
    4861             : 
    4862          50 :                         if (fk->type != fkey || rk->rkey != k->base.id)
    4863           0 :                                 continue;
    4864             : 
    4865             :                         /* All rows of the foreign key table which are
    4866             :                            affected by the primary key update should all
    4867             :                            match one of the updated primary keys again.
    4868             :                          */
    4869          50 :                         switch (((sql_fkey*)fk)->on_update) {
    4870             :                         case ACT_NO_ACTION:
    4871             :                                 break;
    4872          32 :                         case ACT_SET_NULL:
    4873             :                         case ACT_SET_DEFAULT:
    4874             :                         case ACT_CASCADE:
    4875          32 :                                 if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update)) {
    4876           0 :                                         list_destroy(keys);
    4877           0 :                                         return -1;
    4878             :                                 }
    4879             :                                 break;
    4880          10 :                         default:        /*RESTRICT*/
    4881          10 :                                 if (!join_updated_pkey(be, fk, tids, updates)) {
    4882           0 :                                         list_destroy(keys);
    4883           0 :                                         return -1;
    4884             :                                 }
    4885             :                         }
    4886             :                 }
    4887          75 :                 list_destroy(keys);
    4888             :         }
    4889             :         return 0;
    4890             : }
    4891             : 
    4892             : static void
    4893         889 : sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
    4894             : {
    4895             :         stmt *ckeys;
    4896             : 
    4897         889 :         if (k->type == pkey || k->type == ukey) {
    4898         195 :                 ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
    4899             :         } else { /* foreign keys */
    4900         694 :                 ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
    4901             :         }
    4902         889 :         list_append(l, ckeys);
    4903         889 : }
    4904             : 
    4905             : static stmt *
    4906          20 : hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
    4907             : {
    4908          20 :         mvc *sql = be->mvc;
    4909             :         /* calculate new value */
    4910             :         node *m;
    4911             :         sql_subtype *it, *lng;
    4912          20 :         int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
    4913             :         stmt *h = NULL, *tids;
    4914             : 
    4915          20 :         if (list_length(i->columns) <= 1)
    4916             :                 return NULL;
    4917             : 
    4918           0 :         tids = stmt_tid(be, i->t, 0);
    4919           0 :         it = sql_bind_localtype("int");
    4920           0 :         lng = sql_bind_localtype("lng");
    4921           0 :         for (m = i->columns->h; m; m = m->next ) {
    4922           0 :                 sql_kc *c = m->data;
    4923             :                 stmt *upd;
    4924             : 
    4925           0 :                 if (updates && updates[c->c->colnr]) {
    4926             :                         upd = updates[c->c->colnr];
    4927           0 :                 } else if (updates && updcol >= 0) {
    4928           0 :                         assert(0);
    4929             :                         upd = stmt_col(be, c->c, rows, rows->partition);
    4930             :                 } else { /* created idx/key using alter */
    4931           0 :                         upd = stmt_col(be, c->c, tids, tids->partition);
    4932             :                 }
    4933             : 
    4934           0 :                 if (h && i->type == hash_idx)  {
    4935           0 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, lng, 3, lng, it, &c->c->type);
    4936             : 
    4937           0 :                         h = stmt_Nop(be, stmt_list( be, list_append( list_append(
    4938             :                                 list_append(sa_list(sql->sa), h),
    4939           0 :                                 stmt_atom_int(be, bits)),  upd)), NULL,
    4940             :                                 xor);
    4941           0 :                 } else if (h)  {
    4942             :                         stmt *h2;
    4943           0 :                         sql_subfunc *lsh = sql_bind_func_result(sql, "sys", "left_shift", F_FUNC, lng, 2, lng, it);
    4944           0 :                         sql_subfunc *lor = sql_bind_func_result(sql, "sys", "bit_or", F_FUNC, lng, 2, lng, lng);
    4945           0 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, lng, 1, &c->c->type);
    4946             : 
    4947           0 :                         h = stmt_binop(be, h, stmt_atom_int(be, bits), NULL, lsh);
    4948           0 :                         h2 = stmt_unop(be, upd, NULL, hf);
    4949           0 :                         h = stmt_binop(be, h, h2, NULL, lor);
    4950             :                 } else {
    4951           0 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, lng, 1, &c->c->type);
    4952           0 :                         h = stmt_unop(be, upd, NULL, hf);
    4953           0 :                         if (i->type == oph_idx)
    4954             :                                 break;
    4955             :                 }
    4956             :         }
    4957             :         return h;
    4958             : }
    4959             : 
    4960             : static stmt *
    4961          43 : join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
    4962             : {
    4963          43 :         mvc *sql = be->mvc;
    4964          43 :         sql_trans *tr = sql->session->tr;
    4965             :         node *m, *o;
    4966          43 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)i->key)->rkey);
    4967          43 :         stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
    4968          43 :         list *lje = sa_list(sql->sa);
    4969          43 :         list *rje = sa_list(sql->sa);
    4970             : 
    4971          88 :         for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    4972          45 :                 sql_kc *c = m->data;
    4973          45 :                 sql_kc *rc = o->data;
    4974             :                 stmt *upd;
    4975             : 
    4976          45 :                 if (updates && updates[c->c->colnr]) {
    4977             :                         upd = updates[c->c->colnr];
    4978           0 :                 } else if (updates && updcol >= 0) {
    4979           0 :                         assert(0);
    4980             :                         upd = stmt_col(be, c->c, ftids, ftids->partition);
    4981             :                 } else { /* created idx/key using alter */
    4982           0 :                         upd = stmt_col(be, c->c, ftids, ftids->partition);
    4983             :                 }
    4984             : 
    4985          45 :                 if (!upd || (upd = check_types(be, &rc->c->type, upd, type_equal)) == NULL)
    4986           0 :                         return NULL;
    4987          45 :                 list_append(lje, upd);
    4988          45 :                 list_append(rje, stmt_col(be, rc->c, ptids, ptids->partition));
    4989             :         }
    4990          43 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 0);
    4991          43 :         l = stmt_result(be, s, 0);
    4992          43 :         r = stmt_result(be, s, 1);
    4993          43 :         r = stmt_project(be, r, ptids);
    4994          43 :         return stmt_left_project(be, ftids, l, r);
    4995             : }
    4996             : 
    4997             : static int
    4998        3754 : cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
    4999             : {
    5000        3754 :         mvc *sql = be->mvc;
    5001             :         node *n;
    5002             : 
    5003        3754 :         if (!ol_length(t->idxs))
    5004             :                 return 0;
    5005             : 
    5006        2142 :         for (n = ol_first_node(t->idxs); n; n = n->next) {
    5007        1113 :                 sql_idx *i = n->data;
    5008             : 
    5009             :                 /* check if update is needed,
    5010             :                  * ie atleast on of the idx columns is updated
    5011             :                  */
    5012        1113 :                 if (is_idx_updated(i, updates) == 0)
    5013         975 :                         continue;
    5014             : 
    5015         138 :                 if (i->key) {
    5016         135 :                         if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
    5017         135 :                                 sql_key *k = i->key;
    5018         135 :                                 sqlid *local_id = SA_NEW(sql->sa, sqlid);
    5019         135 :                                 if (!sql->cascade_action)
    5020          60 :                                         sql->cascade_action = sa_list(sql->sa);
    5021         135 :                                 *local_id = i->key->base.id;
    5022         135 :                                 list_append(sql->cascade_action, local_id);
    5023         135 :                                 if (k->type == pkey || k->type == ukey) {
    5024          75 :                                         if (cascade_ukey(be, updates, k, rows))
    5025             :                                                 return -1;
    5026             :                                 }
    5027             :                         }
    5028             :                 }
    5029             :         }
    5030             :         return 0;
    5031             : }
    5032             : 
    5033             : static list *
    5034          43 : update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
    5035             : {
    5036          43 :         mvc *sql = be->mvc;
    5037             :         node *n;
    5038             :         int updcol;
    5039          43 :         list *idx_updates = sa_list(sql->sa);
    5040             : 
    5041          43 :         if (!ol_length(t->idxs))
    5042             :                 return idx_updates;
    5043             : 
    5044          43 :         updcol = first_updated_col(updates, ol_length(t->columns));
    5045         106 :         for (n = ol_first_node(t->idxs); n; n = n->next) {
    5046          63 :                 sql_idx *i = n->data;
    5047             :                 stmt *is = NULL;
    5048             : 
    5049             :                 /* check if update is needed,
    5050             :                  * ie atleast on of the idx columns is updated
    5051             :                  */
    5052          63 :                 if (is_idx_updated(i, updates) == 0)
    5053           0 :                         continue;
    5054             : 
    5055          63 :                 if (hash_index(i->type)) {
    5056          20 :                         is = hash_update(be, i, rows, updates, updcol);
    5057          43 :                 } else if (i->type == join_idx) {
    5058          43 :                         if (updcol < 0)
    5059             :                                 return NULL;
    5060          43 :                         if (!(is = join_idx_update(be, i, rows, updates, updcol)))
    5061             :                                 return NULL;
    5062             :                 }
    5063          63 :                 if (i->key)
    5064          63 :                         sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
    5065          63 :                 if (is)
    5066          43 :                         list_append(idx_updates, stmt_update_idx(be, i, rows, is));
    5067             :         }
    5068             :         return idx_updates;
    5069             : }
    5070             : 
    5071             : static int
    5072         408 : sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
    5073             : {
    5074             :         /* Put single relation of updates and old values on to the stack */
    5075             :         sql_rel *r = NULL;
    5076             :         node *n;
    5077         408 :         list *exps = sa_list(sql->sa);
    5078         408 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    5079             : 
    5080         408 :         ti->t = t;
    5081         408 :         ti->tids = tids;
    5082         408 :         ti->updates = updates;
    5083         408 :         ti->type = 2;
    5084         408 :         ti->on = on;
    5085         408 :         ti->nn = nn;
    5086        2899 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    5087        2491 :                 sql_column *c = n->data;
    5088             : 
    5089        2491 :                 if (updates[c->colnr]) {
    5090         408 :                         sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5091         408 :                         sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5092             : 
    5093         408 :                         append(exps, oe);
    5094         408 :                         append(exps, ne);
    5095             :                 } else {
    5096        2083 :                         sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5097        2083 :                         sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5098             : 
    5099        2083 :                         append(exps, oe);
    5100        2083 :                         append(exps, ne);
    5101             :                 }
    5102             :         }
    5103         408 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    5104         408 :         r->l = ti;
    5105             : 
    5106             :         /* put single table into the stack with 2 names, needed for the psm code */
    5107         408 :         if (!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
    5108           0 :                 return 0;
    5109             :         return 1;
    5110             : }
    5111             : 
    5112             : static int
    5113        7508 : sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time )
    5114             : {
    5115        7508 :         mvc *sql = be->mvc;
    5116             :         node *n;
    5117             :         int res = 1;
    5118             : 
    5119        7508 :         if (!ol_length(t->triggers))
    5120             :                 return res;
    5121             : 
    5122        1604 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    5123         836 :                 sql_trigger *trigger = n->data;
    5124             : 
    5125         836 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    5126             :                         return 0;
    5127         836 :                 if (trigger->event == 2 && trigger->time == time) {
    5128             :                         /* add name for the 'inserted' to the stack */
    5129         408 :                         const char *n = trigger->new_name;
    5130         408 :                         const char *o = trigger->old_name;
    5131             : 
    5132         408 :                         if (!n) n = "new";
    5133         408 :                         if (!o) o = "old";
    5134             : 
    5135         408 :                         if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
    5136           0 :                                 stack_pop_frame(sql);
    5137           0 :                                 return 0;
    5138             :                         }
    5139             : 
    5140         408 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    5141           0 :                                 stack_pop_frame(sql);
    5142           0 :                                 return 0;
    5143             :                         }
    5144             :                 }
    5145         836 :                 stack_pop_frame(sql);
    5146             :         }
    5147             :         return res;
    5148             : }
    5149             : 
    5150             : static void
    5151        3754 : sql_update_check_null(backend *be, sql_table *t, stmt **updates)
    5152             : {
    5153        3754 :         mvc *sql = be->mvc;
    5154             :         node *n;
    5155        3754 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    5156             : 
    5157       42139 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    5158       38385 :                 sql_column *c = n->data;
    5159             : 
    5160       38385 :                 if (updates[c->colnr] && !c->null) {
    5161             :                         stmt *s = updates[c->colnr];
    5162             :                         char *msg = NULL;
    5163             : 
    5164         128 :                         if (!(s->key && s->nrcols == 0)) {
    5165         128 :                                 s = stmt_selectnil(be, updates[c->colnr]);
    5166         128 :                                 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    5167             :                         } else {
    5168           0 :                                 sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC);
    5169             : 
    5170           0 :                                 s = stmt_unop(be, updates[c->colnr], NULL, isnil);
    5171             :                         }
    5172         128 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
    5173         128 :                         (void)stmt_exception(be, s, msg, 00001);
    5174             :                 }
    5175             :         }
    5176        3754 : }
    5177             : 
    5178             : /* updates: an array of table width, per column holds the values for the to be updated rows  */
    5179             : static list *
    5180          43 : sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
    5181             : {
    5182          43 :         mvc *sql = be->mvc;
    5183             :         list *idx_updates = NULL;
    5184          43 :         int i, nr_cols = ol_length(t->columns);
    5185          43 :         list *l = sa_list(sql->sa);
    5186             :         node *n;
    5187             : 
    5188          43 :         sql_update_check_null(be, t, updates);
    5189             : 
    5190             :         /* check keys + get idx */
    5191          43 :         idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
    5192          43 :         if (!idx_updates) {
    5193           0 :                 assert(0);
    5194             :                 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
    5195             :         }
    5196             : 
    5197             : /* before */
    5198          43 :         if (!sql_update_triggers(be, t, rows, updates, 0))
    5199           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    5200             : 
    5201             : /* apply updates */
    5202         131 :         for (i = 0, n = ol_first_node(t->columns); i < nr_cols && n; i++, n = n->next) {
    5203          88 :                 sql_column *c = n->data;
    5204             : 
    5205          88 :                 if (updates[i])
    5206          45 :                         append(l, stmt_update_col(be, c, rows, updates[i]));
    5207             :         }
    5208          43 :         if (cascade_updates(be, t, rows, updates))
    5209           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
    5210             : 
    5211             : /* after */
    5212          43 :         if (!sql_update_triggers(be, t, rows, updates, 1))
    5213           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    5214             : 
    5215             : /* cascade ?? */
    5216             :         return l;
    5217             : }
    5218             : 
    5219             : /* updates with empty list is alter with create idx or keys */
    5220             : static stmt *
    5221        3964 : rel2bin_update(backend *be, sql_rel *rel, list *refs)
    5222             : {
    5223        3964 :         mvc *sql = be->mvc;
    5224             :         stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL, *cnt;
    5225        3964 :         list *l = sa_list(sql->sa);
    5226             :         int nr_cols, updcol, idx_ups = 0;
    5227             :         node *m;
    5228        3964 :         sql_rel *tr = rel->l, *prel = rel->r;
    5229             :         sql_table *t = NULL;
    5230             : 
    5231        3964 :         if ((rel->flag&UPD_COMP)) {  /* special case ! */
    5232             :                 idx_ups = 1;
    5233             :                 prel = rel->l;
    5234             :                 rel = rel->r;
    5235         955 :                 tr = rel->l;
    5236             :         }
    5237        3964 :         if (tr->op == op_basetable) {
    5238        2710 :                 t = tr->l;
    5239             :         } else {
    5240        1254 :                 ddl = subrel_bin(be, tr, refs);
    5241        1254 :                 ddl = subrel_project(be, ddl, refs, NULL);
    5242        1254 :                 if (!ddl)
    5243             :                         return NULL;
    5244        1254 :                 t = rel_ddl_table_get(tr);
    5245             : 
    5246             :                 /* no columns to update (probably an new pkey!) */
    5247        1254 :                 if (!rel->exps)
    5248             :                         return ddl;
    5249             :         }
    5250             : 
    5251        3711 :         if (rel->r) /* first construct the update relation */
    5252        3711 :                 update = subrel_bin(be, rel->r, refs);
    5253        3711 :         update = subrel_project(be, update, refs, rel->r);
    5254             : 
    5255        3711 :         if (!update)
    5256             :                 return NULL;
    5257             : 
    5258        3711 :         if (idx_ups)
    5259             :                 pup = refs_find_rel(refs, prel);
    5260             : 
    5261        3711 :         updates = table_update_stmts(sql, t, &nr_cols);
    5262        3711 :         tids = update->op4.lval->h->data;
    5263             : 
    5264             :         /* lookup the updates */
    5265       10288 :         for (m = rel->exps->h; m; m = m->next) {
    5266        6577 :                 sql_exp *ce = m->data;
    5267        6577 :                 sql_column *c = find_sql_column(t, exp_name(ce));
    5268             : 
    5269        6577 :                 if (c)
    5270        2898 :                         updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
    5271             :         }
    5272        3711 :         sql_update_check_null(be, t, updates);
    5273             : 
    5274             :         /* check keys + get idx */
    5275        3711 :         updcol = first_updated_col(updates, ol_length(t->columns));
    5276       10288 :         for (m = rel->exps->h; m; m = m->next) {
    5277        6577 :                 sql_exp *ce = m->data;
    5278        6577 :                 sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
    5279             :                 stmt *update_idx, *is = NULL;
    5280             : 
    5281        6577 :                 if (i) {
    5282         969 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    5283           0 :                                 continue;
    5284             : 
    5285         969 :                         update_idx = bin_find_column(be, update, ce->l, ce->r);
    5286         969 :                         if (update_idx)
    5287             :                                 is = update_idx;
    5288         969 :                         if (hash_index(i->type) && list_length(i->columns) <= 1) {
    5289             :                                 is = NULL;
    5290             :                                 update_idx = NULL;
    5291             :                         }
    5292         969 :                         if (i->key)
    5293        1580 :                                 sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
    5294         969 :                         if (is)
    5295         738 :                                 list_append(l, stmt_update_idx(be,  i, tids, is));
    5296             :                 }
    5297             :         }
    5298             : 
    5299             : /* before */
    5300        3711 :         if (!sql_update_triggers(be, t, tids, updates, 0)) {
    5301           0 :                 if (sql->cascade_action)
    5302           0 :                         sql->cascade_action = NULL;
    5303           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    5304             :         }
    5305             : 
    5306             : /* apply the update */
    5307       10288 :         for (m = rel->exps->h; m; m = m->next) {
    5308        6577 :                 sql_exp *ce = m->data;
    5309        6577 :                 sql_column *c = find_sql_column(t, exp_name(ce));
    5310             : 
    5311        6577 :                 if (c)
    5312        2898 :                         append(l, stmt_update_col(be,  c, tids, updates[c->colnr]));
    5313             :         }
    5314             : 
    5315        3711 :         if (cascade_updates(be, t, tids, updates)) {
    5316           0 :                 if (sql->cascade_action)
    5317           0 :                         sql->cascade_action = NULL;
    5318           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
    5319             :         }
    5320             : 
    5321             : /* after */
    5322        3711 :         if (!sql_update_triggers(be, t, tids, updates, 1)) {
    5323           0 :                 if (sql->cascade_action)
    5324           0 :                         sql->cascade_action = NULL;
    5325           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    5326             :         }
    5327             : 
    5328        3711 :         if (ddl) {
    5329        1001 :                 list_prepend(l, ddl);
    5330        1001 :                 cnt = stmt_list(be, l);
    5331             :         } else {
    5332        2710 :                 cnt = stmt_aggr(be, tids, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5333        2710 :                 if (!be->silent) {
    5334             :                         /* if there are multiple update statements, update total count, otherwise use the the current count */
    5335        2700 :                         be->rowcount = be->rowcount ? add_to_rowcount_accumulator(be, cnt->nr) : cnt->nr;
    5336             :                 }
    5337             :         }
    5338             : 
    5339        3711 :         if (sql->cascade_action)
    5340          60 :                 sql->cascade_action = NULL;
    5341        3711 :         if (rel->r && !rel_predicates(be, rel->r))
    5342             :                 return NULL;
    5343        3711 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK)
    5344           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5345             :         return cnt;
    5346             : }
    5347             : 
    5348             : static int
    5349          18 : sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, stmt **deleted_cols, int type)
    5350             : {
    5351             :         /* Put single relation of updates and old values on to the stack */
    5352             :         sql_rel *r = NULL;
    5353             :         node *n;
    5354          18 :         list *exps = sa_list(sql->sa);
    5355          18 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    5356             : 
    5357          18 :         ti->t = t;
    5358          18 :         ti->tids = tids;
    5359          18 :         ti->updates = deleted_cols;
    5360          18 :         ti->type = type;
    5361          18 :         ti->nn = name;
    5362          52 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    5363          34 :                 sql_column *c = n->data;
    5364          34 :                 sql_exp *ne = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5365             : 
    5366          34 :                 append(exps, ne);
    5367             :         }
    5368          18 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    5369          18 :         r->l = ti;
    5370             : 
    5371          18 :         return stack_push_rel_view(sql, name, r) ? 1 : 0;
    5372             : }
    5373             : 
    5374             : static int
    5375        1054 : sql_delete_triggers(backend *be, sql_table *t, stmt *tids, stmt **deleted_cols, int time, int firing_type, int internal_type)
    5376             : {
    5377        1054 :         mvc *sql = be->mvc;
    5378             :         node *n;
    5379             :         int res = 1;
    5380             : 
    5381        1054 :         if (!ol_length(t->triggers))
    5382             :                 return res;
    5383             : 
    5384         180 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    5385         138 :                 sql_trigger *trigger = n->data;
    5386             : 
    5387         138 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    5388             :                         return 0;
    5389         138 :                 if (trigger->event == firing_type && trigger->time == time) {
    5390             :                         /* add name for the 'deleted' to the stack */
    5391          18 :                         const char *o = trigger->old_name;
    5392             : 
    5393          18 :                         if (!o) o = "old";
    5394             : 
    5395          18 :                         if(!sql_stack_add_deleted(sql, o, t, tids, deleted_cols, internal_type)) {
    5396           0 :                                 stack_pop_frame(sql);
    5397           0 :                                 return 0;
    5398             :                         }
    5399             : 
    5400          18 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    5401           0 :                                 stack_pop_frame(sql);
    5402           0 :                                 return 0;
    5403             :                         }
    5404             :                 }
    5405         138 :                 stack_pop_frame(sql);
    5406             :         }
    5407             :         return res;
    5408             : }
    5409             : 
    5410             : static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
    5411             : 
    5412             : static stmt *
    5413           9 : sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
    5414             : {
    5415           9 :         sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
    5416           9 :         return sql_delete(be, t, ftids);
    5417             : }
    5418             : 
    5419             : static void
    5420         144 : sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
    5421             : {
    5422         144 :         mvc *sql = be->mvc;
    5423         144 :         sql_subtype *lng = sql_bind_localtype("lng");
    5424         144 :         sql_subtype *bt = sql_bind_localtype("bit");
    5425         144 :         sql_trans *tr = be->mvc->session->tr;
    5426         144 :         list *keys = sql_trans_get_dependencies(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    5427             : 
    5428         144 :         if (keys) {
    5429         205 :                 for (node *n = keys->h; n; n = n->next->next) {
    5430          61 :                         sqlid fkey_id = *(sqlid*)n->data;
    5431          61 :                         sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    5432             :                         sql_key *fk = (sql_key*)b;
    5433             :                         sql_fkey *rk = (sql_fkey*)b;
    5434             : 
    5435          61 :                         if (fk->type != fkey || rk->rkey != k->base.id)
    5436           0 :                                 continue;
    5437             :                         char *msg = NULL;
    5438          61 :                         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR);
    5439          61 :                         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, bt, 2, lng, lng);
    5440             :                         stmt *s, *tids;
    5441             : 
    5442          61 :                         tids = stmt_tid(be, fk->idx->t, 0);
    5443          61 :                         s = stmt_idx(be, fk->idx, tids, tids->partition);
    5444          61 :                         s = stmt_join(be, s, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    5445          61 :                         s = stmt_result(be, s, 0);
    5446          61 :                         tids = stmt_project(be, s, tids);
    5447          61 :                         if(cascade) { /* for truncate statements with the cascade option */
    5448           1 :                                 s = sql_delete_cascade_Fkeys(be, fk, tids);
    5449           1 :                                 list_prepend(l, s);
    5450             :                         } else {
    5451          60 :                                 switch (((sql_fkey*)fk)->on_delete) {
    5452             :                                         case ACT_NO_ACTION:
    5453             :                                                 break;
    5454          11 :                                         case ACT_SET_NULL:
    5455             :                                         case ACT_SET_DEFAULT:
    5456          11 :                                                 s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
    5457          11 :                                                 list_prepend(l, s);
    5458          11 :                                                 break;
    5459           8 :                                         case ACT_CASCADE:
    5460           8 :                                                 s = sql_delete_cascade_Fkeys(be, fk, tids);
    5461           8 :                                                 list_prepend(l, s);
    5462           8 :                                                 break;
    5463          39 :                                         default:        /*RESTRICT*/
    5464             :                                                 /* The overlap between deleted primaries and foreign should be empty */
    5465          39 :                                                 s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    5466          39 :                                                 msg = sa_message(sql->sa, SQLSTATE(40002) "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
    5467          39 :                                                 s = stmt_exception(be, s, msg, 00001);
    5468          39 :                                                 list_prepend(l, s);
    5469             :                                 }
    5470             :                         }
    5471             :                 }
    5472         144 :                 list_destroy(keys);
    5473             :         }
    5474         144 : }
    5475             : 
    5476             : static int
    5477         527 : sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
    5478             : {
    5479         527 :         mvc *sql = be->mvc;
    5480             :         int res = 1;
    5481             :         node *n;
    5482             : 
    5483         527 :         if (!ol_length(t->keys))
    5484             :                 return res;
    5485             : 
    5486         322 :         for (n = ol_first_node(t->keys); n; n = n->next) {
    5487         186 :                 sql_key *k = n->data;
    5488             : 
    5489         186 :                 if (k->type == pkey || k->type == ukey) {
    5490         145 :                         if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
    5491         144 :                                 sqlid *local_id = SA_NEW(sql->sa, sqlid);
    5492         144 :                                 if (!sql->cascade_action)
    5493         126 :                                         sql->cascade_action = sa_list(sql->sa);
    5494             : 
    5495         144 :                                 *local_id = k->base.id;
    5496         144 :                                 list_append(sql->cascade_action, local_id);
    5497         144 :                                 sql_delete_ukey(be, rows, k, l, which, cascade);
    5498             :                         }
    5499             :                 }
    5500             :         }
    5501             :         return res;
    5502             : }
    5503             : 
    5504             : static stmt *
    5505         455 : sql_delete(backend *be, sql_table *t, stmt *rows)
    5506             : {
    5507         455 :         mvc *sql = be->mvc;
    5508             :         stmt *v = NULL, *s = NULL;
    5509         455 :         list *l = sa_list(sql->sa);
    5510             :         stmt **deleted_cols = NULL;
    5511             : 
    5512         455 :         if (rows) {
    5513             :                 v = rows;
    5514             :         } else { /* delete all */
    5515         111 :                 v = stmt_tid(be, t, 0);
    5516             :         }
    5517             : 
    5518             :         /*  project all columns */
    5519         455 :         if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
    5520          36 :                 int nr = 0;
    5521          36 :                 deleted_cols = table_update_stmts(sql, t, &nr);
    5522             :                 int i = 0;
    5523         101 :                 for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
    5524          65 :                         sql_column *c = n->data;
    5525          65 :                         stmt *s = stmt_col(be, c, v, v->partition);
    5526             : 
    5527          65 :                         deleted_cols[i] = s;
    5528          65 :                         list_append(l, s);
    5529             :                 }
    5530             :         }
    5531             : 
    5532             : /* before */
    5533         455 :         if (!sql_delete_triggers(be, t, v, deleted_cols, 0, 1, 3))
    5534           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
    5535             : 
    5536         455 :         if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
    5537           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
    5538             : 
    5539         455 :         if (rows) {
    5540         344 :                 s = stmt_delete(be, t, rows);
    5541         344 :                 if (!be->silent)
    5542         342 :                         s = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5543             :         } else { /* delete all */
    5544         111 :                 s = stmt_table_clear(be, t); /* first column */
    5545             :         }
    5546             : 
    5547             : /* after */
    5548         455 :         if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
    5549           0 :                 return sql_error(sql, 02, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
    5550             :         return s;
    5551             : }
    5552             : 
    5553             : static stmt *
    5554         446 : rel2bin_delete(backend *be, sql_rel *rel, list *refs)
    5555             : {
    5556         446 :         mvc *sql = be->mvc;
    5557             :         stmt *stdelete = NULL, *tids = NULL;
    5558         446 :         sql_rel *tr = rel->l;
    5559             :         sql_table *t = NULL;
    5560             : 
    5561         446 :         if (tr->op == op_basetable)
    5562         446 :                 t = tr->l;
    5563             :         else
    5564           0 :                 assert(0/*ddl statement*/);
    5565             : 
    5566         446 :         if (rel->r) { /* first construct the deletes relation */
    5567         335 :                 stmt *rows = subrel_bin(be, rel->r, refs);
    5568         335 :                 rows = subrel_project(be, rows, refs, rel->r);
    5569         335 :                 if (!rows)
    5570             :                         return NULL;
    5571         335 :                 assert(rows->type == st_list);
    5572         335 :                 tids = rows->op4.lval->h->data; /* TODO this should be the candidate list instead */
    5573             :         }
    5574         446 :         stdelete = sql_delete(be, t, tids);
    5575         446 :         if (sql->cascade_action)
    5576         117 :                 sql->cascade_action = NULL;
    5577         446 :         if (!stdelete)
    5578             :                 return NULL;
    5579             : 
    5580         446 :         if (!be->silent) {
    5581             :                 /* if there are multiple update statements, update total count, otherwise use the the current count */
    5582         441 :                 be->rowcount = be->rowcount ? add_to_rowcount_accumulator(be, stdelete->nr) : stdelete->nr;
    5583             :         }
    5584         446 :         if (rel->r && !rel_predicates(be, rel->r))
    5585             :                 return NULL;
    5586         446 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK)
    5587           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5588             : 
    5589             :         return stdelete;
    5590             : }
    5591             : 
    5592             : struct tablelist {
    5593             :         sql_table *table;
    5594             :         struct tablelist* next;
    5595             : };
    5596             : 
    5597             : static void /* inspect the other tables recursively for foreign key dependencies */
    5598          74 : check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct tablelist* next_append, sql_table *t, int cascade, int *error)
    5599             : {
    5600             :         node *n;
    5601             :         int found;
    5602             :         struct tablelist* new_node, *node_check;
    5603          74 :         sql_trans *tr = sql->session->tr;
    5604             : 
    5605          74 :         if (THRhighwater()) {
    5606           0 :                 sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    5607           0 :                 *error = 1;
    5608           0 :                 return;
    5609             :         }
    5610             : 
    5611          74 :         if (*error)
    5612             :                 return;
    5613             : 
    5614          74 :         sqlstore *store = sql->session->tr->store;
    5615          74 :         if (t->keys) { /* Check for foreign key references */
    5616          88 :                 for (n = ol_first_node(t->keys); n; n = n->next) {
    5617          16 :                         sql_key *k = n->data;
    5618             : 
    5619          16 :                         if (k->type == ukey || k->type == pkey) {
    5620          13 :                                 list *keys = sql_trans_get_dependencies(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    5621             : 
    5622          13 :                                 if (keys) {
    5623          17 :                                         for (node *n = keys->h; n; n = n->next->next) {
    5624           6 :                                                 sqlid fkey_id = *(sqlid*)n->data;
    5625           6 :                                                 sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    5626             :                                                 sql_key *fk = (sql_key*)b;
    5627             :                                                 sql_fkey *rk = (sql_fkey*)b;
    5628             : 
    5629           6 :                                                 if (fk->type != fkey || rk->rkey != k->base.id)
    5630           1 :                                                         continue;
    5631             :                                                 k = fk;
    5632             :                                                 /* make sure it is not a self referencing key */
    5633           5 :                                                 if (k->t != t && !cascade && isTable(t)) {
    5634           4 :                                                         node *n = ol_first_node(t->columns);
    5635           4 :                                                         sql_column *c = n->data;
    5636           4 :                                                         size_t n_rows = store->storage_api.count_col(sql->session->tr, c, 10);
    5637           4 :                                                         if (n_rows > 0) {
    5638           2 :                                                                 list_destroy(keys);
    5639           2 :                                                                 sql_error(sql, 02, SQLSTATE(23000) "TRUNCATE: FOREIGN KEY %s.%s depends on %s", k->t->base.name, k->base.name, t->base.name);
    5640           2 :                                                                 *error = 1;
    5641           2 :                                                                 return;
    5642             :                                                         }
    5643           1 :                                                 } else if (k->t != t) {
    5644             :                                                         found = 0;
    5645           2 :                                                         for (node_check = tlist; node_check; node_check = node_check->next) {
    5646           1 :                                                                 if (node_check->table == k->t)
    5647             :                                                                         found = 1;
    5648             :                                                         }
    5649           1 :                                                         if (!found) {
    5650           1 :                                                                 if ((new_node = SA_NEW(sql->ta, struct tablelist)) == NULL) {
    5651           0 :                                                                         list_destroy(keys);
    5652           0 :                                                                         sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5653           0 :                                                                         *error = 1;
    5654           0 :                                                                         return;
    5655             :                                                                 }
    5656           1 :                                                                 new_node->table = k->t;
    5657           1 :                                                                 new_node->next = NULL;
    5658           1 :                                                                 next_append->next = new_node;
    5659           1 :                                                                 check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade, error);
    5660             :                                                         }
    5661             :                                                 }
    5662             :                                         }
    5663          11 :                                         list_destroy(keys);
    5664             :                                 }
    5665             :                         }
    5666             :                 }
    5667             :         }
    5668             : }
    5669             : 
    5670             : static stmt *
    5671          73 : sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
    5672             : {
    5673          73 :         mvc *sql = be->mvc;
    5674          73 :         list *l = sa_list(sql->sa);
    5675             :         stmt *v, *ret = NULL, *other = NULL;
    5676             :         const char *next_value_for = "next value for ";
    5677             :         sql_column *col = NULL;
    5678             :         sql_schema *sche = NULL;
    5679             :         sql_table *next = NULL;
    5680          73 :         sql_trans *tr = sql->session->tr;
    5681          73 :         int error = 0;
    5682          73 :         struct tablelist* new_list = SA_NEW(sql->ta, struct tablelist), *list_node;
    5683             :         stmt **deleted_cols = NULL;
    5684             : 
    5685          73 :         if (!new_list) {
    5686           0 :                 sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5687           0 :                 error = 1;
    5688           0 :                 goto finalize;
    5689             :         }
    5690             : 
    5691          73 :         new_list->table = t;
    5692          73 :         new_list->next = NULL;
    5693          73 :         check_for_foreign_key_references(sql, new_list, new_list, t, cascade, &error);
    5694          73 :         if (error)
    5695           2 :                 goto finalize;
    5696             : 
    5697         143 :         for (list_node = new_list; list_node; list_node = list_node->next) {
    5698          72 :                 next = list_node->table;
    5699          72 :                 sche = next->s;
    5700             : 
    5701          72 :                 if (restart_sequences) { /* restart the sequences if it's the case */
    5702           3 :                         for (node *n = ol_first_node(next->columns); n; n = n->next) {
    5703           2 :                                 col = n->data;
    5704             : 
    5705           2 :                                 if (col->def && !strncmp(col->def, next_value_for, strlen(next_value_for))) {
    5706             :                                         sql_schema *s = NULL;
    5707             :                                         sql_sequence *seq = NULL;
    5708           1 :                                         char *schema = NULL, *seq_name = NULL;
    5709             : 
    5710           1 :                                         extract_schema_and_sequence_name(sql->ta, col->def + strlen(next_value_for), &schema, &seq_name);
    5711           1 :                                         if (!schema || !seq_name || !(s = find_sql_schema(tr, schema)))
    5712           0 :                                                 continue;
    5713             : 
    5714           1 :                                         assert(s->base.id == sche->base.id);
    5715           1 :                                         if ((seq = find_sql_sequence(tr, s, seq_name))) {
    5716           1 :                                                 switch (sql_trans_sequence_restart(tr, seq, seq->start)) {
    5717           0 :                                                         case -1:
    5718           0 :                                                                 sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5719           0 :                                                                 error = 1;
    5720           0 :                                                                 goto finalize;
    5721           0 :                                                         case -2:
    5722             :                                                         case -3:
    5723           0 :                                                                 sql_error(sql, 02, SQLSTATE(HY005) "RESTART SEQUENCE: transaction conflict detected");
    5724           0 :                                                                 error = 1;
    5725           0 :                                                                 goto finalize;
    5726           0 :                                                         case -4:
    5727           0 :                                                                 sql_error(sql, 02, SQLSTATE(HY005) "Could not restart sequence %s.%s", sche->base.name, seq_name);
    5728           0 :                                                                 error = 1;
    5729           0 :                                                                 goto finalize;
    5730             :                                                         default:
    5731             :                                                                 break;
    5732             :                                                 }
    5733           0 :                                         }
    5734             :                                 }
    5735             :                         }
    5736             :                 }
    5737             : 
    5738          72 :                 v = stmt_tid(be, next, 0);
    5739             : 
    5740             :                 /*  project all columns */
    5741          72 :                 if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
    5742          18 :                         int nr = 0;
    5743          18 :                         deleted_cols = table_update_stmts(sql, t, &nr);
    5744             :                         int i = 0;
    5745          50 :                         for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
    5746          32 :                                 sql_column *c = n->data;
    5747          32 :                                 stmt *s = stmt_col(be, c, v, v->partition);
    5748             : 
    5749          32 :                                 deleted_cols[i] = s;
    5750          32 :                                 list_append(l, s);
    5751             :                         }
    5752             :                 }
    5753             : 
    5754             :                 /* before */
    5755          72 :                 if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
    5756           0 :                         sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
    5757           0 :                         error = 1;
    5758           0 :                         goto finalize;
    5759             :                 }
    5760             : 
    5761          72 :                 if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
    5762           0 :                         sql_error(sql, 02, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
    5763           0 :                         error = 1;
    5764           0 :                         goto finalize;
    5765             :                 }
    5766             : 
    5767          72 :                 other = stmt_table_clear(be, next);
    5768          72 :                 list_append(l, other);
    5769          72 :                 if (next == t)
    5770             :                         ret = other;
    5771             : 
    5772             :                 /* after */
    5773          72 :                 if (!sql_delete_triggers(be, next, v, deleted_cols, 1, 3, 4)) {
    5774           0 :                         sql_error(sql, 02, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
    5775           0 :                         error = 1;
    5776           0 :                         goto finalize;
    5777             :                 }
    5778             : 
    5779          72 :                 if (!be->silent) {
    5780             :                         /* if there are multiple update statements, update total count, otherwise use the the current count */
    5781          67 :                         be->rowcount = be->rowcount ? add_to_rowcount_accumulator(be, other->nr) : other->nr;
    5782             :                 }
    5783             :         }
    5784             : 
    5785          71 : finalize:
    5786          73 :         sa_reset(sql->ta);
    5787          73 :         if (error)
    5788           2 :                 return NULL;
    5789             :         return ret;
    5790             : }
    5791             : 
    5792             : #define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
    5793             : #define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
    5794             : 
    5795             : static stmt *
    5796          73 : rel2bin_truncate(backend *be, sql_rel *rel)
    5797             : {
    5798          73 :         mvc *sql = be->mvc;
    5799             :         stmt *truncate = NULL;
    5800          73 :         sql_rel *tr = rel->l;
    5801             :         sql_table *t = NULL;
    5802             :         node *n = NULL;
    5803             :         int restart_sequences, cascade;
    5804             : 
    5805          73 :         if (tr->op == op_basetable)
    5806          73 :                 t = tr->l;
    5807             :         else
    5808           0 :                 assert(0/*ddl statement*/);
    5809             : 
    5810          73 :         n = rel->exps->h;
    5811          73 :         restart_sequences = E_ATOM_INT(n->data);
    5812          73 :         cascade = E_ATOM_INT(n->next->data);
    5813             : 
    5814          73 :         if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK)
    5815           0 :                 return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    5816             : 
    5817          73 :         truncate = sql_truncate(be, t, restart_sequences, cascade);
    5818          73 :         if (sql->cascade_action)
    5819           9 :                 sql->cascade_action = NULL;
    5820             :         return truncate;
    5821             : }
    5822             : 
    5823             : static stmt *
    5824          12 : rel2bin_output(backend *be, sql_rel *rel, list *refs)
    5825             : {
    5826          12 :         mvc *sql = be->mvc;
    5827             :         node *n;
    5828             :         const char *tsep, *rsep, *ssep, *ns;
    5829             :         const char *fn   = NULL;
    5830             :         int onclient = 0;
    5831             :         stmt *s = NULL, *fns = NULL;
    5832          12 :         list *slist = sa_list(sql->sa);
    5833             : 
    5834          12 :         if (rel->l)  /* first construct the sub relation */
    5835          12 :                 s = subrel_bin(be, rel->l, refs);
    5836          12 :         s = subrel_project(be, s, refs, rel->l);
    5837          12 :         if (!s)
    5838             :                 return NULL;
    5839             : 
    5840          12 :         if (!rel->exps)
    5841             :                 return s;
    5842          12 :         n = rel->exps->h;
    5843          12 :         tsep = sa_strdup(sql->sa, E_ATOM_STRING(n->data));
    5844          12 :         rsep = sa_strdup(sql->sa, E_ATOM_STRING(n->next->data));
    5845          12 :         ssep = sa_strdup(sql->sa, E_ATOM_STRING(n->next->next->data));
    5846          12 :         ns   = sa_strdup(sql->sa, E_ATOM_STRING(n->next->next->next->data));
    5847             : 
    5848          12 :         if (n->next->next->next->next) {
    5849           3 :                 fn = E_ATOM_STRING(n->next->next->next->next->data);
    5850           3 :                 fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
    5851           3 :                 onclient = E_ATOM_INT(n->next->next->next->next->next->data);
    5852             :         }
    5853          12 :         list_append(slist, stmt_export(be, s, tsep, rsep, ssep, ns, onclient, fns));
    5854          12 :         if (s->type == st_list && ((stmt*)s->op4.lval->h->data)->nrcols != 0) {
    5855          11 :                 stmt *cnt = stmt_aggr(be, s->op4.lval->h->data, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5856          11 :                 return cnt;
    5857             :         } else {
    5858           1 :                 return stmt_atom_lng(be, 1);
    5859             :         }
    5860             : }
    5861             : 
    5862             : static list *
    5863          47 : merge_stmt_join_projections(backend *be, stmt *left, stmt *right, stmt *jl, stmt *jr, stmt *diff)
    5864             : {
    5865          47 :         mvc *sql = be->mvc;
    5866          47 :         list *l = sa_list(sql->sa);
    5867             : 
    5868          47 :         if (left)
    5869          96 :                 for( node *n = left->op4.lval->h; n; n = n->next ) {
    5870          72 :                         stmt *c = n->data;
    5871          72 :                         const char *rnme = table_name(sql->sa, c);
    5872          72 :                         const char *nme = column_name(sql->sa, c);
    5873          72 :                         stmt *s = stmt_project(be, jl ? jl : diff, column(be, c));
    5874             : 
    5875          72 :                         s = stmt_alias(be, s, rnme, nme);
    5876          72 :                         list_append(l, s);
    5877             :                 }
    5878          47 :         if (right)
    5879         153 :                 for( node *n = right->op4.lval->h; n; n = n->next ) {
    5880         114 :                         stmt *c = n->data;
    5881         114 :                         const char *rnme = table_name(sql->sa, c);
    5882         114 :                         const char *nme = column_name(sql->sa, c);
    5883         172 :                         stmt *s = stmt_project(be, jr ? jr : diff, column(be, c));
    5884             : 
    5885         114 :                         s = stmt_alias(be, s, rnme, nme);
    5886         114 :                         list_append(l, s);
    5887             :                 }
    5888          47 :         return l;
    5889             : }
    5890             : 
    5891             : static void
    5892          24 : validate_merge_delete_update(backend *be, bool delete, stmt *bt_stmt, sql_rel *bt, stmt *jl, stmt *ld)
    5893             : {
    5894          24 :         mvc *sql = be->mvc;
    5895             :         str msg;
    5896          24 :         sql_table *t = bt->l;
    5897          24 :         char *alias = (char *) rel_name(bt);
    5898          24 :         stmt *cnt1 = stmt_aggr(be, jl, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5899          24 :         stmt *cnt2 = stmt_aggr(be, ld, NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5900          24 :         sql_subfunc *add = sql_bind_func(sql, "sys", "sql_add", tail_type(cnt1), tail_type(cnt2), F_FUNC);
    5901          24 :         stmt *s1 = stmt_binop(be, cnt1, cnt2, NULL, add);
    5902          24 :         stmt *cnt3 = stmt_aggr(be, bin_find_smallest_column(be, bt_stmt), NULL, NULL, sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR), 1, 0, 1);
    5903          24 :         sql_subfunc *bf = sql_bind_func(sql, "sys", ">", tail_type(s1), tail_type(cnt3), F_FUNC);
    5904          24 :         stmt *s2 = stmt_binop(be, s1, cnt3, NULL, bf);
    5905             : 
    5906          24 :         if (alias && strcmp(alias, t->base.name) == 0) /* detect if alias is present */
    5907             :                 alias = NULL;
    5908          86 :         msg = sa_message(sql->sa, SQLSTATE(40002) "MERGE %s: Multiple rows in the input relation match the same row in the target %s '%s%s%s'",
    5909             :                                          delete ? "DELETE" : "UPDATE",
    5910             :                                          alias ? "relation" : "table",
    5911          18 :                                          alias ? alias : t->s ? t->s->base.name : "", alias ? "" : ".", alias ? "" : t->base.name);
    5912          24 :         (void)stmt_exception(be, s2, msg, 00001);
    5913          24 : }
    5914             : 
    5915             : static stmt *
    5916          47 : rel2bin_merge_apply_update(backend *be, sql_rel *join, sql_rel *upd, list *refs, stmt *bt_stmt, stmt *target_stmt, stmt *jl, stmt *jr, stmt *ld, stmt **rd)
    5917             : {
    5918          47 :         if (is_insert(upd->op)) {
    5919          23 :                 if (!*rd) {
    5920          23 :                         *rd = stmt_tdiff(be, stmt_mirror(be, bin_find_smallest_column(be, target_stmt)), jr, NULL);
    5921             :                 }
    5922          23 :                 stmt *s = stmt_list(be, merge_stmt_join_projections(be, NULL, target_stmt, NULL, NULL, *rd));
    5923             :                 refs_update_stmt(refs, join, s); /* project the differences on the target side for inserts */
    5924             : 
    5925          23 :                 return rel2bin_insert(be, upd, refs);
    5926             :         } else {
    5927          40 :                 stmt *s = stmt_list(be, merge_stmt_join_projections(be, bt_stmt, is_update(upd->op) ? target_stmt : NULL, jl, is_update(upd->op) ? jr : NULL, NULL));
    5928             :                 refs_update_stmt(refs, join, s); /* project the matched values on both sides for updates and deletes */
    5929             : 
    5930          24 :                 assert(is_update(upd->op) || is_delete(upd->op));
    5931             :                 /* the left joined values + left difference must be smaller than the table count */
    5932          24 :                 validate_merge_delete_update(be, is_update(upd->op), bt_stmt, join->l, jl, ld);
    5933             : 
    5934          24 :                 return is_update(upd->op) ? rel2bin_update(be, upd, refs) : rel2bin_delete(be, upd, refs);
    5935             :         }
    5936             : }
    5937             : 
    5938             : static stmt *
    5939          39 : rel2bin_merge(backend *be, sql_rel *rel, list *refs)
    5940             : {
    5941          39 :         mvc *sql = be->mvc;
    5942          39 :         sql_rel *join = rel->l, *r = rel->r;
    5943          39 :         stmt *join_st, *bt_stmt, *target_stmt, *jl, *jr, *ld, *rd = NULL, *ns;
    5944          39 :         list *slist = sa_list(sql->sa);
    5945             : 
    5946          39 :         assert(rel_is_ref(join) && is_left(join->op));
    5947          39 :         join_st = subrel_bin(be, join, refs);
    5948          39 :         if (!join_st)
    5949             :                 return NULL;
    5950             : 
    5951             :         /* grab generated left join outputs and generate updates accordingly to matched and not matched values */
    5952          39 :         assert(join_st->type == st_list && list_length(join_st->extra) == 5);
    5953          39 :         bt_stmt = join_st->extra->h->data;
    5954          39 :         target_stmt = join_st->extra->h->next->data;
    5955          39 :         jl = join_st->extra->h->next->next->data;
    5956          39 :         jr = join_st->extra->h->next->next->next->data;
    5957          39 :         ld = join_st->extra->h->next->next->next->next->data;
    5958             : 
    5959          39 :         if (is_ddl(r->op)) {
    5960          39 :                 assert(r->flag == ddl_list);
    5961          39 :                 if (r->l) {
    5962          39 :                         if ((ns = rel2bin_merge_apply_update(be, join, r->l, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
    5963             :                                 return NULL;
    5964          39 :                         list_append(slist, ns);
    5965             :                 }
    5966          39 :                 if (r->r) {
    5967           8 :                         if ((ns = rel2bin_merge_apply_update(be, join, r->r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
    5968             :                                 return NULL;
    5969           8 :                         list_append(slist, ns);
    5970             :                 }
    5971             :         } else {
    5972           0 :                 if (!(ns = rel2bin_merge_apply_update(be, join, r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)))
    5973             :                         return NULL;
    5974           0 :                 list_append(slist, ns);
    5975             :         }
    5976          39 :         return stmt_list(be, slist);
    5977             : }
    5978             : 
    5979             : static stmt *
    5980         315 : rel2bin_list(backend *be, sql_rel *rel, list *refs)
    5981             : {
    5982         315 :         mvc *sql = be->mvc;
    5983             :         stmt *l = NULL, *r = NULL;
    5984         315 :         list *slist = sa_list(sql->sa);
    5985             : 
    5986         315 :         if (rel->l)  /* first construct the sub relation */
    5987         315 :                 l = subrel_bin(be, rel->l, refs);
    5988         315 :         if (rel->r)  /* first construct the sub relation */
    5989         315 :                 r = subrel_bin(be, rel->r, refs);
    5990         315 :         l = subrel_project(be, l, refs, rel->l);
    5991         315 :         r = subrel_project(be, r, refs, rel->r);
    5992         315 :         if (!l || !r)
    5993             :                 return NULL;
    5994         315 :         list_append(slist, l);
    5995         315 :         list_append(slist, r);
    5996         315 :         return stmt_list(be, slist);
    5997             : }
    5998             : 
    5999             : static stmt *
    6000       12504 : rel2bin_psm(backend *be, sql_rel *rel)
    6001             : {
    6002       12504 :         mvc *sql = be->mvc;
    6003             :         node *n;
    6004       12504 :         list *l = sa_list(sql->sa);
    6005             :         stmt *sub = NULL;
    6006             : 
    6007       22371 :         for (n = rel->exps->h; n; n = n->next) {
    6008       13007 :                 sql_exp *e = n->data;
    6009       13007 :                 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6010       13007 :                 if (!s)
    6011             :                         return NULL;
    6012             : 
    6013        9867 :                 if (s && s->type == st_table) /* relational statement */
    6014          34 :                         sub = s->op1;
    6015             :                 else
    6016        9833 :                         append(l, s);
    6017             :         }
    6018        9364 :         return stmt_list(be, l);
    6019             : }
    6020             : 
    6021             : static stmt *
    6022         251 : rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
    6023             : {
    6024             :         stmt *l = NULL, *r = NULL;
    6025             :         node *n = NULL;
    6026         251 :         list *slist = sa_list(be->mvc->sa);
    6027             : 
    6028         251 :         if (rel->l)  /* first construct the sub relation */
    6029           0 :                 l = subrel_bin(be, rel->l, refs);
    6030         251 :         if (rel->r)  /* first construct the sub relation */
    6031           0 :                 r = subrel_bin(be, rel->r, refs);
    6032         251 :         l = subrel_project(be, l, refs, rel->l);
    6033         251 :         r = subrel_project(be, r, refs, rel->r);
    6034         251 :         if ((rel->l && !l) || (rel->r && !r))
    6035             :                 return NULL;
    6036             : 
    6037         251 :         assert(rel->exps);
    6038         251 :         assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
    6039             : 
    6040             :         if (rel->exps) {
    6041        2311 :                 for (n = rel->exps->h; n; n = n->next) {
    6042        2060 :                         sql_exp *e = n->data;
    6043        2060 :                         stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
    6044        2060 :                         if (!s)
    6045             :                                 return NULL;
    6046        2060 :                         append(slist, s);
    6047             :                 }
    6048             :         }
    6049         251 :         return stmt_catalog(be, rel->flag, stmt_list(be, slist));
    6050             : }
    6051             : 
    6052             : static stmt *
    6053         400 : rel2bin_exception(backend *be, sql_rel *rel, list *refs)
    6054             : {
    6055             :         stmt *l = NULL, *r = NULL;
    6056         400 :         list *slist = sa_list(be->mvc->sa);
    6057             : 
    6058         400 :         if (rel->l)  /* first construct the sub relation */
    6059         393 :                 l = subrel_bin(be, rel->l, refs);
    6060         400 :         if (rel->r)  /* first construct the sub relation */
    6061         400 :                 r = subrel_bin(be, rel->r, refs);
    6062         400 :         l = subrel_project(be, l, refs, rel->l);
    6063         400 :         r = subrel_project(be, r, refs, rel->r);
    6064         400 :         if ((rel->l && !l) || (rel->r && !r))
    6065             :                 return NULL;
    6066             : 
    6067         400 :         assert(rel->exps);
    6068         800 :         for (node *n = rel->exps->h; n; n = n->next) {
    6069         400 :                 sql_exp *e = n->data;
    6070         400 :                 stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
    6071         400 :                 if (!s)
    6072             :                         return NULL;
    6073         400 :                 list_append(slist, s);
    6074             :         }
    6075         400 :         return stmt_list(be, slist);
    6076             : }
    6077             : 
    6078             : static stmt *
    6079         337 : rel2bin_seq(backend *be, sql_rel *rel, list *refs)
    6080             : {
    6081         337 :         mvc *sql = be->mvc;
    6082         337 :         node *en = rel->exps->h;
    6083             :         stmt *restart, *sname, *seq, *seqname, *sl = NULL;
    6084         337 :         list *l = sa_list(sql->sa);
    6085             : 
    6086         337 :         if (rel->l) { /* first construct the sub relation */
    6087           0 :                 sl = subrel_bin(be, rel->l, refs);
    6088           0 :                 sl = subrel_project(be, sl, refs, rel->l);
    6089           0 :                 if (!sl)
    6090             :                         return NULL;
    6091             :         }
    6092             : 
    6093         337 :         restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6094         337 :         sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6095         337 :         seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6096         337 :         seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6097         337 :         if (!restart || !sname || !seqname || !seq)
    6098             :                 return NULL;
    6099             : 
    6100             :         (void)refs;
    6101         337 :         append(l, sname);
    6102         337 :         append(l, seqname);
    6103         337 :         append(l, seq);
    6104         337 :         append(l, restart);
    6105         337 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    6106             : }
    6107             : 
    6108             : static stmt *
    6109        2687 : rel2bin_trans(backend *be, sql_rel *rel, list *refs)
    6110             : {
    6111        2687 :         node *en = rel->exps->h;
    6112        2687 :         stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6113             :         stmt *name = NULL;
    6114             : 
    6115        2687 :         if (!chain)
    6116             :                 return NULL;
    6117             : 
    6118             :         (void)refs;
    6119        2687 :         if (en->next) {
    6120          61 :                 name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6121          61 :                 if (!name)
    6122             :                         return NULL;
    6123             :         }
    6124        2687 :         return stmt_trans(be, rel->flag, chain, name);
    6125             : }
    6126             : 
    6127             : static stmt *
    6128        1250 : rel2bin_catalog_schema(backend *be, sql_rel *rel, list *refs)
    6129             : {
    6130        1250 :         mvc *sql = be->mvc;
    6131        1250 :         node *en = rel->exps->h;
    6132        1250 :         stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6133             :         stmt *sname = NULL, *name = NULL, *ifexists = NULL;
    6134        1250 :         list *l = sa_list(sql->sa);
    6135             : 
    6136        1250 :         if (!action)
    6137             :                 return NULL;
    6138             : 
    6139             :         (void)refs;
    6140        1250 :         en = en->next;
    6141        1250 :         sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6142        1250 :         if (!sname)
    6143             :                 return NULL;
    6144        1250 :         append(l, sname);
    6145        1250 :         en = en->next;
    6146        1250 :         if (rel->flag == ddl_create_schema) {
    6147        1091 :                 if (en) {
    6148          34 :                         name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6149          34 :                         if (!name)
    6150             :                                 return NULL;
    6151             :                 } else {
    6152        1057 :                         name = stmt_atom_string_nil(be);
    6153             :                 }
    6154        1091 :                 append(l, name);
    6155             :         } else {
    6156         159 :                 assert(rel->flag == ddl_drop_schema);
    6157         159 :                 ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6158         159 :                 if (!ifexists)
    6159             :                         return NULL;
    6160         159 :                 append(l, ifexists);
    6161             :         }
    6162        1250 :         append(l, action);
    6163        1250 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    6164             : }
    6165             : 
    6166             : static stmt *
    6167       30171 : rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
    6168             : {
    6169       30171 :         mvc *sql = be->mvc;
    6170       30171 :         node *en = rel->exps->h;
    6171       30171 :         stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6172             :         stmt *table = NULL, *sname, *tname = NULL, *kname = NULL, *ifexists = NULL, *replace = NULL;
    6173       30171 :         list *l = sa_list(sql->sa);
    6174             : 
    6175       30171 :         if (!action)
    6176             :                 return NULL;
    6177             : 
    6178             :         (void)refs;
    6179       30171 :         en = en->next;
    6180       30171 :         sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6181       30171 :         if (!sname)
    6182             :                 return NULL;
    6183       30171 :         en = en->next;
    6184       30171 :         if (en) {
    6185       30171 :                 tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6186       30171 :                 if (!tname)
    6187             :                         return NULL;
    6188       30171 :                 en = en->next;
    6189             :         }
    6190       30171 :         append(l, sname);
    6191       30171 :         assert(tname);
    6192       30171 :         append(l, tname);
    6193       30171 :         if (rel->flag == ddl_drop_constraint) { /* needs extra string parameter for constraint name */
    6194         146 :                 if (en) {
    6195         146 :                         kname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6196         146 :                         if (!kname)
    6197             :                                 return NULL;
    6198         146 :                         en = en->next;
    6199             :                 }
    6200         146 :                 append(l, kname);
    6201             :         }
    6202       30171 :         if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
    6203       26216 :                 if (en) {
    6204       26216 :                         table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6205       26216 :                         if (!table)
    6206             :                                 return NULL;
    6207       26216 :                         en = en->next;
    6208             :                 }
    6209       26216 :                 append(l, table);
    6210             :         } else {
    6211        3955 :                 if (en) {
    6212        3955 :                         ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6213        3955 :                         if (!ifexists)
    6214             :                                 return NULL;
    6215        3955 :                         en = en->next;
    6216             :                 } else {
    6217           0 :                         ifexists = stmt_atom_int(be, 0);
    6218             :                 }
    6219        3955 :                 append(l, ifexists);
    6220             :         }
    6221       30171 :         append(l, action);
    6222       30171 :         if (rel->flag == ddl_create_view) {
    6223       16617 :                 if (en) {
    6224       16617 :                         replace = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6225       16617 :                         if (!replace)
    6226             :                                 return NULL;
    6227             :                 } else {
    6228           0 :                         replace = stmt_atom_int(be, 0);
    6229             :                 }
    6230       16617 :                 append(l, replace);
    6231             :         }
    6232       30171 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    6233             : }
    6234             : 
    6235             : static stmt *
    6236      171701 : rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
    6237             : {
    6238      171701 :         mvc *sql = be->mvc;
    6239             :         node *en;
    6240      171701 :         list *l = sa_list(sql->sa);
    6241             : 
    6242             :         (void)refs;
    6243     1021203 :         for (en = rel->exps->h; en; en = en->next) {
    6244             :                 stmt *es = NULL;
    6245             : 
    6246      849502 :                 if (en->data) {
    6247      840067 :                         es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    6248      840067 :                         if (!es)
    6249             :                                 return NULL;
    6250             :                 } else {
    6251        9435 :                         es = stmt_atom_string_nil(be);
    6252             :                 }
    6253      849502 :                 append(l,es);
    6254             :         }
    6255      171701 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    6256             : }
    6257             : 
    6258             : static stmt *
    6259      219628 : rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
    6260             : {
    6261      219628 :         mvc *sql = be->mvc;
    6262             :         stmt *s = NULL;
    6263             : 
    6264      219628 :         switch (rel->flag) {
    6265          12 :                 case ddl_output:
    6266          12 :                         s = rel2bin_output(be, rel, refs);
    6267          12 :                         sql->type = Q_TABLE;
    6268          12 :                         break;
    6269         315 :                 case ddl_list:
    6270         315 :                         s = rel2bin_list(be, rel, refs);
    6271         315 :                         break;
    6272       12504 :                 case ddl_psm:
    6273       12504 :                         s = rel2bin_psm(be, rel);
    6274       12504 :                         break;
    6275         400 :                 case ddl_exception:
    6276         400 :                         s = rel2bin_exception(be, rel, refs);
    6277         400 :                         break;
    6278         337 :                 case ddl_create_seq:
    6279             :                 case ddl_alter_seq:
    6280         337 :                         s = rel2bin_seq(be, rel, refs);
    6281         337 :                         sql->type = Q_SCHEMA;
    6282         337 :                         break;
    6283         251 :                 case ddl_alter_table_add_range_partition:
    6284             :                 case ddl_alter_table_add_list_partition:
    6285         251 :                         s = rel2bin_partition_limits(be, rel, refs);
    6286         251 :                         sql->type = Q_SCHEMA;
    6287         251 :                         break;
    6288        2687 :                 case ddl_release:
    6289             :                 case ddl_commit:
    6290             :                 case ddl_rollback:
    6291             :                 case ddl_trans:
    6292        2687 :                         s = rel2bin_trans(be, rel, refs);
    6293        2687 :                         sql->type = Q_TRANS;
    6294        2687 :                         break;
    6295        1250 :                 case ddl_create_schema:
    6296             :                 case ddl_drop_schema:
    6297        1250 :                         s = rel2bin_catalog_schema(be, rel, refs);
    6298        1250 :                         sql->type = Q_SCHEMA;
    6299        1250 :                         break;
    6300       30171 :                 case ddl_create_table:
    6301             :                 case ddl_drop_table:
    6302             :                 case ddl_create_view:
    6303             :                 case ddl_drop_view:
    6304             :                 case ddl_drop_constraint:
    6305             :                 case ddl_alter_table:
    6306       30171 :                         s = rel2bin_catalog_table(be, rel, refs);
    6307       30171 :                         sql->type = Q_SCHEMA;
    6308       30171 :                         break;
    6309      171701 :                 case ddl_drop_seq:
    6310             :                 case ddl_create_type:
    6311             :                 case ddl_drop_type:
    6312             :                 case ddl_drop_index:
    6313             :                 case ddl_create_function:
    6314             :                 case ddl_drop_function:
    6315             :                 case ddl_create_trigger:
    6316             :                 case ddl_drop_trigger:
    6317             :                 case ddl_grant_roles:
    6318             :                 case ddl_revoke_roles:
    6319             :                 case ddl_grant:
    6320             :                 case ddl_revoke:
    6321             :                 case ddl_grant_func:
    6322             :                 case ddl_revoke_func:
    6323             :                 case ddl_create_user:
    6324             :                 case ddl_drop_user:
    6325             :                 case ddl_alter_user:
    6326             :                 case ddl_rename_user:
    6327             :                 case ddl_create_role:
    6328             :                 case ddl_drop_role:
    6329             :                 case ddl_alter_table_add_table:
    6330             :                 case ddl_alter_table_del_table:
    6331             :                 case ddl_alter_table_set_access:
    6332             :                 case ddl_comment_on:
    6333             :                 case ddl_rename_schema:
    6334             :                 case ddl_rename_table:
    6335             :                 case ddl_rename_column:
    6336      171701 :                         s = rel2bin_catalog2(be, rel, refs);
    6337      171701 :                         sql->type = Q_SCHEMA;
    6338      171701 :                         break;
    6339             :                 default:
    6340           0 :                         assert(0);
    6341             :         }
    6342      219628 :         return s;
    6343             : }
    6344             : 
    6345             : static stmt *
    6346      996423 : subrel_bin(backend *be, sql_rel *rel, list *refs)
    6347             : {
    6348      996423 :         mvc *sql = be->mvc;
    6349             :         stmt *s = NULL;
    6350             : 
    6351      996423 :         if (THRhighwater())
    6352           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    6353             : 
    6354      996423 :         if (!rel)
    6355             :                 return s;
    6356      996423 :         if (rel_is_ref(rel)) {
    6357             :                 s = refs_find_rel(refs, rel);
    6358             :                 /* needs a proper fix!! */
    6359       28455 :                 if (s)
    6360             :                         return s;
    6361             :         }
    6362      984472 :         switch (rel->op) {
    6363      167793 :         case op_basetable:
    6364      167793 :                 s = rel2bin_basetable(be, rel);
    6365      167793 :                 sql->type = Q_TABLE;
    6366      167793 :                 break;
    6367        6347 :         case op_table:
    6368        6347 :                 s = rel2bin_table(be, rel, refs);
    6369        6347 :                 sql->type = Q_TABLE;
    6370        6347 :                 break;
    6371      112836 :         case op_join:
    6372             :         case op_left:
    6373             :         case op_right:
    6374             :         case op_full:
    6375      112836 :                 s = rel2bin_join(be, rel, refs);
    6376      112836 :                 sql->type = Q_TABLE;
    6377      112836 :                 break;
    6378        4769 :         case op_semi:
    6379             :         case op_anti:
    6380        4769 :                 s = rel2bin_semijoin(be, rel, refs);
    6381        4769 :                 sql->type = Q_TABLE;
    6382        4769 :                 break;
    6383       13239 :         case op_union:
    6384       13239 :                 s = rel2bin_union(be, rel, refs);
    6385       13239 :                 sql->type = Q_TABLE;
    6386       13239 :                 break;
    6387        2059 :         case op_except:
    6388        2059 :                 s = rel2bin_except(be, rel, refs);
    6389        2059 :                 sql->type = Q_TABLE;
    6390        2059 :                 break;
    6391         395 :         case op_inter:
    6392         395 :                 s = rel2bin_inter(be, rel, refs);
    6393         395 :                 sql->type = Q_TABLE;
    6394         395 :                 break;
    6395      283171 :         case op_project:
    6396      283171 :                 s = rel2bin_project(be, rel, refs, NULL);
    6397      283171 :                 sql->type = Q_TABLE;
    6398      283171 :                 break;
    6399       84141 :         case op_select:
    6400       84141 :                 s = rel2bin_select(be, rel, refs);
    6401       84141 :                 sql->type = Q_TABLE;
    6402       84141 :                 break;
    6403       15582 :         case op_groupby:
    6404       15582 :                 s = rel2bin_groupby(be, rel, refs);
    6405       15582 :                 sql->type = Q_TABLE;
    6406       15582 :                 break;
    6407         780 :         case op_topn:
    6408         780 :                 s = rel2bin_topn(be, rel, refs);
    6409         780 :                 sql->type = Q_TABLE;
    6410         780 :                 break;
    6411          21 :         case op_sample:
    6412          21 :                 s = rel2bin_sample(be, rel, refs);
    6413          21 :                 sql->type = Q_TABLE;
    6414          21 :                 break;
    6415       69213 :         case op_insert:
    6416       69213 :                 s = rel2bin_insert(be, rel, refs);
    6417       69213 :                 if (sql->type == Q_TABLE)
    6418       66058 :                         sql->type = Q_UPDATE;
    6419             :                 break;
    6420        3948 :         case op_update:
    6421        3948 :                 s = rel2bin_update(be, rel, refs);
    6422        3948 :                 if (sql->type == Q_TABLE)
    6423        3683 :                         sql->type = Q_UPDATE;
    6424             :                 break;
    6425         438 :         case op_delete:
    6426         438 :                 s = rel2bin_delete(be, rel, refs);
    6427         438 :                 if (sql->type == Q_TABLE)
    6428         321 :                         sql->type = Q_UPDATE;
    6429             :                 break;
    6430          73 :         case op_truncate:
    6431          73 :                 s = rel2bin_truncate(be, rel);
    6432          73 :                 if (sql->type == Q_TABLE)
    6433           3 :                         sql->type = Q_UPDATE;
    6434             :                 break;
    6435          39 :         case op_merge:
    6436          39 :                 s = rel2bin_merge(be, rel, refs);
    6437          39 :                 if (sql->type == Q_TABLE)
    6438          39 :                         sql->type = Q_UPDATE;
    6439             :                 break;
    6440      219628 :         case op_ddl:
    6441      219628 :                 s = rel2bin_ddl(be, rel, refs);
    6442      219628 :                 break;
    6443             :         }
    6444      984472 :         if (s && rel_is_ref(rel)) {
    6445       16504 :                 list_append(refs, rel);
    6446       16504 :                 list_append(refs, s);
    6447             :         }
    6448             :         return s;
    6449             : }
    6450             : 
    6451             : stmt *
    6452        7199 : rel_bin(backend *be, sql_rel *rel)
    6453             : {
    6454        7199 :         mvc *sql = be->mvc;
    6455        7199 :         list *refs = sa_list(sql->sa);
    6456        7199 :         mapi_query_t sqltype = sql->type;
    6457        7199 :         stmt *s = subrel_bin(be, rel, refs);
    6458             : 
    6459        7199 :         s = subrel_project(be, s, refs, rel);
    6460        7199 :         if (sqltype == Q_SCHEMA)
    6461          32 :                 sql->type = sqltype;  /* reset */
    6462             : 
    6463        7199 :         return s;
    6464             : }
    6465             : 
    6466             : stmt *
    6467      362323 : output_rel_bin(backend *be, sql_rel *rel, int top)
    6468             : {
    6469      362323 :         mvc *sql = be->mvc;
    6470      362323 :         list *refs = sa_list(sql->sa);
    6471      362323 :         mapi_query_t sqltype = sql->type;
    6472             :         stmt *s;
    6473             : 
    6474      362323 :         be->join_idx = 0;
    6475      362323 :         be->rowcount = 0;
    6476      362323 :         be->silent = !top;
    6477             : 
    6478      362323 :         s = subrel_bin(be, rel, refs);
    6479      362323 :         s = subrel_project(be, s, refs, rel);
    6480      362323 :         if (!s)
    6481             :                 return NULL;
    6482      362318 :         if (sqltype == Q_SCHEMA)
    6483      203900 :                 sql->type = sqltype; /* reset */
    6484             : 
    6485      362318 :         if (!be->silent) { /* don't generate outputs when we are silent */
    6486      356062 :                 if (!is_ddl(rel->op) && sql->type == Q_TABLE && stmt_output(be, s) < 0) {
    6487             :                         return NULL;
    6488      356062 :                 } else if (be->rowcount > 0 && sqltype == Q_UPDATE && stmt_affected_rows(be, be->rowcount) < 0) {
    6489             :                         /* only call stmt_affected_rows outside functions and ddl */
    6490           0 :                         return NULL;
    6491             :                 }
    6492             :         }
    6493             :         return s;
    6494             : }

Generated by: LCOV version 1.14