LCOV - code coverage report
Current view: top level - sql/backends/monet5 - rel_bin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4541 4894 92.8 %
Date: 2025-03-24 23:16:36 Functions: 131 134 97.8 %

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

Generated by: LCOV version 1.14