LCOV - code coverage report
Current view: top level - sql/backends/monet5 - rel_bin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4094 4422 92.6 %
Date: 2024-04-25 20:03:45 Functions: 121 124 97.6 %

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

Generated by: LCOV version 1.14