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

Generated by: LCOV version 1.14