LCOV - code coverage report
Current view: top level - sql/backends/monet5 - rel_bin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4817 5224 92.2 %
Date: 2025-03-25 21:27:32 Functions: 139 142 97.9 %

          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 "rel_tvtree.h"
      28             : #include "sql_env.h"
      29             : #include "sql_optimizer.h"
      30             : #include "sql_gencode.h"
      31             : #include "mal_builder.h"
      32             : 
      33             : static stmt * rel_bin(backend *be, sql_rel *rel);
      34             : static stmt * subrel_bin(backend *be, sql_rel *rel, list *refs);
      35             : 
      36             : static stmt *check_types(backend *be, sql_subtype *fromtype, stmt *s, check_type tpe);
      37             : 
      38             : static void
      39       46150 : clean_mal_statements(backend *be, int oldstop, int oldvtop)
      40             : {
      41       46150 :         MSresetInstructions(be->mb, oldstop);
      42       46171 :         freeVariables(be->client, be->mb, NULL, oldvtop);
      43       46162 :         be->mvc->session->status = 0; /* clean possible generated error */
      44       46162 :         be->mvc->errstr[0] = '\0';
      45       46162 : }
      46             : 
      47             : static int
      48      150122 : add_to_rowcount_accumulator(backend *be, int nr)
      49             : {
      50      150122 :         if (be->silent)
      51             :                 return 0;
      52             : 
      53      149995 :         if (be->rowcount == 0) {
      54      149721 :                 be->rowcount = nr;
      55      149721 :                 return 0;
      56             :         }
      57             : 
      58         274 :         InstrPtr q = newStmt(be->mb, calcRef, plusRef);
      59         274 :         if (q == NULL) {
      60           0 :                 if (be->mvc->sa->eb.enabled)
      61           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);
      62             :                 return -1;
      63             :         }
      64         274 :         q = pushArgument(be->mb, q, be->rowcount);
      65         274 :         q = pushArgument(be->mb, q, nr);
      66         274 :         pushInstruction(be->mb, q);
      67             : 
      68         274 :         be->rowcount = getDestVar(q);
      69         274 :         return 0;
      70             : }
      71             : 
      72             : static stmt *
      73       12873 : stmt_selectnil(backend *be, stmt *col)
      74             : {
      75       12873 :         sql_subtype *t = tail_type(col);
      76       12873 :         return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, NULL, 0, 1);
      77             : }
      78             : 
      79             : static stmt *
      80        5886 : sql_unop_(backend *be, const char *fname, stmt *rs)
      81             : {
      82        5886 :         mvc *sql = be->mvc;
      83        5886 :         sql_subtype *rt = NULL;
      84        5886 :         sql_subfunc *f = NULL;
      85             : 
      86        5886 :         rt = tail_type(rs);
      87        5886 :         f = sql_bind_func(sql, "sys", fname, rt, NULL, F_FUNC, true, true);
      88             :         /* try to find the function without a type, and convert
      89             :          * the value to the type needed by this function!
      90             :          */
      91        5886 :         if (!f && (f = sql_find_func(sql, "sys", fname, 1, F_FUNC, true, NULL)) != NULL) {
      92           0 :                 sql_arg *a = f->func->ops->h->data;
      93             : 
      94           0 :                 sql->session->status = 0;
      95           0 :                 sql->errstr[0] = '\0';
      96           0 :                 rs = check_types(be, &a->type, rs, type_equal);
      97           0 :                 if (!rs)
      98             :                         f = NULL;
      99             :         }
     100             :         if (f) {
     101             :                 /*
     102             :                 if (f->func->res.scale == INOUT) {
     103             :                         f->res.digits = rt->digits;
     104             :                         f->res.scale = rt->scale;
     105             :                 }
     106             :                 */
     107        5886 :                 return stmt_unop(be, rs, NULL, f);
     108           0 :         } else if (rs) {
     109           0 :                 char *type = tail_type(rs)->type->base.name;
     110             : 
     111           0 :                 return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such unary operator '%s(%s)'", fname, type);
     112             :         }
     113             :         return NULL;
     114             : }
     115             : 
     116             : static stmt *
     117       16792 : refs_find_rel(list *refs, sql_rel *rel)
     118             : {
     119       21090 :         for (node *n = refs->h; n; n = n->next->next) {
     120       11612 :                 sql_rel *ref = n->data;
     121       11612 :                 stmt *s = n->next->data;
     122             : 
     123       11612 :                 if (rel == ref)
     124             :                         return s;
     125             :         }
     126             :         return NULL;
     127             : }
     128             : 
     129             : static void
     130        5226 : refs_update_stmt(list *refs, sql_rel *rel, stmt *s)
     131             : {
     132        6465 :         for (node *n = refs->h; n; n = n->next->next) {
     133        6464 :                 sql_rel *ref = n->data;
     134             : 
     135        6464 :                 if (rel == ref) {
     136        5225 :                         n->next->data = s;
     137        5225 :                         break;
     138             :                 }
     139             :         }
     140             : }
     141             : 
     142             : 
     143             : static void
     144           0 : print_stmtlist(allocator *sa, stmt *l)
     145             : {
     146           0 :         node *n;
     147           0 :         if (l) {
     148           0 :                 for (n = l->op4.lval->h; n; n = n->next) {
     149           0 :                         sql_alias *rnme = table_name(sa, n->data);
     150           0 :                         const char *nme = column_name(sa, n->data);
     151             : 
     152           0 :                         TRC_INFO(SQL_EXECUTION, "%s.%s\n", rnme ? rnme->name : "(null!)", nme ? nme : "(null!)");
     153             :                 }
     154             :         }
     155           0 : }
     156             : 
     157             : static stmt *
     158        4437 : list_find_column(backend *be, list *l, sql_alias *rname, const char *name)
     159             : {
     160        4437 :         stmt *res = NULL;
     161        4437 :         node *n;
     162             : 
     163        4437 :         if (!l)
     164             :                 return NULL;
     165        4437 :         if (!l->ht && list_length(l) > HASH_MIN_SIZE) {
     166         800 :                 l->ht = hash_new(l->sa, MAX(list_length(l), l->expected_cnt), (fkeyvalue)&stmt_key);
     167         800 :                 if (l->ht != NULL) {
     168       16150 :                         for (n = l->h; n; n = n->next) {
     169       15350 :                                 const char *nme = column_name(be->mvc->sa, n->data);
     170       15350 :                                 if (nme) {
     171       15350 :                                         int key = hash_key(nme);
     172             : 
     173       15350 :                                         if (hash_add(l->ht, key, n->data) == NULL) {
     174           0 :                                                 hash_destroy(l->ht);
     175           0 :                                                 l->ht = NULL;
     176           0 :                                                 break;
     177             :                                         }
     178             :                                 }
     179             :                         }
     180             :                 }
     181             :         }
     182        4437 :         if (l->ht) {
     183         878 :                 int key = hash_key(name);
     184         878 :                 sql_hash_e *e = l->ht->buckets[key&(l->ht->size-1)];
     185             : 
     186         878 :                 if (rname) {
     187         909 :                         for (; e; e = e->chain) {
     188         851 :                                 stmt *s = e->value;
     189         851 :                                 sql_alias *rnme = table_name(be->mvc->sa, s);
     190         851 :                                 const char *nme = column_name(be->mvc->sa, s);
     191             : 
     192         851 :                                 if (rnme && a_match(rnme, rname) &&
     193         842 :                                                 strcmp(nme, name) == 0) {
     194             :                                         res = s;
     195             :                                         break;
     196             :                                 }
     197             :                         }
     198             :                 } else {
     199           0 :                         for (; e; e = e->chain) {
     200           0 :                                 stmt *s = e->value;
     201           0 :                                 sql_alias *rnme = table_name(be->mvc->sa, s);
     202           0 :                                 const char *nme = column_name(be->mvc->sa, s);
     203             : 
     204           0 :                                 if (!rnme && nme && strcmp(nme, name) == 0) {
     205             :                                         res = s;
     206             :                                         break;
     207             :                                 }
     208             :                         }
     209             :                 }
     210         878 :                 if (!res)
     211             :                         return NULL;
     212             :                 return res;
     213             :         }
     214        3559 :         if (rname) {
     215        7886 :                 for (n = l->h; n; n = n->next) {
     216        7848 :                         sql_alias *rnme = table_name(be->mvc->sa, n->data);
     217        7848 :                         const char *nme = column_name(be->mvc->sa, n->data);
     218             : 
     219        7848 :                         if (rnme && a_match(rnme, rname) &&
     220        7771 :                                         strcmp(nme, name) == 0) {
     221        3521 :                                 res = n->data;
     222        3521 :                                 break;
     223             :                         }
     224             :                 }
     225             :         } else {
     226           0 :                 for (n = l->h; n; n = n->next) {
     227           0 :                         sql_alias *rnme = table_name(be->mvc->sa, n->data);
     228           0 :                         const char *nme = column_name(be->mvc->sa, n->data);
     229             : 
     230           0 :                         if (!rnme && nme && strcmp(nme, name) == 0) {
     231           0 :                                 res = n->data;
     232           0 :                                 break;
     233             :                         }
     234             :                 }
     235             :         }
     236        3559 :         if (!res)
     237             :                 return NULL;
     238             :         return res;
     239             : }
     240             : 
     241             : static stmt *
     242        4437 : bin_find_column(backend *be, stmt *sub, sql_alias *rname, const char *name)
     243             : {
     244        4437 :         return list_find_column(be, sub->op4.lval, rname, name);
     245             : }
     246             : 
     247             : static stmt *
     248     1199133 : list_find_column_nid(backend *be, list *l, int label)
     249             : {
     250     1199133 :         (void)be;
     251     1199133 :         if (!l)
     252             :                 return NULL;
     253    12262021 :         for (node *n = l->h; n; n = n->next) {
     254    12207816 :                 stmt *s = n->data;
     255             : 
     256    12207816 :                 if (s->label == label)
     257     1144795 :                         return s;
     258    11063021 :                 if (s->nested) {
     259        1012 :                         while(s->type == st_alias)
     260         565 :                                 s = s->op1;
     261         447 :                         if (s->type == st_list) {
     262         447 :                                 s = list_find_column_nid(be, s->op4.lval, label);
     263         447 :                                 if (s)
     264         133 :                                         return s;
     265             :                         }
     266             :                 }
     267             :         }
     268             :         return NULL;
     269             : }
     270             : 
     271             : static stmt *
     272     1169163 : bin_find_column_nid(backend *be, stmt *sub, int label)
     273             : {
     274     1169163 :         list *l = sub->op4.lval;
     275     1169163 :         return list_find_column_nid(be, l, label);
     276             : }
     277             : 
     278             : static list *
     279             : bin_find_columns(backend *be, stmt *sub, const char *name)
     280             : {
     281             :         node *n;
     282             :         list *l = sa_list(be->mvc->sa);
     283             : 
     284             :         for (n = sub->op4.lval->h; n; n = n->next) {
     285             :                 const char *nme = column_name(be->mvc->sa, n->data);
     286             : 
     287             :                 if (strcmp(nme, name) == 0)
     288             :                         append(l, n->data);
     289             :         }
     290             :         if (list_length(l))
     291             :                 return l;
     292             :         return NULL;
     293             : }
     294             : 
     295             : static stmt *
     296     2343296 : column(backend *be, stmt *val)
     297             : {
     298     2343296 :         if (val->nrcols == 0)
     299       26034 :                 return const_column(be, val);
     300             :         return val;
     301             : }
     302             : 
     303             : static stmt *
     304       85980 : create_const_column(backend *be, stmt *val, stmt *d1)
     305             : {
     306       85980 :         (void)d1;
     307       85980 :         if (val->nrcols == 0)
     308          15 :                 val = const_column(be, val);
     309       85980 :         if (val->nested)
     310          72 :                 return stmt_nest(be, val, NULL, &create_const_column);
     311       85908 :         return stmt_append(be, stmt_temp(be, tail_type(val)), val);
     312             : }
     313             : 
     314             : static int
     315      800719 : statment_score(stmt *c)
     316             : {
     317      800719 :         sql_subtype *t = tail_type(c);
     318      800720 :         int score = 0;
     319             : 
     320      800720 :         if (c->nrcols != 0) /* no need to create an extra intermediate */
     321      800407 :                 score += 200;
     322             : 
     323      800720 :         if (!t || c->nested)
     324             :                 return score;
     325      800671 :         switch (ATOMstorage(t->type->localtype)) { /* give preference to smaller types */
     326       58174 :                 case TYPE_bte:
     327       58174 :                         score += 150 - 8;
     328       58174 :                         break;
     329       60179 :                 case TYPE_sht:
     330       60179 :                         score += 150 - 16;
     331       60179 :                         break;
     332      257687 :                 case TYPE_int:
     333      257687 :                         score += 150 - 32;
     334      257687 :                         break;
     335       45432 :                 case TYPE_void:
     336             :                 case TYPE_lng:
     337       45432 :                         score += 150 - 64;
     338       45432 :                         break;
     339        1434 :                 case TYPE_uuid:
     340             : #ifdef HAVE_HGE
     341             :                 case TYPE_hge:
     342             : #endif
     343        1434 :                         score += 150 - 128;
     344        1434 :                         break;
     345        3339 :                 case TYPE_flt:
     346        3339 :                         score += 75 - 24;
     347        3339 :                         break;
     348        5954 :                 case TYPE_dbl:
     349        5954 :                         score += 75 - 53;
     350        5954 :                         break;
     351             :                 default:
     352             :                         break;
     353             :         }
     354             :         return score;
     355             : }
     356             : 
     357             : static stmt *
     358       95858 : bin_find_smallest_column(backend *be, stmt *sub)
     359             : {
     360       95858 :         stmt *res = sub->op4.lval->h->data;
     361       95858 :         int best_score = statment_score(res);
     362             : 
     363       95859 :         if (sub->op4.lval->h->next)
     364      784256 :                 for (node *n = sub->op4.lval->h->next ; n ; n = n->next) {
     365      704861 :                         stmt *c = n->data;
     366      704861 :                         int next_score = statment_score(c);
     367             : 
     368      704861 :                         if (next_score > best_score) {
     369       55988 :                                 res = c;
     370       55988 :                                 best_score = next_score;
     371             :                         }
     372             :                 }
     373       95859 :         if (res->nrcols == 0)
     374         260 :                 return const_column(be, res);
     375             :         return res;
     376             : }
     377             : 
     378             : static stmt *
     379      240806 : row2cols(backend *be, stmt *sub)
     380             : {
     381      240806 :         if (sub->nrcols == 0 && sub->key) {
     382        8368 :                 node *n;
     383        8368 :                 list *l = sa_list(be->mvc->sa);
     384        8368 :                 if (l == NULL)
     385             :                         return NULL;
     386             : 
     387       31432 :                 for (n = sub->op4.lval->h; n; n = n->next) {
     388       23064 :                         stmt *sc = n->data;
     389       23064 :                         assert(sc->type == st_alias);
     390       23064 :                         const char *cname = column_name(be->mvc->sa, sc);
     391       23064 :                         sql_alias *tname = table_name(be->mvc->sa, sc);
     392       23064 :                         int label = sc->label;
     393             : 
     394       23064 :                         sc = column(be, sc);
     395       23064 :                         list_append(l, stmt_alias(be, sc, label, tname, cname));
     396             :                 }
     397        8368 :                 sub = stmt_list(be, l);
     398             :         }
     399             :         return sub;
     400             : }
     401             : 
     402             : static stmt*
     403          44 : distinct_value_list(backend *be, list *vals, stmt **last_null_value, int depth, int push)
     404             : {
     405          44 :         list *l = sa_list(be->mvc->sa);
     406          44 :         stmt *s;
     407             : 
     408             :         /* create bat append values */
     409        1843 :         for (node *n = vals->h; n; n = n->next) {
     410        1799 :                 sql_exp *e = n->data;
     411        1799 :                 stmt *i = exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, depth, 0, push);
     412             : 
     413        1799 :                 if (exp_is_null(e))
     414           0 :                         *last_null_value = i;
     415             : 
     416        1799 :                 if (!i)
     417             :                         return NULL;
     418             : 
     419        1799 :                 list_append(l, i);
     420             :         }
     421          44 :         s = stmt_append_bulk(be, stmt_temp(be, exp_subtype(vals->h->data)), l);
     422             :         /* Probably faster to filter out the values directly in the underlying list of atoms.
     423             :            But for now use groupby to filter out duplicate values. */
     424          44 :         stmt* groupby = stmt_group(be, s, NULL, NULL, NULL, 1);
     425          44 :         stmt* ext = stmt_result(be, groupby, 1);
     426             : 
     427          44 :         return stmt_project(be, ext, s);
     428             : }
     429             : 
     430             : static stmt *
     431        3069 : stmt_selectnonil(backend *be, stmt *col, stmt *s)
     432             : {
     433        3069 :         sql_subtype *t = tail_type(col);
     434        3069 :         return stmt_uselect(be, col, stmt_atom(be, atom_general(be->mvc->sa, t, NULL, 0)), cmp_equal, s, 1, 1);
     435             : }
     436             : 
     437             : static int
     438       14898 : is_tid_chain(stmt *cand)
     439             : {
     440       18577 :         while(cand && cand->type != st_tid && cand->cand) {
     441             :                 cand = cand->cand;
     442             :         }
     443       14898 :         if (cand && cand->type == st_tid)
     444       12722 :                 return 1;
     445             :         return 0;
     446             : }
     447             : 
     448             : static stmt *
     449     1178620 : subrel_project(backend *be, stmt *s, list *refs, sql_rel *rel)
     450             : {
     451     1178620 :         if (!s || s->type != st_list || !s->cand)
     452             :                 return s;
     453             : 
     454      162072 :         list *l = sa_list(be->mvc->sa);
     455      162069 :         stmt *cand = s->cand;
     456      162069 :         if (!l)
     457             :                 return NULL;
     458      742493 :         for (node *n = s->op4.lval->h; n; n = n->next) {
     459      580419 :                 stmt *c = n->data;
     460             : 
     461      580419 :                 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);
     462      580419 :                 if (c->type != st_alias || c->flag) {
     463          47 :                         c = stmt_project(be, cand, c);
     464      580372 :                 } else if (c->op1->type == st_mirror && is_tid_chain(cand)) { /* alias with mirror (ie full row ids) */
     465             :                         //c = stmt_alias(be, cand, 0, c->tname, c->cname);
     466       12722 :                         c = stmt_as(be, cand, c);
     467             :                 } else { /* st_alias */
     468      567650 :                         stmt *s = c->op1;
     469      567650 :                         if (s->nrcols == 0)
     470           0 :                                 s = stmt_const(be, cand, s);
     471             :                         else
     472      567650 :                                 s = stmt_project(be, cand, s);
     473             :                         //c = stmt_alias(be, s, c->flag, c->tname, c->cname);
     474      567653 :                         c = stmt_as(be, s, c);
     475             :                 }
     476      580433 :                 append(l, c);
     477             :         }
     478      162074 :         s = stmt_list(be, l);
     479      162074 :         if (rel && rel_is_ref(rel))
     480        5101 :                 refs_update_stmt(refs, rel, s);
     481             :         return s;
     482             : }
     483             : 
     484             : static stmt *
     485          72 : 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)
     486             : {
     487          72 :         mvc *sql = be->mvc;
     488          72 :         stmt *s = NULL;
     489             : 
     490          72 :         list *lvals = ce->f, *lstmts = sa_list(sql->sa);
     491         328 :         for(node *n = lvals->h; n; n = n->next) {
     492         256 :                 sql_exp *ce = n->data;
     493         256 :                 stmt *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     494             : 
     495         256 :                 if (c && reduce && c->nrcols == 0)
     496           0 :                         c = stmt_const(be, bin_find_smallest_column(be, left), c);
     497           0 :                 if(!c)
     498             :                         return NULL;
     499         256 :                 lstmts = append(lstmts, c);
     500             :         }
     501             : 
     502          72 :         sql_subtype *bt = sql_bind_localtype("bit");
     503          72 :         sql_subfunc *and = sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
     504          72 :         sql_subfunc *or = sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true);
     505         574 :         for (node *n = nl->h; n; n = n->next) {
     506         502 :                 sql_exp *e = n->data;
     507         502 :                 list *vals = e->f;
     508         502 :                 stmt *cursel = NULL;
     509             : 
     510        2072 :                 for (node *m = vals->h, *o = lstmts->h; m && o; m = m->next, o = o->next) {
     511        1570 :                         stmt *c = o->data;
     512        3140 :                         sql_subfunc *cmp = (in)
     513        1570 :                                 ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
     514        1570 :                                 :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
     515        1570 :                         sql_exp *e = m->data;
     516             : 
     517        1570 :                         stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     518        1570 :                         if(!i)
     519             :                                 return NULL;
     520             : 
     521        1570 :                         i = stmt_binop(be, c, i, NULL, cmp);
     522        1570 :                         if (cursel)
     523        1068 :                                 cursel = stmt_binop(be, cursel, i, NULL, in?and:or);
     524             :                         else
     525             :                                 cursel = i;
     526             :                 }
     527         502 :                 if (s)
     528         430 :                         s = stmt_binop(be, s, cursel, NULL, in?or:and);
     529             :                 else
     530             :                         s = cursel;
     531             :         }
     532          72 :         if (!depth && reduce)
     533         144 :                 s = stmt_uselect(be,
     534          72 :                         s->nrcols == 0?stmt_const(be, bin_find_smallest_column(be, left), s): s,
     535             :                         stmt_bool(be, 1), cmp_equal, sel, 0, 0);
     536             :         return s;
     537             : }
     538             : 
     539             : static stmt *
     540       15763 : 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)
     541             : {
     542       15763 :         if (ce && is_values(ce))
     543          72 :                 return handle_in_tuple_exps(be, ce, nl, left, right, grp, ext, cnt, sel, in, depth, reduce, push);
     544       15691 :         mvc *sql = be->mvc;
     545       15691 :         node *n;
     546       15691 :         stmt *s = NULL, *c = exp_bin(be, ce, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     547             : 
     548       15691 :         if(!c)
     549             :                 return NULL;
     550             : 
     551       15691 :         if (reduce && c->nrcols == 0)
     552          47 :                 c = stmt_const(be, bin_find_smallest_column(be, left), c);
     553             : 
     554       15691 :         if (c->nrcols == 0 || depth || !reduce) {
     555           2 :                 sql_subtype *bt = sql_bind_localtype("bit");
     556           4 :                 sql_subfunc *cmp = (in)
     557           2 :                         ?sql_bind_func(sql, "sys", "=", tail_type(c), tail_type(c), F_FUNC, true, true)
     558           2 :                         :sql_bind_func(sql, "sys", "<>", tail_type(c), tail_type(c), F_FUNC, true, true);
     559           2 :                 sql_subfunc *a = (in)?sql_bind_func(sql, "sys", "or", bt, bt, F_FUNC, true, true)
     560           2 :                                          :sql_bind_func(sql, "sys", "and", bt, bt, F_FUNC, true, true);
     561             : 
     562           6 :                 for (n = nl->h; n; n = n->next) {
     563           4 :                         sql_exp *e = n->data;
     564           4 :                         stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     565           4 :                         if(!i)
     566             :                                 return NULL;
     567             : 
     568           4 :                         i = stmt_binop(be, c, i, NULL, cmp);
     569           4 :                         if (s)
     570           2 :                                 s = stmt_binop(be, s, i, NULL, a);
     571             :                         else
     572             :                                 s = i;
     573             :                 }
     574           2 :                 if (sel && !(depth || !reduce))
     575           0 :                         s = stmt_uselect(be,
     576             :                                 stmt_const(be, bin_find_smallest_column(be, left), s),
     577             :                                 stmt_bool(be, 1), cmp_equal, sel, 0, 0);
     578       15689 :         } else if (list_length(nl) < 16) {
     579       15645 :                 comp_type cmp = (in)?cmp_equal:cmp_notequal;
     580             : 
     581       15645 :                 if (!in)
     582        5474 :                         s = sel;
     583       80094 :                 for (n = nl->h; n; n = n->next) {
     584       64449 :                         sql_exp *e = n->data;
     585       64449 :                         stmt *i = exp_bin(be, e, left, right, grp, ext, cnt, NULL, depth+1, 0, push);
     586       64449 :                         if(!i)
     587             :                                 return NULL;
     588             : 
     589       64449 :                         if (in) {
     590       51545 :                                 i = stmt_uselect(be, c, i, cmp, sel, 0, 0);
     591       51545 :                                 if (s)
     592       41374 :                                         s = stmt_tunion(be, s, i);
     593             :                                 else
     594             :                                         s = i;
     595             :                         } else {
     596       12904 :                                 s = stmt_uselect(be, c, i, cmp, s, 0, 0);
     597             :                         }
     598             :                 }
     599             :         } else {
     600             :                 /* TODO: handle_in_exps should contain all necessary logic for in-expressions to be SQL compliant.
     601             :                    For non-SQL-standard compliant behavior, e.g. PostgreSQL backwards compatibility, we should
     602             :                    make sure that this behavior is replicated by the sql optimizer and not handle_in_exps. */
     603             : 
     604          44 :                 stmt* last_null_value = NULL;  /* CORNER CASE ALERT: See description below. */
     605             : 
     606             :                 /* The actual in-value-list should not contain duplicates to ensure that final join results are unique. */
     607          44 :                 s = distinct_value_list(be, nl, &last_null_value, depth+1, push);
     608          44 :                 if (!s)
     609           0 :                         return NULL;
     610             : 
     611          44 :                 if (last_null_value) {
     612             :                         /* The actual in-value-list should not contain null values. */
     613           0 :                         s = stmt_project(be, stmt_selectnonil(be, s, NULL), s);
     614             :                 }
     615             : 
     616          44 :                 if (in) {
     617          42 :                         s = stmt_semijoin(be, c, s, sel, NULL, 0, false);
     618             :                 } else {
     619           2 :                         if (last_null_value) {
     620             :                                 /* CORNER CASE ALERT:
     621             :                                    In case of a not-in-expression with the associated in-value-list containing a null value,
     622             :                                    the entire in-predicate is forced to always return false, i.e. an empty candidate list.
     623             :                                    This is similar to postgres behavior.
     624             :                                    TODO: However I do not think this behavior is in accordance with SQL standard 2003.
     625             : 
     626             :                                    Ugly trick to return empty candidate list, because for all x it holds that: (x == null) == false.
     627             :                                    list* singleton_bat = sa_list(sql->sa);
     628             :                                    list_append(singleton_bat, null_value); */
     629           0 :                                 s = stmt_uselect(be, c, last_null_value, cmp_equal, NULL, 0, 0);
     630             :                         } else {
     631             :                                 /* BACK TO HAPPY FLOW:
     632             :                                    Make sure that null values are never returned. */
     633           2 :                                 stmt* non_nulls;
     634           2 :                                 non_nulls = stmt_selectnonil(be, c, sel);
     635           2 :                                 s = stmt_tdiff(be, stmt_project(be, non_nulls, c), s, NULL);
     636           2 :                                 s = stmt_project(be, s, non_nulls);
     637             :                         }
     638             :                 }
     639             :         }
     640             :         return s;
     641             : }
     642             : 
     643             : 
     644             : static stmt * value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel);
     645             : 
     646             : static stmt *
     647             : composite_value_list(backend *be, sql_exp *tuple, stmt *left, stmt *sel)
     648             : {
     649             :         assert(is_row(tuple));
     650             :         list *fields = exp_get_values(tuple);
     651             :         list *f = sa_list(be->mvc->sa);
     652             :         for (node *n = fields->h; n; n = n->next) {
     653             :                 sql_exp *e = n->data;
     654             :                 stmt *i;
     655             : 
     656             :                 if(is_values(e))
     657             :                         i = value_list(be, e, left, sel);
     658             :                 else
     659             :                         i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     660             :                 if (!i)
     661             :                         return NULL;
     662             :                 if (i->type == st_list) {
     663             :                         for( node *n = i->op4.lval->h; n; n = n->next)
     664             :                                 list_append(f, n->data);
     665             :                 } else
     666             :                         list_append(f, i);
     667             :         }
     668             :         return stmt_list(be, f);
     669             : }
     670             : 
     671             : static stmt *
     672             : set_value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
     673             : {
     674             :         assert(is_values(vals_exp));
     675             :         list *vals = exp_get_values(vals_exp);
     676             :         sql_subtype *type = exp_subtype(vals->h->data);
     677             :         bool single_value = list_length(vals) <= 1;
     678             :         int multi_result = 0;
     679             : 
     680             :         if (!type)
     681             :                 return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
     682             : 
     683             :         /* create bat append values */
     684             :         list *l = sa_list(be->mvc->sa);
     685             :         for (node *n = vals->h; n; n = n->next) {
     686             :                 sql_exp *e = n->data;
     687             :                 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     688             : 
     689             :                 if (!i)
     690             :                         return NULL;
     691             :                 if (single_value)
     692             :                         return i;
     693             :                 list_append(l, i);
     694             : 
     695             :                 if (i->type == st_list && list_length(i->op4.lval) > 1)
     696             :                         multi_result = list_length(i->op4.lval);
     697             :         }
     698             :         /*  n-tuples */
     699             :         if (multi_result) {
     700             :                 list *rl = sa_list(be->mvc->sa);
     701             :                 for(int i = 0; i < multi_result; i++) {
     702             :                         node *n = l->h;
     703             :                         stmt *s = n->data;
     704             :                         stmt *input = list_fetch(s->op4.lval, i);
     705             :                         sql_subtype *type = tail_type(input);
     706             :                         list *nl = list_append(sa_list(be->mvc->sa), input);
     707             :                         for (n = n->next; n; n = n->next) {
     708             :                                 stmt *s = n->data;
     709             :                                 stmt *input = list_fetch(s->op4.lval, i);
     710             :                                 nl = list_append(nl, input);
     711             :                         }
     712             :                         append(rl, stmt_append_bulk(be, stmt_temp(be, type), nl));
     713             :                 }
     714             :                 return stmt_list(be, rl);
     715             :         }
     716             :         return stmt_append_bulk(be, stmt_temp(be, type), l);
     717             : }
     718             : 
     719             : static int
     720             : type_create_result(backend *be, sql_subtype *type, list *cols)
     721             : {
     722             :         if (type->type->composite) {
     723             :                 for(node *n = type->type->d.fields->h; n; n = n->next) {
     724             :                         sql_arg *a = n->data;
     725             : 
     726             :                         if (a->type.type->composite) {
     727             :                                 if(type_create_result(be, &a->type, cols) < 0)
     728             :                                         return -1;
     729             :                         } else {
     730             :                                 append(cols, sa_list(be->mvc->sa));
     731             :                         }
     732             :                 }
     733             :         } else {
     734             :                 append(cols, sa_list(be->mvc->sa));
     735             :         }
     736             :         if (type->multiset) /* multisetid */
     737             :                 append(cols, sa_list(be->mvc->sa));
     738             :         if (type->multiset == MS_ARRAY) /* multisetnr */
     739             :                 append(cols, sa_list(be->mvc->sa));
     740             :         if (type->multiset) /* rowid */
     741             :                 append(cols, sa_list(be->mvc->sa));
     742             :         return 0;
     743             : }
     744             : 
     745             : static node *
     746             : append_tuple(backend *be, sql_exp *tuple, sql_subtype *type, stmt *left, stmt *sel, node *cols, int rowcnt, int lcnt, bool row)
     747             : {
     748             :         if (row && !is_row(tuple)) { /* multiset data */
     749             :                 node *ncols = cols;
     750             :                 assert(is_values(tuple));
     751             :                 list *tuples = exp_get_values(tuple);
     752             :                 int i = 1;
     753             :                 if (list_empty(tuples)) {
     754             :                         list *vals = cols->data;
     755             :                         append(vals, stmt_atom_int(be, int_nil));
     756             :                         if (type->type->composite) {
     757             :                                 node *n = cols;
     758             :                                 if (type->multiset)
     759             :                                         n = n->next;
     760             :                                 for(node *o = type->type->d.fields->h; n && o; n = n->next, o = o->next)
     761             :                                         ;
     762             :                                 if (type->multiset)
     763             :                                         n = n->next;
     764             :                                 if (type->multiset == MS_ARRAY)
     765             :                                         n = n->next;
     766             :                                 return n;
     767             :                         } else
     768             :                                 return cols->next;
     769             :                 }
     770             :                 for(node *n = tuples->h; n; n = n->next, i++)
     771             :                         if ((ncols=append_tuple(be, n->data, type, left, sel, cols, rowcnt, i, 0)) == cols)
     772             :                                 return cols;
     773             :                 return ncols;
     774             :         }
     775             :         assert(tuple->row);
     776             :         list *attr = exp_get_values(tuple);
     777             :         node *n, *m = cols, *o;
     778             :         sql_subtype *ntype = type;
     779             :         if (is_row(tuple) && list_length(type->type->d.fields) == 1) {
     780             :                 sql_arg *f = type->type->d.fields->h->data;
     781             :                 ntype = &f->type;
     782             :         }
     783             :         if (ntype->type->composite) {
     784             :                 for(n = attr->h, o = ntype->type->d.fields->h; n && o; n = n->next, o = o->next) {
     785             :                         sql_arg *f = o->data;
     786             :                         sql_exp *e = n->data;
     787             :                         list *vals = m->data;
     788             :                         if (f->type.type->composite) {
     789             :                                 node *nm = append_tuple(be, e, &f->type, left, sel, m, rowcnt, lcnt, ntype->multiset);
     790             :                                 if (nm == m)
     791             :                                         return m;
     792             :                                 m = nm;
     793             :                         } else {
     794             :                                 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     795             :                                 append(vals, i);
     796             :                                 m = m->next;
     797             :                         }
     798             :                 }
     799             :         } else {
     800             :                 assert(list_length(attr) == 1);
     801             :                 sql_exp *e = attr->h->data;
     802             :                 list *vals = m->data;
     803             :                 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     804             :                 m = m->next;
     805             :                 append(vals, i);
     806             :         }
     807             :         if (type->multiset) {
     808             :                 list *vals = m->data;
     809             :                 append(vals, stmt_atom_int(be, rowcnt));
     810             :                 m = m->next;
     811             :         }
     812             :         if (type->multiset == MS_ARRAY) {
     813             :                 list *vals = m->data;
     814             :                 append(vals, stmt_atom_int(be, lcnt));
     815             :                 m = m->next;
     816             :         }
     817             :         if (type->multiset) {
     818             :                 if (lcnt == 1) {
     819             :                         list *vals = m->data;
     820             :                         append(vals, stmt_atom_int(be, rowcnt));
     821             :                 }
     822             :                 m = m->next;
     823             :         }
     824             :         return m;
     825             : }
     826             : 
     827             : static stmt *
     828             : tuple_result(backend *be, list *cols)
     829             : {
     830             :         list *row = sa_list(be->mvc->sa);
     831             : 
     832             :         for (node *n = cols->h; n; n = n->next) {
     833             :                 list *vals = n->data;
     834             :                 sql_subtype *type = tail_type(vals->h->data);
     835             :                 append(row, stmt_append_bulk(be, stmt_temp(be, type), vals));
     836             :         }
     837             :         return stmt_list(be, row);
     838             : }
     839             : 
     840             : // TODO: >>>>>>>>>>>>>>>>>>>> remove value_list and friends
     841             : static stmt *
     842             : value_list(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
     843             : {
     844             :         if (!be) return NULL;
     845             : 
     846             :         assert(is_values(vals_exp));
     847             :         list *vals = exp_get_values(vals_exp);
     848             :         sql_subtype *type = exp_subtype(vals_exp);
     849             :         list *l;
     850             : 
     851             :         if (!type || list_empty(vals))
     852             :                 return sql_error(be->mvc, 02, SQLSTATE(42000) "Could not infer the type of a value list column");
     853             : 
     854             :         if (!is_row(vals_exp) && type->type->composite) {
     855             :                 list *attr = sa_list(be->mvc->sa);
     856             :                 sql_exp *v = vals->h->data;
     857             :                 if (type_create_result(be, type, attr) < 0)
     858             :                         return NULL;
     859             :                 int rowcnt = 0, lcnt = 1;
     860             :                 int irc = is_row(v)?0:1;
     861             :                 int lrc = is_row(v)?1:0;
     862             :                 for (node *n = vals->h; n; n = n->next, rowcnt += irc, lcnt += lrc) {
     863             :                         if (append_tuple(be, n->data, type, left, sel, attr->h, rowcnt, lcnt, 1) == attr->h)
     864             :                                 return NULL;
     865             :                 }
     866             :                 return tuple_result(be, attr);
     867             :         }
     868             :         if (type->multiset || (!is_row(vals_exp) && type->type->composite))
     869             :                 return set_value_list(be, vals_exp, left, sel);
     870             : 
     871             :         if (is_row(vals_exp))
     872             :                 return composite_value_list(be, vals_exp, left, sel);
     873             : 
     874             :         type = exp_subtype(vals->h->data);
     875             : 
     876             :         /* create bat append values */
     877             :         l = sa_list(be->mvc->sa);
     878             :         for (node *n = vals->h; n; n = n->next) {
     879             :                 sql_exp *e = n->data;
     880             :                 stmt *i = exp_bin(be, e, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     881             : 
     882             :                 if (!i)
     883             :                         return NULL;
     884             : 
     885             :                 if (list_length(vals) == 1)
     886             :                         return i;
     887             :                 list_append(l, i);
     888             :         }
     889             :         return stmt_append_bulk(be, stmt_temp(be, type), l);
     890             : }
     891             : 
     892             : static stmt *
     893      139640 : value_tvtree(backend *be, sql_exp *vals_exp, stmt *left, stmt *sel)
     894             : {
     895      139640 :         if (!be) return NULL;
     896             : 
     897      139640 :         assert(is_values(vals_exp));
     898             : 
     899      139640 :         sql_subtype *st = exp_subtype(vals_exp);
     900      139665 :         tv_tree *t = tv_create(be, st);
     901             : 
     902             :         /* EXCEPTION: we might get cases were we have a single basic type
     903             :          * value wrapped in e_atom->f (probably coming from unnest) in this
     904             :          * case we just generate the stmt and we bail out. hopefully this
     905             :          * will be cleaned up in the future */
     906      139358 :         if (t->tvt == TV_BASIC) {
     907      139415 :                 list *vals = exp_get_values(vals_exp);
     908      139267 :                 if (list_length(vals) == 1) {
     909        1978 :                         sql_exp *v = vals->h->data;
     910        1978 :                         if (v->type == e_atom && v->l)
     911        1746 :                                 return stmt_atom(be, v->l);
     912         232 :                         return exp_bin(be, v, left, NULL, NULL, NULL, NULL, sel, 0, 0, 0);
     913             :                 }
     914             :         }
     915             : 
     916      137264 :         if (false == tv_parse_values(be, t, vals_exp, left, sel))
     917             :                 return NULL;
     918             : 
     919      137635 :         stmt *ret = tv_generate_stmts(be, t);
     920             : 
     921      137635 :         return ret;
     922             : }
     923             : 
     924             : static stmt *
     925         284 : exp_list(backend *be, list *exps, stmt *l, stmt *r, stmt *grp, stmt *ext, stmt *cnt, stmt *sel)
     926             : {
     927         284 :         mvc *sql = be->mvc;
     928         284 :         node *n;
     929         284 :         list *nl = sa_list(sql->sa);
     930             : 
     931         284 :         if (nl == NULL)
     932             :                 return NULL;
     933         677 :         for (n = exps->h; n; n = n->next) {
     934         393 :                 sql_exp *e = n->data;
     935         393 :                 stmt *i = exp_bin(be, e, l, r, grp, ext, cnt, sel, 0, 0, 0);
     936         393 :                 if(!i)
     937             :                         return NULL;
     938             : 
     939         393 :                 if (n->next && i->type == st_table) /* relational statement */
     940           3 :                         l = i->op1;
     941             :                 else
     942         390 :                         append(nl, i);
     943             :         }
     944         284 :         return stmt_list(be, nl);
     945             : }
     946             : 
     947             : static stmt *
     948        1652 : exp_count_no_nil_arg(sql_exp *e, stmt *ext, sql_exp *ae, stmt *as)
     949             : {
     950             :         /* small optimization, ie use candidates directly on count(*) */
     951        1652 :         if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || !has_nil(ae))) {
     952             :                 /* skip alias statements */
     953        3170 :                 while (as->type == st_alias)
     954        1655 :                         as = as->op1;
     955             :                 /* use candidate */
     956        1515 :                 if (as && as->type == st_join && as->flag == cmp_project) {
     957        1381 :                         if (as->op1 && (as->op1->type != st_result || as->op1->op1->type != st_group)) /* exclude a subquery with select distinct under the count */
     958        1652 :                                 as = as->op1;
     959             :                 }
     960             :         }
     961        1652 :         return as;
     962             : }
     963             : 
     964             : static stmt *
     965       10026 : 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)
     966             : {
     967       10026 :         sql_subtype *bt = sql_bind_localtype("bit");
     968       10026 :         list *l = e->l;
     969       10026 :         node *n;
     970       10026 :         stmt *sel1 = NULL, *sel2 = NULL, *s = NULL;
     971       10026 :         int anti = is_anti(e);
     972             : 
     973       10026 :         sel1 = sel;
     974       10026 :         sel2 = sel;
     975       21200 :         for (n = l->h; n; n = n->next) {
     976       11174 :                 sql_exp *c = n->data;
     977       11174 :                 stmt *sin = (sel1 && sel1->nrcols)?sel1:NULL;
     978             : 
     979             :                 /* propagate the anti flag */
     980       11174 :                 if (anti)
     981          55 :                         set_anti(c);
     982       11178 :                 s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
     983       11174 :                 if (!s)
     984             :                         return s;
     985             : 
     986       11174 :                 if (!reduce && sin) {
     987           0 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
     988           0 :                         assert(f);
     989           0 :                         s = stmt_binop(be, sin, s, NULL, f);
     990       11174 :                 } else if (!sin && sel1 && sel1->nrcols == 0 && s->nrcols == 0) {
     991           0 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
     992           0 :                         assert(f);
     993           0 :                         s = stmt_binop(be, sel1, s, sin, f);
     994       11174 :                 } else if (sel1 && (sel1->nrcols == 0 || s->nrcols == 0)) {
     995           1 :                         stmt *predicate = bin_find_smallest_column(be, left);
     996             : 
     997           1 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
     998           1 :                         if (s->nrcols == 0)
     999           0 :                                 s = stmt_uselect(be, predicate, s, cmp_equal, sel1, anti, is_semantics(c));
    1000             :                         else
    1001           1 :                                 s = stmt_uselect(be, predicate, sel1, cmp_equal, s, anti, is_semantics(c));
    1002             :                 }
    1003       11174 :                 sel1 = s;
    1004             :         }
    1005       10026 :         l = e->r;
    1006       22433 :         for (n = l->h; n; n = n->next) {
    1007       12407 :                 sql_exp *c = n->data;
    1008       12407 :                 stmt *sin = (sel2 && sel2->nrcols)?sel2:NULL;
    1009             : 
    1010             :                 /* propagate the anti flag */
    1011       12407 :                 if (anti)
    1012          55 :                         set_anti(c);
    1013       12412 :                 s = exp_bin(be, c, left, right, grp, ext, cnt, reduce?sin:NULL, depth, reduce, push);
    1014       12407 :                 if (!s)
    1015             :                         return s;
    1016             : 
    1017       12407 :                 if (!reduce && sin) {
    1018           2 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
    1019           1 :                         assert(f);
    1020           1 :                         s = stmt_binop(be, sin, s, NULL, f);
    1021       12406 :                 } else if (!sin && sel2 && sel2->nrcols == 0 && s->nrcols == 0) {
    1022           0 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"or":"and", bt, bt, F_FUNC, true, true);
    1023           0 :                         assert(f);
    1024           0 :                         s = stmt_binop(be, sel2, s, sin, f);
    1025       12406 :                 } else if (sel2 && (sel2->nrcols == 0 || s->nrcols == 0)) {
    1026           6 :                         stmt *predicate = bin_find_smallest_column(be, left);
    1027             : 
    1028           6 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
    1029           6 :                         if (s->nrcols == 0)
    1030           5 :                                 s = stmt_uselect(be, predicate, s, cmp_equal, sel2, anti, 0);
    1031             :                         else
    1032           1 :                                 s = stmt_uselect(be, predicate, sel2, cmp_equal, s, anti, 0);
    1033             :                 }
    1034       12407 :                 sel2 = s;
    1035             :         }
    1036       10026 :         if (sel1->nrcols == 0 && sel2->nrcols == 0) {
    1037           0 :                 sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
    1038           0 :                 assert(f);
    1039           0 :                 return stmt_binop(be, sel1, sel2, NULL, f);
    1040             :         }
    1041       10026 :         if (sel1->nrcols == 0) {
    1042           3 :                 stmt *predicate = bin_find_smallest_column(be, left);
    1043             : 
    1044           3 :                 if (!reduce) {
    1045           0 :                         predicate = stmt_const(be, predicate, sel1);
    1046             :                 } else {
    1047           3 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
    1048           3 :                         sel1 = stmt_uselect(be, predicate, sel1, cmp_equal, NULL, 0/*anti*/, 0);
    1049             :                 }
    1050             :         }
    1051       10026 :         if (sel2->nrcols == 0) {
    1052          81 :                 stmt *predicate = bin_find_smallest_column(be, left);
    1053             : 
    1054          81 :                 if (!reduce) {
    1055           0 :                         predicate = stmt_const(be, predicate, sel2);
    1056             :                 } else {
    1057          81 :                         predicate = stmt_const(be, predicate, stmt_bool(be, 1));
    1058          81 :                         sel2 = stmt_uselect(be, predicate, sel2, cmp_equal, NULL, 0/*anti*/, 0);
    1059             :                 }
    1060             :         }
    1061       10026 :         if (!reduce) {
    1062           8 :                         sql_subfunc *f = sql_bind_func(be->mvc, "sys", anti?"and":"or", bt, bt, F_FUNC, true, true);
    1063           4 :                         assert(f);
    1064           4 :                         return stmt_binop(be, sel1, sel2, NULL, f);
    1065             :         }
    1066       10022 :         if (anti)
    1067          55 :                 return stmt_project(be, stmt_tinter(be, sel1, sel2, false), sel1);
    1068        9967 :         return stmt_tunion(be, sel1, sel2);
    1069             : }
    1070             : 
    1071             : static stmt *
    1072       18292 : exp2bin_case(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
    1073             : {
    1074       18292 :         stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
    1075       18292 :         int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
    1076       18292 :         char name[16], *nme = NULL;
    1077       18292 :         sql_subtype *bt = sql_bind_localtype("bit");
    1078       18292 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    1079       18292 :         sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    1080       18292 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
    1081             : 
    1082       18292 :         if (single_value) {
    1083             :                 /* var_x = nil; */
    1084          91 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
    1085          91 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
    1086             :         }
    1087             : 
    1088       18292 :         list *exps = fe->l;
    1089             : 
    1090             :         /*
    1091             :          * left - isel: calls down need id's from the range of left
    1092             :          * res  - rsel: updates to res need id's in the range from res
    1093             :          */
    1094       78338 :         for (node *en = exps->h; en; en = en->next) {
    1095       60046 :                 sql_exp *e = en->data;
    1096             : 
    1097       60046 :                 next_cond = next_cond && en->next; /* last else is only a value */
    1098             : 
    1099       60046 :                 stmt *nsel = rsel;
    1100       60046 :                 if (!single_value) {
    1101       59719 :                         if (/*!next_cond &&*/ rsel && isel) {
    1102             :                                 /* back into left range */
    1103        8590 :                                 nsel = stmt_project(be, rsel, isel);
    1104       51129 :                         } else if (isel && !rsel)
    1105       60046 :                                 nsel = isel;
    1106             :                 }
    1107       60046 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
    1108             : 
    1109       60046 :                 if (!es)
    1110             :                         return NULL;
    1111       60046 :                 if (!single_value) {
    1112             :                         /* create result */
    1113       59719 :                         if (!res) {
    1114       18201 :                                 stmt *l = isel;
    1115       18201 :                                 if (!l)
    1116       13920 :                                         l = bin_find_smallest_column(be, left);
    1117       18201 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
    1118       18201 :                                 ires = l;
    1119       18201 :                                 if (res)
    1120       18201 :                                         res->cand = isel;
    1121       41518 :                         } else if (res && !next_cond) { /* use result to update column */
    1122       38960 :                                 stmt *val = es;
    1123       38960 :                                 stmt *pos = rsel;
    1124             : 
    1125       38960 :                                 if (val->nrcols == 0)
    1126       19251 :                                         val = stmt_const(be, pos, val);
    1127       19709 :                                 else if (!val->cand && nsel)
    1128        4118 :                                         val = stmt_project(be, nsel, val);
    1129       38960 :                                 res = stmt_replace(be, res, pos, val);
    1130             : 
    1131       38960 :                                 assert(cond);
    1132             : 
    1133       38960 :                                 if (en->next) {
    1134             :                                         /* osel - rsel */
    1135       20759 :                                         if (!osel)
    1136       18201 :                                                 osel = stmt_mirror(be, ires);
    1137       20759 :                                         stmt *d = stmt_tdiff(be, osel, rsel, NULL);
    1138       20759 :                                         osel = rsel = stmt_project(be, d, osel);
    1139             :                                 }
    1140             :                         }
    1141       59719 :                         if (next_cond) {
    1142       20759 :                                 ncond = cond = es;
    1143       20759 :                                 if (!ncond->nrcols) {
    1144         134 :                                         if (osel) {
    1145          76 :                                                 ncond = stmt_const(be, nsel, ncond);
    1146          76 :                                                 ncond->cand = nsel;
    1147          58 :                                         } else if (isel) {
    1148           3 :                                                 ncond = stmt_const(be, isel, ncond);
    1149           3 :                                                 ncond->cand = isel;
    1150             :                                         } else
    1151          55 :                                                 ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
    1152             :                                 }
    1153       20759 :                                 if (isel && !ncond->cand) {
    1154          10 :                                         ncond = stmt_project(be, nsel, ncond);
    1155          10 :                                         ncond->cand = nsel;
    1156             :                                 }
    1157       27590 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
    1158       20759 :                                 if (rsel && ncond->cand)
    1159        2550 :                                         rsel = stmt_project(be, s, rsel);
    1160             :                                 else
    1161             :                                         rsel = s;
    1162             :                         }
    1163             :                 } else {
    1164         327 :                         if (!res) {
    1165             :                                 /* if_barrier ... */
    1166         118 :                                 assert(next_cond);
    1167         118 :                                 if (next_cond) {
    1168         118 :                                         if (cond) {
    1169          27 :                                                 ncond = stmt_binop(be, cond, es, nsel, and);
    1170             :                                         } else {
    1171             :                                                 ncond = es;
    1172             :                                         }
    1173             :                                         cond = es;
    1174             :                                 }
    1175             :                         } else {
    1176             :                                 /* var_x = s */
    1177         209 :                                 (void)stmt_assign(be, NULL, nme, es, 2);
    1178             :                                 /* endif_barrier */
    1179         209 :                                 (void)stmt_control_end(be, res);
    1180         209 :                                 res = NULL;
    1181             : 
    1182         209 :                                 if (en->next) {
    1183         118 :                                         cond = stmt_unop(be, cond, nsel, not);
    1184             : 
    1185         118 :                                         sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    1186         118 :                                         cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
    1187         118 :                                         if (ocond)
    1188          27 :                                                 cond = stmt_binop(be, ocond, cond, nsel, and);
    1189         118 :                                         ocond = cond;
    1190         118 :                                         if (!en->next->next)
    1191          91 :                                                 ncond = cond;
    1192             :                                 }
    1193             :                         }
    1194         327 :                         if (ncond && (next_cond || (en->next && !en->next->next))) {
    1195             :                                 /* if_barrier ... */
    1196         209 :                                 res = stmt_cond(be, ncond, NULL, 0, 0);
    1197             :                         }
    1198             :                 }
    1199       60046 :                 next_cond = !next_cond;
    1200             :         }
    1201       18292 :         if (single_value)
    1202          91 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
    1203             :         return res;
    1204             : }
    1205             : 
    1206             : static stmt *
    1207           3 : exp2bin_named_placeholders(backend *be, sql_exp *fe)
    1208             : {
    1209           3 :         int argc = 0;
    1210           3 :         char arg[IDLENGTH];
    1211           3 :         list *args = fe->l;
    1212             : 
    1213           3 :         if (list_empty(args))
    1214             :                 return NULL;
    1215           8 :         for (node *n = args->h; n; n = n->next, argc++) {
    1216           5 :                 sql_exp *a = n->data;
    1217           5 :                 sql_subtype *t = exp_subtype(a);
    1218           5 :                 stmt *s = exp_bin(be, a, NULL, NULL, NULL, NULL, NULL, NULL, 1, 0, 1);
    1219           5 :                 InstrPtr q = newAssignment(be->mb);
    1220             : 
    1221           5 :                 if (!q || !t || !s) {
    1222           0 :                         sql_error(be->mvc, 10, SQLSTATE(42000) MAL_MALLOC_FAIL);
    1223           0 :                         return NULL;
    1224             :                 }
    1225           5 :                 int type = t->type->localtype, varid = 0;
    1226             : 
    1227           5 :                 snprintf(arg, IDLENGTH, "A%d", argc);
    1228           5 :                 if ((varid = newVariable(be->mb, arg, strlen(arg), type)) < 0) {
    1229           0 :                         sql_error(be->mvc, 10, SQLSTATE(42000) "Internal error while compiling statement: variable id too long");
    1230           0 :                         return NULL;
    1231             :                 }
    1232           5 :                 if (q)
    1233           5 :                         getDestVar(q) = varid;
    1234           5 :                 q = pushArgument(be->mb, q, s->nr);
    1235           5 :                 pushInstruction(be->mb, q);
    1236             :         }
    1237             :         return NULL;
    1238             : }
    1239             : 
    1240             : static stmt *
    1241        2282 : exp2bin_casewhen(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
    1242             : {
    1243        2282 :         stmt *res = NULL, *ires = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL, *cond = NULL;
    1244        2282 :         int next_cond = 1, single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
    1245        2282 :         char name[16], *nme = NULL;
    1246        2282 :         sql_subtype *bt = sql_bind_localtype("bit");
    1247        2283 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    1248        2283 :         sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    1249        2283 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
    1250        2283 :         sql_subfunc *cmp;
    1251             : 
    1252        2283 :         if (single_value) {
    1253             :                 /* var_x = nil; */
    1254          86 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
    1255          85 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
    1256             :         }
    1257             : 
    1258        2283 :         list *exps = fe->l;
    1259        2283 :         node *en = exps->h;
    1260        2283 :         sql_exp *e = en->data;
    1261             : 
    1262        2283 :         stmt *nsel = !single_value?isel:NULL;
    1263        2283 :         stmt *case_when = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
    1264        2283 :         if (!case_when)
    1265             :                 return NULL;
    1266        2283 :         cmp = sql_bind_func(be->mvc, "sys", "=", exp_subtype(e), exp_subtype(e), F_FUNC, true, true);
    1267        2283 :         if (!cmp)
    1268             :                 return NULL;
    1269        2283 :         if (!single_value && !case_when->nrcols) {
    1270          32 :                 stmt *l = isel;
    1271          32 :                 if (!l && left)
    1272          27 :                         l = bin_find_smallest_column(be, left);
    1273           5 :                 else if (!l)
    1274             :                         return NULL;
    1275          32 :                 case_when = stmt_const(be, l, case_when);
    1276          32 :                 if (case_when)
    1277          32 :                         case_when->cand = isel;
    1278             :         }
    1279        2283 :         if (!single_value && isel && !case_when->cand) {
    1280         308 :                 case_when = stmt_project(be, isel, case_when);
    1281         308 :                 case_when->cand = isel;
    1282             :         }
    1283             : 
    1284             :         /*
    1285             :          * left - isel: calls down need id's from the range of left
    1286             :          * res  - rsel: updates to res need id's in the range from res
    1287             :          */
    1288       32030 :         for (en = en->next; en; en = en->next) {
    1289       29747 :                 sql_exp *e = en->data;
    1290             : 
    1291       29747 :                 next_cond = next_cond && en->next; /* last else is only a value */
    1292             : 
    1293       29747 :                 stmt *nsel = rsel;
    1294       29747 :                 if (!single_value) {
    1295       28919 :                         if (/*!next_cond &&*/ rsel && isel) {
    1296             :                                 /* back into left range */
    1297        3954 :                                 nsel = stmt_project(be, rsel, isel);
    1298       24965 :                         } else if (isel && !rsel)
    1299       29747 :                                 nsel = isel;
    1300             :                 }
    1301       29747 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
    1302             : 
    1303       29746 :                 if (!es)
    1304             :                         return NULL;
    1305       29746 :                 if (next_cond) {
    1306       13731 :                         stmt *l = case_when;
    1307       13731 :                         if (!single_value) {
    1308       13361 :                                 if (rsel && isel) {
    1309        1662 :                                         assert(l->cand == isel);
    1310        1662 :                                         l = stmt_project(be, rsel, l);
    1311        1662 :                                         l->cand = nsel;
    1312             :                                 }
    1313             : 
    1314       13361 :                                 if (es->cand && !l->cand) {
    1315           9 :                                         assert(es->cand == rsel);
    1316           9 :                                         l = stmt_project(be, es->cand, l);
    1317           9 :                                         l->cand = es->cand;
    1318       13352 :                                 } else if (nsel && !es->cand) {
    1319       11468 :                                         es = stmt_project(be, nsel, es);
    1320       11468 :                                         es->cand = nsel;
    1321       11468 :                                         if (!l->cand) {
    1322        9493 :                                                 l = stmt_project(be, nsel, l);
    1323        9493 :                                                 l->cand = nsel;
    1324             :                                         }
    1325             :                                 }
    1326       13361 :                                 assert(l->cand == es->cand);
    1327             :                         }
    1328       13731 :                         es = stmt_binop(be, l, es, NULL, cmp);
    1329             :                 }
    1330       29747 :                 if (!single_value) {
    1331             :                         /* create result */
    1332       28919 :                         if (!res) {
    1333        2197 :                                 stmt *l = isel;
    1334        2197 :                                 if (!l)
    1335        1882 :                                         l = bin_find_smallest_column(be, left);
    1336        2197 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
    1337        2197 :                                 ires = l;
    1338        2197 :                                 if (res)
    1339        2197 :                                         res->cand = isel;
    1340       26722 :                         } else if (res && !next_cond) { /* use result to update column */
    1341       15558 :                                 stmt *val = es;
    1342       15558 :                                 stmt *pos = rsel;
    1343             : 
    1344       15558 :                                 if (val->nrcols == 0)
    1345       13888 :                                         val = stmt_const(be, pos, val);
    1346        1670 :                                 else if (!val->cand && nsel)
    1347         209 :                                         val = stmt_project(be, nsel, val);
    1348       15558 :                                 res = stmt_replace(be, res, pos, val);
    1349             : 
    1350       15558 :                                 assert(cond);
    1351             : 
    1352       15558 :                                 if (en->next) {
    1353             :                                         /* osel - rsel */
    1354       13361 :                                         if (!osel)
    1355        2197 :                                                 osel = stmt_mirror(be, ires);
    1356       13361 :                                         stmt *d = stmt_tdiff(be, osel, rsel, NULL);
    1357       13361 :                                         osel = rsel = stmt_project(be, d, osel);
    1358             :                                 }
    1359             :                         }
    1360       28919 :                         if (next_cond) {
    1361       13361 :                                 ncond = cond = es;
    1362       13361 :                                 if (!ncond->nrcols) {
    1363           0 :                                         if (osel) {
    1364           0 :                                                 ncond = stmt_const(be, nsel, ncond);
    1365           0 :                                                 ncond->cand = nsel;
    1366           0 :                                         } else if (isel) {
    1367           0 :                                                 ncond = stmt_const(be, isel, ncond);
    1368           0 :                                                 ncond->cand = isel;
    1369             :                                         } else
    1370           0 :                                                 ncond = stmt_const(be, bin_find_smallest_column(be, left), ncond);
    1371             :                                 }
    1372       13361 :                                 if (isel && !ncond->cand)
    1373           0 :                                         ncond = stmt_project(be, nsel, ncond);
    1374       24840 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, !ncond->cand?rsel:NULL, 0/*anti*/, 0);
    1375       13361 :                                 if (rsel && ncond->cand)
    1376       11164 :                                         rsel = stmt_project(be, s, rsel);
    1377             :                                 else
    1378             :                                         rsel = s;
    1379             :                         }
    1380             :                 } else {
    1381         828 :                         if (!res) {
    1382             :                                 /* if_barrier ... */
    1383         371 :                                 assert(next_cond);
    1384         371 :                                 if (next_cond) {
    1385         371 :                                         if (cond) {
    1386         285 :                                                 ncond = stmt_binop(be, cond, es, nsel, and);
    1387             :                                         } else {
    1388             :                                                 ncond = es;
    1389             :                                         }
    1390             :                                         cond = es;
    1391             :                                 }
    1392             :                         } else {
    1393             :                                 /* var_x = s */
    1394         457 :                                 (void)stmt_assign(be, NULL, nme, es, 2);
    1395             :                                 /* endif_barrier */
    1396         456 :                                 (void)stmt_control_end(be, res);
    1397         457 :                                 res = NULL;
    1398             : 
    1399         457 :                                 if (en->next) {
    1400         371 :                                         cond = stmt_unop(be, cond, nsel, not);
    1401             : 
    1402         371 :                                         sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    1403         371 :                                         cond = stmt_binop(be, cond, stmt_unop(be, cond, nsel, isnull), nsel, or);
    1404         371 :                                         if (ocond)
    1405         285 :                                                 cond = stmt_binop(be, ocond, cond, nsel, and);
    1406         371 :                                         ocond = cond;
    1407         371 :                                         if (!en->next->next)
    1408          86 :                                                 ncond = cond;
    1409             :                                 }
    1410             :                         }
    1411         828 :                         if (ncond && (next_cond || (en->next && !en->next->next))) {
    1412             :                                 /* if_barrier ... */
    1413         457 :                                 res = stmt_cond(be, ncond, NULL, 0, 0);
    1414             :                         }
    1415             :                 }
    1416       29747 :                 next_cond = !next_cond;
    1417             :         }
    1418        2283 :         if (single_value)
    1419          86 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
    1420             :         return res;
    1421             : }
    1422             : 
    1423             : static stmt*
    1424         528 : exp2bin_coalesce(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel, int depth)
    1425             : {
    1426         528 :         stmt *res = NULL, *rsel = NULL, *osel = NULL, *ncond = NULL, *ocond = NULL;
    1427         528 :         int single_value = (fe->card <= CARD_ATOM && (!left || !left->nrcols));
    1428         528 :         char name[16], *nme = NULL;
    1429         528 :         sql_subtype *bt = sql_bind_localtype("bit");
    1430         528 :         sql_subfunc *and = sql_bind_func(be->mvc, "sys", "and", bt, bt, F_FUNC, true, true);
    1431         528 :         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    1432             : 
    1433         528 :         if (single_value) {
    1434             :                 /* var_x = nil; */
    1435          57 :                 nme = number2name(name, sizeof(name), ++be->mvc->label);
    1436          57 :                 (void)stmt_var(be, NULL, nme, exp_subtype(fe), 1, 2);
    1437             :         }
    1438             : 
    1439         528 :         list *exps = fe->l;
    1440        2031 :         for (node *en = exps->h; en; en = en->next) {
    1441        1503 :                 sql_exp *e = en->data;
    1442             : 
    1443        1503 :                 stmt *nsel = rsel;
    1444        1503 :                 if (!single_value) {
    1445        1348 :                         if (/*!next_cond &&*/ rsel && isel) {
    1446             :                                 /* back into left range */
    1447          48 :                                 nsel = stmt_project(be, rsel, isel);
    1448        1300 :                         } else if (isel && !rsel)
    1449        1503 :                                 nsel = isel;
    1450             :                 }
    1451        1503 :                 stmt *es = exp_bin(be, e, left, right, NULL, NULL, NULL, nsel, depth+1, 0, 1);
    1452             : 
    1453        1503 :                 if (!es)
    1454             :                         return NULL;
    1455             :                 /* create result */
    1456        1503 :                 if (!single_value) {
    1457        1348 :                         if (!res) {
    1458         471 :                                 stmt *l = isel;
    1459         471 :                                 if (!l)
    1460         437 :                                         l = bin_find_smallest_column(be, left);
    1461         471 :                                 res = stmt_const(be, l, stmt_atom(be, atom_general(be->mvc->sa, exp_subtype(fe), NULL, 0)));
    1462         471 :                                 if (res)
    1463         471 :                                         res->cand = isel;
    1464             :                         }
    1465         471 :                         if (res) {
    1466        1348 :                                 stmt *val = es;
    1467        1348 :                                 stmt *pos = rsel;
    1468             : 
    1469        1348 :                                 if (en->next) {
    1470         877 :                                         sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
    1471         877 :                                         ncond = stmt_unop(be, es, NULL, a);
    1472         877 :                                         if (ncond->nrcols == 0) {
    1473         120 :                                                 stmt *l = bin_find_smallest_column(be, left);
    1474         120 :                                                 if (nsel && l)
    1475          61 :                                                         l = stmt_project(be, nsel, l);
    1476         120 :                                                 ncond = stmt_const(be, l, ncond);
    1477         120 :                                                 if (nsel)
    1478          61 :                                                         ncond->cand = nsel;
    1479         757 :                                         } else if (!ncond->cand && nsel)
    1480         348 :                                                 ncond = stmt_project(be, nsel, ncond);
    1481         877 :                                         stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 0/*anti*/, 0);
    1482         877 :                                         if (!val->cand && nsel)
    1483         409 :                                                 val = stmt_project(be, nsel, val);
    1484         877 :                                         val = stmt_project(be, s, val);
    1485         877 :                                         if (osel)
    1486         406 :                                                 rsel = stmt_project(be, s, osel);
    1487             :                                         else
    1488             :                                                 rsel = s;
    1489         877 :                                         pos = rsel;
    1490         877 :                                         val->cand = pos;
    1491             :                                 }
    1492        1348 :                                 if (val->nrcols == 0)
    1493         164 :                                         val = stmt_const(be, pos, val);
    1494        1184 :                                 else if (!val->cand && nsel)
    1495         171 :                                         val = stmt_project(be, nsel, val);
    1496             : 
    1497        1348 :                                 res = stmt_replace(be, res, pos, val);
    1498             :                         }
    1499        1348 :                         if (en->next) { /* handled then part */
    1500         877 :                                 stmt *s = stmt_uselect(be, ncond, stmt_bool(be, 1), cmp_equal, NULL, 1/*anti*/, 0);
    1501         877 :                                 if (osel)
    1502         406 :                                         rsel = stmt_project(be, s, osel);
    1503             :                                 else
    1504             :                                         rsel = s;
    1505             :                                 osel = rsel;
    1506             :                         }
    1507             :                 } else {
    1508         155 :                         stmt *cond = ocond;
    1509         155 :                         if (en->next) {
    1510          98 :                                 sql_subfunc *a = sql_bind_func(be->mvc, "sys", "isnotnull", tail_type(es), NULL, F_FUNC, true, true);
    1511          98 :                                 ncond = stmt_unop(be, es, nsel, a);
    1512             : 
    1513          98 :                                 if (ocond)
    1514          41 :                                         cond = stmt_binop(be, ocond, ncond, nsel, and);
    1515             :                                 else
    1516             :                                         cond = ncond;
    1517             :                         }
    1518             : 
    1519             :                         /* if_barrier ... */
    1520         155 :                         stmt *b = stmt_cond(be, cond, NULL, 0, 0);
    1521             :                         /* var_x = s */
    1522         155 :                         (void)stmt_assign(be, NULL, nme, es, 2);
    1523             :                         /* endif_barrier */
    1524         155 :                         (void)stmt_control_end(be, b);
    1525             : 
    1526         155 :                         cond = stmt_unop(be, ncond, nsel, not);
    1527         155 :                         if (ocond)
    1528          98 :                                 ocond = stmt_binop(be, cond, ocond, nsel, and);
    1529             :                         else
    1530             :                                 ocond = cond;
    1531             :                 }
    1532             :         }
    1533         528 :         if (single_value)
    1534          57 :                 return stmt_var(be, NULL, nme, exp_subtype(fe), 0, 2);
    1535             :         return res;
    1536             : }
    1537             : 
    1538             : // This is the per-column portion of exp2bin_copyfrombinary
    1539             : static stmt *
    1540         216 : emit_loadcolumn(backend *be, stmt *onclient_stmt, stmt *bswap_stmt,  int *count_var, node *file_node, node *type_node)
    1541             : {
    1542         216 :         MalBlkPtr mb = be->mb;
    1543             : 
    1544         216 :         sql_exp *file_exp = file_node->data;
    1545         216 :         stmt *file_stmt = exp_bin(be, file_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    1546         216 :         sql_subtype *subtype = type_node->data;
    1547         216 :         int data_type = subtype->type->localtype;
    1548         216 :         int bat_type = newBatType(data_type);
    1549             : 
    1550             :         // The sql.importColumn operator takes a 'method' string to determine how to
    1551             :         // load the data. This leaves the door open to have multiple loaders for the
    1552             :         // same backend type, for example nul- and newline terminated strings.
    1553             :         // For the time being we just use the name of the storage type as the method
    1554             :         // name.
    1555         216 :         const char *method = ATOMname(data_type);
    1556             : 
    1557         216 :         int width;
    1558         216 :         switch (subtype->type->eclass) {
    1559          37 :                 case EC_DEC:
    1560             :                 case EC_STRING:
    1561          37 :                         width = subtype->digits;
    1562          37 :                         break;
    1563             :                 default:
    1564             :                         width = 0;
    1565             :                         break;
    1566             :         }
    1567             : 
    1568         216 :         int new_count_var = newTmpVariable(mb, TYPE_oid);
    1569             : 
    1570         216 :         InstrPtr p = newStmt(mb, sqlRef, importColumnRef);
    1571         216 :         if (p != NULL) {
    1572         216 :                 setArgType(mb, p, 0, bat_type);
    1573         216 :                 p = pushReturn(mb, p, new_count_var);
    1574             :                 //
    1575         216 :                 p = pushStr(mb, p, method);
    1576         216 :                 p = pushInt(mb, p, width);
    1577         216 :                 p = pushArgument(mb, p, bswap_stmt->nr);
    1578         216 :                 p = pushArgument(mb, p, file_stmt->nr);
    1579         216 :                 p = pushArgument(mb, p, onclient_stmt->nr);
    1580         216 :                 if (*count_var < 0)
    1581          94 :                         p = pushOid(mb, p, 0);
    1582             :                 else
    1583         122 :                         p = pushArgument(mb, p, *count_var);
    1584         216 :                 pushInstruction(mb, p);
    1585             :         }
    1586         216 :         if (p == NULL || mb->errors) {
    1587           0 :                 if (be->mvc->sa->eb.enabled)
    1588           0 :                         eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1589           0 :                 return sql_error(be->mvc, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1590             :         }
    1591             : 
    1592         216 :         *count_var = new_count_var;
    1593             : 
    1594         216 :         stmt *s = stmt_blackbox_result(be, p, 0, subtype);
    1595         216 :         return s;
    1596             : }
    1597             : 
    1598             : // Try to predict which column will be quickest to load first
    1599             : static int
    1600         216 : node_type_score(node *n)
    1601             : {
    1602         216 :         sql_subtype *st = n->data;
    1603         216 :         int tpe = st->type->localtype;
    1604         216 :         int stpe = ATOMstorage(tpe);
    1605         216 :         int score = stpe + (stpe == TYPE_bit);
    1606         216 :         return score;
    1607             : }
    1608             : 
    1609             : static stmt*
    1610          94 : exp2bin_copyfrombinary(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *isel)
    1611             : {
    1612          94 :         mvc *sql = be->mvc;
    1613          94 :         assert(left == NULL); (void)left;
    1614          94 :         assert(right == NULL); (void)right;
    1615          94 :         assert(isel == NULL); (void)isel;
    1616          94 :         sql_subfunc *f = fe->f;
    1617             : 
    1618          94 :         list *arg_list = fe->l;
    1619          94 :         list *type_list = f->res;
    1620          94 :         assert(4 + list_length(type_list) == list_length(arg_list));
    1621             : 
    1622          94 :         sql_exp * onclient_exp = arg_list->h->next->next->data;
    1623          94 :         stmt *onclient_stmt = exp_bin(be, onclient_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    1624          94 :         sql_exp *bswap_exp = arg_list->h->next->next->next->data;
    1625          94 :         stmt *bswap_stmt = exp_bin(be, bswap_exp, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    1626             : 
    1627             :         // If it's ON SERVER we can optimize by running the imports in parallel
    1628          94 :         bool onserver = false;
    1629          94 :         if (onclient_exp->type == e_atom) {
    1630          94 :                 atom *onclient_atom = onclient_exp->l;
    1631          94 :                 int onclient = onclient_atom->data.val.ival;
    1632          94 :                 onserver = (onclient == 0);
    1633             :         }
    1634             : 
    1635          94 :         node *const first_file = arg_list->h->next->next->next->next;
    1636          94 :         node *const first_type = type_list->h;
    1637          94 :         node *file, *type;
    1638             : 
    1639             :         // The first column we load determines the number of rows.
    1640             :         // We pass it on to the other columns.
    1641             :         // The first column to load should therefore be an 'easy' one.
    1642             :         // We identify the columns by the address of their type node.
    1643          94 :         node *prototype_file = first_file;
    1644          94 :         node *prototype_type = first_type;
    1645          94 :         int score = node_type_score(prototype_type);
    1646         216 :         for (file = first_file->next, type = first_type->next; file && type; file = file->next, type = type->next) {
    1647         122 :                 int sc = node_type_score(type);
    1648         122 :                 if (sc < score) {
    1649           6 :                         prototype_file = file;
    1650           6 :                         prototype_type = type;
    1651           6 :                         score = sc;
    1652             :                 }
    1653             :         }
    1654             : 
    1655             :         // Emit the columns
    1656          94 :         int count_var = -1;
    1657          94 :         list *columns = sa_list(sql->sa);
    1658          94 :         if (columns == NULL)
    1659             :                 return NULL;
    1660          94 :         stmt *prototype_stmt = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, prototype_file, prototype_type);
    1661          94 :         if (!prototype_stmt)
    1662             :                 return NULL;
    1663          94 :         int orig_count_var = count_var;
    1664         310 :         for (file = first_file, type = first_type; file && type; file = file->next, type = type->next) {
    1665         216 :                 stmt *s;
    1666         216 :                 if (type == prototype_type) {
    1667             :                         s = prototype_stmt;
    1668             :                 } else {
    1669         122 :                         s = emit_loadcolumn(be, onclient_stmt, bswap_stmt, &count_var, file, type);
    1670         122 :                         if (!s)
    1671             :                                 return NULL;
    1672             :                 }
    1673         216 :                 list_append(columns, s);
    1674         216 :                 if (onserver) {
    1675             :                         // Not threading the count variable from one importColumn to the next
    1676             :                         // makes it possible to run them in parallel in a dataflow region.
    1677         106 :                         count_var = orig_count_var;
    1678             :                 }
    1679             :         }
    1680             : 
    1681          94 :         return stmt_list(be, columns);
    1682             : }
    1683             : 
    1684             : static bool
    1685         237 : is_const_func(sql_subfunc *f, list *attr)
    1686             : {
    1687         237 :         if (list_length(attr) != 2)
    1688             :                 return false;
    1689         134 :         if (strcmp(f->func->base.name, "quantile") == 0 ||
    1690         107 :                 strcmp(f->func->base.name, "quantile_avg") == 0)
    1691          30 :                 return true;
    1692             :         return false;
    1693             : }
    1694             : 
    1695             : static stmt*
    1696           0 : exp2bin_multiset(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
    1697             : {
    1698           0 :         assert(0);
    1699             :         return left;
    1700             :         (void)fe;
    1701             :         (void)right;
    1702             :         (void)sel;
    1703             :         list *l = sa_list(be->mvc->sa);
    1704             :         for(node *n = left->op4.lval->h; n; n = n->next) {
    1705             :                 stmt *s = n->data, *ns = s;
    1706             :                 while(ns->type == st_alias)
    1707             :                         ns = ns->op1;
    1708             :                 if (ns->type == st_list) {
    1709             :                         for(node *m = ns->op4.lval->h; m; m = m->next)
    1710             :                                 append(l, m->data);
    1711             :                 } else {
    1712             :                         append(l, s);
    1713             :                 }
    1714             :         }
    1715             :         return stmt_list(be, l);
    1716             : }
    1717             : 
    1718             : static stmt*
    1719          27 : exp2bin_file_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
    1720             : {
    1721          27 :         assert(left == NULL); (void)left;
    1722          27 :         assert(right == NULL); (void)right;
    1723          27 :         assert(sel == NULL); (void)sel;
    1724          27 :         sql_subfunc *f = fe->f;
    1725             : 
    1726          27 :         list *arg_list = fe->l;
    1727             :         /*
    1728             :         list *type_list = f->res;
    1729             :         assert(1 + list_length(type_list) == list_length(arg_list));
    1730             :         */
    1731             : 
    1732          27 :         sql_exp *eexp = arg_list->h->next->data;
    1733          27 :         assert(is_atom(eexp->type));
    1734          27 :         atom *ea = eexp->l;
    1735          27 :         assert(ea->data.vtype == TYPE_str);
    1736          27 :         char *ext = ea->data.val.sval;
    1737             : 
    1738          27 :         file_loader_t *fl = fl_find(ext);
    1739          27 :         if (!fl)
    1740           0 :                 fl = fl_find("csv");
    1741           0 :         if (!fl)
    1742             :                 return NULL;
    1743          27 :         sql_exp *fexp = arg_list->h->data;
    1744          27 :         assert(is_atom(fexp->type));
    1745          27 :         atom *fa = fexp->l;
    1746          27 :         assert(fa->data.vtype == TYPE_str);
    1747          27 :         char *filename = fa->data.val.sval;
    1748          27 :         sql_exp *topn = NULL;
    1749          27 :         if (list_length(arg_list) == 3)
    1750           0 :                 topn = list_fetch(arg_list, 2);
    1751          27 :         return (stmt*)fl->load(be, f, filename, topn);
    1752             : }
    1753             : 
    1754             : static stmt*
    1755          53 : exp2bin_proto_loader(backend *be, sql_exp *fe, stmt *left, stmt *right, stmt *sel)
    1756             : {
    1757          53 :         assert(left == NULL); (void)left;
    1758          53 :         assert(right == NULL); (void)right;
    1759          53 :         assert(sel == NULL); (void)sel;
    1760          53 :         sql_subfunc *f = fe->f;
    1761             : 
    1762          53 :         list *arg_list = fe->l;
    1763             :         /*
    1764             :         list *type_list = f->res;
    1765             :         assert(1 + list_length(type_list) == list_length(arg_list));
    1766             :         */
    1767             : 
    1768          53 :         sql_exp *eexp = arg_list->h->next->data;
    1769          53 :         assert(is_atom(eexp->type));
    1770          53 :         atom *ea = eexp->l;
    1771          53 :         assert(ea->data.vtype == TYPE_str);
    1772          53 :         char *ext = ea->data.val.sval;
    1773             : 
    1774          53 :         proto_loader_t *pl = pl_find(ext);
    1775          53 :         if (!pl)
    1776           0 :                 pl = pl_find("mapi");
    1777           0 :         if (!pl)
    1778             :                 return NULL;
    1779          53 :         sql_exp *fexp = arg_list->h->data;
    1780          53 :         assert(is_atom(fexp->type));
    1781          53 :         atom *fa = fexp->l;
    1782          53 :         assert(fa->data.vtype == TYPE_str);
    1783          53 :         char *filename = fa->data.val.sval;
    1784          53 :         sql_exp *topn = NULL;
    1785          53 :         if (list_length(arg_list) == 3)
    1786           0 :                 topn = list_fetch(arg_list, 2);
    1787          53 :         return (stmt*)pl->load(be, f, filename, topn);
    1788             : }
    1789             : 
    1790             : static stmt *
    1791         133 : nested_stmts(backend *be, sql_exp *e, node **M)
    1792             : {
    1793         133 :         assert(is_nested(e));
    1794         133 :         node *m = *M;
    1795         133 :         list *r = sa_list(be->mvc->sa);
    1796         133 :         list *exps = e->f;
    1797             : 
    1798         133 :         if (!list_empty(exps)) {
    1799         558 :                 for (node *n = exps->h; n && m; n = n->next) {
    1800         425 :                         sql_exp *e = n->data;
    1801         513 :                         if (e->type == e_column && e->f) {
    1802          88 :                                 stmt *s = nested_stmts(be, e, &m);
    1803          88 :                                 s = stmt_alias(be, s, e->alias.label, exp_relname(e), exp_name(e));
    1804          88 :                                 s->subtype = *exp_subtype(e);
    1805          88 :                                 s->nested = true;
    1806          88 :                                 append(r, s);
    1807             :                         } else {
    1808         337 :                                 stmt *s = m->data;
    1809         337 :                                 s = stmt_alias(be, s, e->alias.label, exp_relname(e), exp_name(e));
    1810         337 :                                 m = m->next;
    1811         337 :                                 append(r, s);
    1812             :                         }
    1813             :                 }
    1814             :         }
    1815         133 :         *M = m;
    1816         133 :         stmt *s = stmt_list(be, r);
    1817         133 :         s->nrcols = 3;
    1818         133 :         s->nested = true;
    1819         133 :         s->subtype = *exp_subtype(e);
    1820         133 :         s->multiset = s->subtype.multiset;
    1821         133 :         return s;
    1822             : }
    1823             : 
    1824             : stmt *
    1825     5072556 : 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)
    1826             : {
    1827     5072556 :         mvc *sql = be->mvc;
    1828     5072556 :         stmt *s = NULL;
    1829             : 
    1830     5072556 :         if (mvc_highwater(sql))
    1831           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    1832             : 
    1833     5074249 :         if (!e) {
    1834           0 :                 assert(0);
    1835             :                 return NULL;
    1836             :         }
    1837             : 
    1838     5074249 :         switch(e->type) {
    1839        7611 :         case e_psm:
    1840        7611 :                 if (e->flag & PSM_SET) {
    1841         602 :                         stmt *r = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1842         602 :                         if(!r)
    1843             :                                 return NULL;
    1844         602 :                         if (e->card <= CARD_ATOM && r->nrcols > 0) /* single value, get result from bat */
    1845           6 :                                 r = stmt_fetch(be, r);
    1846         602 :                         return stmt_assign(be, exp_relname(e), exp_name(e), r, GET_PSM_LEVEL(e->flag));
    1847        7009 :                 } else if (e->flag & PSM_VAR) {
    1848         176 :                         if (e->f)
    1849          20 :                                 return stmt_vars(be, exp_name(e), e->f, 1, GET_PSM_LEVEL(e->flag));
    1850             :                         else
    1851         156 :                                 return stmt_var(be, exp_relname(e), exp_name(e), &e->tpe, 1, GET_PSM_LEVEL(e->flag));
    1852        6833 :                 } else if (e->flag & PSM_RETURN) {
    1853         666 :                         sql_exp *l = e->l;
    1854         666 :                         stmt *r = exp_bin(be, l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1855             : 
    1856         665 :                         if (!r)
    1857             :                                 return NULL;
    1858             :                         /* handle table returning functions */
    1859         665 :                         if (l->type == e_psm && l->flag & PSM_REL) {
    1860         242 :                                 stmt *lst = r->op1;
    1861         282 :                                 if (r->type == st_table && lst->nrcols == 0 && lst->key && e->card > CARD_ATOM) {
    1862          40 :                                         node *n;
    1863          40 :                                         list *l = sa_list(sql->sa);
    1864          40 :                                         if (l == NULL)
    1865             :                                                 return NULL;
    1866             : 
    1867          86 :                                         for (n=lst->op4.lval->h; n; n = n->next)
    1868          46 :                                                 list_append(l, const_column(be, (stmt*)n->data));
    1869          40 :                                         r = stmt_list(be, l);
    1870         202 :                                 } else if (r->type == st_table && e->card == CARD_ATOM) { /* fetch value */
    1871          35 :                                         r = lst->op4.lval->h->data;
    1872          35 :                                         if (!r->aggr) /* if the cardinality is atom, no fetch call needed */
    1873           4 :                                                 r = stmt_fetch(be, r);
    1874             :                                 }
    1875         242 :                                 if (r->type == st_list)
    1876          40 :                                         r = stmt_table(be, r, 1);
    1877             :                         }
    1878         665 :                         return stmt_return(be, r, GET_PSM_LEVEL(e->flag));
    1879        6167 :                 } else if (e->flag & PSM_WHILE) {
    1880             :                         /* while is a if - block true with leave statement
    1881             :                          * needed because the condition needs to be inside this outer block */
    1882          17 :                         stmt *ifstmt = stmt_cond(be, stmt_bool(be, 1), NULL, 0, 0);
    1883          17 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1884          17 :                         stmt *wstmt;
    1885             : 
    1886          17 :                         if(!cond)
    1887             :                                 return NULL;
    1888          17 :                         wstmt = stmt_cond(be, cond, ifstmt, 1, 0);
    1889             : 
    1890          17 :                         if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
    1891             :                                 return NULL;
    1892          17 :                         (void)stmt_control_end(be, wstmt);
    1893          17 :                         return stmt_control_end(be, ifstmt);
    1894        6150 :                 } else if (e->flag & PSM_IF) {
    1895         241 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1896         241 :                         stmt *ifstmt, *res;
    1897             : 
    1898         241 :                         if(!cond)
    1899             :                                 return NULL;
    1900         241 :                         ifstmt = stmt_cond(be, cond, NULL, 0, 0);
    1901         241 :                         if (!exp_list(be, e->r, left, right, grp, ext, cnt, sel))
    1902             :                                 return NULL;
    1903         241 :                         res = stmt_control_end(be, ifstmt);
    1904         241 :                         if (e->f) {
    1905          26 :                                 stmt *elsestmt = stmt_cond(be, cond, NULL, 0, 1);
    1906             : 
    1907          26 :                                 if (!exp_list(be, e->f, left, right, grp, ext, cnt, sel))
    1908             :                                         return NULL;
    1909          26 :                                 res = stmt_control_end(be, elsestmt);
    1910             :                         }
    1911         241 :                         return res;
    1912        5909 :                 } else if (e->flag & PSM_REL) {
    1913        5752 :                         sql_rel *rel = e->l;
    1914        5752 :                         stmt *r = rel_bin(be, rel);
    1915             : 
    1916        5752 :                         if (!r)
    1917             :                                 return NULL;
    1918         862 :                         if (is_modify(rel->op) || is_ddl(rel->op))
    1919             :                                 return r;
    1920         649 :                         return stmt_table(be, r, 1);
    1921         157 :                 } else if (e->flag & PSM_EXCEPTION) {
    1922         157 :                         stmt *cond = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, 0, 0, push);
    1923         157 :                         if (!cond)
    1924             :                                 return NULL;
    1925         157 :                         if (cond->nrcols)
    1926           0 :                                 cond = stmt_fetch(be, cond);
    1927         157 :                         return stmt_exception(be, cond, (const char *) e->r, 0);
    1928             :                 }
    1929             :                 break;
    1930     3446357 :         case e_atom: {
    1931     3446357 :                 if (e->l) {                  /* literals */
    1932     3302499 :                         s = stmt_atom(be, e->l);
    1933      143858 :                 } else if (e->r) {           /* parameters and declared variables */
    1934        2136 :                         sql_var_name *vname = (sql_var_name*) e->r;
    1935        2136 :                         assert(vname->name);
    1936        2136 :                         s = stmt_var(be, vname->sname ? a_create(sql->sa, sa_strdup(sql->sa, vname->sname)) : NULL, sa_strdup(sql->sa, vname->name), e->tpe.type?&e->tpe:NULL, 0, e->flag);
    1937      141722 :                 } else if (e->f) {           /* values */
    1938      139672 :                         s = value_tvtree(be, e, left, sel);
    1939             :                 } else {                        /* arguments */
    1940        2050 :                         sql_subtype *t = e->tpe.type?&e->tpe:NULL;
    1941        2050 :                         if (!t && 0) {
    1942             :                                 sql_arg *a = sql_bind_paramnr(be->mvc, e->flag);
    1943             :                                 t = a->type.type?&a->type:NULL;
    1944             :                         }
    1945        2050 :                         s = stmt_varnr(be, e->flag, t);
    1946             :                 }
    1947             :         }       break;
    1948       50883 :         case e_convert: {
    1949             :                 /* if input is type any NULL or column of nulls, change type */
    1950       50883 :                 list *tps = e->r;
    1951       50883 :                 sql_subtype *from = tps->h->data;
    1952       50883 :                 sql_subtype *to = tps->h->next->data;
    1953       50883 :                 stmt *l;
    1954             : 
    1955       50883 :                 if (from->type->localtype == 0) {
    1956         752 :                         l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
    1957         752 :                         if (l)
    1958         751 :                                 l = stmt_atom(be, atom_general(sql->sa, to, NULL, 0));
    1959             :                 } else {
    1960       50131 :                         l = exp_bin(be, e->l, left, right, grp, ext, cnt, sel, depth+1, 0, push);
    1961             :                 }
    1962       50882 :                 if (!l)
    1963         237 :                         return NULL;
    1964       50646 :                 if (from->type->eclass == EC_SEC && to->type->eclass == EC_SEC) {
    1965             :                         // trivial conversion because EC_SEC is always in milliseconds
    1966             :                         s = l;
    1967       51002 :                 } else if (depth && sel && l->nrcols == 0 && left && left->nrcols && exp_unsafe(e, false, true)) {
    1968         419 :                         stmt *rows = bin_find_smallest_column(be, left);
    1969         419 :                         l = stmt_const(be, rows, l);
    1970         419 :                         s = stmt_convert(be, l, sel, from, to);
    1971       50428 :                 } else if (depth && l->nrcols == 0 && left && left->nrcols && from->type->localtype > to->type->localtype &&
    1972         522 :                                 exp_unsafe(e, false, true)) {
    1973         258 :                         stmt *rows = bin_find_smallest_column(be, left);
    1974         258 :                         l = stmt_const(be, rows, l);
    1975         258 :                         s = stmt_convert(be, l, sel, from, to);
    1976             :                 } else {
    1977       90562 :                         s = stmt_convert(be, l, (!push&&l->nrcols==0)?NULL:sel, from, to);
    1978             :                 }
    1979       50646 :                 if (s && s->type == st_list && e->f) {
    1980          45 :                         s = nested_stmts(be, e, &s->op4.lval->h);
    1981             :                 }
    1982             :         }       break;
    1983      232119 :         case e_func: {
    1984      232119 :                 node *en;
    1985      232119 :                 list *l = sa_list(sql->sa), *exps = e->l;
    1986      232122 :                 sql_subfunc *f = e->f;
    1987      232122 :                 const char *fname = f->func->base.name;
    1988      232122 :                 stmt *rows = NULL;
    1989      232122 :                 const char *mod, *fimp;
    1990             : 
    1991      232122 :                 if (l == NULL)
    1992             :                         return NULL;
    1993             : 
    1994             :                 /* attempt to instantiate MAL functions now, so we can know if we can push candidate lists */
    1995      232122 :                 if (f->func->lang == FUNC_LANG_MAL && backend_create_mal_func(be->mvc, f) < 0)
    1996             :                         return NULL;
    1997      232114 :                 mod = sql_func_mod(f->func);
    1998      232111 :                 fimp = backend_function_imp(be, f->func);
    1999             : 
    2000      232087 :                 if (f->func->side_effect && left && left->nrcols > 0 && f->func->type != F_LOADER && exps_card(exps) < CARD_MULTI) {
    2001         105 :                         rows = bin_find_smallest_column(be, left);
    2002             :                 }
    2003      232087 :                 assert(!e->r);
    2004      232087 :                 if (strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
    2005       21842 :                         if (strcmp(fname, "star") == 0) {
    2006         467 :                                 if (!left)
    2007           1 :                                         return const_column(be, stmt_bool(be, 1));
    2008         466 :                                 return left->op4.lval->h->data;
    2009             :                         }
    2010       21375 :                         if (strcmp(fname, "case") == 0)
    2011       18292 :                                 return exp2bin_case(be, e, left, right, sel, depth);
    2012        3083 :                         if (strcmp(fname, "casewhen") == 0)
    2013        2283 :                                 return exp2bin_casewhen(be, e, left, right, sel, depth);
    2014         800 :                         if (strcmp(fname, "coalesce") == 0)
    2015         528 :                                 return exp2bin_coalesce(be, e, left, right, sel, depth);
    2016         272 :                         if (strcmp(fname, "copyfrombinary") == 0)
    2017          94 :                                 return exp2bin_copyfrombinary(be, e, left, right, sel);
    2018         178 :                         if (strcmp(fname, "file_loader") == 0)
    2019          27 :                                 return exp2bin_file_loader(be, e, left, right, sel);
    2020         151 :                         if (strcmp(fname, "proto_loader") == 0)
    2021          53 :                                 return exp2bin_proto_loader(be, e, left, right, sel);
    2022          98 :                         if (strcmp(fname, "multiset") == 0)
    2023           0 :                                 return exp2bin_multiset(be, e, left, right, sel);
    2024          98 :                         if (strcmp(fname, "-1") == 0) /* map arguments to A0 .. An */
    2025           3 :                                 return exp2bin_named_placeholders(be, e);
    2026             :                 }
    2027      210340 :                 if (!list_empty(exps)) {
    2028      208446 :                         unsigned nrcols = 0;
    2029      208446 :                         int push_cands = can_push_cands(sel, mod, fimp);
    2030             : 
    2031      582835 :                         for (en = exps->h; en; en = en->next) {
    2032      384964 :                                 sql_exp *e = en->data;
    2033      651619 :                                 stmt *es = exp_bin(be, e, left, right, grp, ext, cnt, (push_cands)?sel:NULL, depth+1, 0, push);
    2034             : 
    2035      384998 :                                 if (!es)
    2036             :                                         return NULL;
    2037             :                                 /*if (rows && en == exps->h && f->func->type != F_LOADER)
    2038             :                                         es = stmt_const(be, rows, es);*/
    2039      374429 :                                 else if (f->func->type == F_ANALYTIC && es->nrcols == 0) {
    2040        7828 :                                         if (en == exps->h && left && left->nrcols)
    2041         465 :                                                 es = stmt_const(be, bin_find_smallest_column(be, left), es); /* ensure the first argument is a column */
    2042        7828 :                                         if (!f->func->s && !strcmp(f->func->base.name, "window_bound")
    2043        3277 :                                                 && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next && left->nrcols)
    2044           2 :                                                 es = stmt_const(be, bin_find_smallest_column(be, left), es);
    2045             :                                 }
    2046      374429 :                                 if (es->nrcols > nrcols)
    2047             :                                         nrcols = es->nrcols;
    2048      374429 :                                 list_append(l, es);
    2049             :                         }
    2050             :                 }
    2051      199760 :                 if (!(s = stmt_Nop(be, stmt_list(be, l), sel, f, rows)))
    2052             :                         return NULL;
    2053             :         }       break;
    2054       11093 :         case e_aggr: {
    2055       11093 :                 list *attr = e->l;
    2056       11093 :                 list *r = e->r;
    2057       11093 :                 stmt *as = NULL;
    2058       11093 :                 sql_subfunc *a = e->f;
    2059             : 
    2060       11093 :                 assert(sel == NULL);
    2061             :                         /* cases
    2062             :                          * 0) count(*)
    2063             :                          * 1) general aggregation
    2064             :                          * 2) aggregation with required order (quantile etc)
    2065             :                          * 3) aggregation with optional order by, group_concat, xml_agg
    2066             :                          * */
    2067       16883 :                 if (attr && attr->h) {
    2068        5791 :                         node *en;
    2069        5791 :                         list *l = sa_list(sql->sa);
    2070             : 
    2071       12003 :                         for (en = attr->h; en; en = en->next) {
    2072        6213 :                                 sql_exp *at = en->data;
    2073             : 
    2074        6213 :                                 as = exp_bin(be, at, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
    2075             : 
    2076        6213 :                                 if (as && as->nrcols <= 0 && left && (!is_const_func(a, attr) || grp))
    2077         219 :                                         as = stmt_const(be, bin_find_smallest_column(be, left), as);
    2078        6213 :                                 if (en == attr->h && !en->next && exp_aggr_is_count(e))
    2079         142 :                                         as = exp_count_no_nil_arg(e, ext, at, as);
    2080             :                                 /* insert single value into a column */
    2081        6213 :                                 if (as && as->nrcols <= 0 && !left)
    2082         161 :                                         as = const_column(be, as);
    2083             : 
    2084         179 :                                 if (!as)
    2085           1 :                                         return NULL;
    2086        6212 :                                 append(l, as);
    2087             :                         }
    2088        5790 :                         if (need_distinct(e) && (grp || list_length(l) > 1)){
    2089          30 :                                 list *nl = sa_list(sql->sa);
    2090          30 :                                 stmt *ngrp = grp;
    2091          30 :                                 stmt *next = ext;
    2092          30 :                                 stmt *ncnt = cnt;
    2093          30 :                                 if (nl == NULL)
    2094             :                                         return NULL;
    2095          62 :                                 for (en = l->h; en; en = en->next) {
    2096          32 :                                         stmt *as = en->data;
    2097          32 :                                         stmt *g = stmt_group(be, as, ngrp, next, ncnt, 1);
    2098          32 :                                         ngrp = stmt_result(be, g, 0);
    2099          32 :                                         next = stmt_result(be, g, 1);
    2100          32 :                                         ncnt = stmt_result(be, g, 2);
    2101             :                                 }
    2102          62 :                                 for (en = l->h; en; en = en->next) {
    2103          32 :                                         stmt *as = en->data;
    2104          32 :                                         append(nl, stmt_project(be, next, as));
    2105             :                                 }
    2106          30 :                                 if (grp)
    2107          29 :                                         grp = stmt_project(be, next, grp);
    2108             :                                 l = nl;
    2109        5760 :                         } else if (need_distinct(e)) {
    2110          76 :                                 stmt *a = l->h->data;
    2111          76 :                                 stmt *u = stmt_unique(be, a);
    2112          76 :                                 if (u == NULL)
    2113             :                                         return NULL;
    2114          76 :                                 l = sa_list(sql->sa);
    2115          76 :                                 if (l == NULL)
    2116             :                                         return NULL;
    2117          76 :                                 append(l, stmt_project(be, u, a));
    2118             :                         }
    2119        5790 :                         if (r) {
    2120          22 :                                 list *obe = r->h->data;
    2121          22 :                                 if (obe && obe->h) {
    2122          22 :                                         stmt *orderby = NULL, *orderby_vals, *orderby_ids, *orderby_grp;
    2123             :                                         /* order by */
    2124          22 :                                         if (grp) {
    2125          22 :                                                 orderby = stmt_order(be, grp, true, true);
    2126             : 
    2127          22 :                                                 orderby_vals = stmt_result(be, orderby, 0);
    2128          22 :                                                 orderby_ids = stmt_result(be, orderby, 1);
    2129          22 :                                                 orderby_grp = stmt_result(be, orderby, 2);
    2130             :                                         }
    2131          44 :                                         for (node *n = obe->h; n; n = n->next) {
    2132          22 :                                                 sql_exp *oe = n->data;
    2133          22 :                                                 stmt *os = exp_bin(be, oe, left, right, NULL, NULL, NULL, sel, depth+1, 0, push);
    2134          22 :                                                 if (orderby)
    2135          22 :                                                         orderby = stmt_reorder(be, os, is_ascending(oe), nulls_last(oe), orderby_ids, orderby_grp);
    2136             :                                                 else
    2137           0 :                                                         orderby = stmt_order(be, os, is_ascending(oe), nulls_last(oe));
    2138          22 :                                                 orderby_vals = stmt_result(be, orderby, 0);
    2139          22 :                                                 orderby_ids = stmt_result(be, orderby, 1);
    2140          22 :                                                 orderby_grp = stmt_result(be, orderby, 2);
    2141             :                                         }
    2142             :                                         /* depending on type of aggr project input or ordered column */
    2143          22 :                                         stmt *h = l->h->data;
    2144          22 :                                         l->h->data = h = stmt_project(be, orderby_ids, h);
    2145          22 :                                         if (grp)
    2146          22 :                                                 grp = stmt_project(be, orderby_ids, grp);
    2147        5790 :                                         (void)orderby_vals;
    2148             :                                 }
    2149             :                         }
    2150        5790 :                         as = stmt_list(be, l);
    2151             :                 } else {
    2152             :                         /* count(*) may need the default group (relation) and
    2153             :                            and/or an attribute to count */
    2154        5302 :                         if (grp) {
    2155             :                                 as = grp;
    2156        1511 :                         } else if (left && !list_empty(left->op4.lval)) {
    2157        1510 :                                 as = bin_find_smallest_column(be, left);
    2158        1511 :                                 as = exp_count_no_nil_arg(e, ext, NULL, as);
    2159             :                         } else {
    2160             :                                 /* create dummy single value in a column */
    2161           1 :                                 as = stmt_atom_lng(be, 0);
    2162           1 :                                 as = const_column(be, as);
    2163             :                         }
    2164             :                 }
    2165       11093 :                 s = stmt_aggr(be, as, grp, ext, a, 1, need_no_nil(e) /* ignore nil*/, !zero_if_empty(e));
    2166             :                 //if (find_prop(e->p, PROP_COUNT)) /* propagate count == 0 ipv NULL in outer joins */
    2167             :                         //s->flag |= OUTER_ZERO;
    2168       11093 :         }       break;
    2169     1158478 :         case e_column: {
    2170     1158478 :                 if (right) /* check relation names */
    2171             :                         //s = bin_find_column(be, right, e->l, e->r);
    2172       56325 :                         s = bin_find_column_nid(be, right, e->nid);
    2173     1158478 :                 if (!s && left)
    2174             :                         //s = bin_find_column(be, left, e->l, e->r);
    2175     1111431 :                         s = bin_find_column_nid(be, left, e->nid);
    2176     1158464 :                 if (s && grp)
    2177         290 :                         s = stmt_project(be, ext, s);
    2178     1158464 :                 if (!s && right) {
    2179           0 :                         TRC_CRITICAL(SQL_EXECUTION, "Could not find %s.%s\n", (char*)e->l, (char*)e->r);
    2180           0 :                         print_stmtlist(sql->sa, left);
    2181           0 :                         print_stmtlist(sql->sa, right);
    2182           0 :                         if (!s) {
    2183           0 :                                 TRC_ERROR(SQL_EXECUTION, "Query: '%s'\n", be->client->query);
    2184             :                         }
    2185           0 :                         assert(s);
    2186             :                         return NULL;
    2187             :                 }
    2188             :         }       break;
    2189      167708 :         case e_cmp: {
    2190      167708 :                 stmt *l = NULL, *r = NULL, *r2 = NULL;
    2191      167708 :                 int swapped = 0, is_select = 0, oldvtop, oldstop;
    2192      167708 :                 sql_exp *re = e->r, *re2 = e->f;
    2193             : 
    2194             :                 /* general predicate, select and join */
    2195      167708 :                 if (e->flag == cmp_filter) {
    2196        4604 :                         list *args;
    2197        4604 :                         list *ops;
    2198        4604 :                         node *n;
    2199        4604 :                         int first = 1;
    2200             : 
    2201        4604 :                         ops = sa_list(sql->sa);
    2202        4604 :                         if (ops == NULL)
    2203             :                                 return NULL;
    2204        4604 :                         args = e->l;
    2205        9206 :                         for (n = args->h; n; n = n->next) {
    2206        4604 :                                 oldvtop = be->mb->vtop;
    2207        4604 :                                 oldstop = be->mb->stop;
    2208        4604 :                                 s = NULL;
    2209        4604 :                                 if (!swapped)
    2210        4604 :                                         s = exp_bin(be, n->data, left, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    2211        4604 :                                 if (!s && right && (first || swapped)) {
    2212           4 :                                         clean_mal_statements(be, oldstop, oldvtop);
    2213           4 :                                         s = exp_bin(be, n->data, right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    2214           4 :                                         swapped = 1;
    2215             :                                 }
    2216        4604 :                                 if (!s)
    2217             :                                         return s;
    2218        4602 :                                 if (s->nrcols == 0 && first && left)
    2219         619 :                                         s = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), s);
    2220        4602 :                                 list_append(ops, s);
    2221        4602 :                                 first = 0;
    2222             :                         }
    2223        4602 :                         l = stmt_list(be, ops);
    2224        4602 :                         ops = sa_list(sql->sa);
    2225        4602 :                         if (ops == NULL)
    2226             :                                 return NULL;
    2227        4602 :                         args = e->r;
    2228       17946 :                         for (n = args->h; n; n = n->next) {
    2229       13454 :                                 s = exp_bin(be, n->data, (swapped || !right)?left:right, NULL, grp, ext, cnt, NULL, depth+1, 0, push);
    2230       13344 :                                 if (!s)
    2231             :                                         return s;
    2232       13344 :                                 list_append(ops, s);
    2233             :                         }
    2234        4602 :                         r = stmt_list(be, ops);
    2235             : 
    2236        4602 :                         if (!reduce) {
    2237         440 :                                 sql_subfunc *f = e->f;
    2238         440 :                                 list *ops = sa_list(sql->sa);
    2239         880 :                                 for (node *n = l->op4.lval->h ; n ; n = n->next)
    2240         440 :                                         append(ops, n->data);
    2241        1629 :                                 for (node *n = r->op4.lval->h ; n ; n = n->next)
    2242        1189 :                                         append(ops, n->data);
    2243         440 :                                 if (!(s = stmt_Nop(be, stmt_list(be, ops), sel, f, NULL)))
    2244             :                                         return NULL;
    2245             :                                 return s;
    2246             :                         }
    2247             : 
    2248        4162 :                         if (left && right && (exps_card(e->r) != CARD_ATOM || !exps_are_atoms(e->r))) {
    2249          48 :                                 sql_subfunc *f = e->f;
    2250          48 :                                 bool first = true;
    2251          96 :                                 for (node *n = l->op4.lval->h ; n ; n = n->next) {
    2252          48 :                                         stmt *s = n->data;
    2253          48 :                                         if (s->nrcols == 0) {
    2254           0 :                                                 if (first)
    2255           0 :                                                         n->data = stmt_const(be, bin_find_smallest_column(be, left), n->data);
    2256             :                                                 else
    2257           0 :                                                         n->data = column(be, s);
    2258             :                                         }
    2259          48 :                                         first = false;
    2260             :                                 }
    2261          48 :                                 first = true;
    2262         158 :                                 for (node *n = r->op4.lval->h ; n ; n = n->next) {
    2263         110 :                                         stmt *s = n->data;
    2264         110 :                                         if (s->nrcols == 0) {
    2265          61 :                                                 if (first)
    2266           3 :                                                         n->data = stmt_const(be, bin_find_smallest_column(be, right), s);
    2267             :                                                 else /* last arg maybe const */
    2268          58 :                                                         n->data = column(be, s);
    2269             :                                         }
    2270         110 :                                         first = false;
    2271             :                                 }
    2272          48 :                                 return stmt_genjoin(be, l, r, f, is_anti(e), swapped);
    2273             :                         }
    2274        4114 :                         assert(!swapped);
    2275        4114 :                         s = stmt_genselect(be, l, r, e->f, sel, is_anti(e));
    2276        4114 :                         return s;
    2277             :                 }
    2278      163104 :                 if (e->flag == cmp_in || e->flag == cmp_notin)
    2279       15763 :                         return handle_in_exps(be, e->l, e->r, left, right, grp, ext, cnt, sel, (e->flag == cmp_in), depth, reduce, push);
    2280      147341 :                 if (e->flag == cmp_or && (!right || right->nrcols == 1))
    2281       10026 :                         return exp_bin_or(be, e, left, right, grp, ext, cnt, sel, depth, reduce, push);
    2282      137315 :                 if (e->flag == cmp_or && right) {  /* join */
    2283           0 :                         assert(0);
    2284             :                 }
    2285             : 
    2286             :                 /* mark use of join indices */
    2287      137315 :                 if (right && find_prop(e->p, PROP_JOINIDX) != NULL)
    2288         623 :                         be->join_idx++;
    2289             : 
    2290      137315 :                 oldvtop = be->mb->vtop;
    2291      137315 :                 oldstop = be->mb->stop;
    2292      137315 :                 if (!l) {
    2293      273689 :                         l = exp_bin(be, e->l, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2294      137314 :                         swapped = 0;
    2295             :                 }
    2296      137314 :                 if (!l && right) {
    2297       17931 :                         clean_mal_statements(be, oldstop, oldvtop);
    2298       17931 :                         l = exp_bin(be, e->l, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2299       17931 :                         swapped = 1;
    2300             :                 }
    2301             : 
    2302      137314 :                 oldvtop = be->mb->vtop;
    2303      137314 :                 oldstop = be->mb->stop;
    2304      137314 :                 if (swapped || !right || !reduce)
    2305       91358 :                         r = exp_bin(be, re, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2306             :                 else
    2307       46893 :                         r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2308      137315 :                 if (!r && !swapped) {
    2309           2 :                         clean_mal_statements(be, oldstop, oldvtop);
    2310           2 :                         r = exp_bin(be, re, left, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2311           2 :                         is_select = 1;
    2312             :                 }
    2313      137315 :                 if (!r && swapped) {
    2314           0 :                         clean_mal_statements(be, oldstop, oldvtop);
    2315           0 :                         r = exp_bin(be, re, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2316           0 :                         is_select = 1;
    2317             :                 }
    2318      137315 :                 if (re2 && (swapped || !right || !reduce))
    2319        5309 :                         r2 = exp_bin(be, re2, left, (!reduce)?right:NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2320          52 :                 else if (re2)
    2321          52 :                         r2 = exp_bin(be, re2, right, NULL, grp, ext, cnt, sel, depth+1, 0, push);
    2322             : 
    2323      137315 :                 if (!l || !r || (re2 && !r2))
    2324             :                         return NULL;
    2325             : 
    2326      137311 :                 (void)is_select;
    2327      137311 :                 if (reduce && left && right) {
    2328       64824 :                         if (l->nrcols == 0)
    2329           0 :                                 l = stmt_const(be, bin_find_smallest_column(be, swapped?right:left), l);
    2330       64824 :                         if (r->nrcols == 0)
    2331           4 :                                 r = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r);
    2332       64824 :                         if (r2 && r2->nrcols == 0)
    2333           8 :                                 r2 = stmt_const(be, bin_find_smallest_column(be, swapped?left:right), r2);
    2334           4 :                         if (r2) {
    2335          54 :                                 s = stmt_join2(be, l, r, r2, (comp_type)e->flag, is_anti(e), is_symmetric(e), swapped);
    2336       64770 :                         } else if (swapped) {
    2337       17929 :                                 s = stmt_join(be, r, l, is_anti(e), swap_compare((comp_type)e->flag), 0, is_semantics(e), false);
    2338             :                         } else {
    2339       46841 :                                 s = stmt_join(be, l, r, is_anti(e), (comp_type)e->flag, 0, is_semantics(e), false);
    2340             :                         }
    2341             :                 } else {
    2342       72487 :                         if (r2) { /* handle all cases in stmt_uselect, reducing, non reducing, scalar etc */
    2343        5059 :                                 if (l->nrcols == 0 && ((sel && sel->nrcols > 0) || r->nrcols > 0 || r2->nrcols > 0 || reduce))
    2344          54 :                                         l = left ? stmt_const(be, bin_find_smallest_column(be, left), l) : column(be, l);
    2345        5059 :                                 s = stmt_uselect2(be, l, r, r2, (comp_type)e->flag, sel, is_anti(e), is_symmetric(e), reduce);
    2346             :                         } else {
    2347             :                                 /* value compare or select */
    2348       67428 :                                 if (!reduce || (l->nrcols == 0 && r->nrcols == 0)) {
    2349         913 :                                         sql_subfunc *f = sql_bind_func(sql, "sys", compare_func((comp_type)e->flag, is_anti(e)),
    2350             :                                                                                                    tail_type(l), tail_type(l), F_FUNC, true, true);
    2351         913 :                                         assert(f);
    2352         913 :                                         if (is_semantics(e)) {
    2353         137 :                                                 if (exp_is_null(e->l) && exp_is_null(e->r) && (e->flag == cmp_equal || e->flag == cmp_notequal)) {
    2354           4 :                                                         s = stmt_bool(be, e->flag == cmp_equal ? !is_anti(e): is_anti(e));
    2355             :                                                 } else {
    2356         133 :                                                         list *args = sa_list(sql->sa);
    2357         133 :                                                         if (args == NULL)
    2358             :                                                                 return NULL;
    2359             :                                                         /* add nil semantics bit */
    2360         133 :                                                         list_append(args, l);
    2361         133 :                                                         list_append(args, r);
    2362         133 :                                                         list_append(args, stmt_bool(be, 1));
    2363         133 :                                                         s = stmt_Nop(be, stmt_list(be, args), sel, f, NULL);
    2364             :                                                 }
    2365             :                                         } else {
    2366         776 :                                                 s = stmt_binop(be, l, r, sel, f);
    2367             :                                         }
    2368         913 :                                         if (l->cand)
    2369           0 :                                                 s->cand = l->cand;
    2370         913 :                                         if (r->cand)
    2371           0 :                                                 s->cand = r->cand;
    2372             :                                 } else {
    2373             :                                         /* this can still be a join (as relational algebra and single value subquery results still means joins */
    2374       66515 :                                         s = stmt_uselect(be, l, r, (comp_type)e->flag, sel, is_anti(e), is_semantics(e));
    2375             :                                 }
    2376             :                         }
    2377             :                 }
    2378             :          }      break;
    2379             :         default:
    2380             :                 ;
    2381             :         }
    2382             :         return s;
    2383             : }
    2384             : 
    2385             : static stmt *
    2386      518543 : stmt_col(backend *be, sql_column *c, stmt *del, int part)
    2387             : {
    2388      518543 :         stmt *sc = stmt_bat(be, c, del?del->tname:NULL, RDONLY, part);
    2389             : 
    2390      518559 :         if (isTable(c->t) && c->t->access != TABLE_READONLY &&
    2391      504722 :            (!isNew(c) || !isNew(c->t) /* alter */) &&
    2392      490145 :            (c->t->persistence == SQL_PERSIST || c->t->s) /*&& !c->t->commit_action*/) {
    2393      490145 :                 stmt *u = stmt_bat(be, c, del?del->tname:NULL, RD_UPD_ID, part);
    2394      490148 :                 assert(u);
    2395      490148 :                 sc = stmt_project_delta(be, sc, u);
    2396      490307 :                 if (c->storage_type && c->storage_type[0] == 'D') {
    2397         176 :                         stmt *v = stmt_bat(be, c, del?del->tname:NULL, RD_EXT, part);
    2398         176 :                         sc = stmt_dict(be, sc, v);
    2399      489955 :                 } else if (c->storage_type && c->storage_type[0] == 'F') {
    2400           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)));
    2401             :                 }
    2402      490131 :                 if (del)
    2403       26286 :                         sc = stmt_project(be, del, sc);
    2404       28414 :         } else if (del) { /* always handle the deletes */
    2405        7008 :                 sc = stmt_project(be, del, sc);
    2406             :         }
    2407      518545 :         return sc;
    2408             : }
    2409             : 
    2410             : static stmt *
    2411        3601 : stmt_idx(backend *be, sql_idx *i, stmt *del, int part)
    2412             : {
    2413        3601 :         stmt *sc = stmt_idxbat(be, i, del?del->tname:NULL, RDONLY, part);
    2414             : 
    2415        3601 :         if (isTable(i->t) && i->t->access != TABLE_READONLY &&
    2416        3601 :            (!isNew(i) || !isNew(i->t) /* alter */) &&
    2417        2871 :            (i->t->persistence == SQL_PERSIST || i->t->s) /*&& !i->t->commit_action*/) {
    2418        2871 :                 stmt *u = stmt_idxbat(be, i, del?del->tname:NULL, RD_UPD_ID, part);
    2419        2871 :                 sc = stmt_project_delta(be, sc, u);
    2420        2871 :                 if (del)
    2421         320 :                         sc = stmt_project(be, del, sc);
    2422         730 :         } else if (del) { /* always handle the deletes */
    2423         618 :                 sc = stmt_project(be, del, sc);
    2424             :         }
    2425        3601 :         return sc;
    2426             : }
    2427             : 
    2428             : static int
    2429           0 : stmt_set_type_param(mvc *sql, sql_subtype *type, stmt *param)
    2430             : {
    2431           0 :         if (!type || !param || param->type != st_var)
    2432             :                 return -1;
    2433             : 
    2434           0 :         if (set_type_param(sql, type, param->flag) == 0) {
    2435           0 :                 param->subtype = *type;
    2436           0 :                 return 0;
    2437             :         }
    2438             :         return -1;
    2439             : }
    2440             : 
    2441             : /* check_types tries to match the t type with the type of s if they don't
    2442             :  * match s is converted. Returns NULL on failure.
    2443             :  */
    2444             : static stmt *
    2445        5179 : check_types(backend *be, sql_subtype *t, stmt *s, check_type tpe)
    2446             : {
    2447             :         /* TODO add checking of composite types */
    2448        5179 :         mvc *sql = be->mvc;
    2449        5179 :         int c, err = 0;
    2450        5179 :         sql_subtype *fromtype = tail_type(s);
    2451             : 
    2452        5179 :         if ((!fromtype || !fromtype->type) && stmt_set_type_param(sql, t, s) == 0)
    2453             :                 return s;
    2454           0 :         if (!fromtype)
    2455           0 :                 return sql_error(sql, 02, SQLSTATE(42000) "statement has no type information");
    2456             : 
    2457        5179 :         if (fromtype && subtype_cmp(t, fromtype) != 0) {
    2458           1 :                 if (EC_INTERVAL(fromtype->type->eclass) && (t->type->eclass == EC_NUM || t->type->eclass == EC_POS) && t->digits < fromtype->digits) {
    2459             :                         err = 1; /* conversion from interval to num depends on the number of digits */
    2460             :                 } else {
    2461           1 :                         c = sql_type_convert(fromtype->type->eclass, t->type->eclass);
    2462           1 :                         if (!c || (c == 2 && tpe == type_set) || (c == 3 && tpe != type_cast)) {
    2463             :                                 err = 1;
    2464             :                         } else {
    2465           1 :                                 s = stmt_convert(be, s, NULL, fromtype, t);
    2466             :                         }
    2467             :                 }
    2468             :         }
    2469           1 :         if (err) {
    2470           0 :                 assert(!fromtype->type->composite && !t->type->composite);
    2471           0 :                 stmt *res = sql_error(sql, 10, SQLSTATE(42000) "types %s(%u,%u) (%s) and %s(%u,%u) (%s) are not equal",
    2472             :                         fromtype->type->base.name,
    2473             :                         fromtype->digits,
    2474             :                         fromtype->scale,
    2475             :                         fromtype->type->d.impl,
    2476             :                         t->type->base.name,
    2477             :                         t->digits,
    2478             :                         t->scale,
    2479             :                         t->type->d.impl
    2480             :                 );
    2481           0 :                 return res;
    2482             :         }
    2483             :         return s;
    2484             : }
    2485             : 
    2486             : static stmt *
    2487        6096 : sql_Nop_(backend *be, const char *fname, stmt *a1, stmt *a2, stmt *a3, stmt *a4)
    2488             : {
    2489        6096 :         mvc *sql = be->mvc;
    2490        6096 :         list *sl = sa_list(sql->sa);
    2491        6096 :         list *tl = sa_list(sql->sa);
    2492        6096 :         sql_subfunc *f = NULL;
    2493             : 
    2494        6096 :         if (sl == NULL || tl == NULL)
    2495             :                 return NULL;
    2496        6096 :         list_append(sl, a1);
    2497        6096 :         list_append(tl, tail_type(a1));
    2498        6096 :         list_append(sl, a2);
    2499        6096 :         list_append(tl, tail_type(a2));
    2500        6096 :         list_append(sl, a3);
    2501        6096 :         list_append(tl, tail_type(a3));
    2502        6096 :         if (a4) {
    2503           0 :                 list_append(sl, a4);
    2504           0 :                 list_append(tl, tail_type(a4));
    2505             :         }
    2506             : 
    2507        6096 :         if ((f = sql_bind_func_(sql, "sys", fname, tl, F_FUNC, true, true, false)))
    2508        6096 :                 return stmt_Nop(be, stmt_list(be, sl), NULL, f, NULL);
    2509           0 :         return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) "SELECT: no such operator '%s'", fname);
    2510             : }
    2511             : 
    2512             : static stmt *
    2513          10 : parse_value(backend *be, sql_schema *s, char *query, sql_subtype *tpe, char emode)
    2514             : {
    2515          10 :         sql_exp *e = NULL;
    2516             : 
    2517          10 :         if (!(e = rel_parse_val(be->mvc, s, query, tpe, emode, NULL)))
    2518             :                 return NULL;
    2519          10 :         return exp_bin(be, e, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    2520             : }
    2521             : 
    2522             : static stmt *
    2523        1212 : rel2bin_sql_table(backend *be, sql_table *t, list *aliases)
    2524             : {
    2525        1212 :         mvc *sql = be->mvc;
    2526        1212 :         list *l = sa_list(sql->sa);
    2527        1212 :         node *n;
    2528        1212 :         stmt *dels = stmt_tid(be, t, 0);
    2529             : 
    2530        1212 :         if (l == NULL || dels == NULL)
    2531             :                 return NULL;
    2532        1212 :         if (aliases) {
    2533       20486 :                 for (n = aliases->h; n; n = n->next) {
    2534       19274 :                         sql_exp *e = n->data;
    2535       19274 :                         if (e->type != e_column)
    2536         108 :                                 continue;
    2537       19166 :                         assert(e->type == e_column);
    2538       19166 :                         char *name = e->r;
    2539       19166 :                         if (name[0] == '%') {
    2540        1206 :                                 if (strcmp(name, TID)==0) {
    2541             :                                         /* tid function  sql.tid(t) */
    2542             : 
    2543        1206 :                                         stmt *sc = dels?dels:stmt_tid(be, t, 0);
    2544        1206 :                                         sc = stmt_alias(be, sc, e->alias.label, sc->tname, TID);
    2545        1206 :                                         list_append(l, sc);
    2546             :                                 } else {
    2547           0 :                                         node *m = ol_find_name(t->idxs, name+1);
    2548           0 :                                         if (!m)
    2549           0 :                                                 assert(0);
    2550           0 :                                         sql_idx *i = m->data;
    2551           0 :                                         stmt *sc = stmt_idx(be, i, dels, dels->partition);
    2552             : 
    2553             :                                         /* index names are prefixed, to make them independent */
    2554           0 :                                         sc = stmt_alias(be, sc, e->alias.label, sc->tname, sa_strconcat(sql->sa, "%", i->base.name));
    2555           0 :                                         list_append(l, sc);
    2556             :                                 }
    2557             :                         } else {
    2558       17960 :                                 node *m = ol_find_name(t->columns, name);
    2559       17960 :                                 if (!m)
    2560           0 :                                         assert(0);
    2561       17960 :                                 sql_column *c = m->data;
    2562       17960 :                                 stmt *sc = stmt_col(be, c, dels, dels->partition);
    2563       17960 :                                 sc = stmt_alias(be, sc, e->alias.label, exp_relname(e), exp_name(e));
    2564       17960 :                                 list_append(l, sc);
    2565             :                         }
    2566             :                 }
    2567             :         } else {
    2568           0 :                 assert(0);
    2569             :                 sql_exp *e = NULL;
    2570             :                 for (n = ol_first_node(t->columns); n; n = n->next) {
    2571             :                         sql_column *c = n->data;
    2572             :                         stmt *sc = stmt_col(be, c, dels, dels->partition);
    2573             : 
    2574             :                         list_append(l, sc);
    2575             :                 }
    2576             :                 /* TID column */
    2577             :                 if (ol_first_node(t->columns)) {
    2578             :                         /* tid function  sql.tid(t) */
    2579             : 
    2580             :                         stmt *sc = dels?dels:stmt_tid(be, t, 0);
    2581             :                         sc = stmt_alias(be, sc, e->alias.label, sc->tname, TID);
    2582             :                         list_append(l, sc);
    2583             :                 }
    2584             :                 if (t->idxs) {
    2585             :                         for (n = ol_first_node(t->idxs); n; n = n->next) {
    2586             :                                 sql_idx *i = n->data;
    2587             :                                 stmt *sc = stmt_idx(be, i, dels, dels->partition);
    2588             : 
    2589             :                                 /* index names are prefixed, to make them independent */
    2590             :                                 sc = stmt_alias(be, sc, e->alias.label, sc->tname, sa_strconcat(sql->sa, "%", i->base.name));
    2591             :                                 list_append(l, sc);
    2592             :                         }
    2593             :                 }
    2594             :         }
    2595        1212 :         return stmt_list(be, l);
    2596             : }
    2597             : 
    2598             : static node *
    2599      485738 : find_next_sql_column(sql_table *t, node *n, const char *name)
    2600             : {
    2601      485738 :         if (!n)
    2602      147928 :                 n = t->columns->l->h;
    2603      939383 :         for(; n; n = n->next) {
    2604      939393 :                 sql_column *c = n->data;
    2605      939393 :                 if (strcmp(c->base.name, name) == 0)
    2606             :                         break;
    2607             :         }
    2608      485738 :         return n;
    2609             : }
    2610             : 
    2611             : static stmt *
    2612         139 : rel2bin_subtable(backend *be, sql_table *t, stmt *dels, sql_column *c, node *cn, list *exps)
    2613             : {
    2614         139 :         mvc *sql = be->mvc;
    2615         139 :         list *l = sa_list(sql->sa);
    2616         139 :         stmt *col = NULL;
    2617             : 
    2618         139 :         if (c->type.multiset) {
    2619          58 :                 t = mvc_bind_table(sql, c->t->s, c->storage_type);
    2620          58 :                 if (!t)
    2621             :                         return NULL;
    2622          58 :                 dels = stmt_tid(be, t, false);
    2623          58 :                 cn = NULL;
    2624             :         }
    2625         518 :         for (node *en = exps->h; en; en = en->next) {
    2626         379 :                 sql_exp *exp = en->data;
    2627         379 :                 sql_alias *rname = exp_relname(exp)?exp_relname(exp):exp->l;
    2628         379 :                 const char *oname = exp->r;
    2629         379 :                 stmt *s = NULL;
    2630             : 
    2631         379 :                 assert(!is_func(exp->type));
    2632         379 :                 if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    2633             :                         /* tid function  sql.tid(t) */
    2634             : 
    2635           0 :                         if (col)
    2636             :                                 s = stmt_mirror(be, col);
    2637             :                         else {
    2638           0 :                                 s = dels?dels:stmt_tid(be, t, 0);
    2639             :                                 dels = NULL;
    2640             :                         }
    2641         379 :                 } else if (oname[0] == '%') {
    2642           0 :                         sql_idx *i = find_sql_idx(t, oname+1);
    2643             : 
    2644             :                         /* do not include empty indices in the plan */
    2645           0 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
    2646           0 :                                 continue;
    2647           0 :                         s = stmt_idx(be, i, dels, dels->partition);
    2648             :                 } else {
    2649         379 :                         cn = find_next_sql_column(t, cn, oname);
    2650         379 :                         assert(cn);
    2651         379 :                         sql_column *c = cn->data;
    2652         379 :                         if (exp->f && (c->type.multiset || c->type.type->composite)) {
    2653          72 :                                 s = rel2bin_subtable(be, t, dels, c, cn, exp->f);
    2654          72 :                                 if (!s)
    2655             :                                         return s;
    2656          72 :                                 s->nested = true;
    2657          72 :                                 if (s && s->type == st_list && c->type.multiset) { /* keep rowid at the end */
    2658          29 :                                         stmt *ls = s->op4.lval->t->data;
    2659          29 :                                         stmt *ns = stmt_col(be, c, dels, dels->partition);
    2660          29 :                                         ns->subtype = ls->subtype;
    2661          29 :                                         list_append(s->op4.lval, ns);
    2662          29 :                                         s->nr = ns->nr;
    2663          29 :                                         s->subtype = *exp_subtype(exp);
    2664          29 :                                         s->multiset = s->subtype.multiset;
    2665          43 :                                 } else if (s && s->type == st_list && c->type.type->composite) {
    2666          43 :                                         s->subtype = *exp_subtype(exp);
    2667             :                                 }
    2668             :                         } else {
    2669         307 :                                 s = stmt_col(be, c, dels, dels->partition);
    2670             :                         }
    2671             :                 }
    2672         379 :                 s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
    2673         379 :                 list_append(l, s);
    2674             :         }
    2675         139 :         return stmt_list(be, l);
    2676             : }
    2677             : 
    2678             : static stmt *
    2679      148845 : rel2bin_basetable(backend *be, sql_rel *rel)
    2680             : {
    2681      148845 :         mvc *sql = be->mvc;
    2682      148845 :         sql_table *t = rel->l;
    2683      148845 :         sql_column *fcol = NULL;
    2684      148845 :         sql_idx *fi = NULL;
    2685      148845 :         list *l = sa_list(sql->sa);
    2686      148850 :         bool complex = (t->multiset || t->composite);
    2687      148850 :         stmt *dels = stmt_tid(be, t, !complex?rel->flag == REL_PARTITION:false), *col = NULL;
    2688      148856 :         node *en, *cn = NULL;
    2689             : 
    2690      148856 :         if (l == NULL || dels == NULL)
    2691             :                 return NULL;
    2692             :         /* add aliases */
    2693      148856 :         assert(rel->exps);
    2694      297736 :         for (en = rel->exps->h; en && !col; en = en->next) {
    2695      148884 :                 sql_exp *exp = en->data;
    2696      148884 :                 const char *oname = exp->r;
    2697             : 
    2698      148884 :                 if (is_func(exp->type) || (oname[0] == '%' && strcmp(oname, TID) == 0))
    2699         933 :                         continue;
    2700      147951 :                 if (oname[0] == '%') {
    2701          61 :                         sql_idx *i = find_sql_idx(t, oname+1);
    2702             : 
    2703             :                         /* do not include empty indices in the plan */
    2704          61 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
    2705           0 :                                 continue;
    2706          61 :                         fi = i;
    2707         122 :                         col = stmt_idx(be, i, complex?dels:NULL, dels->partition);
    2708             :                 } else {
    2709      147890 :                         sql_column *c = find_sql_column(t, oname);
    2710             : 
    2711      147890 :                         if (!c || c->type.multiset || c->type.type->composite)
    2712          45 :                                 continue;
    2713      147845 :                         fcol = c;
    2714      295651 :                         col = stmt_col(be, c, complex?dels:NULL, dels->partition);
    2715             :                 }
    2716             :         }
    2717      651929 :         for (en = rel->exps->h; en; en = en->next) {
    2718      503074 :                 sql_exp *exp = en->data;
    2719      503074 :                 sql_alias *rname = exp_relname(exp)?exp_relname(exp):exp->l;
    2720      503074 :                 const char *oname = exp->r;
    2721      503074 :                 stmt *s = NULL;
    2722             : 
    2723      503074 :                 assert(!is_func(exp->type));
    2724      503074 :                 if (oname[0] == '%' && strcmp(oname, TID) == 0) {
    2725             :                         /* tid function  sql.tid(t) */
    2726             : 
    2727       15054 :                         if (col)
    2728       14134 :                                 s = stmt_mirror(be, col);
    2729             :                         else {
    2730         920 :                                 s = dels?dels:stmt_tid(be, t, 0);
    2731             :                                 dels = NULL;
    2732             :                         }
    2733      488020 :                 } else if (oname[0] == '%') {
    2734        2663 :                         sql_idx *i = find_sql_idx(t, oname+1);
    2735             : 
    2736             :                         /* do not include empty indices in the plan */
    2737        2663 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
    2738           0 :                                 continue;
    2739        2663 :                         s = (i == fi) ? col : stmt_idx(be, i, complex?dels:NULL, dels->partition);
    2740             :                 } else {
    2741      485357 :                         cn = find_next_sql_column(t, cn, oname);
    2742      485373 :                         assert(cn);
    2743      485373 :                         sql_column *c = cn->data;
    2744      485373 :                         if (exp->f && (c->type.multiset || c->type.type->composite)) {
    2745          67 :                                 s = rel2bin_subtable(be, t, dels, c, cn, exp->f);
    2746          67 :                                 if (!s)
    2747             :                                         return s;
    2748          67 :                                 s->nested = true;
    2749          67 :                                 if (s && s->type == st_list && c->type.multiset) { /* keep rowid at the end */
    2750          29 :                                         stmt *ls = s->op4.lval->t->data;
    2751          58 :                                         stmt *ns = (c == fcol) ? col : stmt_col(be, c, complex?dels:NULL, dels->partition);
    2752          29 :                                         ns->subtype = ls->subtype;
    2753          29 :                                         list_append(s->op4.lval, ns);
    2754          29 :                                         s->nr = ns->nr;
    2755          29 :                                         s->subtype = *exp_subtype(exp);
    2756          29 :                                         s->multiset = s->subtype.multiset;
    2757          38 :                                 } else if (s && s->type == st_list && c->type.type->composite) {
    2758          38 :                                         s->subtype = *exp_subtype(exp);
    2759             :                                 }
    2760             :                         } else {
    2761      485314 :                                 s = (c == fcol) ? col : stmt_col(be, c, complex?dels:NULL, dels->partition);
    2762             :                         }
    2763             :                 }
    2764      503082 :                 s = stmt_alias(be, s, exp->alias.label, rname, exp_name(exp));
    2765      503097 :                 list_append(l, s);
    2766             :         }
    2767      148855 :         stmt *res = stmt_list(be, l);
    2768      148855 :         if (res && !complex && dels)
    2769      147867 :                 res->cand = dels;
    2770             :         return res;
    2771             : }
    2772             : 
    2773             : static int
    2774          21 : alias_cmp(stmt *s, const char *nme)
    2775             : {
    2776          21 :         return strcmp(s->cname, nme);
    2777             : }
    2778             : 
    2779             : static list* exps2bin_args(backend *be, list *exps, list *args);
    2780             : 
    2781             : static list *
    2782        1946 : exp2bin_args(backend *be, sql_exp *e, list *args)
    2783             : {
    2784        2017 :         mvc *sql = be->mvc;
    2785             : 
    2786        2017 :         if (mvc_highwater(sql))
    2787           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    2788             : 
    2789        2017 :         if (!e || !args)
    2790             :                 return args;
    2791        2017 :         switch(e->type){
    2792             :         case e_column:
    2793             :         case e_psm:
    2794             :                 return args;
    2795          79 :         case e_cmp:
    2796          79 :                 if (e->flag == cmp_or || e->flag == cmp_filter) {
    2797           7 :                         args = exps2bin_args(be, e->l, args);
    2798           7 :                         args = exps2bin_args(be, e->r, args);
    2799          72 :                 } else if (e->flag == cmp_in || e->flag == cmp_notin) {
    2800           2 :                         args = exp2bin_args(be, e->l, args);
    2801           2 :                         args = exps2bin_args(be, e->r, args);
    2802             :                 } else {
    2803          70 :                         args = exp2bin_args(be, e->l, args);
    2804          70 :                         args = exp2bin_args(be, e->r, args);
    2805          70 :                         if (e->f)
    2806             :                                 args = exp2bin_args(be, e->f, args);
    2807             :                 }
    2808             :                 return args;
    2809          54 :         case e_convert:
    2810          54 :                 if (e->l)
    2811             :                         return exp2bin_args(be, e->l, args);
    2812             :                 break;
    2813         150 :         case e_aggr:
    2814             :         case e_func:
    2815         150 :                 if (e->l)
    2816         117 :                         return exps2bin_args(be, e->l, args);
    2817             :                 break;
    2818         337 :         case e_atom:
    2819         337 :                 if (e->l) {
    2820             :                         return args;
    2821          22 :                 } else if (e->f) {
    2822           0 :                         return exps2bin_args(be, e->f, args);
    2823          22 :                 } else if (e->r) {
    2824          22 :                         sql_var_name *vname = (sql_var_name*) e->r;
    2825          22 :                         const char *nme = sql_escape_ident(sql->sa, vname->name);
    2826          22 :                         char *buf = NULL;
    2827             : 
    2828          22 :                         if (vname->sname) { /* Global variable */
    2829           3 :                                 const char *sname = sql_escape_ident(sql->sa, vname->sname);
    2830           6 :                                 if (!nme || !sname || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(sname) + strlen(nme) + 6)))
    2831           0 :                                         return NULL;
    2832           3 :                                 stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(buf, "0\""), sname), "\"\""), nme), "\""); /* escape variable name */
    2833             :                         } else { /* Parameter or local variable */
    2834          19 :                                 char levelstr[16];
    2835          19 :                                 snprintf(levelstr, sizeof(levelstr), "%u", e->flag);
    2836          38 :                                 if (!nme || !(buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(nme) + 3)))
    2837           0 :                                         return NULL;
    2838          19 :                                 stpcpy(stpcpy(stpcpy(stpcpy(buf, levelstr), "\""), nme), "\""); /* escape variable name */
    2839             :                         }
    2840          22 :                         if (!list_find(args, buf, (fcmp)&alias_cmp)) {
    2841          22 :                                 stmt *s = stmt_var(be, vname->sname?a_create(be->mvc->sa, vname->sname):NULL, vname->name, &e->tpe, 0, e->flag);
    2842             : 
    2843          22 :                                 if (!e->alias.label)
    2844          18 :                                         exp_label(be->mvc->sa, e, ++be->mvc->label);
    2845          22 :                                 s = stmt_alias(be, s, e->alias.label, NULL, sa_strdup(sql->sa, buf));
    2846          22 :                                 list_append(args, s);
    2847             :                         }
    2848             :                 }
    2849             :         }
    2850             :         return args;
    2851             : }
    2852             : 
    2853             : static list *
    2854         417 : exps2bin_args(backend *be, list *exps, list *args)
    2855             : {
    2856         417 :         node *n;
    2857             : 
    2858         417 :         if (!exps)
    2859             :                 return args;
    2860        2221 :         for (n = exps->h; n; n = n->next)
    2861        1804 :                 args = exp2bin_args(be, n->data, args);
    2862             :         return args;
    2863             : }
    2864             : 
    2865             : static list *
    2866         197 : rel2bin_args(backend *be, sql_rel *rel, list *args)
    2867             : {
    2868         479 :         if (mvc_highwater(be->mvc))
    2869           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    2870             : 
    2871         479 :         if (!rel || !args)
    2872             :                 return args;
    2873         479 :         switch(rel->op) {
    2874             :         case op_basetable:
    2875             :         case op_table:
    2876             :                 break;
    2877          11 :         case op_join:
    2878             :         case op_left:
    2879             :         case op_right:
    2880             :         case op_full:
    2881             : 
    2882             :         case op_semi:
    2883             :         case op_anti:
    2884             : 
    2885             :         case op_union:
    2886             :         case op_inter:
    2887             :         case op_except:
    2888             :         case op_merge:
    2889          11 :                 args = rel2bin_args(be, rel->l, args);
    2890          11 :                 args = rel2bin_args(be, rel->r, args);
    2891          11 :                 break;
    2892           0 :         case op_munion:
    2893           0 :                 if (rel->l) {
    2894           0 :                         for (node* n = ((list*)rel->l)->h; n; n = n->next) {
    2895           0 :                                 args = rel2bin_args(be, n->data, args);
    2896             :                         }
    2897             :                 }
    2898             :                 break;
    2899          49 :         case op_groupby:
    2900          49 :                 if (rel->r)
    2901          13 :                         args = exps2bin_args(be, rel->r, args);
    2902             :                 /* fall through */
    2903             :         case op_project:
    2904             :         case op_select:
    2905             :         case op_topn:
    2906             :         case op_sample:
    2907         271 :                 if (rel->exps)
    2908         271 :                         args = exps2bin_args(be, rel->exps, args);
    2909         271 :                 args = rel2bin_args(be, rel->l, args);
    2910         271 :                 break;
    2911           0 :         case op_ddl:
    2912           0 :                 args = rel2bin_args(be, rel->l, args);
    2913           0 :                 if (rel->r)
    2914             :                         args = rel2bin_args(be, rel->r, args);
    2915             :                 break;
    2916           0 :         case op_insert:
    2917             :         case op_update:
    2918             :         case op_delete:
    2919             :         case op_truncate:
    2920           0 :                 args = rel2bin_args(be, rel->r, args);
    2921           0 :                 break;
    2922             :         }
    2923             :         return args;
    2924             : }
    2925             : 
    2926             : typedef struct trigger_input {
    2927             :         sql_table *t;
    2928             :         stmt *tids;
    2929             :         stmt **updates;
    2930             :         int type; /* insert 1, update 2, delete 3, truncate 4 */
    2931             :         const char *on;
    2932             :         const char *nn;
    2933             : } trigger_input;
    2934             : 
    2935             : static stmt *
    2936        3193 : rel2bin_table(backend *be, sql_rel *rel, list *refs)
    2937             : {
    2938        3193 :         mvc *sql = be->mvc;
    2939        3193 :         list *l;
    2940        3193 :         stmt *sub = NULL, *osub = NULL;
    2941        3193 :         node *en, *n;
    2942        3193 :         sql_exp *op = rel->r;
    2943             : 
    2944        3193 :         if (rel->flag == TRIGGER_WRAPPER) {
    2945          11 :                 trigger_input *ti = rel->l;
    2946          11 :                 l = sa_list(sql->sa);
    2947          11 :                 if (l == NULL)
    2948             :                         return NULL;
    2949             : 
    2950          20 :                 assert(list_length(rel->exps) == ((ti->type == 2)?2:1) * ol_length(ti->t->columns));
    2951          11 :                 sql_alias *oname = a_create(be->mvc->sa, ti->on);
    2952          11 :                 sql_alias *nname = a_create(be->mvc->sa, ti->nn);
    2953          30 :                 for (n = ol_first_node(ti->t->columns), en = rel->exps->h; n && en; n = n->next, en = en->next) {
    2954          19 :                         sql_column *c = n->data;
    2955          19 :                         sql_exp *e = en->data;
    2956             : 
    2957          19 :                         if (ti->type == 2) { /* updates */
    2958           4 :                                 stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
    2959           4 :                                 append(l, stmt_alias(be, s, e->alias.label, oname, c->base.name));
    2960           4 :                                 en = en->next;
    2961           4 :                                 e = en->data;
    2962             :                         }
    2963          19 :                         if (ti->updates && ti->updates[c->colnr]) {
    2964          17 :                                 append(l, stmt_alias(be, ti->updates[c->colnr], e->alias.label, nname, c->base.name));
    2965             :                         } else {
    2966           2 :                                 stmt *s = stmt_col(be, c, ti->tids, ti->tids->partition);
    2967           2 :                                 append(l, stmt_alias(be, s, e->alias.label, nname, c->base.name));
    2968           2 :                                 assert(ti->type != 1);
    2969             :                         }
    2970             :                 }
    2971          11 :                 sub = stmt_list(be, l);
    2972          11 :                 return sub;
    2973        3182 :         } else if (op) {
    2974        2996 :                 int i;
    2975        2996 :                 sql_subfunc *f = op->f;
    2976        2996 :                 stmt *psub = NULL;
    2977        2996 :                 list *ops = NULL;
    2978        2996 :                 stmt *ids = NULL;
    2979             : 
    2980        2996 :                 if (rel->l) { /* first construct the sub relation */
    2981          75 :                         sql_rel *l = rel->l;
    2982          75 :                         if (l->op == op_ddl) {
    2983           0 :                                 sql_table *t = rel_ddl_table_get(l);
    2984             : 
    2985           0 :                                 if (t)
    2986           0 :                                         sub = rel2bin_sql_table(be, t, NULL);
    2987             :                         } else {
    2988          75 :                                 sub = subrel_bin(be, rel->l, refs);
    2989             :                         }
    2990          75 :                         sub = subrel_project(be, sub, refs, rel->l);
    2991          75 :                         if (!sub)
    2992             :                                 return NULL;
    2993             :                 }
    2994             : 
    2995        2996 :                 assert(f);
    2996        2996 :                 if (f->func->res && list_length(f->func->res) + 1 == list_length(rel->exps) && !f->func->varres) {
    2997             :                         /* add inputs in correct order ie loop through args of f and pass column */
    2998          23 :                         list *exps = op->l;
    2999          23 :                         ops = sa_list(be->mvc->sa);
    3000          23 :                         if (exps) {
    3001          83 :                                 for (node *en = exps->h; en; en = en->next) {
    3002          60 :                                         sql_exp *e = en->data;
    3003             : 
    3004             :                                         /* find column */
    3005          60 :                                         stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3006          60 :                                         if (!s)
    3007             :                                                 return NULL;
    3008          60 :                                         if (en->next)
    3009          37 :                                                 append(ops, s);
    3010             :                                         else /* last added exp is the ids (todo use name base lookup !!) */
    3011             :                                                 ids = s;
    3012             :                                 }
    3013             :                         }
    3014             :                 } else {
    3015        2973 :                         psub = exp_bin(be, op, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0); /* table function */
    3016        2973 :                         if (!psub)
    3017             :                                 return NULL;
    3018             :                 }
    3019        2996 :                 l = sa_list(sql->sa);
    3020        2996 :                 if (l == NULL)
    3021             :                         return NULL;
    3022        2996 :                 if (f->func->res) {
    3023        2971 :                         if (f->func->varres) {
    3024       12116 :                                 for (i=0, en = rel->exps->h, n = f->res->h; en; en = en->next, n = n->next, i++) {
    3025       10822 :                                         sql_exp *exp = en->data;
    3026       10822 :                                         sql_subtype *st = n->data;
    3027       10822 :                                         sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
    3028       10822 :                                         stmt *s = stmt_rs_column(be, psub, i, st);
    3029             : 
    3030       10822 :                                         s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
    3031       10822 :                                         list_append(l, s);
    3032             :                                 }
    3033             :                         } else {
    3034        1677 :                                 node *m = rel->exps->h;
    3035        1677 :                                 int i = 0;
    3036             : 
    3037             :                                 /* correlated table returning function */
    3038        1677 :                                 if (list_length(f->func->res) + 1 == list_length(rel->exps)) {
    3039             :                                         /* use a simple nested loop solution for this case, ie
    3040             :                                          * output a table of (input) row-ids, the output of the table producing function
    3041             :                                          */
    3042             :                                         /* make sure the input for sql.unionfunc are bats */
    3043          23 :                                         if (ids)
    3044          23 :                                                 ids = column(be, ids);
    3045          23 :                                         if (ops)
    3046          60 :                                                 for (node *en = ops->h; en; en = en->next)
    3047          37 :                                                         en->data = column(be, (stmt *) en->data);
    3048             : 
    3049          23 :                                         int narg = 3 + list_length(rel->exps);
    3050          23 :                                         if (ops)
    3051          23 :                                                 narg += list_length(ops);
    3052          23 :                                         InstrPtr q = newStmtArgs(be->mb, sqlRef, "unionfunc", narg);
    3053          23 :                                         if (q == NULL) {
    3054           0 :                                                 if (be->mvc->sa->eb.enabled)
    3055           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);
    3056           0 :                                                 return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    3057             :                                         }
    3058             :                                         /* Generate output rowid column and output of function f */
    3059          69 :                                         for (i=0; m; m = m->next, i++) {
    3060          46 :                                                 sql_exp *e = m->data;
    3061          46 :                                                 int type = exp_subtype(e)->type->localtype;
    3062             : 
    3063          46 :                                                 type = newBatType(type);
    3064          46 :                                                 if (i)
    3065          23 :                                                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, type));
    3066             :                                                 else
    3067          23 :                                                         getArg(q, 0) = newTmpVariable(be->mb, type);
    3068             :                                         }
    3069          23 :                                         if (backend_create_subfunc(be, f, ops) < 0) {
    3070           0 :                                                 freeInstruction(q);
    3071           0 :                                                 return NULL;
    3072             :                                         }
    3073          23 :                                         str mod = sql_func_mod(f->func);
    3074          23 :                                         str fcn = backend_function_imp(be, f->func);
    3075          23 :                                         q = pushStr(be->mb, q, mod);
    3076          23 :                                         q = pushStr(be->mb, q, fcn);
    3077          23 :                                         psub = stmt_direct_func(be, q);
    3078          23 :                                         if (psub == NULL) {
    3079           0 :                                                 freeInstruction(q);
    3080           0 :                                                 return NULL;
    3081             :                                         }
    3082             : 
    3083          23 :                                         if (ids) /* push input rowids column */
    3084          23 :                                                 q = pushArgument(be->mb, q, ids->nr);
    3085             : 
    3086             :                                         /* add inputs in correct order ie loop through args of f and pass column */
    3087          23 :                                         if (ops) {
    3088          60 :                                                 for (node *en = ops->h; en; en = en->next) {
    3089          37 :                                                         stmt *op = en->data;
    3090             : 
    3091          37 :                                                         q = pushArgument(be->mb, q, op->nr);
    3092             :                                                 }
    3093             :                                         }
    3094          23 :                                         pushInstruction(be->mb, q);
    3095             : 
    3096             :                                         /* name output of dependent columns, output of function is handled the same as without correlation */
    3097          23 :                                         int len = list_length(rel->exps)-list_length(f->func->res);
    3098          23 :                                         assert(len== 1);
    3099          46 :                                         for (i=0, m=rel->exps->h; m && i<len; m = m->next, i++) {
    3100          23 :                                                 sql_exp *exp = m->data;
    3101          23 :                                                 stmt *s = stmt_rs_column(be, psub, i, exp_subtype(exp));
    3102             : 
    3103          23 :                                                 s = stmt_alias(be, s, exp->alias.label, exp->l, exp->r);
    3104          23 :                                                 list_append(l, s);
    3105             :                                         }
    3106             :                                 }
    3107       15460 :                                 for (n = f->func->res->h; n && m; n = n->next, m = m->next, i++) {
    3108       13783 :                                         sql_arg *a = n->data;
    3109       13783 :                                         sql_exp *exp = m->data;
    3110       13783 :                                         stmt *s = stmt_rs_column(be, psub, i, &a->type);
    3111       13783 :                                         sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp_find_rel_name(op);
    3112             : 
    3113       13783 :                                         s = stmt_alias(be, s, exp->alias.label, rnme, a->name);
    3114       13783 :                                         list_append(l, s);
    3115             :                                 }
    3116             :                         }
    3117             :                 }
    3118             :                 //assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols));
    3119        2996 :                 sub = stmt_list(be, l);
    3120        2996 :                 return sub;
    3121         186 :         } else if (rel->l) { /* handle sub query via function */
    3122         186 :                 int i;
    3123         186 :                 char name[16], *nme;
    3124             : 
    3125         186 :                 nme = number2name(name, sizeof(name), ++be->remote);
    3126             : 
    3127         186 :                 l = rel2bin_args(be, rel->l, sa_list(sql->sa));
    3128         186 :                 if (!l)
    3129           0 :                         return NULL;
    3130         186 :                 sub = stmt_list(be, l);
    3131         186 :                 if (!(sub = stmt_func(be, sub, sa_strdup(sql->sa, nme), rel->l, 0)))
    3132             :                         return NULL;
    3133         186 :                 rel->l = sub->op4.rel; /* rel->l may get rewritten */
    3134         186 :                 l = sa_list(sql->sa);
    3135        1593 :                 for (i = 0, n = rel->exps->h; n; n = n->next, i++) {
    3136        1407 :                         sql_exp *c = n->data;
    3137        1407 :                         stmt *s = stmt_rs_column(be, sub, i, exp_subtype(c));
    3138        1407 :                         const char *nme = exp_name(c);
    3139        1407 :                         sql_alias *rnme = exp_relname(c);
    3140             : 
    3141        1407 :                         s = stmt_alias(be, s, c->alias.label, rnme, nme);
    3142        1407 :                         list_append(l, s);
    3143             :                 }
    3144         186 :                 sub = stmt_list(be, l);
    3145             :         }
    3146         186 :         if (!sub) {
    3147           0 :                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3148             :                 return NULL;
    3149             :         }
    3150         186 :         l = sa_list(sql->sa);
    3151         186 :         if (l == NULL)
    3152             :                 return NULL;
    3153        1593 :         for (en = rel->exps->h; en; en = en->next) {
    3154        1407 :                 sql_exp *exp = en->data;
    3155        1407 :                 sql_alias *rnme = exp_relname(exp)?exp_relname(exp):exp->l;
    3156        1407 :                 stmt *s = bin_find_column_nid(be, sub, exp->nid);
    3157             : 
    3158        1407 :                 if (!s) {
    3159           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3160             :                         return NULL;
    3161             :                 }
    3162        1407 :                 if (sub && sub->nrcols >= 1 && s->nrcols == 0)
    3163           0 :                         s = stmt_const(be, bin_find_smallest_column(be, sub), s);
    3164        1407 :                 s = stmt_alias(be, s, exp->alias.label, rnme, exp_name(exp));
    3165        1407 :                 list_append(l, s);
    3166             :         }
    3167         186 :         if (osub && osub->nrcols)
    3168             :                 list_merge(l, osub->op4.lval, NULL);
    3169         186 :         sub = stmt_list(be, l);
    3170         186 :         return sub;
    3171             : }
    3172             : 
    3173             : static stmt *
    3174          90 : rel2bin_hash_lookup(backend *be, sql_rel *rel, stmt *left, stmt *right, sql_idx *i, node *en)
    3175             : {
    3176          90 :         mvc *sql = be->mvc;
    3177          90 :         node *n;
    3178          90 :         sql_subtype *it = sql_bind_localtype("int");
    3179          90 :         sql_subtype *lng = sql_bind_localtype("lng");
    3180          90 :         stmt *h = NULL;
    3181          90 :         stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1));
    3182          90 :         sql_exp *e = en->data;
    3183          90 :         sql_exp *l = e->l;
    3184          90 :         stmt *idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    3185          90 :         int swap_exp = 0, swap_rel = 0, semantics = 0;
    3186             : 
    3187          90 :         if (!idx) {
    3188          49 :                 swap_exp = 1;
    3189          49 :                 l = e->r;
    3190          49 :                 idx = bin_find_column(be, left, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    3191             :         }
    3192          90 :         if (!idx && right) {
    3193          47 :                 swap_exp = 0;
    3194          47 :                 swap_rel = 1;
    3195          47 :                 l = e->l;
    3196          47 :                 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    3197             :         }
    3198          90 :         if (!idx && right) {
    3199           0 :                 swap_exp = 1;
    3200           0 :                 swap_rel = 1;
    3201           0 :                 l = e->r;
    3202           0 :                 idx = bin_find_column(be, right, l->l, sa_strconcat(sql->sa, "%", i->base.name));
    3203             :         }
    3204          90 :         if (!idx)
    3205             :                 return NULL;
    3206             :         /* should be in key order! */
    3207         314 :         for (en = rel->exps->h, n = i->columns->h; en && n; en = en->next, n = n->next) {
    3208         226 :                 sql_exp *e = en->data;
    3209         226 :                 stmt *s = NULL;
    3210             : 
    3211         226 :                 if (e->type == e_cmp && e->flag == cmp_equal) {
    3212         226 :                         sql_exp *ee = (swap_exp)?e->l:e->r;
    3213         226 :                         if (swap_rel)
    3214         109 :                                 s = exp_bin(be, ee, left, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3215             :                         else
    3216         117 :                                 s = exp_bin(be, ee, right, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    3217             :                 }
    3218             : 
    3219         226 :                 if (!s)
    3220           2 :                         return NULL;
    3221         224 :                 if (h) {
    3222         136 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
    3223             : 
    3224         136 :                         h = stmt_Nop(be, stmt_list(be, list_append(list_append(
    3225             :                                 list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
    3226         136 :                         semantics = 1;
    3227             :                 } else {
    3228          88 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
    3229             : 
    3230          88 :                         h = stmt_unop(be, s, NULL, hf);
    3231             :                 }
    3232             :         }
    3233          88 :         if (n != NULL) /* need to use all cols of the index */
    3234             :                 return NULL;
    3235          87 :         if (h && h->nrcols) {
    3236          78 :                 if (!swap_rel) {
    3237          31 :                         return stmt_join(be, idx, h, 0, cmp_equal, 0, semantics, false);
    3238             :                 } else {
    3239          47 :                         return stmt_join(be, h, idx, 0, cmp_equal, 0, semantics, false);
    3240             :                 }
    3241             :         } else {
    3242           9 :                 return stmt_uselect(be, idx, h, cmp_equal, NULL, 0, semantics);
    3243             :         }
    3244             : }
    3245             : 
    3246             : static stmt *
    3247        5812 : join_hash_key(backend *be, list *l)
    3248             : {
    3249        5812 :         mvc *sql = be->mvc;
    3250        5812 :         node *m;
    3251        5812 :         sql_subtype *it, *lng;
    3252        5812 :         stmt *h = NULL;
    3253        5812 :         stmt *bits = stmt_atom_int(be, 1 + ((sizeof(lng)*8)-1)/(list_length(l)+1));
    3254             : 
    3255        5812 :         it = sql_bind_localtype("int");
    3256        5812 :         lng = sql_bind_localtype("lng");
    3257       18370 :         for (m = l->h; m; m = m->next) {
    3258       12558 :                 stmt *s = m->data;
    3259             : 
    3260       12558 :                 if (h) {
    3261        6746 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, tail_type(s));
    3262             : 
    3263        6746 :                         h = stmt_Nop(be, stmt_list(be, list_append(list_append(list_append(sa_list(sql->sa), h), bits), s)), NULL, xor, NULL);
    3264             :                 } else {
    3265        5812 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, tail_type(s));
    3266        5812 :                         h = stmt_unop(be, s, NULL, hf);
    3267             :                 }
    3268             :         }
    3269        5812 :         return h;
    3270             : }
    3271             : 
    3272             : static stmt *
    3273        5569 : releqjoin(backend *be, list *l1, list *l2, list *exps, int used_hash, int need_left, int is_semantics)
    3274             : {
    3275        5569 :         node *n1 = l1->h, *n2 = l2->h, *n3 = NULL;
    3276        5569 :         stmt *l, *r, *res;
    3277        5569 :         sql_exp *e;
    3278             : 
    3279        5569 :         if (exps)
    3280        2835 :                 n3 = exps->h;
    3281        5569 :         if (list_length(l1) <= 1) {
    3282        2333 :                 l = l1->h->data;
    3283        2333 :                 r = l2->h->data;
    3284        2333 :                 if (!is_semantics && exps) {
    3285           0 :                         e = n3->data;
    3286           0 :                         is_semantics = is_semantics(e);
    3287             :                 }
    3288        2333 :                 r =  stmt_join(be, l, r, 0, cmp_equal, need_left, is_semantics, false);
    3289        2333 :                 return r;
    3290             :         }
    3291        3236 :         if (used_hash) {
    3292         330 :                 l = n1->data;
    3293         330 :                 r = n2->data;
    3294         330 :                 n1 = n1->next;
    3295         330 :                 n2 = n2->next;
    3296         330 :                 n3 = n3?n3->next:NULL;
    3297         330 :                 res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
    3298             :         } else { /* need hash */
    3299        2906 :                 l = join_hash_key(be, l1);
    3300        2906 :                 r = join_hash_key(be, l2);
    3301        2906 :                 res = stmt_join(be, l, r, 0, cmp_equal, need_left, 1, false);
    3302             :         }
    3303        3236 :         l = stmt_result(be, res, 0);
    3304        3236 :         r = stmt_result(be, res, 1);
    3305       19547 :         for (; n1 && n2; n1 = n1->next, n2 = n2->next, n3 = n3?n3->next:NULL) {
    3306        7033 :                 int semantics = is_semantics;
    3307        7033 :                 stmt *ld = n1->data;
    3308        7033 :                 stmt *rd = n2->data;
    3309        7033 :                 stmt *le = stmt_project(be, l, ld);
    3310        7033 :                 stmt *re = stmt_project(be, r, rd);
    3311        7033 :                 stmt *cmp;
    3312             :                 /* intentional both tail_type's of le (as re sometimes is a find for bulk loading */
    3313             : 
    3314        7033 :                 if (!semantics && exps) {
    3315        6042 :                         e = n3->data;
    3316        6042 :                         semantics = is_semantics(e);
    3317             :                 }
    3318        7033 :                 cmp = stmt_uselect(be, le, re, cmp_equal, NULL, 0, semantics);
    3319        7033 :                 l = stmt_project(be, cmp, l);
    3320        7033 :                 r = stmt_project(be, cmp, r);
    3321             :         }
    3322        3236 :         res = stmt_join(be, l, r, 0, cmp_joined, 0, 0, false);
    3323        3236 :         return res;
    3324             : }
    3325             : 
    3326             : static bool
    3327       80377 : can_join_exp(sql_rel *rel, sql_exp *e, bool anti)
    3328             : {
    3329       80377 :         bool can_join = 0;
    3330             : 
    3331       80377 :         if (e->type == e_cmp) {
    3332       80257 :                 int flag = e->flag;
    3333             :                 /* check if its a select or join expression, ie use only expressions of one relation left and of the other right (than join) */
    3334       80257 :                 if (flag < cmp_filter) { /* theta and range joins */
    3335             :                         /* join or select ? */
    3336       80167 :                         sql_exp *l = e->l, *r = e->r, *f = e->f;
    3337             : 
    3338       80167 :                         if (f) {
    3339         100 :                                 int ll = rel_has_exp(rel->l, l, true) == 0;
    3340         100 :                                 int rl = rel_has_exp(rel->r, l, true) == 0;
    3341         100 :                                 int lr = rel_has_exp(rel->l, r, true) == 0;
    3342         100 :                                 int rr = rel_has_exp(rel->r, r, true) == 0;
    3343         100 :                                 int lf = rel_has_exp(rel->l, f, true) == 0;
    3344         100 :                                 int rf = rel_has_exp(rel->r, f, true) == 0;
    3345         100 :                                 int nrcr1 = 0, nrcr2 = 0, nrcl1 = 0, nrcl2 = 0;
    3346             : 
    3347         100 :                                 if ((ll && !rl &&
    3348          82 :                                    ((rr && !lr) || (nrcr1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
    3349          70 :                                    ((rf && !lf) || (nrcr2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcr1+nrcr2) <= 1) ||
    3350          31 :                                         (rl && !ll &&
    3351          16 :                                    ((lr && !rr) || (nrcl1 = r->card == CARD_ATOM && exp_is_atom(r))) &&
    3352          15 :                                    ((lf && !rf) || (nrcl2 = f->card == CARD_ATOM && exp_is_atom(f))) && (nrcl1+nrcl2) <= 1)) {
    3353             :                                         can_join = 1;
    3354             :                                 }
    3355             :                         } else {
    3356       80067 :                                 int ll = 0, lr = 0, rl = 0, rr = 0, cst = 0;
    3357       80067 :                                 if (l->card != CARD_ATOM || !exp_is_atom(l)) {
    3358       79866 :                                         ll = rel_has_exp(rel->l, l, true) == 0;
    3359       79866 :                                         rl = rel_has_exp(rel->r, l, true) == 0;
    3360         201 :                                 } else if (anti) {
    3361          15 :                                         ll = 1;
    3362          15 :                                         cst = 1;
    3363             :                                 }
    3364       80067 :                                 if (r->card != CARD_ATOM || !exp_is_atom(r)) {
    3365       79902 :                                         lr = rel_has_exp(rel->l, r, true) == 0;
    3366       79902 :                                         rr = rel_has_exp(rel->r, r, true) == 0;
    3367         165 :                                 } else if (anti) {
    3368           5 :                                         rr = cst?0:1;
    3369             :                                 }
    3370       80067 :                                 if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
    3371       79732 :                                         can_join = 1;
    3372             :                         }
    3373          90 :                 } else if (flag == cmp_filter) {
    3374          60 :                         list *l = e->l, *r = e->r;
    3375          60 :                         int ll = 0, lr = 0, rl = 0, rr = 0;
    3376             : 
    3377         120 :                         for (node *n = l->h ; n ; n = n->next) {
    3378          60 :                                 sql_exp *ee = n->data;
    3379             : 
    3380          60 :                                 if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
    3381          57 :                                         ll |= rel_has_exp(rel->l, ee, true) == 0;
    3382          57 :                                         rl |= rel_has_exp(rel->r, ee, true) == 0;
    3383             :                                 }
    3384             :                         }
    3385         203 :                         for (node *n = r->h ; n ; n = n->next) {
    3386         143 :                                 sql_exp *ee = n->data;
    3387             : 
    3388         143 :                                 if (ee->card != CARD_ATOM || !exp_is_atom(ee)) {
    3389          62 :                                         lr |= rel_has_exp(rel->l, ee, true) == 0;
    3390          62 :                                         rr |= rel_has_exp(rel->r, ee, true) == 0;
    3391             :                                 }
    3392             :                         }
    3393          60 :                         if ((ll && !lr && !rl && rr) || (!ll && lr && rl && !rr))
    3394       79732 :                                 can_join = 1;
    3395             :                 }
    3396             :         }
    3397       80377 :         return can_join;
    3398             : }
    3399             : 
    3400             : static void
    3401       66956 : split_join_exps(sql_rel *rel, list *joinable, list *not_joinable, bool anti)
    3402             : {
    3403       66956 :         if (!list_empty(rel->exps)) {
    3404      138544 :                 for (node *n = rel->exps->h; n; n = n->next) {
    3405       71594 :                         sql_exp *e = n->data;
    3406             : 
    3407             :                         /* we can handle thetajoins, rangejoins and filter joins (like) */
    3408             :                         /* ToDo how about atom expressions? */
    3409       71594 :                         if (can_join_exp(rel, e, anti)) {
    3410       71178 :                                 append(joinable, e);
    3411             :                         } else {
    3412         416 :                                 append(not_joinable, e);
    3413             :                         }
    3414             :                 }
    3415             :         }
    3416       66956 : }
    3417             : 
    3418             : 
    3419             : #define is_equi_exp_(e) ((e)->flag == cmp_equal)
    3420             : 
    3421             : static list *
    3422        3143 : get_simple_equi_joins_first(mvc *sql, sql_rel *rel, list *exps, bool *equality_only)
    3423             : {
    3424        3143 :         list *new_exps = sa_list(sql->sa);
    3425        3143 :         *equality_only = true;
    3426             : 
    3427        3143 :         if (!exps)
    3428             :                 return new_exps;
    3429             : 
    3430        6188 :         for (node *n = exps->h; n; n = n->next) {
    3431        3148 :                 sql_exp *e = n->data;
    3432             : 
    3433        3148 :                 if (can_join_exp(rel, e, false) && is_equi_exp_(e) && !is_any(e))
    3434         219 :                         list_append(new_exps, e);
    3435             :                 else
    3436        2929 :                         *equality_only = false;
    3437             :         }
    3438        6188 :         for (node *n = exps->h; n; n = n->next) {
    3439        3148 :                 sql_exp *e = n->data;
    3440             : 
    3441        3148 :                 if (!is_equi_exp_(e) || !can_join_exp(rel, e, false) || is_any(e))
    3442        2929 :                         list_append(new_exps, e);
    3443             :         }
    3444             :         return new_exps;
    3445             : }
    3446             : 
    3447             : static stmt *
    3448        3143 : rel2bin_groupjoin(backend *be, sql_rel *rel, list *refs)
    3449             : {
    3450        3143 :         mvc *sql = be->mvc;
    3451        3143 :         list *l;
    3452        3143 :         node *n , *en;
    3453        3143 :         stmt *left = NULL, *right = NULL, *join = NULL, *jl = NULL, *jr = NULL, *m = NULL, *ls = NULL, *res;
    3454        3143 :         bool need_project = false, exist = true, mark = false;
    3455             : 
    3456        3143 :         if (rel->op == op_left) { /* left outer group join */
    3457        3056 :                 if (list_length(rel->attr) == 1) {
    3458        3056 :                         sql_exp *e = rel->attr->h->data;
    3459        3056 :                         if (exp_is_atom(e))
    3460        3056 :                                 mark = true;
    3461        3056 :                         if (exp_is_atom(e) && exp_is_false(e))
    3462        3143 :                                 exist = false;
    3463             :                 }
    3464             :         }
    3465             : 
    3466        3143 :         if (rel->l) /* first construct the left sub relation */
    3467        3143 :                 left = subrel_bin(be, rel->l, refs);
    3468        3143 :         if (rel->r) /* first construct the right sub relation */
    3469        3143 :                 right = subrel_bin(be, rel->r, refs);
    3470        3143 :         left = subrel_project(be, left, refs, rel->l);
    3471        3143 :         right = subrel_project(be, right, refs, rel->r);
    3472        3143 :         if (!left || !right)
    3473             :                 return NULL;
    3474        3143 :         left = row2cols(be, left);
    3475        3143 :         right = row2cols(be, right);
    3476             : 
    3477        3143 :         bool equality_only = true;
    3478        3143 :         list *jexps = get_simple_equi_joins_first(sql, rel, rel->exps, &equality_only);
    3479             : 
    3480        3143 :         en = jexps?jexps->h:NULL;
    3481        3578 :         if (list_empty(jexps) || !(is_equi_exp_((sql_exp*)en->data) && can_join_exp(rel, en->data, false))) {
    3482         435 :                 stmt *l = bin_find_smallest_column(be, left);
    3483         435 :                 stmt *r = bin_find_smallest_column(be, right);
    3484         435 :                 if (list_empty(jexps)) {
    3485         114 :                         stmt *limit = stmt_limit(be, r, NULL, NULL, stmt_atom_lng(be, 0), stmt_atom_lng(be, 1), 0, 0, 0, 0, 0);
    3486         114 :                         r = stmt_project(be, limit, r);
    3487             :                 }
    3488         435 :                 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);
    3489         435 :                 need_project = true;
    3490         435 :                 jl = stmt_result(be, join, 0);
    3491         435 :                 jr = stmt_result(be, join, 1);
    3492             :         } else {
    3493        2708 :                 sql_exp *e = en->data;
    3494        2708 :                 en = en->next;
    3495        2708 :                 stmt *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 0, 1, 0), *r = NULL;
    3496        2708 :                 bool swap = false;
    3497             : 
    3498        2708 :                 if (!l) {
    3499          17 :                         swap = true;
    3500          17 :                         l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 0, 1, 0);
    3501             :                 }
    3502          17 :                 if (!l)
    3503             :                         return NULL;
    3504        2708 :                 if ((r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 0, 1, 0)) == NULL)
    3505             :                         return NULL;
    3506             : 
    3507        2708 :                 if (l && l->nrcols == 0)
    3508           0 :                         l = stmt_const(be, bin_find_smallest_column(be, left), l);
    3509        2708 :                 if (r && r->nrcols == 0)
    3510           0 :                         r = stmt_const(be, bin_find_smallest_column(be, right), r);
    3511        2708 :                 if (swap) {
    3512          17 :                         stmt *t = l;
    3513          17 :                         l = r;
    3514          17 :                         r = t;
    3515             :                 }
    3516        2708 :                 if ((!is_semantics(e) && is_anti(e)) || !mark)
    3517          87 :                         ls = l;
    3518        2708 :                 if (en || !mark) {
    3519             :                         /* split out (left)join vs (left)mark-join */
    3520             :                         /* call 3 result version */
    3521         168 :                         if (mark && is_any(e)) {
    3522           5 :                                 join = stmt_markjoin(be, l, r, 0);
    3523             :                         } else
    3524         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);
    3525         168 :                         jl = stmt_result(be, join, 0);
    3526         168 :                         jr = stmt_result(be, join, 1);
    3527         168 :                         if (mark && is_any(e))
    3528           5 :                                 m = stmt_result(be, join, 2);
    3529             :                 } else {
    3530        2540 :                         join = stmt_markjoin(be, l, r, 1);
    3531        2540 :                         jl = stmt_result(be, join, 0);
    3532        2540 :                         m = stmt_result(be, join, 1);
    3533             :                 }
    3534             :         }
    3535             : 
    3536        3143 :         if (en) {
    3537         402 :                 stmt *sub, *sel = NULL, *osel = NULL;
    3538         402 :                 list *nl;
    3539             : 
    3540         402 :                 need_project = false;
    3541             : 
    3542             :                 /* construct relation */
    3543         402 :                 nl = sa_list(sql->sa);
    3544             : 
    3545             :                 /* first project using equi-joins */
    3546        2085 :                 for (n = left->op4.lval->h; n; n = n->next) {
    3547        1683 :                         stmt *c = n->data;
    3548        1683 :                         assert(c->type == st_alias);
    3549        1683 :                         sql_alias *rnme = table_name(sql->sa, c);
    3550        1683 :                         const char *nme = column_name(sql->sa, c);
    3551        1683 :                         stmt *s = stmt_project(be, jl, column(be, c));
    3552             : 
    3553        1683 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    3554        1683 :                         list_append(nl, s);
    3555             :                 }
    3556        1027 :                 for (n = right->op4.lval->h; n; n = n->next) {
    3557         625 :                         stmt *c = n->data;
    3558         625 :                         assert(c->type == st_alias);
    3559         625 :                         sql_alias *rnme = table_name(sql->sa, c);
    3560         625 :                         const char *nme = column_name(sql->sa, c);
    3561         625 :                         stmt *s = stmt_project(be, jr, column(be, c));
    3562             : 
    3563         625 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    3564         625 :                         list_append(nl, s);
    3565             :                 }
    3566         402 :                 left = sub = stmt_list(be, nl);
    3567             : 
    3568         402 :                 if (!m) {
    3569         397 :                         if (ls) {
    3570           0 :                                 stmt *nls = stmt_project(be, jl, ls);
    3571           0 :                                         m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", nls), stmt_bool(be, bit_nil),
    3572             :                                                 sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL),
    3573             :                                                 NULL);
    3574             :                         } else {
    3575             :                                 /* 0 == empty (no matches possible), nil - no match (but has nil), 1 match */
    3576         397 :                                 m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, 0), stmt_bool(be, 1), NULL);
    3577             :                         }
    3578             :                 }
    3579             : 
    3580             :                 /* continue with non equi-joins */
    3581         842 :                 for ( ; en; en = en->next) {
    3582         440 :                         sql_exp *e = en->data;
    3583         440 :                         stmt *p = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    3584             : 
    3585         440 :                         if (!p) {
    3586           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3587             :                                 return NULL;
    3588             :                         }
    3589         440 :                         if (p->nrcols == 0)
    3590           1 :                                 p = stmt_const(be, bin_find_smallest_column(be, sub), p);
    3591         440 :                         if (sel)
    3592          38 :                                 p = stmt_project(be, sel, column(be, p));
    3593          38 :                         stmt *li = jl;
    3594          38 :                         if (sel)
    3595          38 :                                 li = stmt_project(be, sel, li);
    3596         440 :                         osel = sel;
    3597         440 :                         if (en->next) {
    3598          38 :                                 join = stmt_outerselect(be, li, m, p, is_any(e));
    3599             :                         } else {
    3600         402 :                                 join = stmt_markselect(be, li, m, p, is_any(e));
    3601             :                         }
    3602         440 :                         sel = stmt_result(be, join, 0);
    3603         440 :                         m = stmt_result(be, join, 1);
    3604             :                         /* go back to offset in the table */
    3605         440 :                         if (sel && osel)
    3606          38 :                                 sel = stmt_project(be, sel, osel);
    3607         440 :                         if (!en->next)
    3608         402 :                                 jl = sel;
    3609             :                 }
    3610             :         }
    3611             :         /* construct relation */
    3612        3143 :         l = sa_list(sql->sa);
    3613       14043 :         for (n = left->op4.lval->h; n; n = n->next) {
    3614       10900 :                 stmt *c = n->data;
    3615       10900 :                 assert(c->type == st_alias);
    3616       10900 :                 sql_alias *rnme = table_name(sql->sa, c);
    3617       10900 :                 const char *nme = column_name(sql->sa, c);
    3618       10900 :                 stmt *s = stmt_project(be, jl, column(be, c));
    3619             : 
    3620       10900 :                 s = stmt_alias(be, s, c->label, rnme, nme);
    3621       10900 :                 list_append(l, s);
    3622             :         }
    3623        3143 :         if (!mark && jr) {
    3624         178 :                 for (n = right->op4.lval->h; n; n = n->next) {
    3625          91 :                         stmt *c = n->data;
    3626          91 :                         assert(c->type == st_alias);
    3627          91 :                         sql_alias *rnme = table_name(sql->sa, c);
    3628          91 :                         const char *nme = column_name(sql->sa, c);
    3629          91 :                         stmt *s = stmt_project(be, jr, column(be, c));
    3630             : 
    3631          91 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    3632          91 :                         list_append(l, s);
    3633             :                 }
    3634          87 :                 left = stmt_list(be, l);
    3635          87 :                 l = sa_list(sql->sa);
    3636             :         }
    3637        3143 :         if (rel->attr) {
    3638        3143 :                 sql_exp *e = rel->attr->h->data;
    3639        3143 :                 sql_alias *rnme = exp_relname(e);
    3640        3143 :                 const char *nme = exp_name(e);
    3641             : 
    3642        3143 :                 if (mark) {
    3643        3056 :                         if (need_project) {
    3644         114 :                                 m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", jr), stmt_bool(be, !exist), stmt_bool(be, exist), NULL);
    3645             :                         } else {
    3646        2942 :                                 assert(m);
    3647        2942 :                                 sql_exp *e = rel->attr->h->data;
    3648        2942 :                                 if (exp_is_atom(e) && need_no_nil(e))
    3649         298 :                                         m = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", m), stmt_bool(be, false), m, NULL);
    3650        2942 :                                 if (!exist) {
    3651          42 :                                         sql_subtype *bt = sql_bind_localtype("bit");
    3652          42 :                                         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    3653          42 :                                         m = stmt_unop(be, m, NULL, not);
    3654             :                                 }
    3655             :                         }
    3656        3056 :                         stmt *s = stmt_alias(be, m, e->alias.label, rnme, nme);
    3657        3056 :                         append(l, s);
    3658             :                 } else {
    3659             :                         /* group / aggrs */
    3660          87 :                         stmt *nls = stmt_project(be, jl, ls);
    3661          87 :                         stmt *groupby = stmt_group(be, nls, NULL, NULL, NULL, true);
    3662          87 :                         stmt *grp = stmt_result(be, groupby, 0);
    3663          87 :                         stmt *ext = stmt_result(be, groupby, 1);
    3664          87 :                         stmt *cnt = stmt_result(be, groupby, 2);
    3665         174 :                         for(node *n = rel->attr->h; n; n = n->next) {
    3666          87 :                                 sql_exp *e = n->data;
    3667          87 :                                 sql_alias *rnme = exp_relname(e);
    3668          87 :                                 const char *nme = exp_name(e);
    3669          87 :                                 stmt *s = exp_bin(be, e, left, NULL, grp, ext, cnt, NULL, 0, 0, 0);
    3670          87 :                                 s = stmt_alias(be, s, e->alias.label, rnme, nme);
    3671          87 :                                 append(l, s);
    3672             :                         }
    3673             :                 }
    3674             :         }
    3675        3143 :         res = stmt_list(be, l);
    3676        3143 :         return res;
    3677             : }
    3678             : 
    3679             : static list *
    3680       65099 : get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
    3681             : {
    3682       65099 :         list *new_exps = sa_list(sql->sa);
    3683             : 
    3684      134565 :         for (node *n = exps->h; n; n = n->next) {
    3685       69466 :                 sql_exp *e = n->data;
    3686             : 
    3687       69466 :                 assert(e->type == e_cmp && e->flag != cmp_in && e->flag != cmp_notin && e->flag != cmp_or);
    3688       69466 :                 if (is_equi_exp_(e))
    3689       65593 :                         list_append(new_exps, e);
    3690             :                 else
    3691        3873 :                         *equality_only = 0;
    3692             :         }
    3693      134565 :         for (node *n = exps->h; n; n = n->next) {
    3694       69466 :                 sql_exp *e = n->data;
    3695             : 
    3696       69466 :                 if (!is_equi_exp_(e))
    3697        3873 :                         list_append(new_exps, e);
    3698             :         }
    3699       65099 :         return new_exps;
    3700             : }
    3701             : 
    3702             : static stmt *
    3703       18774 : stmt_append_nil(backend *be, stmt *s, stmt *rows)
    3704             : {
    3705       18774 :         if (s->nested)
    3706           8 :                 return stmt_nest(be, s, rows, &stmt_append_nil);
    3707       18766 :         return stmt_append(be, s, stmt_const(be, rows, (s->flag&OUTER_ZERO)?stmt_atom_lng(be, 0):stmt_atom(be, atom_general(be->mvc->sa, tail_type(s), NULL, 0))));
    3708             : }
    3709             : 
    3710             : static stmt *
    3711       76655 : rel2bin_join(backend *be, sql_rel *rel, list *refs)
    3712             : {
    3713       76655 :         mvc *sql = be->mvc;
    3714       76655 :         list *l, *sexps = NULL, *l2 = NULL;
    3715       76655 :         node *en = NULL, *n;
    3716       76655 :         stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *ld = NULL, *rd = NULL, *res;
    3717       76655 :         int need_left = (rel->flag & LEFT_JOIN);
    3718             : 
    3719       76655 :         if (rel->attr && list_length(rel->attr) > 0)
    3720        3143 :                 return rel2bin_groupjoin(be, rel, refs);
    3721             : 
    3722       73512 :         if (rel->l) /* first construct the left sub relation */
    3723       73512 :                 left = subrel_bin(be, rel->l, refs);
    3724       73512 :         if (rel->r) /* first construct the right sub relation */
    3725       73512 :                 right = subrel_bin(be, rel->r, refs);
    3726       73512 :         left = subrel_project(be, left, refs, rel->l);
    3727       73512 :         right = subrel_project(be, right, refs, rel->r);
    3728       73512 :         if (!left || !right)
    3729             :                 return NULL;
    3730       73512 :         left = row2cols(be, left);
    3731       73512 :         right = row2cols(be, right);
    3732             :         /*
    3733             :          * split in 2 steps,
    3734             :          *      first cheap join(s) (equality or idx)
    3735             :          *      second selects/filters
    3736             :          */
    3737       73512 :         if (!list_empty(rel->exps)) {
    3738       62253 :                 list *jexps = sa_list(sql->sa);
    3739       62253 :                 sexps = sa_list(sql->sa);
    3740             : 
    3741       62253 :                 split_join_exps(rel, jexps, sexps, false);
    3742       62253 :                 if (list_empty(jexps)) { /* cross product and continue after project */
    3743         273 :                         stmt *l = bin_find_smallest_column(be, left);
    3744         273 :                         stmt *r = bin_find_smallest_column(be, right);
    3745         273 :                         join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    3746             :                 }
    3747             : 
    3748         273 :                 if (join) {
    3749         273 :                         en = jexps->h;
    3750             :                 } else {
    3751       61980 :                         list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
    3752       61980 :                         int used_hash = 0, idx = 0, equality_only = 1;
    3753             : 
    3754       61980 :                         (void) equality_only;
    3755       61980 :                         jexps = get_equi_joins_first(sql, jexps, &equality_only);
    3756             :                         /* generate a relational join (releqjoin) which does a multi attribute (equi) join */
    3757      124128 :                         for (en = jexps->h; en ; en = en->next) {
    3758       64497 :                                 int join_idx = be->join_idx;
    3759       64497 :                                 sql_exp *e = en->data;
    3760       64497 :                                 stmt *s = NULL;
    3761       64497 :                                 prop *p;
    3762             : 
    3763             :                                 /* stop search for equi joins on first non equi */
    3764       64497 :                                 if (list_length(lje) && (idx || e->type != e_cmp || e->flag != cmp_equal))
    3765             :                                         break;
    3766             : 
    3767             :                                 /* handle possible index lookups, expressions are in index order! */
    3768       64403 :                                 if (!join && (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
    3769          78 :                                         sql_idx *i = p->value.pval;
    3770          78 :                                         int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
    3771             : 
    3772          78 :                                         join = s = rel2bin_hash_lookup(be, rel, left, right, i, en);
    3773          78 :                                         if (s) {
    3774          78 :                                                 list_append(lje, s->op1);
    3775          78 :                                                 list_append(rje, s->op2);
    3776          78 :                                                 list_append(exps, NULL);
    3777          78 :                                                 used_hash = 1;
    3778             :                                         } else {
    3779             :                                                 /* hash lookup cannot be used, clean leftover mal statements */
    3780           0 :                                                 clean_mal_statements(be, oldstop, oldvtop);
    3781             :                                         }
    3782             :                                 }
    3783             : 
    3784       64403 :                                 s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
    3785       64403 :                                 if (!s) {
    3786           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3787           0 :                                         return NULL;
    3788             :                                 }
    3789       64403 :                                 if (join_idx != be->join_idx)
    3790         623 :                                         idx = 1;
    3791       64403 :                                 assert(s->type == st_join || s->type == st_join2 || s->type == st_joinN);
    3792       64403 :                                 if (!join)
    3793       61902 :                                         join = s;
    3794       64403 :                                 if (e->flag != cmp_equal) { /* only collect equi joins */
    3795        2255 :                                         en = en->next;
    3796        2255 :                                         break;
    3797             :                                 }
    3798       62148 :                                 list_append(lje, s->op1);
    3799       62148 :                                 list_append(rje, s->op2);
    3800       62148 :                                 list_append(exps, e);
    3801             :                         }
    3802       61980 :                         if (list_length(lje) > 1) {
    3803        2176 :                                 join = releqjoin(be, lje, rje, exps, used_hash, need_left, 0);
    3804       59804 :                         } else if (!join || need_left) {
    3805         632 :                                 sql_exp *e = exps->h->data;
    3806         632 :                                 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, need_left, is_semantics(e), false);
    3807             :                         }
    3808             :                 }
    3809             :         } else {
    3810       11259 :                 stmt *l = bin_find_smallest_column(be, left);
    3811       11259 :                 stmt *r = bin_find_smallest_column(be, right);
    3812       11259 :                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, is_single(rel));
    3813             :         }
    3814       73512 :         jl = stmt_result(be, join, 0);
    3815       73512 :         jr = stmt_result(be, join, 1);
    3816       73512 :         if (en || (sexps && list_length(sexps))) {
    3817        1447 :                 stmt *sub, *sel = NULL;
    3818        1447 :                 list *nl;
    3819             : 
    3820             :                 /* construct relation */
    3821        1447 :                 nl = sa_list(sql->sa);
    3822             : 
    3823             :                 /* first project using equi-joins */
    3824        6872 :                 for (n = left->op4.lval->h; n; n = n->next) {
    3825        5425 :                         stmt *c = n->data;
    3826        5425 :                         assert(c->type == st_alias);
    3827        5425 :                         sql_alias *rnme = table_name(sql->sa, c);
    3828        5425 :                         const char *nme = column_name(sql->sa, c);
    3829        5425 :                         stmt *s = stmt_project(be, jl, column(be, c));
    3830             : 
    3831        5425 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    3832        5425 :                         list_append(nl, s);
    3833             :                 }
    3834        4671 :                 for (n = right->op4.lval->h; n; n = n->next) {
    3835        3224 :                         stmt *c = n->data;
    3836        3224 :                         assert(c->type == st_alias);
    3837        3224 :                         sql_alias *rnme = table_name(sql->sa, c);
    3838        3224 :                         const char *nme = column_name(sql->sa, c);
    3839        3224 :                         stmt *s = stmt_project(be, jr, column(be, c));
    3840             : 
    3841        3224 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    3842        3224 :                         list_append(nl, s);
    3843             :                 }
    3844        1447 :                 sub = stmt_list(be, nl);
    3845             : 
    3846             :                 /* continue with non equi-joins */
    3847        4034 :                 while(sexps) {
    3848        2587 :                         if (!en) {
    3849        1447 :                                 en = sexps->h;
    3850        1447 :                                 sexps = NULL;
    3851             :                         }
    3852        4056 :                         for ( ; en; en = en->next) {
    3853        1469 :                                 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    3854             : 
    3855        1469 :                                 if (!s) {
    3856           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    3857             :                                         return NULL;
    3858             :                                 }
    3859        1469 :                                 if (s->nrcols == 0) {
    3860         123 :                                         stmt *l = bin_find_smallest_column(be, sub);
    3861         123 :                                         s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
    3862             :                                 }
    3863        1469 :                                 sel = s;
    3864             :                         }
    3865             :                 }
    3866             :                 /* recreate join output */
    3867        1447 :                 jl = stmt_project(be, sel, jl);
    3868        1447 :                 jr = stmt_project(be, sel, jr);
    3869             :         }
    3870             : 
    3871             :         /* construct relation */
    3872       73512 :         l = sa_list(sql->sa);
    3873             : 
    3874       73512 :         if (rel->op == op_left || rel->op == op_full || is_single(rel)) {
    3875             :                 /* we need to add the missing oid's */
    3876       11473 :                 stmt *l = ld = stmt_mirror(be, bin_find_smallest_column(be, left));
    3877       11473 :                 if (rel->op == op_left || rel->op == op_full)
    3878        8282 :                         ld = stmt_tdiff(be, ld, jl, NULL);
    3879       11473 :                 if (is_single(rel) && !list_empty(rel->exps)) {
    3880         284 :                         join = stmt_semijoin(be, l, jl, NULL, NULL, 0, true);
    3881         284 :                         jl = stmt_result(be, join, 0);
    3882         284 :                         jr = stmt_project(be, stmt_result(be, join, 1), jr);
    3883             :                 }
    3884             :         }
    3885       73512 :         if (rel->op == op_right || rel->op == op_full) {
    3886             :                 /* we need to add the missing oid's */
    3887         169 :                 rd = stmt_mirror(be, bin_find_smallest_column(be, right));
    3888         169 :                 rd = stmt_tdiff(be, rd, jr, NULL);
    3889             :         }
    3890             : 
    3891       73512 :         if (rel->op == op_left) { /* used for merge statements, this will be cleaned out on the pushcands branch :) */
    3892        8210 :                 l2 = sa_list(sql->sa);
    3893        8210 :                 list_append(l2, left);
    3894        8210 :                 list_append(l2, right);
    3895        8210 :                 list_append(l2, jl);
    3896        8210 :                 list_append(l2, jr);
    3897        8210 :                 list_append(l2, ld);
    3898             :         }
    3899             : 
    3900       73512 :         int op = rel->op;
    3901     1942236 :         for (n = left->op4.lval->h; n; n = n->next) {
    3902     1868724 :                 stmt *c = n->data;
    3903     1868724 :                 sql_alias *rnme = table_name(sql->sa, c);
    3904     1868724 :                 const char *nme = column_name(sql->sa, c);
    3905     1868724 :                 stmt *s = stmt_project(be, jl, column(be, c));
    3906             : 
    3907             :                 /* as append isn't save, we append to a new copy */
    3908     1868724 :                 if (op == op_left || op == op_full || op == op_right)
    3909       61163 :                         s = create_const_column(be, s, NULL);
    3910     1868724 :                 if (op == op_left || op == op_full)
    3911       60957 :                         s = stmt_append(be, s, stmt_project(be, ld, c));
    3912     1868724 :                 if (op == op_right || op == op_full) {
    3913         329 :                         s->flag = c->flag; /* push OUTER_ZERO */
    3914         329 :                         s = stmt_append_nil(be, s, rd);
    3915             :                 }
    3916     1868724 :                 s = stmt_alias(be, s, c->label, rnme, nme);
    3917     1868724 :                 list_append(l, s);
    3918             :         }
    3919      280072 :         for (n = right->op4.lval->h; n; n = n->next) {
    3920      206560 :                 stmt *c = n->data;
    3921      206560 :                 sql_alias *rnme = table_name(sql->sa, c);
    3922      206560 :                 const char *nme = column_name(sql->sa, c);
    3923      206560 :                 stmt *s = stmt_project(be, jr, column(be, c));
    3924             : 
    3925             :                 /* as append isn't save, we append to a new copy */
    3926      206560 :                 if (op == op_left || op == op_full || op == op_right)
    3927       18693 :                         s = create_const_column(be, s, NULL);
    3928      206560 :                 if (op == op_left || op == op_full) {
    3929       18431 :                         s->flag = c->flag; /* push OUTER_ZERO */
    3930       18431 :                         s = stmt_append_nil(be, s, ld);
    3931             :                 }
    3932      206560 :                 if (op == op_right || op == op_full)
    3933         375 :                         s = stmt_append(be, s, stmt_project(be, rd, c));
    3934             : 
    3935      206560 :                 s = stmt_alias(be, s, c->label, rnme, nme);
    3936      206560 :                 list_append(l, s);
    3937             :         }
    3938       73512 :         if (rel->attr) {
    3939           0 :                 sql_exp *e = rel->attr->h->data;
    3940           0 :                 sql_alias *rnme = exp_relname(e);
    3941           0 :                 const char *nme = exp_name(e);
    3942           0 :                 stmt *last = l->t->data;
    3943           0 :                 sql_subtype *tp = tail_type(last);
    3944             : 
    3945           0 :                 sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", tp, NULL, F_FUNC, true, true);
    3946             : 
    3947           0 :                 stmt *s = stmt_unop(be, last, NULL, isnil);
    3948             : 
    3949           0 :                 sql_subtype *bt = sql_bind_localtype("bit");
    3950           0 :                 sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    3951             : 
    3952           0 :                 s = stmt_unop(be, s, NULL, not);
    3953           0 :                 s = stmt_alias(be, s, e->alias.label, rnme, nme);
    3954           0 :                 list_append(l, s);
    3955             :         }
    3956             : 
    3957       73512 :         res = stmt_list(be, l);
    3958       73512 :         res->extra = l2; /* used for merge statements, this will be cleaned out on the pushcands branch :) */
    3959       73512 :         return res;
    3960             : }
    3961             : 
    3962             : static stmt *
    3963        1531 : rel2bin_antijoin(backend *be, sql_rel *rel, list *refs)
    3964             : {
    3965        1531 :         mvc *sql = be->mvc;
    3966        1531 :         list *l, *jexps = NULL, *sexps = NULL;
    3967        1531 :         node *en = NULL, *n;
    3968        1531 :         stmt *left = NULL, *right = NULL, *join = NULL, *sel = NULL, *sub = NULL;
    3969             : 
    3970        1531 :         if (rel->l) /* first construct the left sub relation */
    3971        1531 :                 left = subrel_bin(be, rel->l, refs);
    3972        1531 :         if (rel->r) /* first construct the right sub relation */
    3973        1531 :                 right = subrel_bin(be, rel->r, refs);
    3974        1531 :         left = subrel_project(be, left, refs, rel->l);
    3975        1531 :         right = subrel_project(be, right, refs, rel->r);
    3976        1531 :         if (!left || !right)
    3977             :                 return NULL;
    3978        1531 :         left = row2cols(be, left);
    3979        1531 :         right = row2cols(be, right);
    3980             : 
    3981        1531 :         stmt *li = NULL;
    3982        1531 :         bool swap = false;
    3983             : 
    3984        1531 :         jexps = sa_list(sql->sa);
    3985        1531 :         sexps = sa_list(sql->sa);
    3986             : 
    3987        1531 :         split_join_exps(rel, jexps, sexps, true);
    3988        1531 :         if (list_empty(jexps)) {
    3989          16 :                 stmt *l = bin_find_smallest_column(be, left);
    3990          16 :                 stmt *r = bin_find_smallest_column(be, right);
    3991          16 :                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    3992             : 
    3993          16 :                 jexps = sexps;
    3994          16 :                 sexps = NULL;
    3995          16 :                 en = jexps->h;
    3996             :         } else {
    3997        1515 :                 if (list_length(sexps))
    3998           3 :                         list_merge(jexps, sexps, NULL);
    3999        1515 :                 en = jexps->h;
    4000        1515 :                 sql_exp *e = en->data;
    4001        1515 :                 assert(e->type == e_cmp);
    4002        1515 :                 stmt *ls = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0), *rs;
    4003        1515 :                 bool constval = false;
    4004        1515 :                 if (!ls) {
    4005          12 :                         swap = true;
    4006          12 :                         ls = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    4007             :                 }
    4008          12 :                 if (!ls)
    4009             :                         return NULL;
    4010             : 
    4011        1515 :                 if (!(rs = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0)))
    4012             :                         return NULL;
    4013             : 
    4014        1515 :                 if (swap) {
    4015          12 :                         stmt *t = ls;
    4016          12 :                         ls = rs;
    4017          12 :                         rs = t;
    4018             :                 }
    4019        1515 :                 if (ls->nrcols == 0) {
    4020          10 :                         constval = true;
    4021          10 :                         ls = stmt_const(be, bin_find_smallest_column(be, left), ls);
    4022             :                 }
    4023        1515 :                 if (rs->nrcols == 0)
    4024           4 :                         rs = stmt_const(be, bin_find_smallest_column(be, right), rs);
    4025             : 
    4026        1515 :                 if (!li)
    4027        1515 :                         li = ls;
    4028             : 
    4029        1515 :                 if (!en->next && (constval || stmt_has_null(ls) /*|| stmt_has_null(rs) (change into check for fk)*/)) {
    4030        1295 :                         assert(e->flag == cmp_equal);
    4031        1295 :                         join = stmt_tdiff2(be, ls, rs, NULL);
    4032        1295 :                         jexps = NULL;
    4033             :                 } else {
    4034         220 :                         join = stmt_join_cand(be, ls, rs, NULL, NULL, is_anti(e), (comp_type) e->flag, 0, is_semantics(e), false, true);
    4035             :                 }
    4036        1515 :                 en = en->next;
    4037             :         }
    4038        1531 :         if (en || jexps) {
    4039         236 :                 stmt *jl = stmt_result(be, join, 0);
    4040         236 :                 stmt *jr = stmt_result(be, join, 1);
    4041         236 :                 stmt *nulls = NULL;
    4042             : 
    4043         236 :                 if (li && stmt_has_null(li)) {
    4044         123 :                         nulls = stmt_selectnil(be, li);
    4045             :                 }
    4046             :                 /* construct relation */
    4047         236 :                 list *nl = sa_list(sql->sa);
    4048             :                 /* first project after equi-joins */
    4049        2261 :                 for (n = left->op4.lval->h; n; n = n->next) {
    4050        2025 :                         stmt *c = n->data;
    4051        2025 :                         assert(c->type == st_alias);
    4052        2025 :                         sql_alias *rnme = table_name(sql->sa, c);
    4053        2025 :                         const char *nme = column_name(sql->sa, c);
    4054        2025 :                         stmt *s = stmt_project(be, jl, column(be, c));
    4055             : 
    4056        2025 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    4057        2025 :                         list_append(nl, s);
    4058             :                 }
    4059         679 :                 for (n = right->op4.lval->h; n; n = n->next) {
    4060         443 :                         stmt *c = n->data;
    4061         443 :                         assert(c->type == st_alias);
    4062         443 :                         sql_alias *rnme = table_name(sql->sa, c);
    4063         443 :                         const char *nme = column_name(sql->sa, c);
    4064         443 :                         stmt *s = stmt_project(be, jr, column(be, c));
    4065             : 
    4066         443 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    4067         443 :                         list_append(nl, s);
    4068             :                 }
    4069         236 :                 sub = stmt_list(be, nl);
    4070             : 
    4071             :                 /* continue with non equi-joins */
    4072         682 :                 for (; en; en = en->next) {
    4073         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);
    4074             : 
    4075             :                         /* ifthenelse if (not(predicate)) then false else true (needed for antijoin) */
    4076         210 :                         sql_subtype *bt = sql_bind_localtype("bit");
    4077         210 :                         sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    4078         210 :                         s = stmt_unop(be, s, NULL, not);
    4079         210 :                         s = sql_Nop_(be, "ifthenelse", s, stmt_bool(be, 0), stmt_bool(be, 1), NULL);
    4080             : 
    4081         210 :                         if (s->nrcols == 0) {
    4082           0 :                                 stmt *l = bin_find_smallest_column(be, sub);
    4083           0 :                                 s = stmt_uselect(be, stmt_const(be, l, s), stmt_bool(be, 1), cmp_equal, sel, 0, 0);
    4084             :                         } else {
    4085         210 :                                 s = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
    4086             :                         }
    4087             : 
    4088         210 :                         if (!s) {
    4089           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    4090             :                                 return NULL;
    4091             :                         }
    4092             : 
    4093         210 :                         sel = s;
    4094             :                 }
    4095         236 :                 stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
    4096         236 :                 if (nulls) {
    4097         123 :                         stmt *nonilcand = stmt_tdiff(be, c, nulls, NULL);
    4098         123 :                         c = stmt_project(be, nonilcand, c);
    4099             :                 }
    4100         236 :                 if (join && sel) {
    4101             :                         /* recreate join output */
    4102         153 :                         jl = stmt_project(be, sel, jl);
    4103         153 :                         join = stmt_tdiff(be, c, jl, NULL);
    4104             :                 } else {
    4105          83 :                         join = stmt_tdiff2(be, c, jl, NULL);
    4106             :                 }
    4107         236 :                 if (nulls)
    4108         123 :                         join = stmt_project(be, join, c);
    4109             : 
    4110             :         } else if (jexps && list_empty(jexps)) {
    4111             :                 stmt *jl = stmt_result(be, join, 0);
    4112             :                 stmt *c = stmt_mirror(be, bin_find_smallest_column(be, left));
    4113             :                 join = stmt_tdiff2(be, c, jl, NULL);
    4114             :         }
    4115             : 
    4116             :         /* construct relation */
    4117        1531 :         l = sa_list(sql->sa);
    4118             : 
    4119             :         /* project all the left columns */
    4120       13210 :         for (n = left->op4.lval->h; n; n = n->next) {
    4121       11679 :                 stmt *c = n->data;
    4122       11679 :                 assert(c->type == st_alias);
    4123       11679 :                 sql_alias *rnme = table_name(sql->sa, c);
    4124       11679 :                 const char *nme = column_name(sql->sa, c);
    4125       11679 :                 stmt *s = stmt_project(be, join, column(be, c));
    4126             : 
    4127       11679 :                 s = stmt_alias(be, s, c->label, rnme, nme);
    4128       11679 :                 list_append(l, s);
    4129             :         }
    4130        1531 :         return stmt_list(be, l);
    4131             : }
    4132             : 
    4133             : static stmt *
    4134        3206 : rel2bin_semijoin(backend *be, sql_rel *rel, list *refs)
    4135             : {
    4136        3206 :         mvc *sql = be->mvc;
    4137        3206 :         list *l, *sexps = NULL;
    4138        3206 :         node *en = NULL, *n;
    4139        3206 :         stmt *left = NULL, *right = NULL, *join = NULL, *jl, *jr, *c, *lcand = NULL;
    4140        3206 :         int semijoin_only = 0, l_is_base = 0;
    4141             : 
    4142        3206 :         assert(rel->op != op_anti);
    4143             : 
    4144        3206 :         if (rel->l) { /* first construct the left sub relation */
    4145        3206 :                 sql_rel *l = rel->l;
    4146        3206 :                 l_is_base = is_basetable(l->op);
    4147        3206 :                 left = subrel_bin(be, l, refs);
    4148             :         }
    4149        3206 :         if (rel->r) /* first construct the right sub relation */
    4150        3206 :                 right = subrel_bin(be, rel->r, refs);
    4151        3206 :         if (!left || !right)
    4152             :                 return NULL;
    4153        3206 :         left = row2cols(be, left);
    4154        3206 :         right = row2cols(be, right);
    4155             :         /*
    4156             :          * split in 2 steps,
    4157             :          *      first cheap join(s) (equality or idx)
    4158             :          *      second selects/filters
    4159             :          */
    4160        3206 :         if (!list_empty(rel->exps)) {
    4161        3172 :                 list *jexps = sa_list(sql->sa);
    4162        3172 :                 sexps = sa_list(sql->sa);
    4163             : 
    4164        3172 :                 split_join_exps(rel, jexps, sexps, false);
    4165        3172 :                 if (list_empty(jexps)) { /* cross product and continue after project */
    4166          53 :                         right = subrel_project(be, right, refs, rel->r);
    4167          53 :                         stmt *l = bin_find_smallest_column(be, left);
    4168          53 :                         stmt *r = bin_find_smallest_column(be, right);
    4169          53 :                         join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    4170          53 :                         lcand = left->cand;
    4171             :                 }
    4172             : 
    4173        3172 :                 if (join) {
    4174          53 :                         en = jexps->h;
    4175             :                 } else {
    4176        3119 :                         list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), *exps = sa_list(sql->sa);
    4177        3119 :                         int idx = 0, equality_only = 1;
    4178             : 
    4179        3119 :                         jexps = get_equi_joins_first(sql, jexps, &equality_only);
    4180        3119 :                         if (!equality_only || list_length(jexps) > 1 || exp_has_func((sql_exp*)jexps->h->data))
    4181        1129 :                                 left = subrel_project(be, left, refs, rel->l);
    4182        3119 :                         right = subrel_project(be, right, refs, rel->r);
    4183             : 
    4184        7019 :                         for (en = jexps->h; en; en = en->next) {
    4185        3913 :                                 int join_idx = be->join_idx;
    4186        3913 :                                 sql_exp *e = en->data;
    4187        3913 :                                 stmt *s = NULL;
    4188             : 
    4189             :                                 /* only handle simple joins here */
    4190        3913 :                                 if ((exp_has_func(e) && e->flag != cmp_filter) || e->flag == cmp_or || (e->f && is_anti(e))) {
    4191           3 :                                         if (!join && !list_length(lje)) {
    4192           3 :                                                 stmt *l = bin_find_smallest_column(be, left);
    4193           3 :                                                 stmt *r = bin_find_smallest_column(be, right);
    4194           3 :                                                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    4195             :                                         }
    4196             :                                         break;
    4197             :                                 }
    4198        3910 :                                 if (list_length(lje) && (idx || e->type != e_cmp || (e->flag != cmp_equal && e->flag != cmp_filter) ||
    4199         784 :                                 (join && e->flag == cmp_filter)))
    4200             :                                         break;
    4201             : 
    4202        3900 :                                 if (equality_only) {
    4203        3431 :                                         int oldvtop = be->mb->vtop, oldstop = be->mb->stop, swap = 0;
    4204        3431 :                                         stmt *r, *l = exp_bin(be, e->l, left, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    4205             : 
    4206        3431 :                                         if (l && left && l->nrcols==0 && left->nrcols >0)
    4207           1 :                                                 l = stmt_const(be, bin_find_smallest_column(be, left), l);
    4208         442 :                                         if (!l) {
    4209         441 :                                                 swap = 1;
    4210         441 :                                                 clean_mal_statements(be, oldstop, oldvtop);
    4211         441 :                                                 l = exp_bin(be, e->l, right, NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
    4212             :                                         }
    4213        3431 :                                         r = exp_bin(be, e->r, left, right, NULL, NULL, NULL, NULL, 1, 0, 0);
    4214             : 
    4215        3431 :                                         if (swap) {
    4216         441 :                                                 stmt *t = l;
    4217         441 :                                                 l = r;
    4218         441 :                                                 r = t;
    4219             :                                         }
    4220             : 
    4221        3431 :                                         if (!l || !r)
    4222           0 :                                                 return NULL;
    4223        3431 :                                         if (be->no_mitosis && list_length(jexps) == 1 && list_empty(sexps) && rel->op == op_semi && !is_anti(e) && is_equi_exp_(e)) {
    4224           0 :                                                 join = stmt_semijoin(be, column(be, l), column(be, r), left->cand, NULL/*right->cand*/, is_semantics(e), false);
    4225           0 :                                                 semijoin_only = 1;
    4226           0 :                                                 en = NULL;
    4227           0 :                                                 break;
    4228             :                                         } else
    4229        3431 :                                                 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);
    4230        3431 :                                         lcand = left->cand;
    4231             :                                 } else {
    4232         469 :                                         s = exp_bin(be, e, left, right, NULL, NULL, NULL, NULL, 0, 1, 0);
    4233             :                                 }
    4234        3900 :                                 if (!s) {
    4235           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    4236             :                                         return NULL;
    4237             :                                 }
    4238        3900 :                                 if (join_idx != be->join_idx)
    4239           0 :                                         idx = 1;
    4240             :                                 /* stop on first non equality join */
    4241        3900 :                                 if (!join) {
    4242        3116 :                                         if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
    4243           0 :                                                 if (!en->next && (s->type == st_uselect || s->type == st_uselect2))
    4244             :                                                         join = s;
    4245             :                                                 else
    4246             :                                                         break;
    4247             :                                         }
    4248             :                                         join = s;
    4249         784 :                                 } else if (s->type != st_join && s->type != st_join2 && s->type != st_joinN) {
    4250             :                                         /* handle select expressions */
    4251             :                                         break;
    4252             :                                 }
    4253        3900 :                                 if (s->type == st_join || s->type == st_join2 || s->type == st_joinN) {
    4254        3900 :                                         list_append(lje, s->op1);
    4255        3900 :                                         list_append(rje, s->op2);
    4256        3900 :                                         list_append(exps, e);
    4257             :                                 }
    4258             :                         }
    4259        3119 :                         if (list_length(lje) > 1) {
    4260         659 :                                 join = releqjoin(be, lje, rje, exps, 0 /* use hash */, 0, rel->op == op_anti?1:0);
    4261        2460 :                         } else if (!join && list_length(lje) == list_length(rje) && list_length(lje)) {
    4262           0 :                                 sql_exp *e = exps->h->data;
    4263           0 :                                 join = stmt_join(be, lje->h->data, rje->h->data, 0, cmp_equal, 0, is_semantics(e), false);
    4264           0 :                         } else if (!join) {
    4265           0 :                                 stmt *l = bin_find_smallest_column(be, left);
    4266           0 :                                 stmt *r = bin_find_smallest_column(be, right);
    4267           0 :                                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    4268             :                         }
    4269             :                 }
    4270             :         } else {
    4271          34 :                 right = subrel_project(be, right, refs, rel->r);
    4272          34 :                 stmt *l = bin_find_smallest_column(be, left);
    4273          34 :                 stmt *r = bin_find_smallest_column(be, right);
    4274          34 :                 join = stmt_join(be, l, r, 0, cmp_all, 0, 0, false);
    4275          34 :                 lcand = left->cand;
    4276             :         }
    4277        3206 :         jl = stmt_result(be, join, 0);
    4278        3206 :         if (en || (sexps && list_length(sexps))) {
    4279          87 :                 stmt *sub, *sel = NULL;
    4280          87 :                 list *nl;
    4281             : 
    4282          87 :                 jr = stmt_result(be, join, 1);
    4283             :                 /* construct relation */
    4284          87 :                 nl = sa_list(sql->sa);
    4285             : 
    4286             :                 /* first project after equi-joins */
    4287         430 :                 for (n = left->op4.lval->h; n; n = n->next) {
    4288         343 :                         stmt *c = n->data;
    4289         343 :                         assert(c->type == st_alias);
    4290         343 :                         sql_alias *rnme = table_name(sql->sa, c);
    4291         343 :                         const char *nme = column_name(sql->sa, c);
    4292         343 :                         stmt *s = stmt_project(be, jl, column(be, c));
    4293             : 
    4294         343 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    4295         343 :                         list_append(nl, s);
    4296             :                 }
    4297         245 :                 for (n = right->op4.lval->h; n; n = n->next) {
    4298         158 :                         stmt *c = n->data;
    4299         158 :                         assert(c->type == st_alias);
    4300         158 :                         sql_alias *rnme = table_name(sql->sa, c);
    4301         158 :                         const char *nme = column_name(sql->sa, c);
    4302         158 :                         stmt *s = stmt_project(be, jr, column(be, c));
    4303             : 
    4304         158 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    4305         158 :                         list_append(nl, s);
    4306             :                 }
    4307          87 :                 sub = stmt_list(be, nl);
    4308             : 
    4309             :                 /* continue with non equi-joins */
    4310         187 :                 while(sexps) {
    4311         100 :                         if (!en) {
    4312          87 :                                 en = sexps->h;
    4313          87 :                                 sexps = NULL;
    4314             :                         }
    4315         197 :                         for ( ; en; en = en->next) {
    4316          97 :                                 stmt *s = exp_bin(be, en->data, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    4317             : 
    4318          97 :                                 if (!s) {
    4319           0 :                                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    4320             :                                         return NULL;
    4321             :                                 }
    4322          97 :                                 if (s->nrcols == 0) {
    4323           2 :                                         stmt *l = bin_find_smallest_column(be, sub);
    4324           2 :                                         s = stmt_uselect(be, stmt_const(be, l, stmt_bool(be, 1)), s, cmp_equal, sel, 0, 0);
    4325             :                                 }
    4326          97 :                                 sel = s;
    4327             :                         }
    4328             :                 }
    4329             :                 /* recreate join output */
    4330          87 :                 jl = stmt_project(be, sel, jl);
    4331             :         }
    4332             : 
    4333             :         /* construct relation */
    4334        3206 :         l = sa_list(sql->sa);
    4335             : 
    4336             :         /* We did a full join, that's too much.
    4337             :            Reduce this using difference and intersect */
    4338        3206 :         if (!semijoin_only) {
    4339        3206 :                 c = stmt_mirror(be, bin_find_smallest_column(be, left));
    4340        3206 :                 if (rel->op == op_anti) {
    4341           0 :                         assert(0);
    4342             :                         join = stmt_tdiff(be, c, jl, lcand);
    4343             :                 } else {
    4344        3206 :                         if (lcand)
    4345        1144 :                                 join = stmt_semijoin(be, c, jl, lcand, NULL/*right->cand*/, 0, false);
    4346             :                         else
    4347        2062 :                                 join = stmt_tinter(be, c, jl, false);
    4348             :                 }
    4349             :         }
    4350             : 
    4351             :         /* project all the left columns */
    4352       24962 :         for (n = left->op4.lval->h; n; n = n->next) {
    4353       21756 :                 stmt *c = n->data, *s;
    4354       21756 :                 sql_alias *rnme = table_name(sql->sa, c);
    4355       21756 :                 const char *nme = column_name(sql->sa, c);
    4356             : 
    4357       21756 :                 if (semijoin_only && l_is_base && nme[0] == '%' && strcmp(nme, TID) == 0)
    4358             :                         s = join;
    4359             :                 else
    4360       21756 :                         s = stmt_project(be, join, column(be, c));
    4361             : 
    4362       21756 :                 s = stmt_alias(be, s, c->label, rnme, nme);
    4363       21756 :                 list_append(l, s);
    4364             :         }
    4365        3206 :         return stmt_list(be, l);
    4366             : }
    4367             : 
    4368             : static stmt *
    4369        1882 : rel2bin_distinct(backend *be, stmt *s, stmt **distinct)
    4370             : {
    4371        1882 :         mvc *sql = be->mvc;
    4372        1882 :         node *n;
    4373        1882 :         stmt *g = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
    4374        1882 :         list *rl = sa_list(sql->sa), *tids;
    4375             : 
    4376             :         /* single values are unique */
    4377        1882 :         if (s->key && s->nrcols == 0)
    4378             :                 return s;
    4379             : 
    4380             :         /* Use 'all' tid columns */
    4381        1867 :         if (/* DISABLES CODE */ (0) && (tids = bin_find_columns(be, s, TID)) != NULL) {
    4382             :                 for (n = tids->h; n; n = n->next) {
    4383             :                         stmt *t = n->data;
    4384             : 
    4385             :                         g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
    4386             :                         grp = stmt_result(be, g, 0);
    4387             :                         ext = stmt_result(be, g, 1);
    4388             :                         cnt = stmt_result(be, g, 2);
    4389             :                 }
    4390             :         } else {
    4391        4133 :                 for (n = s->op4.lval->h; n; n = n->next) {
    4392        2266 :                         stmt *t = n->data;
    4393             : 
    4394        2266 :                         g = stmt_group(be, column(be, t), grp, ext, cnt, !n->next);
    4395        2266 :                         grp = stmt_result(be, g, 0);
    4396        2266 :                         ext = stmt_result(be, g, 1);
    4397        2266 :                         cnt = stmt_result(be, g, 2);
    4398             :                 }
    4399             :         }
    4400        1867 :         if (!ext)
    4401             :                 return NULL;
    4402             : 
    4403        4133 :         for (n = s->op4.lval->h; n; n = n->next) {
    4404        2266 :                 stmt *t = n->data;
    4405             : 
    4406        2266 :                 stmt *s = stmt_project(be, ext, t);
    4407        2266 :                 t = stmt_alias(be, s, t->label, table_name(sql->sa, t), column_name(sql->sa, t));
    4408        2266 :                 list_append(rl, t);
    4409             :         }
    4410             : 
    4411        1867 :         if (distinct)
    4412         113 :                 *distinct = ext;
    4413        1867 :         s = stmt_list(be, rl);
    4414        1867 :         return s;
    4415             : }
    4416             : 
    4417             : static stmt *
    4418          11 : rel2bin_single(backend *be, stmt *s)
    4419             : {
    4420          11 :         if (!s || (s->key && s->nrcols == 0))
    4421             :                 return s;
    4422             : 
    4423          11 :         mvc *sql = be->mvc;
    4424          11 :         list *rl = sa_list(sql->sa);
    4425             : 
    4426          25 :         for (node *n = s->op4.lval->h; n; n = n->next) {
    4427          14 :                 stmt *t = n->data;
    4428          14 :                 assert(t->type == st_alias);
    4429          14 :                 sql_alias *rnme = table_name(sql->sa, t);
    4430          14 :                 const char *nme = column_name(sql->sa, t);
    4431          14 :                 int label = t->label;
    4432          14 :                 sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", "zero_or_one", tail_type(t), NULL, F_AGGR, true, true);
    4433             : 
    4434          14 :                 t = stmt_aggr(be, t, NULL, NULL, zero_or_one, 1, 0, 1);
    4435          14 :                 t = stmt_alias(be, t, label, rnme, nme);
    4436          14 :                 list_append(rl, t);
    4437             :         }
    4438          11 :         s = stmt_list(be, rl);
    4439          11 :         return s;
    4440             : }
    4441             : 
    4442             : static stmt *
    4443        6955 : rel_rename(backend *be, sql_rel *rel, stmt *sub)
    4444             : {
    4445        6955 :         if (rel->exps) {
    4446        6955 :                 node *en, *n;
    4447        6955 :                 list *l = sa_list(be->mvc->sa);
    4448             : 
    4449       32130 :                 for (en = rel->exps->h, n = sub->op4.lval->h; en && n; en = en->next, n = n->next) {
    4450       25175 :                         sql_exp *exp = en->data;
    4451       25175 :                         stmt *s = n->data;
    4452             : 
    4453       25175 :                         if (!s) {
    4454           0 :                                 assert(be->mvc->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    4455             :                                 return NULL;
    4456             :                         }
    4457       25175 :                         s = stmt_rename(be, exp, s);
    4458       25175 :                         list_append(l, s);
    4459             :                 }
    4460        6955 :                 sub = stmt_list(be, l);
    4461             :         }
    4462             :         return sub;
    4463             : }
    4464             : 
    4465             : static stmt*
    4466          71 : subres_assign_newresultvars(backend *be, stmt *rel_stmt)
    4467             : {
    4468          71 :         list *stmts = rel_stmt->op4.lval;
    4469          71 :         list *nstmt = sa_list(be->mvc->sa);
    4470         187 :         for (node *n = stmts->h; n; n = n->next) {
    4471         116 :                 stmt *r = n->data;
    4472         116 :                 InstrPtr a = newAssignment(be->mb);
    4473         116 :                 stmt *ns = NULL;
    4474         116 :                 sql_alias *rnme = table_name(be->mvc->sa, r);
    4475         116 :                 const char *nme = column_name(be->mvc->sa, r);
    4476         116 :                 int label = r->label;
    4477             : 
    4478         116 :                 if (r->nrcols == 0)
    4479          43 :                         r = const_column(be, r);
    4480         116 :                 ns = stmt_alias(be, r, label, rnme, nme);
    4481         116 :                 ns->flag = cmp_project; /* mark as special */
    4482         116 :                 a = pushArgument(be->mb, a, ns->nr);
    4483         116 :                 pushInstruction(be->mb, a);
    4484         116 :                 ns->q = a;
    4485         116 :                 ns->nr = a->argv[0];
    4486         116 :                 append(nstmt, ns);
    4487             :         }
    4488          71 :         return stmt_list(be, nstmt);
    4489             : }
    4490             : 
    4491             : static stmt*
    4492         102 : subres_assign_resultvars(backend *be, stmt *rel_stmt, list *vars)
    4493             : {
    4494         102 :         list *stmts = rel_stmt->op4.lval;
    4495         102 :         list *nstmt = sa_list(be->mvc->sa);
    4496         262 :         for (node *n = stmts->h, *m = vars->h; n && m; n = n->next, m = m->next) {
    4497         160 :                 stmt *r = n->data;
    4498         160 :                 stmt *v = m->data;
    4499         160 :                 InstrPtr a = newAssignment(be->mb);
    4500         160 :                 stmt *ns = NULL;
    4501         160 :                 sql_alias *rnme = table_name(be->mvc->sa, r);
    4502         160 :                 const char *nme = column_name(be->mvc->sa, r);
    4503         160 :                 int label = r->label;
    4504             : 
    4505         160 :                 if (r->nrcols == 0)
    4506           4 :                         r = const_column(be, r);
    4507         160 :                 ns = stmt_alias(be, r, label, rnme, nme);
    4508         160 :                 a->argv[0] = v->nr;
    4509         160 :                 a = pushArgument(be->mb, a, ns->nr);
    4510         160 :                 pushInstruction(be->mb, a);
    4511         160 :                 ns->q = a;
    4512         160 :                 ns->nr = a->argv[0];
    4513         160 :                 append(nstmt, ns);
    4514             :         }
    4515         102 :         return stmt_list(be, nstmt);
    4516             : }
    4517             : 
    4518             : static sql_exp*
    4519       16924 : topn_limit(sql_rel *rel)
    4520             : {
    4521       16924 :         if (rel->exps) {
    4522       16924 :                 sql_exp *limit = rel->exps->h->data;
    4523       16924 :                 if (exp_is_null(limit)) /* If the limit is NULL, ignore the value */
    4524             :                         return NULL;
    4525             :                 return limit;
    4526             :         }
    4527             :         return NULL;
    4528             : }
    4529             : 
    4530             : static sql_exp*
    4531       16924 : topn_offset(sql_rel *rel)
    4532             : {
    4533       16924 :         if (rel->exps && list_length(rel->exps) > 1) {
    4534         150 :                 sql_exp *offset = rel->exps->h->next->data;
    4535             : 
    4536         150 :                 return offset;
    4537             :         }
    4538             :         return NULL;
    4539             : }
    4540             : 
    4541             : static stmt *
    4542      400919 : stmt_limit_value(backend *be, sql_rel *topn)
    4543             : {
    4544      400919 :         stmt *l = NULL;
    4545             : 
    4546      400919 :         if (topn) {
    4547         331 :                 sql_exp *le = topn_limit(topn);
    4548         331 :                 sql_exp *oe = topn_offset(topn);
    4549             : 
    4550         331 :                 if (le) {
    4551         306 :                         l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    4552         306 :                         if(!l)
    4553             :                                 return NULL;
    4554         306 :                         if (oe) {
    4555          42 :                                 sql_subtype *lng = sql_bind_localtype("lng");
    4556          42 :                                 sql_subfunc *add = sql_bind_func_result(be->mvc, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
    4557          42 :                                 stmt *o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    4558          42 :                                 if(!o)
    4559             :                                         return NULL;
    4560          42 :                                 l = stmt_binop(be, l, o, NULL, add);
    4561             :                         }
    4562             :                 }
    4563             :         }
    4564             :         return l;
    4565             : }
    4566             : 
    4567             : static stmt *
    4568          71 : rel2bin_recursive_munion(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
    4569             : {
    4570          71 :         mvc *sql = be->mvc;
    4571          71 :         stmt *rel_stmt = NULL, *sub = NULL;
    4572          71 :         int nr_unions = list_length((list*)rel->l);
    4573          71 :         if (nr_unions != 2)
    4574           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "UNION: recursive unions need a base and recursive part");
    4575          71 :         stmt *l = stmt_limit_value(be, topn);
    4576             : 
    4577          71 :         bool distinct = need_distinct(rel);
    4578          71 :         sql_rel *base = ((list*)rel->l)->h->data;
    4579          71 :         sql_rel *recursive = ((list*)rel->l)->h->next->data;
    4580             : 
    4581             :         /* base part */
    4582          71 :         rel_stmt = subrel_bin(be, base, refs);
    4583          71 :         rel_stmt = subrel_project(be, rel_stmt, refs, base);
    4584          71 :         if (!rel_stmt)
    4585             :                 return NULL;
    4586             : 
    4587          71 :         if (recursive) {
    4588          71 :                 int gcnt = 0;
    4589          71 :                 list *result_table = sa_list(be->mvc->sa);
    4590         187 :                 for(node *n = rel->exps->h; n; n = n->next) {
    4591         116 :                         sql_exp *e = n->data;
    4592         116 :                         stmt *s = stmt_bat_new(be, exp_subtype(e), -1);
    4593         116 :                         append(result_table, s);
    4594             :                 }
    4595          71 :                 rel_stmt = subres_assign_newresultvars(be, rel_stmt);
    4596          71 :                 if (distinct)
    4597          31 :                         rel_stmt = rel2bin_distinct(be, rel_stmt, NULL);
    4598          71 :                 refs_update_stmt(refs, base, rel_stmt);
    4599             : 
    4600             :                 /* cnt = count(temptable) */
    4601          71 :                 sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    4602          71 :                 stmt *cnts = stmt_aggr(be, rel_stmt->op4.lval->h->data, NULL, NULL, cnt, 1, 0, 1);
    4603             : 
    4604             :                 /* if topn keep total count */
    4605          71 :                 if (l) {
    4606           4 :                         InstrPtr r = newAssignment(be->mb);
    4607           4 :                         gcnt = r->argv[0];
    4608           4 :                         r->argc = r->retc = 1;
    4609           4 :                         r = pushArgument(be->mb, r, cnts->nr);
    4610           4 :                         pushInstruction(be->mb, r);
    4611             :                 }
    4612             : 
    4613             :                 /* while cnt > 0 (and total < limit): */
    4614          71 :                 InstrPtr r = newAssignment(be->mb);
    4615          71 :                 if (r == NULL)
    4616             :                         return NULL;
    4617          71 :                 int barrier_var = r->argv[0];
    4618          71 :                 r->argc = r->retc = 1;
    4619          71 :                 r->barrier = BARRIERsymbol;
    4620          71 :                 r = pushBit(be->mb, r, TRUE);
    4621          71 :                 pushInstruction(be->mb, r);
    4622             : 
    4623          71 :                 if (l)
    4624           4 :                         r = newStmtArgs(be->mb, calcRef, "between", 9);
    4625             :                 else
    4626          67 :                         r = newStmtArgs(be->mb, calcRef, "<=", 3);
    4627          71 :                 if (r == NULL)
    4628             :                         return NULL;
    4629          71 :                 getArg(r, 0) = barrier_var;
    4630          71 :                 r->barrier = LEAVEsymbol;
    4631          71 :                 r = pushArgument(be->mb, r, cnts->nr);
    4632          71 :                 r = pushLng(be->mb, r, 0);
    4633          71 :                 if (l) {
    4634           4 :                         r = pushArgument(be->mb, r, l->nr);
    4635           4 :                         r = pushBit(be->mb, r, FALSE); /* not symmetrical */
    4636           4 :                         r = pushBit(be->mb, r, TRUE);  /* including lower bound */
    4637           4 :                         r = pushBit(be->mb, r, FALSE); /* excluding upper bound */
    4638           4 :                         r = pushBit(be->mb, r, FALSE); /* nils_false */
    4639           4 :                         r = pushBit(be->mb, r, TRUE);  /* anti */
    4640             :                 }
    4641          71 :                 pushInstruction(be->mb, r);
    4642             : 
    4643             :                 /* insert temptable into result_table and make link between result_table and table name */
    4644         187 :                 for(node *n = result_table->h, *m = rel_stmt->op4.lval->h; n && m; n = n->next, m = m->next) {
    4645         116 :                         stmt *a = m->data;
    4646         116 :                         stmt *v = n->data;
    4647         116 :                         stmt *r = stmt_append(be, v, a);
    4648         116 :                         r->nr = r->q->argv[0] = v->nr;
    4649         116 :                         n->data = stmt_alias(be, r, a->label, a->tname, a->cname);
    4650             :                 }
    4651             : 
    4652          71 :                 if (l) {
    4653           4 :                         InstrPtr r = newStmtArgs(be->mb, calcRef, "+", 3);
    4654           4 :                         r->argv[0] = gcnt;
    4655           4 :                         r->argc = r->retc = 1;
    4656           4 :                         r = pushArgument(be->mb, r, cnts->nr);
    4657           4 :                         r = pushArgument(be->mb, r, gcnt);
    4658           4 :                         pushInstruction(be->mb, r);
    4659             : 
    4660           4 :                         r = newStmtArgs(be->mb, calcRef, ">", 3);
    4661           4 :                         if (r == NULL)
    4662             :                                 return NULL;
    4663           4 :                         getArg(r, 0) = barrier_var;
    4664           4 :                         r->barrier = LEAVEsymbol;
    4665           4 :                         r = pushArgument(be->mb, r, gcnt);
    4666           4 :                         r = pushArgument(be->mb, r, l->nr);
    4667           4 :                         pushInstruction(be->mb, r);
    4668             :                 }
    4669             : 
    4670             :                 /* recursive part */
    4671          71 :                 stmt *rec = subrel_bin(be, recursive, refs);
    4672          71 :                 if (!rec)
    4673             :                         return NULL;
    4674          71 :                 rec = subrel_project(be, rec, refs, recursive);
    4675          71 :                 rec = subres_assign_resultvars(be, rec, rel_stmt->op4.lval);
    4676          71 :                 if (distinct) {
    4677          31 :                         rec = rel2bin_distinct(be, rec, NULL);
    4678             :                         /* remove values already in the result table */
    4679          31 :                         stmt *s = releqjoin(be, rec->op4.lval, result_table, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
    4680          31 :                         stmt *lm = stmt_result(be, s, 0);
    4681             : 
    4682          31 :                         s = stmt_mirror(be, rec->op4.lval->h->data);
    4683          31 :                         s = stmt_tdiff(be, s, lm, NULL);
    4684          31 :                         rec->cand = s;
    4685          31 :                         rec = subrel_project(be, rec, refs, recursive);
    4686          31 :                         rec = subres_assign_resultvars(be, rec, rel_stmt->op4.lval);
    4687             :                 }
    4688             : 
    4689             :                 /* cnt = count(temptable) */
    4690          71 :                 stmt *s = stmt_aggr(be, rec->op4.lval->h->data, NULL, NULL, cnt, 1, 0, 1);
    4691          71 :                 s->nr = s->q->argv[0] = cnts->nr;
    4692             : 
    4693             :                 /* jump back */
    4694          71 :                 r = newStmtArgs(be->mb, calcRef, ">", 3);
    4695          71 :                 if (r == NULL)
    4696             :                         return NULL;
    4697          71 :                 getArg(r, 0) = barrier_var;
    4698          71 :                 r->argc = r->retc = 1;
    4699          71 :                 r = pushArgument(be->mb, r, cnts->nr);
    4700          71 :                 r = pushLng(be->mb, r, 0);
    4701          71 :                 r->barrier = REDOsymbol;
    4702          71 :                 pushInstruction(be->mb, r);
    4703             : 
    4704          71 :                 r = newAssignment(be->mb);
    4705          71 :                 if (r == NULL)
    4706             :                         return NULL;
    4707          71 :                 getArg(r, 0) = barrier_var;
    4708          71 :                 r->argc = r->retc = 1;
    4709          71 :                 r->barrier = EXITsymbol;
    4710          71 :                 pushInstruction(be->mb, r);
    4711             : 
    4712             :                 /* relabel */
    4713         187 :                 for(node *n = result_table->h, *m = rel->exps->h; n && m; n = n->next, m = m->next) {
    4714         116 :                         stmt *r = n->data;
    4715         116 :                         sql_exp *e = m->data;
    4716         116 :                         const char *cname = exp_name(e);
    4717         116 :                         sql_alias *tname = exp_relname(e);
    4718             : 
    4719         116 :                         n->data = stmt_alias(be, r, e->alias.label, tname, cname);
    4720             :                 }
    4721          71 :                 sub = stmt_list(be, result_table);
    4722             :         }
    4723             : 
    4724          71 :         if (is_single(rel))
    4725           0 :                 sub = rel2bin_single(be, sub);
    4726             :         return sub;
    4727             : }
    4728             : 
    4729             : static stmt *
    4730        4319 : rel2bin_munion(backend *be, sql_rel *rel, list *refs)
    4731             : {
    4732        4319 :         if (is_recursive(rel))
    4733          67 :                 return rel2bin_recursive_munion(be, rel, refs, NULL);
    4734             : 
    4735        4252 :         mvc *sql = be->mvc;
    4736        4252 :         list *l, *rstmts;
    4737        4252 :         node *n, *m;
    4738        4252 :         stmt *rel_stmt = NULL, *sub;
    4739        4252 :         int i, len = 0, nr_unions = list_length((list*)rel->l);
    4740             : 
    4741             :         /* convert to stmt and store the munion operands in rstmts list */
    4742        4252 :         rstmts = sa_list(sql->sa);
    4743       15665 :         for (n = ((list*)rel->l)->h; n; n = n->next) {
    4744       11413 :                 rel_stmt = subrel_bin(be, n->data, refs);
    4745       11413 :                 rel_stmt = subrel_project(be, rel_stmt, refs, n->data);
    4746       11413 :                 if (!rel_stmt)
    4747             :                         return NULL;
    4748       11413 :                 list_append(rstmts, rel_stmt);
    4749       11413 :                 if (!len || len > list_length(rel_stmt->op4.lval))
    4750        4252 :                         len = list_length(rel_stmt->op4.lval);
    4751             :         }
    4752             : 
    4753             :         /* construct relation */
    4754        4252 :         l = sa_list(sql->sa);
    4755             : 
    4756             :         /* for every op4 lval node */
    4757       24974 :         for (i = 0; i < len; i++) {
    4758             :                 /* extract t and c name from the first stmt */
    4759       16470 :                 stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
    4760       16470 :                 if (s == NULL)
    4761             :                         return NULL;
    4762       16470 :                 sql_alias *rnme = table_name(sql->sa, s);
    4763       16470 :                 const char *nme = column_name(sql->sa, s);
    4764       16470 :                 int label = s->label;
    4765             :                 /* create a const column also from the first stmt */
    4766       16470 :                 s = stmt_pack(be, column(be, s), nr_unions);
    4767             :                 /* for every other rstmt */
    4768       46639 :                 for (m = rstmts->h->next; m; m = m->next) {
    4769       30169 :                         stmt *t = list_fetch(((stmt*)m->data)->op4.lval, i);
    4770       30169 :                         if (t == NULL)
    4771             :                                 return NULL;
    4772       30169 :                         s = stmt_pack_add(be, s, column(be, t));
    4773       30169 :                         if (s == NULL)
    4774             :                                 return NULL;
    4775             :                 }
    4776       16470 :                 s = stmt_alias(be, s, label, rnme, nme);
    4777       16470 :                 if (s == NULL)
    4778             :                         return NULL;
    4779       16470 :                 list_append(l, s);
    4780             :         }
    4781        4252 :         sub = stmt_list(be, l);
    4782             : 
    4783        4252 :         sub = rel_rename(be, rel, sub);
    4784        4252 :         if (need_distinct(rel))
    4785        1692 :                 sub = rel2bin_distinct(be, sub, NULL);
    4786        4252 :         if (is_single(rel))
    4787          11 :                 sub = rel2bin_single(be, sub);
    4788             :         return sub;
    4789             : }
    4790             : 
    4791             : static stmt *
    4792         303 : rel2bin_union(backend *be, sql_rel *rel, list *refs)
    4793             : {
    4794         303 :         mvc *sql = be->mvc;
    4795         303 :         list *l;
    4796         303 :         node *n, *m;
    4797         303 :         stmt *left = NULL, *right = NULL, *sub;
    4798             : 
    4799         303 :         if (rel->l) /* first construct the left sub relation */
    4800         303 :                 left = subrel_bin(be, rel->l, refs);
    4801         303 :         if (rel->r) /* first construct the right sub relation */
    4802         303 :                 right = subrel_bin(be, rel->r, refs);
    4803         303 :         left = subrel_project(be, left, refs, rel->l);
    4804         303 :         right = subrel_project(be, right, refs, rel->r);
    4805         303 :         if (!left || !right)
    4806             :                 return NULL;
    4807             : 
    4808             :         /* construct relation */
    4809         303 :         l = sa_list(sql->sa);
    4810        6331 :         for (n = left->op4.lval->h, m = right->op4.lval->h; n && m;
    4811        6028 :                  n = n->next, m = m->next) {
    4812        6028 :                 stmt *c1 = n->data;
    4813        6028 :                 assert(c1->type == st_alias);
    4814        6028 :                 stmt *c2 = m->data;
    4815        6028 :                 sql_alias *rnme = table_name(sql->sa, c1);
    4816        6028 :                 const char *nme = column_name(sql->sa, c1);
    4817        6028 :                 stmt *s;
    4818             : 
    4819        6028 :                 s = stmt_append(be, create_const_column(be, c1, NULL), c2);
    4820        6028 :                 if (s == NULL)
    4821             :                         return NULL;
    4822        6028 :                 s = stmt_alias(be, s, c1->label, rnme, nme);
    4823        6028 :                 if (s == NULL)
    4824             :                         return NULL;
    4825        6028 :                 list_append(l, s);
    4826             :         }
    4827         303 :         sub = stmt_list(be, l);
    4828             : 
    4829         303 :         sub = rel_rename(be, rel, sub);
    4830         303 :         if (need_distinct(rel))
    4831           0 :                 sub = rel2bin_distinct(be, sub, NULL);
    4832         303 :         if (is_single(rel))
    4833           0 :                 sub = rel2bin_single(be, sub);
    4834             :         return sub;
    4835             : }
    4836             : 
    4837             : static stmt *
    4838        2025 : rel2bin_except(backend *be, sql_rel *rel, list *refs)
    4839             : {
    4840        2025 :         mvc *sql = be->mvc;
    4841        2025 :         sql_subtype *lng = sql_bind_localtype("lng");
    4842        2025 :         list *stmts;
    4843        2025 :         node *n, *m;
    4844        2025 :         stmt *left = NULL, *right = NULL, *sub;
    4845        2025 :         sql_subfunc *min;
    4846             : 
    4847        2025 :         stmt *lg = NULL, *rg = NULL;
    4848        2025 :         stmt *lgrp = NULL, *rgrp = NULL;
    4849        2025 :         stmt *lext = NULL, *rext = NULL, *next = NULL;
    4850        2025 :         stmt *lcnt = NULL, *rcnt = NULL, *ncnt = NULL, *zero = NULL;
    4851        2025 :         stmt *s, *lm, *rm;
    4852        2025 :         list *lje = sa_list(sql->sa);
    4853        2025 :         list *rje = sa_list(sql->sa);
    4854             : 
    4855        2025 :         if (rel->l) /* first construct the left sub relation */
    4856        2025 :                 left = subrel_bin(be, rel->l, refs);
    4857        2025 :         if (rel->r) /* first construct the right sub relation */
    4858        2025 :                 right = subrel_bin(be, rel->r, refs);
    4859        2025 :         if (!left || !right)
    4860             :                 return NULL;
    4861        2025 :         left = subrel_project(be, left, refs, rel->l);
    4862        2025 :         right = subrel_project(be, right, refs, rel->r);
    4863        2025 :         left = row2cols(be, left);
    4864        2025 :         right = row2cols(be, right);
    4865             : 
    4866             :         /*
    4867             :          * The multi column except is handled using group by's and
    4868             :          * group size counts on both sides of the intersect. We then
    4869             :          * return for each group of L with min(L.count,R.count),
    4870             :          * number of rows.
    4871             :          */
    4872        4239 :         for (n = left->op4.lval->h; n; n = n->next) {
    4873        2214 :                 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
    4874        2214 :                 lgrp = stmt_result(be, lg, 0);
    4875        2214 :                 lext = stmt_result(be, lg, 1);
    4876        2214 :                 lcnt = stmt_result(be, lg, 2);
    4877             :         }
    4878        4239 :         for (n = right->op4.lval->h; n; n = n->next) {
    4879        2214 :                 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
    4880        2214 :                 rgrp = stmt_result(be, rg, 0);
    4881        2214 :                 rext = stmt_result(be, rg, 1);
    4882        2214 :                 rcnt = stmt_result(be, rg, 2);
    4883             :         }
    4884             : 
    4885        2025 :         if (!lg || !rg)
    4886             :                 return NULL;
    4887             : 
    4888        2025 :         if (need_distinct(rel)) {
    4889        1943 :                 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
    4890        1943 :                 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
    4891             :         }
    4892             : 
    4893             :         /* now find the matching groups */
    4894        4239 :         for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
    4895        2214 :                 stmt *l = column(be, n->data);
    4896        2214 :                 stmt *r = column(be, m->data);
    4897             : 
    4898        2214 :                 l = stmt_project(be, lext, l);
    4899        2214 :                 r = stmt_project(be, rext, r);
    4900        2214 :                 list_append(lje, l);
    4901        2214 :                 list_append(rje, r);
    4902             :         }
    4903        2025 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /*is_semantics*/);
    4904        2025 :         lm = stmt_result(be, s, 0);
    4905        2025 :         rm = stmt_result(be, s, 1);
    4906             : 
    4907        2025 :         s = stmt_mirror(be, lext);
    4908        2025 :         s = stmt_tdiff(be, s, lm, NULL);
    4909             : 
    4910             :         /* first we find those missing in R */
    4911        2025 :         next = stmt_project(be, s, lext);
    4912        2025 :         ncnt = stmt_project(be, s, lcnt);
    4913        2025 :         zero = stmt_const(be, s, stmt_atom_lng(be, 0));
    4914             : 
    4915             :         /* ext, lcount, rcount */
    4916        2025 :         lext = stmt_project(be, lm, lext);
    4917        2025 :         lcnt = stmt_project(be, lm, lcnt);
    4918        2025 :         rcnt = stmt_project(be, rm, rcnt);
    4919             : 
    4920             :         /* append those missing in L */
    4921        2025 :         lext = stmt_append(be, lext, next);
    4922        2025 :         lcnt = stmt_append(be, lcnt, ncnt);
    4923        2025 :         rcnt = stmt_append(be, rcnt, zero);
    4924             : 
    4925        2025 :         min = sql_bind_func_result(sql, "sys", "sql_sub", F_FUNC, true, lng, 2, lng, lng);
    4926        2025 :         s = stmt_binop(be, lcnt, rcnt, NULL, min); /* use count */
    4927             : 
    4928             :         /* now we have gid,cnt, blowup to full groupsizes */
    4929        2025 :         s = stmt_gen_group(be, lext, s);
    4930             : 
    4931             :         /* project columns of left hand expression */
    4932        2025 :         stmts = sa_list(sql->sa);
    4933        4239 :         for (n = left->op4.lval->h; n; n = n->next) {
    4934        2214 :                 stmt *c1 = column(be, n->data);
    4935        2214 :                 assert(c1->type == st_alias);
    4936        2214 :                 sql_alias *rnme = NULL;
    4937        2214 :                 const char *nme = column_name(sql->sa, c1);
    4938        2214 :                 int label = c1->label;
    4939             : 
    4940             :                 /* retain name via the stmt_alias */
    4941        2214 :                 c1 = stmt_project(be, s, c1);
    4942             : 
    4943        2214 :                 rnme = table_name(sql->sa, c1);
    4944        2214 :                 c1 = stmt_alias(be, c1, label, rnme, nme);
    4945        2214 :                 list_append(stmts, c1);
    4946             :         }
    4947        2025 :         sub = stmt_list(be, stmts);
    4948        2025 :         return rel_rename(be, rel, sub);
    4949             : }
    4950             : 
    4951             : static stmt *
    4952         375 : rel2bin_inter(backend *be, sql_rel *rel, list *refs)
    4953             : {
    4954         375 :         mvc *sql = be->mvc;
    4955         375 :         sql_subtype *lng = sql_bind_localtype("lng");
    4956         375 :         list *stmts;
    4957         375 :         node *n, *m;
    4958         375 :         stmt *left = NULL, *right = NULL, *sub;
    4959         375 :         sql_subfunc *min;
    4960             : 
    4961         375 :         stmt *lg = NULL, *rg = NULL;
    4962         375 :         stmt *lgrp = NULL, *rgrp = NULL;
    4963         375 :         stmt *lext = NULL, *rext = NULL;
    4964         375 :         stmt *lcnt = NULL, *rcnt = NULL;
    4965         375 :         stmt *s, *lm, *rm;
    4966         375 :         list *lje = sa_list(sql->sa);
    4967         375 :         list *rje = sa_list(sql->sa);
    4968             : 
    4969         375 :         if (rel->l) /* first construct the left sub relation */
    4970         375 :                 left = subrel_bin(be, rel->l, refs);
    4971         375 :         if (rel->r) /* first construct the right sub relation */
    4972         375 :                 right = subrel_bin(be, rel->r, refs);
    4973         375 :         left = subrel_project(be, left, refs, rel->l);
    4974         375 :         right = subrel_project(be, right, refs, rel->r);
    4975         375 :         if (!left || !right)
    4976             :                 return NULL;
    4977         375 :         left = row2cols(be, left);
    4978             : 
    4979             :         /*
    4980             :          * The multi column intersect is handled using group by's and
    4981             :          * group size counts on both sides of the intersect. We then
    4982             :          * return for each group of L with min(L.count,R.count),
    4983             :          * number of rows.
    4984             :          */
    4985         839 :         for (n = left->op4.lval->h; n; n = n->next) {
    4986         464 :                 lg = stmt_group(be, column(be, n->data), lgrp, lext, lcnt, !n->next);
    4987         464 :                 lgrp = stmt_result(be, lg, 0);
    4988         464 :                 lext = stmt_result(be, lg, 1);
    4989         464 :                 lcnt = stmt_result(be, lg, 2);
    4990             :         }
    4991         839 :         for (n = right->op4.lval->h; n; n = n->next) {
    4992         464 :                 rg = stmt_group(be, column(be, n->data), rgrp, rext, rcnt, !n->next);
    4993         464 :                 rgrp = stmt_result(be, rg, 0);
    4994         464 :                 rext = stmt_result(be, rg, 1);
    4995         464 :                 rcnt = stmt_result(be, rg, 2);
    4996             :         }
    4997             : 
    4998         375 :         if (!lg || !rg)
    4999             :                 return NULL;
    5000             : 
    5001         375 :         if (need_distinct(rel)) {
    5002         364 :                 lcnt = stmt_const(be, lcnt, stmt_atom_lng(be, 1));
    5003         364 :                 rcnt = stmt_const(be, rcnt, stmt_atom_lng(be, 1));
    5004             :         }
    5005             : 
    5006             :         /* now find the matching groups */
    5007         839 :         for (n = left->op4.lval->h, m = right->op4.lval->h; n && m; n = n->next, m = m->next) {
    5008         464 :                 stmt *l = column(be, n->data);
    5009         464 :                 stmt *r = column(be, m->data);
    5010             : 
    5011         464 :                 l = stmt_project(be, lext, l);
    5012         464 :                 r = stmt_project(be, rext, r);
    5013         464 :                 list_append(lje, l);
    5014         464 :                 list_append(rje, r);
    5015             :         }
    5016         375 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 1 /* is_semantics */);
    5017         375 :         lm = stmt_result(be, s, 0);
    5018         375 :         rm = stmt_result(be, s, 1);
    5019             : 
    5020             :         /* ext, lcount, rcount */
    5021         375 :         lext = stmt_project(be, lm, lext);
    5022         375 :         lcnt = stmt_project(be, lm, lcnt);
    5023         375 :         rcnt = stmt_project(be, rm, rcnt);
    5024             : 
    5025         375 :         min = sql_bind_func(sql, "sys", "sql_min", lng, lng, F_FUNC, true, true);
    5026         375 :         s = stmt_binop(be, lcnt, rcnt, NULL, min);
    5027             : 
    5028             :         /* now we have gid,cnt, blowup to full groupsizes */
    5029         375 :         s = stmt_gen_group(be, lext, s);
    5030             : 
    5031             :         /* project columns of left hand expression */
    5032         375 :         stmts = sa_list(sql->sa);
    5033         839 :         for (n = left->op4.lval->h; n; n = n->next) {
    5034         464 :                 stmt *c1 = column(be, n->data);
    5035         464 :                 assert(c1->type == st_alias);
    5036         464 :                 sql_alias *rnme = NULL;
    5037         464 :                 const char *nme = column_name(sql->sa, c1);
    5038         464 :                 int label = c1->label;
    5039             : 
    5040             :                 /* retain name via the stmt_alias */
    5041         464 :                 c1 = stmt_project(be, s, c1);
    5042             : 
    5043         464 :                 rnme = table_name(sql->sa, c1);
    5044         464 :                 c1 = stmt_alias(be, c1, label, rnme, nme);
    5045         464 :                 list_append(stmts, c1);
    5046             :         }
    5047         375 :         sub = stmt_list(be, stmts);
    5048         375 :         return rel_rename(be, rel, sub);
    5049             : }
    5050             : 
    5051             : static int
    5052       47250 : find_matching_exp(list *exps, sql_exp *e)
    5053             : {
    5054       47250 :         int i = 0;
    5055      162735 :         for (node *n = exps->h; n; n = n->next, i++) {
    5056      137193 :                 if (exp_match(n->data, e))
    5057       21708 :                         return i;
    5058             :         }
    5059             :         return -1;
    5060             : }
    5061             : 
    5062             : static stmt *
    5063       12729 : sql_reorder(backend *be, stmt *order, list *exps, stmt *s, list *oexps, list *ostmts)
    5064             : {
    5065       12729 :         list *l = sa_list(be->mvc->sa);
    5066             : 
    5067       59979 :         for (node *n = s->op4.lval->h, *m = exps->h; n && m; n = n->next, m = m->next) {
    5068       47250 :                 int pos = 0;
    5069       47250 :                 stmt *sc = n->data;
    5070       47250 :                 sql_exp *pe = m->data;
    5071       47250 :                 const char *cname = column_name(be->mvc->sa, sc);
    5072       47250 :                 sql_alias *tname = table_name(be->mvc->sa, sc);
    5073             : 
    5074       47250 :                 if (oexps && (pos = find_matching_exp(oexps, pe)) >= 0 && list_fetch(ostmts, pos)) {
    5075       21708 :                         sc = list_fetch(ostmts, pos);
    5076             :                 } else {
    5077       25542 :                         sc = stmt_project(be, order, sc);
    5078             :                 }
    5079       47250 :                 sc = stmt_alias(be, sc, pe->alias.label, tname, cname);
    5080       47250 :                 list_append(l, sc);
    5081             :         }
    5082       12729 :         return stmt_list(be, l);
    5083             : }
    5084             : 
    5085             : static stmt *
    5086      400877 : rel2bin_project(backend *be, sql_rel *rel, list *refs, sql_rel *topn)
    5087             : {
    5088      400877 :         mvc *sql = be->mvc;
    5089      400877 :         list *pl;
    5090      400877 :         node *en, *n;
    5091      400877 :         stmt *sub = NULL, *psub = NULL;
    5092      400877 :         stmt *l = NULL;
    5093             : 
    5094      400877 :         if (!rel->exps)
    5095           0 :                 return stmt_none(be);
    5096             : 
    5097      400877 :         l = stmt_limit_value(be, topn);
    5098      400853 :         if (!l)
    5099      400550 :                 topn = NULL;
    5100             : 
    5101      400853 :         if (rel->l) { /* first construct the sub relation */
    5102      224375 :                 sql_rel *l = rel->l;
    5103      224375 :                 if (l->op == op_ddl) {
    5104        1212 :                         sql_table *t = rel_ddl_table_get(l);
    5105             : 
    5106        1212 :                         if (t)
    5107        1212 :                                 sub = rel2bin_sql_table(be, t, rel->exps);
    5108             :                 } else {
    5109      223163 :                         sub = subrel_bin(be, rel->l, refs);
    5110             :                 }
    5111      224342 :                 sub = subrel_project(be, sub, refs, rel->l);
    5112      224310 :                 if (!sub)
    5113             :                         return NULL;
    5114             :         }
    5115             : 
    5116      400788 :         pl = sa_list(sql->sa);
    5117      400848 :         if (pl == NULL)
    5118             :                 return NULL;
    5119      400848 :         if (sub)
    5120      224349 :                 pl->expected_cnt = list_length(sub->op4.lval);
    5121      400867 :         psub = stmt_list(be, pl);
    5122      400834 :         if (psub == NULL)
    5123             :                 return NULL;
    5124     2025580 :         for (en = rel->exps->h; en; en = en->next) {
    5125     1624692 :                 sql_exp *exp = en->data;
    5126             : 
    5127     1624692 :                 if (exp->virt) {
    5128             :                         /* we need to ouput composite properly, for insert statements */
    5129           0 :                         continue;
    5130             :                 }
    5131     1624692 :                 int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
    5132     1624692 :                 stmt *s = exp_bin(be, exp, sub, NULL /*psub*/, NULL, NULL, NULL, NULL, 0, 0, 0);
    5133             : 
    5134     1624795 :                 if (!s) { /* try with own projection as well, but first clean leftover statements */
    5135       11254 :                         clean_mal_statements(be, oldstop, oldvtop);
    5136       11254 :                         s = exp_bin(be, exp, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    5137             :                 }
    5138       11254 :                 if (!s) /* error */
    5139             :                         return NULL;
    5140             :                 /* single value with limit */
    5141     1624795 :                 if (topn && rel->r && sub && sub->nrcols == 0 && s->nrcols == 0)
    5142          14 :                         s = const_column(be, s);
    5143     1624781 :                 else if (sub && sub->nrcols >= 1 && s->nrcols == 0)
    5144       31716 :                         s = stmt_const(be, bin_find_smallest_column(be, sub), s);
    5145             : 
    5146     1624795 :                 if (!exp_name(exp))
    5147       80175 :                         exp_label(sql->sa, exp, ++sql->label);
    5148     1624537 :                 if (exp_name(exp)) {
    5149     1624766 :                         s = stmt_rename(be, exp, s);
    5150             :                         //column_name(sql->sa, s); /* save column name */
    5151     1625168 :                         s->label = exp->alias.label;
    5152             :                 }
    5153     1625168 :                 list_append(pl, s);
    5154             :         }
    5155      400888 :         stmt_set_nrcols(psub);
    5156             : 
    5157             :         /* In case of a topn
    5158             :                 if both order by and distinct: then get first order by col
    5159             :                 do topn on it. Project all again! Then rest
    5160             :         */
    5161      400843 :         if (topn && rel->r) {
    5162         282 :                 list *oexps = rel->r, *npl = sa_list(sql->sa);
    5163             :                 /* distinct, topn returns at least N (unique groups) */
    5164         282 :                 int distinct = need_distinct(rel);
    5165         282 :                 stmt *limit = NULL, *lpiv = NULL, *lgid = NULL;
    5166         282 :                 int nr_obe = list_length(oexps);
    5167             : 
    5168             :                 /* check for partition columns */
    5169         282 :                 stmt *grp = NULL, *ext = NULL, *cnt = NULL;
    5170         288 :                 for (n=oexps->h; n; n = n->next, nr_obe--) {
    5171         288 :                         sql_exp *gbe = n->data;
    5172         288 :                         bool last = (!n->next || !is_partitioning((sql_exp*)n->next->data));
    5173             : 
    5174         288 :                         if (!topn->grouped || !is_partitioning(gbe))
    5175             :                                 break;
    5176             :                         /* create group by */
    5177           6 :                         stmt *gbcol = exp_bin(be, gbe, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5178             : 
    5179           6 :                         if (!gbcol) {
    5180           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    5181             :                                 return NULL;
    5182             :                         }
    5183           6 :                         if (!gbcol->nrcols)
    5184           0 :                                 gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
    5185           6 :                         stmt *groupby = stmt_group(be, gbcol, grp, ext, cnt, last);
    5186           6 :                         grp = stmt_result(be, groupby, 0);
    5187           6 :                         ext = stmt_result(be, groupby, 1);
    5188           6 :                         cnt = stmt_result(be, groupby, 2);
    5189           6 :                         gbcol = stmt_alias(be, gbcol, gbe->alias.label, exp_find_rel_name(gbe), exp_name(gbe));
    5190             :                 }
    5191             : 
    5192         282 :                 if (grp)
    5193             :                         lgid = grp;
    5194         874 :                 for (; n; n = n->next, nr_obe--) {
    5195         592 :                         sql_exp *orderbycole = n->data;
    5196             : 
    5197         592 :                         stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    5198             : 
    5199         592 :                         if (!orderbycolstmt)
    5200             :                                 return NULL;
    5201             : 
    5202             :                         /* handle constants */
    5203         592 :                         if (orderbycolstmt->nrcols == 0 && n->next) /* no need to sort on constant */
    5204           0 :                                 continue;
    5205         592 :                         orderbycolstmt = column(be, orderbycolstmt);
    5206         592 :                         if (!limit) {   /* topn based on a single column */
    5207         282 :                                 limit = stmt_limit(be, orderbycolstmt, NULL, grp, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), nr_obe, 1);
    5208             :                         } else {        /* topn based on 2 columns */
    5209         310 :                                 limit = stmt_limit(be, orderbycolstmt, lpiv, lgid, stmt_atom_lng(be, 0), l, distinct, is_ascending(orderbycole), nulls_last(orderbycole), nr_obe, 1);
    5210             :                         }
    5211         592 :                         if (!limit)
    5212             :                                 return NULL;
    5213         592 :                         lpiv = limit;
    5214         592 :                         if (!grp && nr_obe > 1) {
    5215         310 :                                 lpiv = stmt_result(be, limit, 0);
    5216         310 :                                 lgid = stmt_result(be, limit, 1);
    5217         310 :                                 if (lpiv == NULL || lgid == NULL)
    5218             :                                         return NULL;
    5219             :                         }
    5220             :                 }
    5221             : 
    5222         282 :                 limit = lpiv;
    5223         282 :                 if (limit && grp)
    5224           6 :                         limit = stmt_project(be, stmt_selectnonil(be, limit, NULL), limit);
    5225         282 :                 stmt *s;
    5226        1514 :                 for (n=pl->h ; n; n = n->next) {
    5227        1232 :                         stmt *os = n->data;
    5228        1232 :                         list_append(npl, s=stmt_project(be, limit, column(be, os)));
    5229        1232 :                         s->label = os->label;
    5230             :                 }
    5231         282 :                 psub = stmt_list(be, npl);
    5232             : 
    5233             :                 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
    5234         282 :                 pl = sub->op4.lval;
    5235         282 :                 npl = sa_list(sql->sa);
    5236        1662 :                 for (n=pl->h ; n; n = n->next) {
    5237        1380 :                         stmt *os = n->data;
    5238        1380 :                         list_append(npl, s = stmt_project(be, limit, column(be, os)));
    5239        1380 :                         s->label = os->label;
    5240             :                 }
    5241         282 :                 sub = stmt_list(be, npl);
    5242             :         }
    5243      400843 :         if (need_distinct(rel)) {
    5244         128 :                 stmt *distinct = NULL;
    5245         128 :                 psub = rel2bin_distinct(be, psub, &distinct);
    5246             :                 /* also rebuild sub as multiple orderby expressions may use the sub table (ie aren't part of the result columns) */
    5247         128 :                 if (sub && distinct) {
    5248         113 :                         list *npl = sa_list(sql->sa);
    5249             : 
    5250         113 :                         pl = sub->op4.lval;
    5251         237 :                         for (n=pl->h ; n; n = n->next)
    5252         124 :                                 list_append(npl, stmt_project(be, distinct, column(be, n->data)));
    5253         113 :                         sub = stmt_list(be, npl);
    5254             :                 }
    5255             :         }
    5256      400843 :         if (/*(!topn || need_distinct(rel)) &&*/ rel->r) {
    5257       12803 :                 list *oexps = rel->r;
    5258       12803 :                 stmt *orderby_ids = NULL, *orderby_grp = NULL;
    5259             : 
    5260       12803 :                 list *ostmts = sa_list(be->mvc->sa);
    5261       39119 :                 for (en = oexps->h; en; en = en->next) {
    5262       26316 :                         stmt *orderby = NULL;
    5263       26316 :                         sql_exp *orderbycole = en->data;
    5264       26316 :                         stmt *orderbycolstmt = exp_bin(be, orderbycole, sub, psub, NULL, NULL, NULL, NULL, 0, 0, 0);
    5265             : 
    5266       26316 :                         if (!orderbycolstmt) {
    5267           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    5268             :                                 return NULL;
    5269             :                         }
    5270             :                         /* single values don't need sorting */
    5271       26316 :                         if (orderbycolstmt->nrcols == 0) {
    5272          68 :                                 append(ostmts, NULL);
    5273          68 :                                 continue;
    5274             :                         }
    5275       26248 :                         if (orderby_ids)
    5276       13519 :                                 orderby = stmt_reorder(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole), orderby_ids, orderby_grp);
    5277             :                         else
    5278       12729 :                                 orderby = stmt_order(be, orderbycolstmt, is_ascending(orderbycole), nulls_last(orderbycole));
    5279       26248 :                         stmt *orderby_vals = stmt_result(be, orderby, 0);
    5280       26248 :                         append(ostmts, orderby_vals);
    5281       26248 :                         orderby_ids = stmt_result(be, orderby, 1);
    5282       26248 :                         orderby_grp = stmt_result(be, orderby, 2);
    5283             :                 }
    5284       12803 :                 if (orderby_ids)
    5285       12729 :                         psub = sql_reorder(be, orderby_ids, rel->exps, psub, oexps, ostmts);
    5286             :         }
    5287             :         return psub;
    5288             : }
    5289             : 
    5290             : static stmt *
    5291           0 : rel2bin_predicate(backend *be)
    5292             : {
    5293           0 :         return const_column(be, stmt_bool(be, 1));
    5294             : }
    5295             : 
    5296             : static stmt *
    5297       73597 : rel2bin_select(backend *be, sql_rel *rel, list *refs)
    5298             : {
    5299       73597 :         mvc *sql = be->mvc;
    5300       73597 :         node *en;
    5301       73597 :         stmt *sub = NULL, *sel = NULL;
    5302       73597 :         stmt *predicate = NULL;
    5303             : 
    5304       73597 :         if (rel->l) { /* first construct the sub relation */
    5305       73597 :                 sub = subrel_bin(be, rel->l, refs);
    5306       73597 :                 if (!sub)
    5307             :                         return NULL;
    5308       73597 :                 sel = sub->cand;
    5309       73597 :                 sub = row2cols(be, sub);
    5310             :         }
    5311       73597 :         if (!sub && !predicate)
    5312           0 :                 predicate = rel2bin_predicate(be);
    5313       73597 :         if (list_empty(rel->exps)) {
    5314        1482 :                 if (sub)
    5315             :                         return sub;
    5316           0 :                 if (predicate)
    5317             :                         return predicate;
    5318           0 :                 assert(0);
    5319             :         }
    5320       72115 :         en = rel->exps->h;
    5321       72115 :         if (!sub && predicate) {
    5322           0 :                 list *l = sa_list(sql->sa);
    5323           0 :                 assert(predicate);
    5324           0 :                 append(l, predicate);
    5325           0 :                 sub = stmt_list(be, l);
    5326             :         }
    5327             :         /* handle possible index lookups */
    5328             :         /* expressions are in index order ! */
    5329       72115 :         if (sub && en) {
    5330       72115 :                 sql_exp *e = en->data;
    5331       72115 :                 prop *p;
    5332             : 
    5333       72115 :                 if ((p=find_prop(e->p, PROP_HASHCOL)) != NULL && !is_anti(e)) {
    5334          12 :                         sql_idx *i = p->value.pval;
    5335          12 :                         int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
    5336             : 
    5337          12 :                         if (!(sel = rel2bin_hash_lookup(be, rel, sub, NULL, i, en))) {
    5338             :                                 /* hash lookup cannot be used, clean leftover mal statements */
    5339           3 :                                 clean_mal_statements(be, oldstop, oldvtop);
    5340             :                         }
    5341             :                 }
    5342             :         }
    5343      153200 :         for (en = rel->exps->h; en; en = en->next) {
    5344       81085 :                 sql_exp *e = en->data;
    5345       81085 :                 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, sel, 0, 1, 0);
    5346             : 
    5347       81085 :                 if (!s) {
    5348           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    5349             :                         return NULL;
    5350             :                 }
    5351       81085 :                 if (s->nrcols == 0){
    5352        4784 :                         if (!predicate && sub && !list_empty(sub->op4.lval))
    5353        4776 :                                 predicate = stmt_const(be, bin_find_smallest_column(be, sub), stmt_bool(be, 1));
    5354           8 :                         else if (!predicate)
    5355           0 :                                 predicate = const_column(be, stmt_bool(be, 1));
    5356        4784 :                         if (e->type != e_cmp) {
    5357        4656 :                                 sql_subtype *bt = sql_bind_localtype("bit");
    5358             : 
    5359        4656 :                                 s = stmt_convert(be, s, NULL, exp_subtype(e), bt);
    5360             :                         }
    5361        4784 :                         sel = stmt_uselect(be, predicate, s, cmp_equal, sel, 0, 0);
    5362       76301 :                 } else if (e->type != e_cmp) {
    5363           0 :                         sel = stmt_uselect(be, s, stmt_bool(be, 1), cmp_equal, sel, 0, 0);
    5364             :                 } else {
    5365             :                         sel = s;
    5366             :                 }
    5367             :         }
    5368             : 
    5369       72115 :         if (sub && sel) {
    5370       72115 :                 sub = stmt_list(be, sub->op4.lval); /* protect against references */
    5371       72115 :                 sub->cand = sel;
    5372             :         }
    5373             :         return sub;
    5374             : }
    5375             : 
    5376             : static stmt *
    5377       13620 : rel2bin_groupby(backend *be, sql_rel *rel, list *refs)
    5378             : {
    5379       13620 :         mvc *sql = be->mvc;
    5380       13620 :         list *l, *aggrs, *gbexps = sa_list(sql->sa);
    5381       13620 :         node *n, *en;
    5382       13620 :         stmt *sub = NULL, *cursub;
    5383       13620 :         stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt = NULL;
    5384             : 
    5385       13620 :         if (rel->l) { /* first construct the sub relation */
    5386       13620 :                 sub = subrel_bin(be, rel->l, refs);
    5387       13619 :                 sub = subrel_project(be, sub, refs, rel->l);
    5388       13619 :                 if (!sub)
    5389             :                         return NULL;
    5390             :         }
    5391             : 
    5392       13619 :         if (sub && sub->type == st_list && sub->op4.lval->h && !((stmt*)sub->op4.lval->h->data)->nrcols) {
    5393         337 :                 list *newl = sa_list(sql->sa);
    5394         337 :                 node *n;
    5395             : 
    5396         766 :                 for (n=sub->op4.lval->h; n; n = n->next) {
    5397         429 :                         stmt *s = n->data;
    5398         429 :                         assert(s->type == st_alias);
    5399         429 :                         const char *cname = column_name(sql->sa, s);
    5400         429 :                         sql_alias *tname = table_name(sql->sa, s);
    5401         429 :                         int label = s->label;
    5402             : 
    5403         429 :                         s = column(be, s);
    5404         429 :                         s = stmt_alias(be, s, label, tname, cname);
    5405         429 :                         append(newl, s);
    5406             :                 }
    5407         337 :                 sub = stmt_list(be, newl);
    5408             :         }
    5409             : 
    5410             :         /* groupby columns */
    5411             : 
    5412             :         /* Keep groupby columns, so that they can be looked up in the aggr list */
    5413       13619 :         if (rel->r) {
    5414       10025 :                 list *exps = rel->r;
    5415             : 
    5416       25262 :                 for (en = exps->h; en; en = en->next) {
    5417       15237 :                         sql_exp *e = en->data;
    5418       15237 :                         stmt *gbcol = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5419             : 
    5420       15237 :                         if (!gbcol) {
    5421           0 :                                 assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    5422             :                                 return NULL;
    5423             :                         }
    5424       15237 :                         if (!gbcol->nrcols)
    5425          11 :                                 gbcol = stmt_const(be, bin_find_smallest_column(be, sub), gbcol);
    5426       15237 :                         groupby = stmt_group(be, gbcol, grp, ext, cnt, !en->next);
    5427       15237 :                         grp = stmt_result(be, groupby, 0);
    5428       15237 :                         ext = stmt_result(be, groupby, 1);
    5429       15237 :                         cnt = stmt_result(be, groupby, 2);
    5430       15237 :                         gbcol = stmt_alias(be, gbcol, e->alias.label, exp_find_rel_name(e), exp_name(e));
    5431       15237 :                         list_append(gbexps, gbcol);
    5432             :                 }
    5433             :         }
    5434             :         /* now aggregate */
    5435       13619 :         l = sa_list(sql->sa);
    5436       13619 :         if (l == NULL)
    5437             :                 return NULL;
    5438       13619 :         aggrs = rel->exps;
    5439       13619 :         cursub = stmt_list(be, l);
    5440       13619 :         if (cursub == NULL)
    5441             :                 return NULL;
    5442       13619 :         if (aggrs && !aggrs->h && ext)
    5443           0 :                 list_append(l, ext);
    5444       39282 :         for (n = aggrs->h; n; n = n->next) {
    5445       25662 :                 sql_exp *aggrexp = n->data;
    5446       25662 :                 stmt *aggrstmt = NULL;
    5447       25662 :                 int oldvtop, oldstop;
    5448             : 
    5449             :                 /* first look in the current aggr list (l) and group by column list */
    5450       25662 :                 if (l && !aggrstmt && aggrexp->type == e_column)
    5451             :                         //aggrstmt = list_find_column(be, l, aggrexp->l, aggrexp->r);
    5452       14784 :                         aggrstmt = list_find_column_nid(be, l, aggrexp->nid);
    5453       25661 :                 if (gbexps && !aggrstmt && aggrexp->type == e_column) {
    5454             :                         //aggrstmt = list_find_column(be, gbexps, aggrexp->l, aggrexp->r);
    5455       14758 :                         aggrstmt = list_find_column_nid(be, gbexps, aggrexp->nid);
    5456       14758 :                         if (aggrstmt && groupby) {
    5457       14555 :                                 aggrstmt = stmt_project(be, ext, aggrstmt);
    5458       14555 :                                 if (list_length(gbexps) == 1)
    5459        5965 :                                         aggrstmt->key = 1;
    5460             :                         }
    5461             :                 }
    5462             : 
    5463       25661 :                 oldvtop = be->mb->vtop;
    5464       25661 :                 oldstop = be->mb->stop;
    5465       25661 :                 if (!aggrstmt)
    5466       11081 :                         aggrstmt = exp_bin(be, aggrexp, sub, NULL, grp, ext, cnt, NULL, 0, 0, 0);
    5467             :                 /* maybe the aggr uses intermediate results of this group by,
    5468             :                    therefore we pass the group by columns too
    5469             :                  */
    5470       11081 :                 if (!aggrstmt) {
    5471           1 :                         clean_mal_statements(be, oldstop, oldvtop);
    5472           1 :                         aggrstmt = exp_bin(be, aggrexp, sub, cursub, grp, ext, cnt, NULL, 0, 0, 0);
    5473             :                 }
    5474           1 :                 if (!aggrstmt) {
    5475           0 :                         assert(sql->session->status == -10); /* Stack overflow errors shouldn't terminate the server */
    5476             :                         return NULL;
    5477             :                 }
    5478             : 
    5479       25661 :                 if (!aggrstmt->nrcols && ext && ext->nrcols)
    5480           0 :                         aggrstmt = stmt_const(be, ext, aggrstmt);
    5481             : 
    5482       25661 :                 aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
    5483       25663 :                 list_append(l, aggrstmt);
    5484             :         }
    5485       13620 :         stmt_set_nrcols(cursub);
    5486       13620 :         return cursub;
    5487             : }
    5488             : 
    5489             : static bool
    5490           8 : has_partitioning( list *exps )
    5491             : {
    5492          10 :         for(node *n = exps->h; n; n = n->next){
    5493           8 :                 sql_exp *gbe = n->data;
    5494           8 :                 if (is_partitioning(gbe))
    5495             :                         return true;
    5496             :         }
    5497             :         return false;
    5498             : }
    5499             : 
    5500             : static stmt *
    5501       16588 : rel2bin_topn(backend *be, sql_rel *rel, list *refs)
    5502             : {
    5503       16588 :         mvc *sql = be->mvc;
    5504       16588 :         sql_exp *oe = NULL, *le = NULL;
    5505       16588 :         stmt *sub = NULL, *l = NULL, *o = NULL;
    5506       16588 :         node *n;
    5507             : 
    5508       16588 :         if (rel->l) { /* first construct the sub relation */
    5509       16588 :                 sql_rel *rl = rel->l;
    5510             : 
    5511       16588 :                 if (rl->op == op_munion && is_recursive(rl)) {
    5512           4 :                         if (rel_is_ref(rl)) {
    5513           0 :                                 sub = refs_find_rel(refs, rl);
    5514           0 :                                 if (!sub)
    5515           0 :                                         sub = rel2bin_recursive_munion(be, rl, refs, rel);
    5516             :                         } else
    5517           4 :                                 sub = rel2bin_recursive_munion(be, rl, refs, rel);
    5518       16584 :                 } else if (rl->op == op_project) {
    5519         332 :                         if (rel_is_ref(rl)) {
    5520           5 :                                 sub = refs_find_rel(refs, rl);
    5521           5 :                                 if (!sub)
    5522           0 :                                         sub = rel2bin_project(be, rl, refs, rel);
    5523             :                         } else
    5524         327 :                                 sub = rel2bin_project(be, rl, refs, rel);
    5525         340 :                         if (rel->grouped && rl->r && has_partitioning(rl->r))
    5526             :                                 return sub;
    5527             :                 } else {
    5528       16252 :                         sub = subrel_bin(be, rl, refs);
    5529             :                 }
    5530       16586 :                 sub = subrel_project(be, sub, refs, rl);
    5531             :         }
    5532       16593 :         if (!sub)
    5533           0 :                 return NULL;
    5534             : 
    5535       16593 :         le = topn_limit(rel);
    5536       16592 :         oe = topn_offset(rel);
    5537             : 
    5538       16592 :         n = sub->op4.lval->h;
    5539       16592 :         if (n) {
    5540       16592 :                 stmt *limit = NULL, *sc = n->data;
    5541       16592 :                 list *newl = sa_list(sql->sa);
    5542       16591 :                 int oldvtop = be->mb->vtop, oldstop = be->mb->stop;
    5543             : 
    5544       16591 :                 if (le)
    5545       16565 :                         l = exp_bin(be, le, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5546       16561 :                 if (!l) {
    5547          26 :                         clean_mal_statements(be, oldstop, oldvtop);
    5548          26 :                         l = stmt_atom_lng_nil(be);
    5549             :                 }
    5550             : 
    5551       16575 :                 oldvtop = be->mb->vtop;
    5552       16575 :                 oldstop = be->mb->stop;
    5553       16575 :                 if (oe)
    5554          83 :                         o = exp_bin(be, oe, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5555          83 :                 if (!o) {
    5556       16492 :                         clean_mal_statements(be, oldstop, oldvtop);
    5557       16508 :                         o = stmt_atom_lng(be, 0);
    5558             :                 }
    5559       16585 :                 if (!l || !o)
    5560             :                         return NULL;
    5561             : 
    5562             : 
    5563       16585 :                 sc = column(be, sc);
    5564       16580 :                 limit = stmt_limit(be, sc, NULL, NULL, o, l, 0,0,0,0,0);
    5565             : 
    5566      116191 :                 for ( ; n; n = n->next) {
    5567       83018 :                         stmt *sc = n->data;
    5568       83018 :                         assert(sc->type == st_alias);
    5569       83018 :                         const char *cname = column_name(sql->sa, sc);
    5570       83018 :                         sql_alias *tname = table_name(sql->sa, sc);
    5571       83018 :                         int label = sc->label;
    5572             : 
    5573       83018 :                         sc = column(be, sc);
    5574       83020 :                         sc = stmt_project(be, limit, sc);
    5575       83018 :                         list_append(newl, stmt_alias(be, sc, label, tname, cname));
    5576             :                 }
    5577       16593 :                 sub = stmt_list(be, newl);
    5578             :         }
    5579             :         return sub;
    5580             : }
    5581             : 
    5582             : static stmt *
    5583          21 : rel2bin_sample(backend *be, sql_rel *rel, list *refs)
    5584             : {
    5585          21 :         mvc *sql = be->mvc;
    5586          21 :         list *newl;
    5587          21 :         stmt *sub = NULL, *sample_size = NULL, *sample = NULL, *seed = NULL;
    5588          21 :         node *n;
    5589             : 
    5590          21 :         if (rel->l) /* first construct the sub relation */
    5591          21 :                 sub = subrel_bin(be, rel->l, refs);
    5592          21 :         sub = subrel_project(be, sub, refs, rel->l);
    5593          21 :         if (!sub)
    5594             :                 return NULL;
    5595             : 
    5596          21 :         n = sub->op4.lval->h;
    5597          21 :         newl = sa_list(sql->sa);
    5598             : 
    5599          21 :         if (n) {
    5600          21 :                 stmt *sc = n->data;
    5601             :                 //const char *cname = column_name(sql->sa, sc);
    5602             :                 //sql_alias *tname = table_name(sql->sa, sc);
    5603             : 
    5604          21 :                  if (!(sample_size = exp_bin(be, rel->exps->h->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0)))
    5605             :                         return NULL;
    5606             : 
    5607          21 :                 if (rel->exps->cnt == 2) {
    5608          12 :                         seed = exp_bin(be, rel->exps->h->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5609          12 :                         if (!seed)
    5610             :                                 return NULL;
    5611             :                 }
    5612             : 
    5613          21 :                 sc = column(be, sc);
    5614          21 :                 sample = stmt_sample(be, sc /*stmt_alias(be, sc, 0, tname, cname)*/,sample_size, seed);
    5615             : 
    5616          63 :                 for ( ; n; n = n->next) {
    5617          21 :                         stmt *sc = n->data;
    5618          21 :                         assert(sc->type == st_alias);
    5619          21 :                         const char *cname = column_name(sql->sa, sc);
    5620          21 :                         sql_alias *tname = table_name(sql->sa, sc);
    5621          21 :                         int label = sc->label;
    5622             : 
    5623          21 :                         sc = column(be, sc);
    5624          21 :                         sc = stmt_project(be, sample, sc);
    5625          21 :                         list_append(newl, stmt_alias(be, sc, label, tname, cname));
    5626             :                 }
    5627             :         }
    5628          21 :         sub = stmt_list(be, newl);
    5629          21 :         return sub;
    5630             : }
    5631             : 
    5632             : static stmt *
    5633        5207 : sql_parse(backend *be, sql_schema *s, const char *query, char mode)
    5634             : {
    5635        5207 :         sql_rel *rel = rel_parse(be->mvc, s, query, mode);
    5636        5207 :         stmt *sq = NULL;
    5637             : 
    5638        5207 :         if (rel && (rel = sql_processrelation(be->mvc, rel, 0, 1, 1, 1)))
    5639        5204 :                 sq = rel_bin(be, rel);
    5640        5207 :         return sq;
    5641             : }
    5642             : 
    5643             : static stmt *
    5644       12904 : insert_check_ukey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts)
    5645             : {
    5646       12904 :         mvc *sql = be->mvc;
    5647             : /* pkey's cannot have NULLs, ukeys however can
    5648             :    current implementation switches on 'NOT NULL' on primary key columns */
    5649             : 
    5650       12904 :         char *msg = NULL;
    5651       12904 :         stmt *res;
    5652             : 
    5653       12904 :         sql_subtype *lng = sql_bind_localtype("lng");
    5654       12920 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    5655       12919 :         sql_subtype *bt = sql_bind_localtype("bit");
    5656       12917 :         stmt *dels = stmt_tid(be, k->t, 0);
    5657       12922 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    5658             : 
    5659       12921 :         if (list_length(k->columns) > 1) {
    5660         825 :                 node *m;
    5661         825 :                 stmt *s = list_fetch(inserts, 0), *ins = s;
    5662         825 :                 sql_subfunc *sum;
    5663         825 :                 stmt *ssum = NULL;
    5664         825 :                 stmt *col = NULL;
    5665             : 
    5666         825 :                 s = ins;
    5667             :                 /* 1st stage: find out if original contains same values */
    5668         825 :                 if (/*s->key &&*/ s->nrcols == 0) {
    5669         586 :                         s = NULL;
    5670         586 :                         if (k->idx && hash_index(k->idx->type))
    5671         586 :                                 s = stmt_uselect(be, stmt_idx(be, k->idx, dels, dels->partition), idx_inserts, cmp_equal, s, 0, 1 /* is_semantics*/);
    5672        2149 :                         for (m = k->columns->h; m; m = m->next) {
    5673        1563 :                                 sql_kc *c = m->data;
    5674        1563 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    5675             : 
    5676             :                                 /* foreach column add predicate */
    5677        1563 :                                 stmt_add_column_predicate(be, c->c);
    5678             : 
    5679        1563 :                                 col = stmt_col(be, c->c, dels, dels->partition);
    5680        1563 :                                 if (k->type == unndkey)
    5681           8 :                                         s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 1);
    5682        1664 :                                 else if ((k->type == ukey) && stmt_has_null(col)) {
    5683         109 :                                         stmt *nn = stmt_selectnonil(be, col, s);
    5684         109 :                                         s = stmt_uselect(be, col, cs, cmp_equal, nn, 0, 0);
    5685             :                                 } else {
    5686        1446 :                                         s = stmt_uselect(be, col, cs, cmp_equal, s, 0, 0);
    5687             :                                 }
    5688             :                         }
    5689             :                 } else {
    5690         239 :                         list *lje = sa_list(sql->sa);
    5691         239 :                         list *rje = sa_list(sql->sa);
    5692         239 :                         if (k->idx && hash_index(k->idx->type)) {
    5693         239 :                                 list_append(lje, stmt_idx(be, k->idx, dels, dels->partition));
    5694         239 :                                 list_append(rje, idx_inserts);
    5695             :                         }
    5696         764 :                         for (m = k->columns->h; m; m = m->next) {
    5697         525 :                                 sql_kc *c = m->data;
    5698         525 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    5699             : 
    5700             :                                 /* foreach column add predicate */
    5701         525 :                                 stmt_add_column_predicate(be, c->c);
    5702             : 
    5703         525 :                                 col = stmt_col(be, c->c, dels, dels->partition);
    5704         525 :                                 list_append(lje, col);
    5705         525 :                                 list_append(rje, cs);
    5706             :                         }
    5707         239 :                         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, k->type == unndkey? 1: 0);
    5708         239 :                         s = stmt_result(be, s, 0);
    5709             :                 }
    5710         825 :                 s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    5711             : 
    5712             :                 /* 2nd stage: find out if inserted are unique */
    5713         825 :                 if ((!idx_inserts && ins->nrcols) || (idx_inserts && idx_inserts->nrcols)) {      /* insert columns not atoms */
    5714         239 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
    5715         239 :                         stmt *orderby_ids = NULL, *orderby_grp = NULL;
    5716         239 :                         stmt *sel = NULL;
    5717             : 
    5718             :                         /* remove any nils as in stmt_order NULL = NULL, instead of NULL != NULL */
    5719         239 :                         if (k->type == ukey) {
    5720         153 :                                 for (m = k->columns->h; m; m = m->next) {
    5721         105 :                                         sql_kc *c = m->data;
    5722         105 :                                         stmt *cs = list_fetch(inserts, c->c->colnr);
    5723         105 :                                         if (stmt_has_null(cs))
    5724         102 :                                                 sel = stmt_selectnonil(be, cs, sel);
    5725             :                                 }
    5726             :                         }
    5727             :                         /* implementation uses sort key check */
    5728         764 :                         for (m = k->columns->h; m; m = m->next) {
    5729         525 :                                 sql_kc *c = m->data;
    5730         525 :                                 stmt *orderby;
    5731         525 :                                 stmt *cs = list_fetch(inserts, c->c->colnr);
    5732             : 
    5733         525 :                                 if (sel)
    5734         102 :                                         cs = stmt_project(be, sel, cs);
    5735         525 :                                 if (orderby_grp)
    5736         286 :                                         orderby = stmt_reorder(be, cs, 1, 0, orderby_ids, orderby_grp);
    5737             :                                 else
    5738         239 :                                         orderby = stmt_order(be, cs, 1, 0);
    5739         525 :                                 orderby_ids = stmt_result(be, orderby, 1);
    5740         525 :                                 orderby_grp = stmt_result(be, orderby, 2);
    5741             :                         }
    5742             : 
    5743         239 :                         if (!orderby_grp || !orderby_ids)
    5744             :                                 return NULL;
    5745             : 
    5746         239 :                         sum = sql_bind_func(sql, "sys", "not_unique", tail_type(orderby_grp), NULL, F_AGGR, true, true);
    5747         239 :                         ssum = stmt_aggr(be, orderby_grp, NULL, NULL, sum, 1, 0, 1);
    5748             :                         /* combine results */
    5749         239 :                         s = stmt_binop(be, s, ssum, NULL, or);
    5750             :                 }
    5751             : 
    5752         825 :                 if (k->type == pkey) {
    5753         330 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    5754             :                 } else {
    5755         495 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    5756             :                 }
    5757         825 :                 res = stmt_exception(be, s, msg, 00001);
    5758             :         } else {                /* single column key */
    5759       12094 :                 sql_kc *c = k->columns->h->data;
    5760       12094 :                 stmt *s = list_fetch(inserts, c->c->colnr), *h = s;
    5761             : 
    5762             :                 /* add predicate for this column */
    5763       12075 :                 stmt_add_column_predicate(be, c->c);
    5764             : 
    5765       12097 :                 s = stmt_col(be, c->c, dels, dels->partition);
    5766       12097 :                 if ((k->type == ukey) && stmt_has_null(s)) {
    5767         202 :                         stmt *nn = stmt_selectnonil(be, s, NULL);
    5768         202 :                         s = stmt_project(be, nn, s);
    5769             :                 }
    5770       12097 :                 if (h->nrcols) {
    5771        4870 :                         s = stmt_join(be, s, h, 0, cmp_equal, 0, k->type == unndkey? 1: 0, false);
    5772             :                         /* s should be empty */
    5773        4870 :                         s = stmt_result(be, s, 0);
    5774        4870 :                         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    5775             :                 } else {
    5776        7227 :                         s = stmt_uselect(be, s, h, cmp_equal, NULL, 0, k->type == unndkey? 1: 0);
    5777             :                         /* s should be empty */
    5778        7223 :                         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    5779             :                 }
    5780             :                 /* s should be empty */
    5781       12097 :                 s = stmt_binop(be, s, stmt_atom_lng(be, 0), NULL, ne);
    5782             : 
    5783             :                 /* 2e stage: find out if inserts are unique */
    5784       12096 :                 if (h->nrcols) {     /* insert multiple atoms */
    5785        4870 :                         sql_subfunc *sum;
    5786        4870 :                         stmt *count_sum = NULL;
    5787        4870 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
    5788        4870 :                         stmt *ssum, *ss;
    5789             : 
    5790        4870 :                         stmt *g = list_fetch(inserts, c->c->colnr), *ins = g;
    5791             : 
    5792             :                         /* inserted values may be null */
    5793        4870 :                         if ((k->type == ukey) && stmt_has_null(ins)) {
    5794        1790 :                                 stmt *nn = stmt_selectnonil(be, ins, NULL);
    5795        1790 :                                 ins = stmt_project(be, nn, ins);
    5796             :                         }
    5797             : 
    5798        4870 :                         g = stmt_group(be, ins, NULL, NULL, NULL, 1);
    5799        4870 :                         ss = stmt_result(be, g, 2); /* use count */
    5800             :                         /* (count(ss) <> sum(ss)) */
    5801        4870 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
    5802        4870 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    5803        4870 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    5804        4870 :                         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);
    5805             : 
    5806             :                         /* combine results */
    5807        4870 :                         s = stmt_binop(be, s, count_sum, NULL, or);
    5808             :                 }
    5809       12096 :                 if (k->type == pkey) {
    5810       10145 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    5811             :                 } else {
    5812        1951 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    5813             :                 }
    5814       12097 :                 res = stmt_exception(be, s, msg, 00001);
    5815             :         }
    5816             :         return res;
    5817             : }
    5818             : 
    5819             : static stmt *
    5820         777 : insert_check_fkey(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
    5821             : {
    5822         777 :         mvc *sql = be->mvc;
    5823         777 :         char *msg = NULL;
    5824         777 :         stmt *cs = list_fetch(inserts, 0), *s = cs;
    5825         777 :         sql_subtype *lng = sql_bind_localtype("lng");
    5826         777 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    5827         777 :         sql_subtype *bt = sql_bind_localtype("bit");
    5828         777 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    5829             : 
    5830         777 :         stmt *nonil_rows = NULL;
    5831        1589 :         for (node *m = k->columns->h; m; m = m->next) {
    5832         812 :                 sql_kc *c = m->data;
    5833             : 
    5834             :                 /* foreach column add predicate */
    5835         812 :                 stmt_add_column_predicate(be, c->c);
    5836             : 
    5837             :                 // foreach column aggregate the nonil (literally 'null') values.
    5838             :                 // mind that null values are valid fkeys with undefined value so
    5839             :                 // we won't have an entry for them in the idx_inserts col
    5840         812 :                 s = list_fetch(inserts, c->c->colnr);
    5841         812 :                 nonil_rows = stmt_selectnonil(be, s, nonil_rows);
    5842             :         }
    5843             : 
    5844         777 :         if (!s && pin && list_length(pin->op4.lval))
    5845           0 :                 s = pin->op4.lval->h->data;
    5846             : 
    5847             :         // we want to make sure that the data column(s) has the same number
    5848             :         // of (nonil) rows as the index column. if that is **not** the case
    5849             :         // then we are obviously dealing with an invalid foreign key
    5850         777 :         if (s->key && s->nrcols == 0) {
    5851           0 :                 s = stmt_binop(be,
    5852             :                         stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
    5853             :                         stmt_aggr(be, const_column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
    5854             :                         NULL, ne);
    5855             :         } else {
    5856             :                 /* relThetaJoin.notNull.count <> inserts[notNull(col1) && ... && notNull(colN)].count */
    5857         777 :                 s = stmt_binop(be,
    5858             :                         stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
    5859             :                         stmt_aggr(be, column(be, nonil_rows), NULL, NULL, cnt, 1, 1, 1),
    5860             :                         NULL, ne);
    5861             :         }
    5862             : 
    5863             :         /* s should be empty */
    5864         777 :         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    5865         777 :         return stmt_exception(be, s, msg, 00001);
    5866             : }
    5867             : 
    5868             : static stmt *
    5869       13682 : sql_insert_key(backend *be, list *inserts, sql_key *k, stmt *idx_inserts, stmt *pin)
    5870             : {
    5871             :         /* int insert = 1;
    5872             :          * while insert and has u/pkey and not deferred then
    5873             :          *      if u/pkey values exist then
    5874             :          *              insert = 0
    5875             :          * while insert and has fkey and not deferred then
    5876             :          *      find id of corresponding u/pkey
    5877             :          *      if (!found)
    5878             :          *              insert = 0
    5879             :          * if insert
    5880             :          *      insert values
    5881             :          *      insert fkey/pkey index
    5882             :          */
    5883       13682 :         if (k->type == pkey || k->type == ukey || k->type == unndkey) {
    5884       12905 :                 return insert_check_ukey(be, inserts, k, idx_inserts);
    5885             :         } else {                /* foreign keys */
    5886         777 :                 return insert_check_fkey(be, inserts, k, idx_inserts, pin);
    5887             :         }
    5888             : }
    5889             : 
    5890             : static int
    5891        4921 : sql_stack_add_inserted(mvc *sql, const char *name, sql_table *t, stmt **updates)
    5892             : {
    5893             :         /* Put single relation of updates and old values on to the stack */
    5894        4921 :         sql_rel *r = NULL;
    5895        4921 :         node *n;
    5896        4921 :         list *exps = sa_list(sql->sa);
    5897        4921 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    5898             : 
    5899        4921 :         ti->t = t;
    5900        4921 :         ti->tids = NULL;
    5901        4921 :         ti->updates = updates;
    5902        4921 :         ti->type = 1;
    5903        4921 :         ti->nn = name;
    5904        4921 :         sql_alias *aname = a_create(sql->sa, name);
    5905             : 
    5906       13129 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    5907        8208 :                 sql_column *c = n->data;
    5908        8208 :                 sql_exp *ne = exp_column(sql->sa, aname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    5909        8208 :                 ne->alias.label = -(sql->nid++);
    5910             : 
    5911        8208 :                 append(exps, ne);
    5912             :         }
    5913        4921 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    5914        4921 :         r->l = ti;
    5915             : 
    5916        4921 :         return stack_push_rel_view(sql, name, r) ? 1 : 0;
    5917             : }
    5918             : 
    5919             : static int
    5920      217109 : sql_insert_triggers(backend *be, sql_table *t, stmt **updates, int time)
    5921             : {
    5922      217109 :         mvc *sql = be->mvc;
    5923      217109 :         node *n;
    5924      217109 :         int res = 1;
    5925             : 
    5926      217109 :         if (!ol_length(t->triggers))
    5927             :                 return res;
    5928             : 
    5929        8451 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    5930        6742 :                 sql_trigger *trigger = n->data;
    5931             : 
    5932        6742 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    5933             :                         return 0;
    5934        6742 :                 if (trigger->event == 0 && trigger->time == time) {
    5935        4921 :                         const char *n = trigger->new_name;
    5936             : 
    5937             :                         /* add name for the 'inserted' to the stack */
    5938        4921 :                         if (!n) n = "new";
    5939             : 
    5940        4921 :                         if(!sql_stack_add_inserted(sql, n, t, updates)) {
    5941           0 :                                 stack_pop_frame(sql);
    5942           0 :                                 return 0;
    5943             :                         }
    5944        4921 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    5945        4893 :                                 stack_pop_frame(sql);
    5946        4893 :                                 return 0;
    5947             :                         }
    5948             :                 }
    5949        1849 :                 stack_pop_frame(sql);
    5950             :         }
    5951             :         return res;
    5952             : }
    5953             : 
    5954             : static void
    5955          83 : sql_insert_check(backend *be, sql_key *key, list *inserts)
    5956             : {
    5957          83 :         mvc *sql = be->mvc;
    5958          83 :         int pos = 0;
    5959          83 :         sql_alias *rname = table_alias(be->mvc->sa, key->t, NULL);
    5960          83 :         sql_rel *rel = rel_basetable(sql, key->t, rname);
    5961          83 :         sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
    5962          83 :         rel->exps = rel_base_projection(sql, rel, 0);
    5963             : 
    5964             :         /* create new sub stmt with needed inserts */
    5965          83 :         list *ins = sa_list(sql->sa);
    5966         173 :         for(node *n = key->columns->h; n; n = n->next) {
    5967          90 :                 sql_kc *kc = n->data;
    5968          90 :                 stmt *in = list_fetch(inserts, kc->c->colnr);
    5969             : 
    5970          90 :                 sql_exp *e = rel_base_bind_column2(sql, rel, rname, kc->c->base.name);
    5971          90 :                 in = stmt_alias(be, in, e->alias.label, rname, kc->c->base.name);
    5972          90 :                 append(ins, in);
    5973             :         }
    5974          83 :         stmt *sub = stmt_list(be, ins);
    5975          83 :         stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    5976          83 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    5977          83 :         s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
    5978          83 :         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    5979          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);
    5980          83 :         (void)stmt_exception(be, s, msg, 00001);
    5981          83 : }
    5982             : 
    5983             : static sql_table *
    5984      110195 : sql_insert_check_null(backend *be, sql_table *t, list *inserts)
    5985             : {
    5986      110195 :         mvc *sql = be->mvc;
    5987      110195 :         node *m, *n;
    5988      110195 :         sql_subfunc *cnt = NULL;
    5989             : 
    5990      825426 :         for (n = ol_first_node(t->columns), m = inserts->h; n && m;
    5991      715231 :                 n = n->next, m = m->next) {
    5992      715174 :                 stmt *i = m->data;
    5993      715174 :                 sql_column *c = n->data;
    5994             : 
    5995      715174 :                 if (!c->null) {
    5996       24660 :                         stmt *s = i;
    5997       24660 :                         char *msg = NULL;
    5998             : 
    5999       24660 :                         if (!(s->key && s->nrcols == 0)) {
    6000       11609 :                                 s = stmt_selectnil(be, column(be, i));
    6001       11609 :                                 if (!cnt)
    6002        3697 :                                         cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    6003       11609 :                                 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    6004             :                         } else {
    6005       13051 :                                 sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
    6006             : 
    6007       13043 :                                 s = stmt_unop(be, i, NULL, isnil);
    6008             :                         }
    6009       24663 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: NOT NULL constraint violated for column %s.%s", c->t->base.name, c->base.name);
    6010       24659 :                         (void)stmt_exception(be, s, msg, 00001);
    6011             :                 }
    6012             :         }
    6013      110252 :         return t; /* return something to say it succeeded */
    6014             : }
    6015             : 
    6016             : static stmt **
    6017      114652 : table_update_stmts(mvc *sql, sql_table *t, int *Len)
    6018             : {
    6019      114652 :         *Len = ol_length(t->columns);
    6020      114636 :         return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len);
    6021             : }
    6022             : 
    6023             : static stmt *insert_ms(backend *be, sql_table *st, sql_subtype *ct, stmt *ms);
    6024             : 
    6025             : static node *
    6026          47 : insert_composite(backend *be, stmt **updates, sql_table *st, sql_column *c, node *n, node *m)
    6027             : {
    6028          47 :         mvc *sql = be->mvc;
    6029          47 :         node *f;
    6030          47 :         stmt *input_tuple = m->data;
    6031             : 
    6032          97 :         while(input_tuple->type == st_alias)
    6033          50 :                 input_tuple = input_tuple->op1;
    6034          47 :         if (input_tuple->type != st_list)
    6035             :                 return NULL;
    6036         147 :         for(n = n->next, f = c->type.type->d.fields->h, m = input_tuple->op4.lval->h; n && m && f; f = f->next) {
    6037         100 :                 sql_column *c = n->data;
    6038             : 
    6039         100 :                 if (c->type.multiset) {
    6040          23 :                         sql_table *nst = mvc_bind_table(sql, st->s, c->storage_type);
    6041          23 :                         if (!nst)
    6042           0 :                                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
    6043          23 :                         updates[c->colnr] = insert_ms(be, nst, &c->type, m->data);
    6044          23 :                         n = n->next;
    6045          23 :                         m = m->next;
    6046          77 :                 } else if (c->type.type->composite && !c->type.multiset) {
    6047           7 :                         n = insert_composite(be, updates, st, c, n, m);
    6048           7 :                         m = m->next;
    6049             :                 } else {
    6050          70 :                         updates[c->colnr] = m->data;
    6051          70 :                         n = n->next;
    6052          70 :                         m = m->next;
    6053             :                 }
    6054             :         }
    6055             :         return n;
    6056             : }
    6057             : 
    6058             : static stmt *
    6059          47 : insert_ms(backend *be, sql_table *st, sql_subtype *ct, stmt *ms)
    6060             : {
    6061          47 :         mvc *sql = be->mvc;
    6062             : 
    6063          80 :         while(ms && ms->type == st_alias)
    6064          33 :                 ms = ms->op1;
    6065          47 :         if (ms->type != st_list)
    6066             :                 return NULL;
    6067             : 
    6068          47 :         int len;
    6069          47 :         stmt **updates = table_update_stmts(sql, st, &len);
    6070          47 :         stmt *insert = NULL, *cnt, *pos = NULL;
    6071             : 
    6072          47 :         node *n, *m;
    6073         206 :         for (n = ol_first_node(st->columns), m = ms->op4.lval->h; n && m; ) {
    6074         159 :                 sql_column *c = n->data;
    6075             : 
    6076         159 :                 if (c->type.multiset) {
    6077           4 :                         sql_table *nst = mvc_bind_table(sql, st->s, c->storage_type);
    6078           4 :                         if (!nst)
    6079           0 :                                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
    6080           4 :                         updates[c->colnr] = insert_ms(be, nst, &c->type, m->data);
    6081           4 :                         n = n->next;
    6082           4 :                         m = m->next;
    6083         155 :                 } else if (c->type.type->composite && !c->type.multiset) {
    6084          11 :                         n = insert_composite(be, updates, st, c, n, m);
    6085          11 :                         m = m->next;
    6086             :                 } else {
    6087         144 :                         insert = updates[c->colnr] = m->data;
    6088         144 :                         n = n->next;
    6089         144 :                         m = m->next;
    6090             :                 }
    6091             :         }
    6092             : 
    6093          47 :         if (!insert || insert->nrcols == 0) {
    6094           0 :                 cnt = stmt_atom_lng(be, 1);
    6095             :         } else {
    6096          47 :                 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);
    6097             :         }
    6098             : 
    6099          47 :         list *l = sa_list(sql->sa);
    6100             : 
    6101          47 :         if (st->s) /* only not declared tables, need this */
    6102          47 :                 pos = stmt_claim(be, st, cnt);
    6103             : 
    6104          47 :         int mvc_var = be->mvc_var;
    6105          47 :         stmt *rowids = m->data;
    6106          47 :         stmt *msid = updates[len-1 -((ct->multiset == MS_ARRAY)?1:0)];
    6107             : 
    6108             :         /* nrowids = next_value_for(rowids, "schema?", st->base.name) */
    6109          47 :         InstrPtr q = newStmt(be->mb, batsqlRef, "next_value_ms");
    6110          47 :         q = pushArgument(be->mb, q, rowids->nr);
    6111          47 :         q = pushStr(be->mb, q, st->s->base.name); /* sequence schema name */
    6112          47 :         q = pushStr(be->mb, q, st->base.name);      /* sequence number name */
    6113          47 :         pushInstruction(be->mb, q);
    6114             : 
    6115             :         /* nrowids = batcalc.int(nrowids) */
    6116          47 :         InstrPtr r = newStmt(be->mb, batcalcRef, "int");
    6117          47 :         r = pushArgument(be->mb, r, getArg(q, 0));
    6118          47 :         pushInstruction(be->mb, r);
    6119             : 
    6120             :         /* msid = renumber(msid, rowids, nrowids); */
    6121          47 :         q = newStmt(be->mb, batsqlRef, "renumber");
    6122          47 :         q = pushArgument(be->mb, q, msid->nr);
    6123          47 :         q = pushArgument(be->mb, q, rowids->nr);
    6124          47 :         q = pushArgument(be->mb, q, getArg(r, 0));
    6125          47 :         pushInstruction(be->mb, q);
    6126             : 
    6127             :         /* now update msid and rowids */
    6128          47 :         rowids->nr = getArg(r, 0);
    6129          47 :         msid->nr = getArg(q, 0);
    6130             : 
    6131         230 :         for (n = ol_first_node(st->columns); n; n = n->next) {
    6132             : 
    6133         183 :                 sql_column *c = n->data;
    6134         183 :                 stmt *ins = updates[c->colnr];
    6135             : 
    6136         183 :                 if (ins) {
    6137         171 :                         insert = stmt_append_col(be, c, pos, ins, &mvc_var, false);
    6138         171 :                         if (!insert)
    6139             :                                 return NULL;
    6140         171 :                         append(l,insert);
    6141             :                 }
    6142             :         }
    6143          47 :         be->mvc_var = mvc_var;
    6144             : 
    6145          47 :         return rowids;
    6146             : }
    6147             : 
    6148             : static stmt *
    6149          47 : rel2bin_insert_ms(backend *be, sql_rel *rel, list *refs)
    6150             : {
    6151          47 :         mvc *sql = be->mvc;
    6152          47 :         list *l;
    6153          47 :         stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
    6154          47 :         int idx_ins = 0, len = 0;
    6155          47 :         node *n, *m, *idx_m = NULL;
    6156          47 :         sql_rel *tr = rel->l, *prel = rel->r;
    6157          47 :         sql_table *t = NULL;
    6158             : 
    6159          47 :         if ((rel->flag&UPD_COMP)) {  /* special case ! */
    6160           0 :                 assert(0);
    6161             :                 idx_ins = 1;
    6162             :                 prel = rel->l;
    6163             :                 rel = rel->r;
    6164             :                 tr = rel->l;
    6165             :         }
    6166             : 
    6167          47 :         if (tr->op == op_basetable) {
    6168          47 :                 t = tr->l;
    6169             :         } else {
    6170           0 :                 ddl = subrel_bin(be, tr, refs);
    6171           0 :                 ddl = subrel_project(be, ddl, refs, NULL);
    6172           0 :                 if (!ddl)
    6173             :                         return NULL;
    6174           0 :                 t = rel_ddl_table_get(tr);
    6175             :         }
    6176             : 
    6177          47 :         if (rel->r) /* first construct the inserts relation */
    6178          47 :                 inserts = subrel_bin(be, rel->r, refs);
    6179          47 :         inserts = subrel_project(be, inserts, refs, rel->r);
    6180             : 
    6181          47 :         if (!inserts)
    6182             :                 return NULL;
    6183             : 
    6184          47 :         if (idx_ins)
    6185             :                 pin = refs_find_rel(refs, prel);
    6186             : 
    6187          47 :         for (n = ol_first_node(t->keys); n; n = n->next) {
    6188           0 :                 sql_key * key = n->data;
    6189           0 :                 if (key->type == ckey)
    6190           0 :                         sql_insert_check(be, key, inserts->op4.lval);
    6191             :         }
    6192             : 
    6193          47 :         if (!sql_insert_check_null(be, t, inserts->op4.lval))
    6194             :                 return NULL;
    6195             : 
    6196          47 :         updates = table_update_stmts(sql, t, &len);
    6197             : 
    6198             :         /* now recursively insert into the sub tables (for each multiset fetch sequence number and renumber the msids) */
    6199         115 :         for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; ) {
    6200          68 :                 sql_column *c = n->data;
    6201             : 
    6202          68 :                 if (c->type.multiset) {
    6203          20 :                         sql_table *st = mvc_bind_table(sql, t->s, c->storage_type);
    6204          20 :                         if (!st)
    6205           0 :                                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: sub table '%s' missing", c->storage_type);
    6206          20 :                         updates[c->colnr] = insert_ms(be, st, &c->type, m->data);
    6207          20 :                         n = n->next;
    6208          20 :                         m = m->next;
    6209          48 :                 } else if (c->type.type->composite && !c->type.multiset) {
    6210          29 :                         n = insert_composite(be, updates, t, c, n, m);
    6211          29 :                         m = m->next;
    6212             :                 } else {
    6213          19 :                         updates[c->colnr] = m->data;
    6214          19 :                         n = n->next;
    6215          19 :                         m = m->next;
    6216             :                 }
    6217             :         }
    6218             : 
    6219             : /* before */
    6220          47 :         if (!sql_insert_triggers(be, t, updates, 0))
    6221           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    6222             : 
    6223          47 :         insert = inserts->op4.lval->h?inserts->op4.lval->h->data:NULL;
    6224          47 :         if (!insert || insert->nrcols == 0) {
    6225           0 :                 cnt = stmt_atom_lng(be, 1);
    6226             :         } else {
    6227          47 :                 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);
    6228             :         }
    6229          47 :         insert = NULL;
    6230             : 
    6231          47 :         l = sa_list(sql->sa);
    6232          47 :         if (t->idxs) {
    6233          47 :                 idx_m = m;
    6234          47 :                 for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
    6235           0 :                         stmt *is = m->data;
    6236           0 :                         sql_idx *i = n->data;
    6237             : 
    6238           0 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    6239           0 :                                 continue;
    6240           0 :                         if (hash_index(i->type) && list_length(i->columns) <= 1)
    6241           0 :                                 is = NULL;
    6242           0 :                         if (i->key) {
    6243           0 :                                 stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
    6244             : 
    6245           0 :                                 list_append(l, ckeys);
    6246             :                         }
    6247           0 :                         if (!insert)
    6248           0 :                                 insert = is;
    6249             :                 }
    6250          47 :                 assert(!n && !m);
    6251             :         }
    6252             : 
    6253          47 :         if (t->s) /* only not declared tables, need this */
    6254          47 :                 pos = stmt_claim(be, t, cnt);
    6255             : 
    6256          47 :         if (t->idxs) {
    6257          47 :                 for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
    6258           0 :                         stmt *is = m->data;
    6259           0 :                         sql_idx *i = n->data;
    6260             : 
    6261           0 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    6262           0 :                                 continue;
    6263           0 :                         if (hash_index(i->type) && list_length(i->columns) <= 1)
    6264             :                                 is = NULL;
    6265           0 :                         if (is)
    6266           0 :                                 is = stmt_append_idx(be, i, pos, is);
    6267             :                 }
    6268          47 :                 assert(!n && !m);
    6269             :         }
    6270             : 
    6271          47 :         int mvc_var = be->mvc_var;
    6272         191 :         for (n = ol_first_node(t->columns)/*, m = inserts->op4.lval->h*/; n /*&& m*/; n = n->next/*, m = m->next*/) {
    6273             : 
    6274             :                 //stmt *ins = m->data;
    6275         144 :                 sql_column *c = n->data;
    6276         144 :                 stmt *ins = updates[c->colnr];
    6277             : 
    6278         144 :                 if (ins) {
    6279         109 :                         insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
    6280         109 :                         append(l,insert);
    6281             :                 }
    6282             :         }
    6283          47 :         be->mvc_var = mvc_var;
    6284          47 :         if (!insert)
    6285             :                 return NULL;
    6286             : 
    6287          47 :         if (rel->returning) {
    6288           0 :                 list* il = sa_list(sql->sa);
    6289           0 :                 sql_rel* inner = rel->l;
    6290           0 :                 assert(inner->op == op_basetable);
    6291           0 :                 for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
    6292           0 :                         sql_exp* ce     = n->data;
    6293           0 :                         stmt*   ins     = m->data;
    6294           0 :                         stmt*   s       = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
    6295           0 :                         append(il, s);
    6296             :                 }
    6297           0 :                 returning = stmt_list(be, il);
    6298           0 :                 sql->type = Q_TABLE;
    6299             :         }
    6300             : 
    6301          47 :         if (!sql_insert_triggers(be, t, updates, 1))
    6302           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    6303             :         /* update predicate list */
    6304          47 :         if (rel->r && !rel_predicates(be, rel->r))
    6305             :                 return NULL;
    6306             : 
    6307          47 :         if (ddl) {
    6308           0 :                 ret = ddl;
    6309           0 :                 list_prepend(l, ddl);
    6310           0 :                 return stmt_list(be, l);
    6311             :         } else {
    6312          47 :                 ret = cnt;
    6313          47 :                 if (add_to_rowcount_accumulator(be, ret->nr) < 0)
    6314           0 :                         return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    6315          47 :                 if (t->s && isGlobal(t) && !isGlobalTemp(t))
    6316          47 :                         stmt_add_dependency_change(be, t, ret);
    6317          47 :                 return returning?returning:ret;
    6318             :         }
    6319             : }
    6320             : 
    6321             : static stmt *
    6322      110207 : rel2bin_insert(backend *be, sql_rel *rel, list *refs)
    6323             : {
    6324      110207 :         mvc *sql = be->mvc;
    6325      110207 :         list *l;
    6326      110207 :         stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, **updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
    6327      110207 :         int idx_ins = 0, len = 0;
    6328      110207 :         node *n, *m, *idx_m = NULL;
    6329      110207 :         sql_rel *tr = rel->l, *prel = rel->r;
    6330      110207 :         sql_table *t = NULL;
    6331             : 
    6332      110207 :         if ((rel->flag&UPD_COMP)) {  /* special case ! */
    6333           0 :                 idx_ins = 1;
    6334           0 :                 prel = rel->l;
    6335           0 :                 rel = rel->r;
    6336           0 :                 tr = rel->l;
    6337             :         }
    6338             : 
    6339      110207 :         if (tr->op == op_basetable) {
    6340      110108 :                 t = tr->l;
    6341             :         } else {
    6342          99 :                 ddl = subrel_bin(be, tr, refs);
    6343          99 :                 ddl = subrel_project(be, ddl, refs, NULL);
    6344          99 :                 if (!ddl)
    6345             :                         return NULL;
    6346          99 :                 t = rel_ddl_table_get(tr);
    6347             :         }
    6348      110207 :         if (t->multiset || t->composite)
    6349          47 :                 return rel2bin_insert_ms(be, rel, refs);
    6350             : 
    6351      110160 :         if (rel->r) /* first construct the inserts relation */
    6352      110161 :                 inserts = subrel_bin(be, rel->r, refs);
    6353      110139 :         inserts = subrel_project(be, inserts, refs, rel->r);
    6354             : 
    6355      110138 :         if (!inserts)
    6356             :                 return NULL;
    6357             : 
    6358      110138 :         if (idx_ins)
    6359           0 :                 pin = refs_find_rel(refs, prel);
    6360             : 
    6361      123909 :         for (n = ol_first_node(t->keys); n; n = n->next) {
    6362       13740 :                 sql_key * key = n->data;
    6363       13740 :                 if (key->type == ckey)
    6364          83 :                         sql_insert_check(be, key, inserts->op4.lval);
    6365             :         }
    6366             : 
    6367      110169 :         if (!sql_insert_check_null(be, t, inserts->op4.lval))
    6368             :                 return NULL;
    6369             : 
    6370      110201 :         updates = table_update_stmts(sql, t, &len);
    6371      825202 :         for (n = ol_first_node(t->columns), m = inserts->op4.lval->h; n && m; ) {
    6372      715010 :                 sql_column *c = n->data;
    6373             : 
    6374      715010 :                 if (c->type.type->composite && !c->type.multiset) {
    6375           0 :                         n = insert_composite(be, updates, t, c, n, m);
    6376          47 :                         m = m->next;
    6377             :                 } else {
    6378      715010 :                         updates[c->colnr] = m->data;
    6379      715010 :                         n = n->next;
    6380      715010 :                         m = m->next;
    6381             :                 }
    6382             :         }
    6383             : 
    6384             : /* before */
    6385      110192 :         if (!sql_insert_triggers(be, t, updates, 0))
    6386        3262 :                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    6387             : 
    6388      106909 :         insert = inserts->op4.lval->h?inserts->op4.lval->h->data:NULL;
    6389      106909 :         if (!insert || insert->nrcols == 0) {
    6390       75235 :                 cnt = stmt_atom_lng(be, 1);
    6391             :         } else {
    6392       31674 :                 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);
    6393             :         }
    6394      106931 :         insert = NULL;
    6395             : 
    6396      106931 :         l = sa_list(sql->sa);
    6397      106932 :         if (t->idxs) {
    6398      106932 :                 idx_m = m;
    6399      122213 :                 for (n = ol_first_node(t->idxs); n && m; n = n->next, m = m->next) {
    6400       15278 :                         stmt *is = m->data;
    6401       15278 :                         sql_idx *i = n->data;
    6402             : 
    6403       15278 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    6404         107 :                                 continue;
    6405       15171 :                         if (hash_index(i->type) && list_length(i->columns) <= 1)
    6406       15173 :                                 is = NULL;
    6407       15173 :                         if (i->key) {
    6408       13689 :                                 stmt *ckeys = sql_insert_key(be, inserts->op4.lval, i->key, is, pin);
    6409             : 
    6410       13698 :                                 list_append(l, ckeys);
    6411             :                         }
    6412       15174 :                         if (!insert)
    6413       15281 :                                 insert = is;
    6414             :                 }
    6415      106935 :                 assert(!n && !m);
    6416             :         }
    6417             : 
    6418      106935 :         if (t->s) /* only not declared tables, need this */
    6419      106917 :                 pos = stmt_claim(be, t, cnt);
    6420             : 
    6421      106879 :         if (t->idxs) {
    6422      122159 :                 for (n = ol_first_node(t->idxs), m = idx_m; n && m; n = n->next, m = m->next) {
    6423       15290 :                         stmt *is = m->data;
    6424       15290 :                         sql_idx *i = n->data;
    6425             : 
    6426       15290 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    6427         107 :                                 continue;
    6428       15183 :                         if (hash_index(i->type) && list_length(i->columns) <= 1)
    6429             :                                 is = NULL;
    6430        2225 :                         if (is)
    6431        2225 :                                 is = stmt_append_idx(be, i, pos, is);
    6432             :                 }
    6433      106869 :                 assert(!n && !m);
    6434             :         }
    6435             : 
    6436      106869 :         int mvc_var = be->mvc_var;
    6437      815264 :         for (n = ol_first_node(t->columns)/*, m = inserts->op4.lval->h*/; n /*&& m*/; n = n->next/*, m = m->next*/) {
    6438             : 
    6439             :                 //stmt *ins = m->data;
    6440      708339 :                 sql_column *c = n->data;
    6441      708339 :                 stmt *ins = updates[c->colnr];
    6442             : 
    6443      708339 :                 if (ins) {
    6444      708339 :                         insert = stmt_append_col(be, c, pos, ins, &mvc_var, rel->flag);
    6445      708444 :                         append(l,insert);
    6446             :                 }
    6447             :         }
    6448      106925 :         be->mvc_var = mvc_var;
    6449      106925 :         if (!insert)
    6450             :                 return NULL;
    6451             : 
    6452      106925 :         if (rel->returning) {
    6453           5 :                 list* il = sa_list(sql->sa);
    6454           5 :                 sql_rel* inner = rel->l;
    6455           5 :                 assert(inner->op == op_basetable);
    6456          15 :                 for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n = n->next, m = m->next) {
    6457          10 :                         sql_exp* ce     = n->data;
    6458          10 :                         stmt*   ins     = m->data;
    6459          10 :                         stmt*   s       = stmt_rename(be, ce, ins);// label each insert statement with the corresponding col exp label
    6460          10 :                         append(il, s);
    6461             :                 }
    6462           5 :                 returning = stmt_list(be, il);
    6463           5 :                 sql->type = Q_TABLE;
    6464             :         }
    6465             : 
    6466      106925 :         if (!sql_insert_triggers(be, t, updates, 1))
    6467        1631 :                 return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO: triggers failed for table '%s'", t->base.name);
    6468             :         /* update predicate list */
    6469      105246 :         if (rel->r && !rel_predicates(be, rel->r))
    6470             :                 return NULL;
    6471             : 
    6472      105216 :         if (ddl) {
    6473          99 :                 ret = ddl;
    6474          99 :                 list_prepend(l, ddl);
    6475          99 :                 return stmt_list(be, l);
    6476             :         } else {
    6477      105117 :                 ret = cnt;
    6478      105117 :                 if (add_to_rowcount_accumulator(be, ret->nr) < 0)
    6479           0 :                         return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    6480      105114 :                 if (t->s && isGlobal(t) && !isGlobalTemp(t))
    6481      105068 :                         stmt_add_dependency_change(be, t, ret);
    6482      105175 :                 return returning?returning:ret;
    6483             :         }
    6484             : }
    6485             : 
    6486             : static int
    6487        1373 : is_idx_updated(sql_idx * i, stmt **updates)
    6488             : {
    6489        1373 :         int update = 0;
    6490        1373 :         node *m;
    6491             : 
    6492        2710 :         for (m = i->columns->h; m; m = m->next) {
    6493        1545 :                 sql_kc *ic = m->data;
    6494             : 
    6495        1545 :                 if (updates[ic->c->colnr]) {
    6496             :                         update = 1;
    6497             :                         break;
    6498             :                 }
    6499             :         }
    6500        1373 :         return update;
    6501             : }
    6502             : 
    6503             : static int
    6504          14 : is_check_updated(sql_key * k, stmt **updates)
    6505             : {
    6506          14 :         int update = 0;
    6507          14 :         node *m;
    6508             : 
    6509          16 :         for (m = k->columns->h; m; m = m->next) {
    6510          14 :                 sql_kc *kc = m->data;
    6511             : 
    6512          14 :                 if (updates[kc->c->colnr]) {
    6513             :                         update = 1;
    6514             :                         break;
    6515             :                 }
    6516             :         }
    6517          14 :         return update;
    6518             : }
    6519             : 
    6520             : static int
    6521        4309 : first_updated_col(stmt **updates, int cnt)
    6522             : {
    6523        4309 :         int i;
    6524             : 
    6525       39145 :         for (i = 0; i < cnt; i++) {
    6526       38047 :                 if (updates[i])
    6527             :                         return i;
    6528             :         }
    6529             :         return -1;
    6530             : }
    6531             : 
    6532             : static stmt *
    6533         207 : update_check_ukey(backend *be, stmt **updates, sql_key *k, stmt *u_tids, stmt *idx_updates, int updcol)
    6534             : {
    6535         207 :         mvc *sql = be->mvc;
    6536         207 :         char *msg = NULL;
    6537         207 :         stmt *res = NULL;
    6538             : 
    6539         207 :         sql_subtype *lng = sql_bind_localtype("lng");
    6540         207 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    6541         207 :         sql_subtype *bt = sql_bind_localtype("bit");
    6542         207 :         sql_subfunc *ne;
    6543             : 
    6544         207 :         ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    6545         207 :         if (list_length(k->columns) > 1) {
    6546          48 :                 stmt *dels = stmt_tid(be, k->t, 0);
    6547          48 :                 node *m;
    6548          48 :                 stmt *s = NULL;
    6549             : 
    6550             :                 /* 1st stage: find out if original (without the updated)
    6551             :                         do not contain the same values as the updated values.
    6552             :                         This is done using a relation join and a count (which
    6553             :                         should be zero)
    6554             :                 */
    6555          48 :                 if (!isNew(k)) {
    6556          11 :                         stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
    6557          11 :                         nu_tids = stmt_project(be, nu_tids, dels);
    6558          11 :                         list *lje = sa_list(sql->sa);
    6559          11 :                         list *rje = sa_list(sql->sa);
    6560             : 
    6561          11 :                         if (k->idx && hash_index(k->idx->type)) {
    6562          11 :                                 list_append(lje, stmt_idx(be, k->idx, nu_tids, nu_tids->partition));
    6563          11 :                                 list_append(rje, idx_updates);
    6564             :                         }
    6565          33 :                         for (m = k->columns->h; m; m = m->next) {
    6566          22 :                                 sql_kc *c = m->data;
    6567          22 :                                 stmt *upd;
    6568             : 
    6569          22 :                                 assert(updates);
    6570          22 :                                 if (updates[c->c->colnr]) {
    6571             :                                         upd = updates[c->c->colnr];
    6572             :                                 } else {
    6573           8 :                                         upd = stmt_col(be, c->c, u_tids, u_tids->partition);
    6574             :                                 }
    6575          22 :                                 list_append(lje, stmt_col(be, c->c, nu_tids, nu_tids->partition));
    6576          22 :                                 list_append(rje, upd);
    6577             :                         }
    6578          11 :                         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
    6579          11 :                         s = stmt_result(be, s, 0);
    6580          11 :                         s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    6581             :                 }
    6582             : 
    6583             :                 /* 2e stage: find out if the updated are unique */
    6584          48 :                 if (!updates || updates[updcol]->nrcols) {   /* update columns not atoms */
    6585          48 :                         sql_subfunc *sum;
    6586          48 :                         stmt *count_sum = NULL, *ssum;
    6587          48 :                         stmt *g = NULL, *grp = NULL, *ext = NULL, *Cnt = NULL;
    6588          48 :                         stmt *cand = NULL;
    6589          48 :                         stmt *ss;
    6590          48 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
    6591             : 
    6592             :                         /* also take the hopefully unique hash keys, to reduce
    6593             :                            (re)group costs */
    6594          48 :                         if (k->idx && hash_index(k->idx->type)) {
    6595          48 :                                 g = stmt_group(be, idx_updates, grp, ext, Cnt, 0);
    6596          48 :                                 grp = stmt_result(be, g, 0);
    6597          48 :                                 ext = stmt_result(be, g, 1);
    6598          48 :                                 Cnt = stmt_result(be, g, 2);
    6599             : 
    6600             :                                 /* continue only with groups with a cnt > 1 */
    6601          48 :                                 cand = stmt_uselect(be, Cnt, stmt_atom_lng(be, 1), cmp_gt, NULL, 0, 0);
    6602             :                                 /* project cand on ext and Cnt */
    6603          48 :                                 Cnt = stmt_project(be, cand, Cnt);
    6604          48 :                                 ext = stmt_project(be, cand, ext);
    6605             : 
    6606             :                                 /* join groups with extend to retrieve all oid's of the original
    6607             :                                  * bat that belong to a group with Cnt >1 */
    6608          48 :                                 g = stmt_join(be, grp, ext, 0, cmp_equal, 0, 0, false);
    6609          48 :                                 cand = stmt_result(be, g, 0);
    6610          48 :                                 grp = stmt_project(be, cand, grp);
    6611             :                         }
    6612             : 
    6613         154 :                         for (m = k->columns->h; m; m = m->next) {
    6614         106 :                                 sql_kc *c = m->data;
    6615         106 :                                 stmt *upd;
    6616             : 
    6617         106 :                                 if (updates && updates[c->c->colnr]) {
    6618             :                                         upd = updates[c->c->colnr];
    6619             :                                 } else {
    6620          92 :                                         upd = stmt_col(be, c->c, dels, dels->partition);
    6621             :                                 }
    6622             : 
    6623             :                                 /* apply cand list first */
    6624         106 :                                 if (cand)
    6625         106 :                                         upd = stmt_project(be, cand, upd);
    6626             : 
    6627             :                                 /* remove nulls */
    6628         106 :                                 if ((k->type == ukey) && stmt_has_null(upd)) {
    6629          31 :                                         stmt *nn = stmt_selectnonil(be, upd, NULL);
    6630          31 :                                         upd = stmt_project(be, nn, upd);
    6631          31 :                                         if (grp)
    6632          31 :                                                 grp = stmt_project(be, nn, grp);
    6633          31 :                                         if (cand)
    6634          31 :                                                 cand = stmt_project(be, nn, cand);
    6635             :                                 }
    6636             : 
    6637             :                                 /* apply group by on groups with Cnt > 1 */
    6638         106 :                                 g = stmt_group(be, upd, grp, ext, Cnt, !m->next);
    6639         106 :                                 grp = stmt_result(be, g, 0);
    6640         106 :                                 ext = stmt_result(be, g, 1);
    6641         106 :                                 Cnt = stmt_result(be, g, 2);
    6642             :                         }
    6643          48 :                         ss = Cnt; /* use count */
    6644             :                         /* (count(ss) <> sum(ss)) */
    6645          48 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
    6646          48 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    6647          48 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    6648          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);
    6649             : 
    6650             :                         /* combine results */
    6651          48 :                         if (s)
    6652          11 :                                 s = stmt_binop(be, s, count_sum, NULL, or);
    6653             :                         else
    6654             :                                 s = count_sum;
    6655             :                 }
    6656             : 
    6657          48 :                 if (k->type == pkey) {
    6658          31 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6659             :                 } else {
    6660          17 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6661             :                 }
    6662          48 :                 res = stmt_exception(be, s, msg, 00001);
    6663             :         } else {                /* single column key */
    6664         159 :                 stmt *dels = stmt_tid(be, k->t, 0);
    6665         159 :                 sql_kc *c = k->columns->h->data;
    6666         159 :                 stmt *s = NULL, *h = NULL, *o;
    6667             : 
    6668             :                 /* s should be empty */
    6669         159 :                 if (!isNew(k)) {
    6670          70 :                         stmt *nu_tids = stmt_tdiff(be, dels, u_tids, NULL); /* not updated ids */
    6671          70 :                         nu_tids = stmt_project(be, nu_tids, dels);
    6672          70 :                         assert (updates);
    6673             : 
    6674          70 :                         h = updates[c->c->colnr];
    6675          70 :                         o = stmt_col(be, c->c, nu_tids, nu_tids->partition);
    6676          70 :                         s = stmt_join(be, o, h, 0, cmp_equal, 0, 0, false);
    6677          70 :                         s = stmt_result(be, s, 0);
    6678          70 :                         s = stmt_binop(be, stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    6679             :                 }
    6680             : 
    6681             :                 /* 2e stage: find out if updated are unique */
    6682          70 :                 if (!h || h->nrcols) {       /* update columns not atoms */
    6683         159 :                         sql_subfunc *sum;
    6684         159 :                         stmt *count_sum = NULL;
    6685         159 :                         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
    6686         159 :                         stmt *ssum, *ss;
    6687         159 :                         stmt *upd;
    6688         159 :                         stmt *g;
    6689             : 
    6690         159 :                         if (updates) {
    6691          72 :                                 upd = updates[c->c->colnr];
    6692             :                         } else {
    6693          87 :                                 upd = stmt_col(be, c->c, dels, dels->partition);
    6694             :                         }
    6695             : 
    6696             :                         /* remove nulls */
    6697         159 :                         if ((k->type == ukey) && stmt_has_null(upd)) {
    6698          15 :                                 stmt *nn = stmt_selectnonil(be, upd, NULL);
    6699          15 :                                 upd = stmt_project(be, nn, upd);
    6700             :                         }
    6701             : 
    6702         159 :                         g = stmt_group(be, upd, NULL, NULL, NULL, 1);
    6703         159 :                         ss = stmt_result(be, g, 2); /* use count */
    6704             : 
    6705             :                         /* (count(ss) <> sum(ss)) */
    6706         159 :                         sum = sql_bind_func(sql, "sys", "sum", lng, NULL, F_AGGR, true, true);
    6707         159 :                         ssum = stmt_aggr(be, ss, NULL, NULL, sum, 1, 0, 1);
    6708         159 :                         ssum = sql_Nop_(be, "ifthenelse", sql_unop_(be, "isnull", ssum), stmt_atom_lng(be, 0), ssum, NULL);
    6709         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);
    6710             : 
    6711             :                         /* combine results */
    6712         159 :                         if (s)
    6713          70 :                                 s = stmt_binop(be, s, count_sum, NULL, or);
    6714             :                         else
    6715             :                                 s = count_sum;
    6716             :                 }
    6717             : 
    6718         159 :                 if (k->type == pkey) {
    6719         142 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: PRIMARY KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6720             :                 } else {
    6721          17 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: UNIQUE constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6722             :                 }
    6723         159 :                 res = stmt_exception(be, s, msg, 00001);
    6724             :         }
    6725         207 :         return res;
    6726             : }
    6727             : 
    6728             : /*
    6729             :          A referential constraint is satisfied if one of the following con-
    6730             :          ditions is true, depending on the <match option> specified in the
    6731             :          <referential constraint definition>:
    6732             : 
    6733             :          -  If no <match type> was specified then, for each row R1 of the
    6734             :             referencing table, either at least one of the values of the
    6735             :             referencing columns in R1 shall be a null value, or the value of
    6736             :             each referencing column in R1 shall be equal to the value of the
    6737             :             corresponding referenced column in some row of the referenced
    6738             :             table.
    6739             : 
    6740             :          -  If MATCH FULL was specified then, for each row R1 of the refer-
    6741             :             encing table, either the value of every referencing column in R1
    6742             :             shall be a null value, or the value of every referencing column
    6743             :             in R1 shall not be null and there shall be some row R2 of the
    6744             :             referenced table such that the value of each referencing col-
    6745             :             umn in R1 is equal to the value of the corresponding referenced
    6746             :             column in R2.
    6747             : 
    6748             :          -  If MATCH PARTIAL was specified then, for each row R1 of the
    6749             :             referencing table, there shall be some row R2 of the refer-
    6750             :             enced table such that the value of each referencing column in
    6751             :             R1 is either null or is equal to the value of the corresponding
    6752             :             referenced column in R2.
    6753             : */
    6754             : 
    6755             : static stmt *
    6756         698 : update_check_fkey(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, stmt *pup)
    6757             : {
    6758         698 :         mvc *sql = be->mvc;
    6759         698 :         char *msg = NULL;
    6760         698 :         stmt *s, *cur, *null = NULL, *cntnulls;
    6761         698 :         sql_subtype *lng = sql_bind_localtype("lng"), *bt = sql_bind_localtype("bit");
    6762         698 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    6763         698 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    6764         698 :         sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true, bt, 2, bt, bt);
    6765         698 :         node *m;
    6766             : 
    6767         698 :         if (!idx_updates)
    6768             :                 return NULL;
    6769             :         /* releqjoin.count <> updates[updcol].count */
    6770         698 :         if (pup && list_length(pup->op4.lval)) {
    6771         655 :                 cur = pup->op4.lval->h->data;
    6772          43 :         } else if (updates) {
    6773          43 :                 cur = updates[updcol];
    6774             :         } else {
    6775           0 :                 sql_kc *c = k->columns->h->data;
    6776           0 :                 stmt *dels = stmt_tid(be, k->t, 0);
    6777           0 :                 assert(0);
    6778             :                 cur = stmt_col(be, c->c, dels, dels->partition);
    6779             :         }
    6780         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);
    6781             : 
    6782        1419 :         for (m = k->columns->h; m; m = m->next) {
    6783         721 :                 sql_kc *c = m->data;
    6784             : 
    6785             :                 /* FOR MATCH FULL/SIMPLE/PARTIAL see above */
    6786             :                 /* Currently only the default MATCH SIMPLE is supported */
    6787         721 :                 if (c->c->null) {
    6788         309 :                         stmt *upd, *nn;
    6789             : 
    6790         309 :                         if (updates && updates[c->c->colnr]) {
    6791             :                                 upd = updates[c->c->colnr];
    6792             :                         } else { /* created idx/key using alter */
    6793         277 :                                 upd = stmt_col(be, c->c, tids, tids->partition);
    6794             :                         }
    6795         309 :                         nn = stmt_selectnil(be, upd);
    6796         309 :                         if (null)
    6797          11 :                                 null = stmt_tunion(be, null, nn);
    6798             :                         else
    6799             :                                 null = nn;
    6800             :                 }
    6801             :         }
    6802         698 :         if (null) {
    6803         298 :                 cntnulls = stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1);
    6804             :         } else {
    6805         400 :                 cntnulls = stmt_atom_lng(be, 0);
    6806             :         }
    6807         698 :         s = stmt_binop(be, s,
    6808             :                 stmt_binop(be, stmt_aggr(be, stmt_selectnil(be, idx_updates), NULL, NULL, cnt, 1, 0, 1), cntnulls, NULL, ne), NULL, or);
    6809             : 
    6810             :         /* s should be empty */
    6811         698 :         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6812         698 :         return stmt_exception(be, s, msg, 00001);
    6813             : }
    6814             : 
    6815             : static stmt *
    6816          10 : join_updated_pkey(backend *be, sql_key * k, stmt *tids, stmt **updates)
    6817             : {
    6818          10 :         mvc *sql = be->mvc;
    6819          10 :         sql_trans *tr = sql->session->tr;
    6820          10 :         char *msg = NULL;
    6821          10 :         int nulls = 0;
    6822          10 :         node *m, *o;
    6823          10 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    6824          10 :         stmt *s = NULL, *dels = stmt_tid(be, rk->t, 0), *fdels, *cnteqjoin;
    6825          10 :         stmt *null = NULL, *rows;
    6826          10 :         sql_subtype *lng = sql_bind_localtype("lng");
    6827          10 :         sql_subtype *bt = sql_bind_localtype("bit");
    6828          10 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    6829          10 :         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    6830          10 :         list *lje = sa_list(sql->sa);
    6831          10 :         list *rje = sa_list(sql->sa);
    6832             : 
    6833          10 :         fdels = stmt_tid(be, k->idx->t, 0);
    6834          10 :         rows = stmt_idx(be, k->idx, fdels, fdels->partition);
    6835             : 
    6836          10 :         rows = stmt_join(be, rows, tids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    6837          10 :         rows = stmt_result(be, rows, 0);
    6838             : 
    6839          22 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    6840          12 :                 sql_kc *fc = m->data;
    6841          12 :                 sql_kc *c = o->data;
    6842          12 :                 stmt *upd, *col;
    6843             : 
    6844          12 :                 if (updates[c->c->colnr]) {
    6845             :                         upd = updates[c->c->colnr];
    6846             :                 } else {
    6847           2 :                         upd = stmt_project(be, tids, stmt_col(be, c->c, dels, dels->partition));
    6848             :                 }
    6849          12 :                 if (c->c->null) { /* new nulls (MATCH SIMPLE) */
    6850           3 :                         stmt *nn = stmt_selectnil(be, upd);
    6851           3 :                         if (null)
    6852           1 :                                 null = stmt_tunion(be, null, nn);
    6853             :                         else
    6854             :                                 null = nn;
    6855             :                         nulls = 1;
    6856             :                 }
    6857          12 :                 col = stmt_col(be, fc->c, rows, rows->partition);
    6858          12 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    6859           0 :                         return NULL;
    6860          12 :                 list_append(lje, upd);
    6861          12 :                 list_append(rje, col);
    6862             :         }
    6863          10 :         s = releqjoin(be, lje, rje, NULL, 1 /* hash used */, 0, 0);
    6864          10 :         s = stmt_result(be, s, 0);
    6865             : 
    6866             :         /* add missing nulls */
    6867          10 :         cnteqjoin = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    6868          10 :         if (nulls) {
    6869           2 :                 sql_subfunc *add = sql_bind_func_result(sql, "sys", "sql_add", F_FUNC, true, lng, 2, lng, lng);
    6870           2 :                 cnteqjoin = stmt_binop(be, cnteqjoin, stmt_aggr(be, null, NULL, NULL, cnt, 1, 0, 1), NULL, add);
    6871             :         }
    6872             : 
    6873             :         /* releqjoin.count <> updates[updcol].count */
    6874          10 :         s = stmt_binop(be, cnteqjoin, stmt_aggr(be, rows, NULL, NULL, cnt, 1, 0, 1), NULL, ne);
    6875             : 
    6876             :         /* s should be empty */
    6877          10 :         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: FOREIGN KEY constraint '%s.%s' violated", k->t->base.name, k->base.name);
    6878          10 :         return stmt_exception(be, s, msg, 00001);
    6879             : }
    6880             : 
    6881             : static list * sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates);
    6882             : 
    6883             : static stmt*
    6884          11 : sql_delete_set_Fkeys(backend *be, sql_key *k, stmt *ftids /* to be updated rows of fkey table */, int action)
    6885             : {
    6886          11 :         mvc *sql = be->mvc;
    6887          11 :         sql_trans *tr = sql->session->tr;
    6888          11 :         list *l = NULL;
    6889          11 :         int len = 0;
    6890          11 :         node *m, *o;
    6891          11 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    6892          11 :         stmt **new_updates;
    6893          11 :         sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
    6894             : 
    6895          11 :         new_updates = table_update_stmts(sql, t, &len);
    6896          24 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    6897          13 :                 sql_kc *fc = m->data;
    6898          13 :                 stmt *upd = NULL;
    6899             : 
    6900          13 :                 if (action == ACT_SET_DEFAULT) {
    6901           4 :                         if (fc->c->def) {
    6902           4 :                                 stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
    6903           4 :                                 if (!sq)
    6904             :                                         return NULL;
    6905             :                                 upd = sq;
    6906             :                         } else {
    6907           0 :                                 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
    6908             :                         }
    6909             :                 } else {
    6910           9 :                         upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
    6911             :                 }
    6912             : 
    6913          13 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    6914           0 :                         return NULL;
    6915             : 
    6916          13 :                 if (upd->nrcols <= 0)
    6917          13 :                         upd = stmt_const(be, ftids, upd);
    6918             : 
    6919          13 :                 new_updates[fc->c->colnr] = upd;
    6920             :         }
    6921          11 :         if ((l = sql_update(be, t, ftids, new_updates)) == NULL)
    6922             :                 return NULL;
    6923          11 :         return stmt_list(be, l);
    6924             : }
    6925             : 
    6926             : static stmt*
    6927          32 : sql_update_cascade_Fkeys(backend *be, sql_key *k, stmt *utids, stmt **updates, int action)
    6928             : {
    6929          32 :         mvc *sql = be->mvc;
    6930          32 :         sql_trans *tr = sql->session->tr;
    6931          32 :         list *l = NULL;
    6932          32 :         int len = 0;
    6933          32 :         node *m, *o;
    6934          32 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey);
    6935          32 :         stmt **new_updates;
    6936          32 :         stmt *rows;
    6937          32 :         sql_table *t = mvc_bind_table(sql, k->t->s, k->t->base.name);
    6938          32 :         stmt *ftids, *upd_ids;
    6939             : 
    6940          32 :         ftids = stmt_tid(be, k->idx->t, 0);
    6941          32 :         rows = stmt_idx(be, k->idx, ftids, ftids->partition);
    6942             : 
    6943          32 :         rows = stmt_join(be, rows, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    6944          32 :         upd_ids = stmt_result(be, rows, 1);
    6945          32 :         rows = stmt_result(be, rows, 0);
    6946          32 :         rows = stmt_project(be, rows, ftids);
    6947             : 
    6948          32 :         new_updates = table_update_stmts(sql, t, &len);
    6949          64 :         for (m = k->idx->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    6950          32 :                 sql_kc *fc = m->data;
    6951          32 :                 sql_kc *c = o->data;
    6952          32 :                 stmt *upd = NULL;
    6953             : 
    6954          32 :                 if (!updates[c->c->colnr]) {
    6955           0 :                         continue;
    6956          32 :                 } else if (action == ACT_CASCADE) {
    6957             :                         upd = updates[c->c->colnr];
    6958          16 :                 } else if (action == ACT_SET_DEFAULT) {
    6959           6 :                         if (fc->c->def) {
    6960           6 :                                 stmt *sq = parse_value(be, fc->c->t->s, fc->c->def, &fc->c->type, sql->emode);
    6961           6 :                                 if (!sq)
    6962             :                                         return NULL;
    6963             :                                 upd = sq;
    6964             :                         } else {
    6965           0 :                                 upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
    6966             :                         }
    6967          10 :                 } else if (action == ACT_SET_NULL) {
    6968          10 :                         upd = stmt_atom(be, atom_general(sql->sa, &fc->c->type, NULL, 0));
    6969             :                 }
    6970             : 
    6971          32 :                 if (!upd || (upd = check_types(be, &fc->c->type, upd, type_equal)) == NULL)
    6972           0 :                         return NULL;
    6973             : 
    6974          32 :                 if (upd->nrcols <= 0)
    6975          16 :                         upd = stmt_const(be, upd_ids, upd);
    6976             :                 else
    6977          16 :                         upd = stmt_project(be, upd_ids, upd);
    6978             : 
    6979          32 :                 new_updates[fc->c->colnr] = upd;
    6980             :         }
    6981             : 
    6982          32 :         if ((l = sql_update(be, t, rows, new_updates)) == NULL)
    6983             :                 return NULL;
    6984          32 :         return stmt_list(be, l);
    6985             : }
    6986             : 
    6987             : static int
    6988          83 : cascade_ukey(backend *be, stmt **updates, sql_key *k, stmt *tids)
    6989             : {
    6990             :         /* now iterate over all keys */
    6991          83 :         sql_trans *tr = be->mvc->session->tr;
    6992          83 :         list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    6993          83 :         if (keys) {
    6994         133 :                 for (node *n = keys->h; n; n = n->next->next) {
    6995          50 :                         sqlid fkey_id = *(sqlid*)n->data;
    6996          50 :                         sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    6997          50 :                         sql_key *fk = (sql_key*)b;
    6998          50 :                         sql_fkey *rk = (sql_fkey*)b;
    6999             : 
    7000          50 :                         if (fk->type != fkey || rk->rkey != k->base.id)
    7001           0 :                                 continue;
    7002             : 
    7003             :                         /* All rows of the foreign key table which are
    7004             :                            affected by the primary key update should all
    7005             :                            match one of the updated primary keys again.
    7006             :                          */
    7007          50 :                         switch (((sql_fkey*)fk)->on_update) {
    7008             :                         case ACT_NO_ACTION:
    7009             :                                 break;
    7010          32 :                         case ACT_SET_NULL:
    7011             :                         case ACT_SET_DEFAULT:
    7012             :                         case ACT_CASCADE:
    7013          32 :                                 if (!sql_update_cascade_Fkeys(be, fk, tids, updates, ((sql_fkey*)fk)->on_update)) {
    7014           0 :                                         list_destroy(keys);
    7015           0 :                                         return -1;
    7016             :                                 }
    7017             :                                 break;
    7018          10 :                         default:        /*RESTRICT*/
    7019          10 :                                 if (!join_updated_pkey(be, fk, tids, updates)) {
    7020           0 :                                         list_destroy(keys);
    7021           0 :                                         return -1;
    7022             :                                 }
    7023             :                         }
    7024             :                 }
    7025          83 :                 list_destroy(keys);
    7026             :         }
    7027             :         return 0;
    7028             : }
    7029             : 
    7030             : static void
    7031         905 : sql_update_check_key(backend *be, stmt **updates, sql_key *k, stmt *tids, stmt *idx_updates, int updcol, list *l, stmt *pup)
    7032             : {
    7033         905 :         stmt *ckeys;
    7034             : 
    7035         905 :         if (k->type == pkey || k->type == ukey) {
    7036         207 :                 ckeys = update_check_ukey(be, updates, k, tids, idx_updates, updcol);
    7037             :         } else { /* foreign keys */
    7038         698 :                 ckeys = update_check_fkey(be, updates, k, tids, idx_updates, updcol, pup);
    7039             :         }
    7040         905 :         list_append(l, ckeys);
    7041         905 : }
    7042             : 
    7043             : static stmt *
    7044          20 : hash_update(backend *be, sql_idx * i, stmt *rows, stmt **updates, int updcol)
    7045             : {
    7046          20 :         mvc *sql = be->mvc;
    7047             :         /* calculate new value */
    7048          20 :         node *m;
    7049          20 :         sql_subtype *it, *lng;
    7050          20 :         int bits = 1 + ((sizeof(lng)*8)-1)/(list_length(i->columns)+1);
    7051          20 :         stmt *h = NULL, *tids;
    7052             : 
    7053          20 :         if (list_length(i->columns) <= 1)
    7054             :                 return NULL;
    7055             : 
    7056           0 :         tids = stmt_tid(be, i->t, 0);
    7057           0 :         it = sql_bind_localtype("int");
    7058           0 :         lng = sql_bind_localtype("lng");
    7059           0 :         for (m = i->columns->h; m; m = m->next) {
    7060           0 :                 sql_kc *c = m->data;
    7061           0 :                 stmt *upd;
    7062             : 
    7063           0 :                 if (updates && updates[c->c->colnr]) {
    7064             :                         upd = updates[c->c->colnr];
    7065           0 :                 } else if (updates && updcol >= 0) {
    7066           0 :                         assert(0);
    7067             :                         upd = stmt_col(be, c->c, rows, rows->partition);
    7068             :                 } else { /* created idx/key using alter */
    7069           0 :                         upd = stmt_col(be, c->c, tids, tids->partition);
    7070             :                 }
    7071             : 
    7072           0 :                 if (h && i->type == hash_idx)  {
    7073           0 :                         sql_subfunc *xor = sql_bind_func_result(sql, "sys", "rotate_xor_hash", F_FUNC, true, lng, 3, lng, it, &c->c->type);
    7074             : 
    7075           0 :                         h = stmt_Nop(be, stmt_list(be, list_append(list_append(
    7076             :                                 list_append(sa_list(sql->sa), h),
    7077           0 :                                 stmt_atom_int(be, bits)),  upd)), NULL,
    7078             :                                 xor, NULL);
    7079           0 :                 } else if (h)  {
    7080           0 :                         stmt *h2;
    7081           0 :                         sql_subfunc *lsh = sql_bind_func_result(sql, "sys", "left_shift", F_FUNC, true, lng, 2, lng, it);
    7082           0 :                         sql_subfunc *lor = sql_bind_func_result(sql, "sys", "bit_or", F_FUNC, true, lng, 2, lng, lng);
    7083           0 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
    7084             : 
    7085           0 :                         h = stmt_binop(be, h, stmt_atom_int(be, bits), NULL, lsh);
    7086           0 :                         h2 = stmt_unop(be, upd, NULL, hf);
    7087           0 :                         h = stmt_binop(be, h, h2, NULL, lor);
    7088             :                 } else {
    7089           0 :                         sql_subfunc *hf = sql_bind_func_result(sql, "sys", "hash", F_FUNC, true, lng, 1, &c->c->type);
    7090           0 :                         h = stmt_unop(be, upd, NULL, hf);
    7091           0 :                         if (i->type == oph_idx)
    7092             :                                 break;
    7093             :                 }
    7094             :         }
    7095             :         return h;
    7096             : }
    7097             : 
    7098             : static stmt *
    7099          43 : join_idx_update(backend *be, sql_idx * i, stmt *ftids, stmt **updates, int updcol)
    7100             : {
    7101          43 :         mvc *sql = be->mvc;
    7102          43 :         sql_trans *tr = sql->session->tr;
    7103          43 :         node *m, *o;
    7104          43 :         sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)i->key)->rkey);
    7105          43 :         stmt *s = NULL, *ptids = stmt_tid(be, rk->t, 0), *l, *r;
    7106          43 :         list *lje = sa_list(sql->sa);
    7107          43 :         list *rje = sa_list(sql->sa);
    7108             : 
    7109          88 :         for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o = o->next) {
    7110          45 :                 sql_kc *c = m->data;
    7111          45 :                 sql_kc *rc = o->data;
    7112          45 :                 stmt *upd;
    7113             : 
    7114          45 :                 if (updates && updates[c->c->colnr]) {
    7115             :                         upd = updates[c->c->colnr];
    7116           0 :                 } else if (updates && updcol >= 0) {
    7117           0 :                         assert(0);
    7118             :                         upd = stmt_col(be, c->c, ftids, ftids->partition);
    7119             :                 } else { /* created idx/key using alter */
    7120           0 :                         upd = stmt_col(be, c->c, ftids, ftids->partition);
    7121             :                 }
    7122             : 
    7123          45 :                 if (!upd || (upd = check_types(be, &rc->c->type, upd, type_equal)) == NULL)
    7124           0 :                         return NULL;
    7125          45 :                 list_append(lje, upd);
    7126          45 :                 list_append(rje, stmt_col(be, rc->c, ptids, ptids->partition));
    7127             :         }
    7128          43 :         s = releqjoin(be, lje, rje, NULL, 0 /* use hash */, 0, 0);
    7129          43 :         l = stmt_result(be, s, 0);
    7130          43 :         r = stmt_result(be, s, 1);
    7131          43 :         r = stmt_project(be, r, ptids);
    7132          43 :         return stmt_left_project(be, ftids, l, r);
    7133             : }
    7134             : 
    7135             : static int
    7136        4309 : cascade_updates(backend *be, sql_table *t, stmt *rows, stmt **updates)
    7137             : {
    7138        4309 :         mvc *sql = be->mvc;
    7139        4309 :         node *n;
    7140             : 
    7141        4309 :         if (!ol_length(t->idxs))
    7142             :                 return 0;
    7143             : 
    7144        2545 :         for (n = ol_first_node(t->idxs); n; n = n->next) {
    7145        1310 :                 sql_idx *i = n->data;
    7146             : 
    7147             :                 /* check if update is needed,
    7148             :                  * ie at least on of the idx columns is updated
    7149             :                  */
    7150        1310 :                 if (is_idx_updated(i, updates) == 0)
    7151        1165 :                         continue;
    7152             : 
    7153         145 :                 if (i->key) {
    7154         142 :                         if (!(sql->cascade_action && list_find_id(sql->cascade_action, i->key->base.id))) {
    7155         142 :                                 sql_key *k = i->key;
    7156         142 :                                 sqlid *local_id = SA_NEW(sql->sa, sqlid);
    7157         142 :                                 if (!sql->cascade_action)
    7158          67 :                                         sql->cascade_action = sa_list(sql->sa);
    7159         142 :                                 *local_id = i->key->base.id;
    7160         142 :                                 list_append(sql->cascade_action, local_id);
    7161         142 :                                 if (k->type == pkey || k->type == ukey) {
    7162          83 :                                         if (cascade_ukey(be, updates, k, rows))
    7163             :                                                 return -1;
    7164             :                                 }
    7165             :                         }
    7166             :                 }
    7167             :         }
    7168             :         return 0;
    7169             : }
    7170             : 
    7171             : static list *
    7172          43 : update_idxs_and_check_keys(backend *be, sql_table *t, stmt *rows, stmt **updates, list *l, stmt *pup)
    7173             : {
    7174          43 :         mvc *sql = be->mvc;
    7175          43 :         node *n;
    7176          43 :         int updcol;
    7177          43 :         list *idx_updates = sa_list(sql->sa);
    7178             : 
    7179          43 :         if (!ol_length(t->idxs))
    7180             :                 return idx_updates;
    7181             : 
    7182          43 :         updcol = first_updated_col(updates, ol_length(t->columns));
    7183         106 :         for (n = ol_first_node(t->idxs); n; n = n->next) {
    7184          63 :                 sql_idx *i = n->data;
    7185          63 :                 stmt *is = NULL;
    7186             : 
    7187             :                 /* check if update is needed,
    7188             :                  * ie at least on of the idx columns is updated
    7189             :                  */
    7190          63 :                 if (is_idx_updated(i, updates) == 0)
    7191           0 :                         continue;
    7192             : 
    7193          63 :                 if (hash_index(i->type)) {
    7194          20 :                         is = hash_update(be, i, rows, updates, updcol);
    7195          43 :                 } else if (i->type == join_idx) {
    7196          43 :                         if (updcol < 0)
    7197             :                                 return NULL;
    7198          43 :                         if (!(is = join_idx_update(be, i, rows, updates, updcol)))
    7199             :                                 return NULL;
    7200             :                 }
    7201          63 :                 if (i->key)
    7202          63 :                         sql_update_check_key(be, updates, i->key, rows, is, updcol, l, pup);
    7203          63 :                 if (is)
    7204          43 :                         list_append(idx_updates, stmt_update_idx(be, i, rows, is));
    7205             :         }
    7206             :         return idx_updates;
    7207             : }
    7208             : 
    7209             : static int
    7210         266 : sql_stack_add_updated(mvc *sql, const char *on, const char *nn, sql_table *t, stmt *tids, stmt **updates)
    7211             : {
    7212             :         /* Put single relation of updates and old values on to the stack */
    7213         266 :         sql_rel *r = NULL;
    7214         266 :         node *n;
    7215         266 :         list *exps = sa_list(sql->sa);
    7216         266 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    7217             : 
    7218         266 :         ti->t = t;
    7219         266 :         ti->tids = tids;
    7220         266 :         ti->updates = updates;
    7221         266 :         ti->type = 2;
    7222         266 :         ti->on = on;
    7223         266 :         ti->nn = nn;
    7224         266 :         sql_alias *oname = a_create(sql->sa, ti->on);
    7225         266 :         sql_alias *nname = a_create(sql->sa, ti->nn);
    7226        1489 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    7227        1223 :                 sql_column *c = n->data;
    7228             : 
    7229        1223 :                 if (updates[c->colnr]) {
    7230         266 :                         sql_exp *oe = exp_column(sql->sa, oname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    7231         266 :                         sql_exp *ne = exp_column(sql->sa, nname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    7232         266 :                         oe->alias.label = -(sql->nid++);
    7233         266 :                         ne->alias.label = -(sql->nid++);
    7234             : 
    7235         266 :                         append(exps, oe);
    7236         266 :                         append(exps, ne);
    7237             :                 } else {
    7238         957 :                         sql_exp *oe = exp_column(sql->sa, oname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    7239         957 :                         sql_exp *ne = exp_column(sql->sa, nname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    7240         957 :                         oe->alias.label = -(sql->nid++);
    7241         957 :                         ne->alias.label = -(sql->nid++);
    7242             : 
    7243         957 :                         append(exps, oe);
    7244         957 :                         append(exps, ne);
    7245             :                 }
    7246             :         }
    7247         266 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    7248         266 :         r->l = ti;
    7249             : 
    7250             :         /* put single table into the stack with 2 names, needed for the psm code */
    7251         266 :         if (!stack_push_rel_view(sql, on, r) || !stack_push_rel_view(sql, nn, rel_dup(r)))
    7252           0 :                 return 0;
    7253             :         return 1;
    7254             : }
    7255             : 
    7256             : static int
    7257        8618 : sql_update_triggers(backend *be, sql_table *t, stmt *tids, stmt **updates, int time)
    7258             : {
    7259        8618 :         mvc *sql = be->mvc;
    7260        8618 :         node *n;
    7261        8618 :         int res = 1;
    7262             : 
    7263        8618 :         if (!ol_length(t->triggers))
    7264             :                 return res;
    7265             : 
    7266        1036 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    7267         552 :                 sql_trigger *trigger = n->data;
    7268             : 
    7269         552 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    7270             :                         return 0;
    7271         552 :                 if (trigger->event == 2 && trigger->time == time) {
    7272             :                         /* add name for the 'inserted' to the stack */
    7273         266 :                         const char *n = trigger->new_name;
    7274         266 :                         const char *o = trigger->old_name;
    7275             : 
    7276         266 :                         if (!n) n = "new";
    7277         266 :                         if (!o) o = "old";
    7278             : 
    7279         266 :                         if(!sql_stack_add_updated(sql, o, n, t, tids, updates)) {
    7280           0 :                                 stack_pop_frame(sql);
    7281           0 :                                 return 0;
    7282             :                         }
    7283             : 
    7284         266 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    7285           0 :                                 stack_pop_frame(sql);
    7286           0 :                                 return 0;
    7287             :                         }
    7288             :                 }
    7289         552 :                 stack_pop_frame(sql);
    7290             :         }
    7291             :         return res;
    7292             : }
    7293             : 
    7294             : static void
    7295          25 : sql_update_check(backend *be, stmt **updates, sql_key *key, stmt *u_tids)
    7296             : {
    7297          25 :         mvc *sql = be->mvc;
    7298          25 :         int pos = 0;
    7299          25 :         sql_rel *rel = rel_basetable(sql, key->t, a_create(be->mvc->sa, key->t->base.name));
    7300          25 :         sql_exp *exp = exp_read(sql, rel, NULL, NULL, sa_strdup(sql->sa, key->check), &pos, 0);
    7301          25 :         rel->exps = rel_base_projection(sql, rel, 0);
    7302             : 
    7303             :         /* create sub stmt with needed updates (or projected col from to be updated table) */
    7304          25 :         list *ups = sa_list(sql->sa);
    7305          55 :         for(node *n = key->columns->h; n; n = n->next) {
    7306          30 :                 sql_kc *kc = n->data;
    7307          30 :                 stmt *upd = NULL;
    7308             : 
    7309          30 :                 if (updates && updates[kc->c->colnr]) {
    7310             :                         upd = updates[kc->c->colnr];
    7311             :                 } else {
    7312          17 :                         upd = stmt_col(be, kc->c, u_tids, u_tids->partition);
    7313             :                 }
    7314          30 :                 sql_exp *e = rel_base_bind_column2(sql, rel, a_create(be->mvc->sa, kc->c->t->base.name), kc->c->base.name);
    7315          30 :                 upd = stmt_alias(be, upd, e->alias.label, a_create(be->mvc->sa, kc->c->t->base.name), kc->c->base.name);
    7316          30 :                 append(ups, upd);
    7317             :         }
    7318             : 
    7319          25 :         stmt *sub = stmt_list(be, ups);
    7320          25 :         stmt *s = exp_bin(be, exp, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    7321             : 
    7322          25 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    7323          25 :         s = stmt_uselect(be, column(be, s), stmt_bool(be, 0), cmp_equal, NULL, 0, 1);
    7324          25 :         s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    7325          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);
    7326          25 :         (void)stmt_exception(be, s, msg, 00001);
    7327          25 : }
    7328             : 
    7329             : static void
    7330        4309 : sql_update_check_null(backend *be, sql_table *t, stmt **updates)
    7331             : {
    7332        4309 :         mvc *sql = be->mvc;
    7333        4309 :         node *n;
    7334        4309 :         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    7335             : 
    7336       51195 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    7337       46886 :                 sql_column *c = n->data;
    7338             : 
    7339       46886 :                 if (updates[c->colnr] && !c->null) {
    7340         131 :                         stmt *s = updates[c->colnr];
    7341         131 :                         char *msg = NULL;
    7342             : 
    7343         131 :                         if (!(s->key && s->nrcols == 0)) {
    7344         131 :                                 s = stmt_selectnil(be, updates[c->colnr]);
    7345         131 :                                 s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1);
    7346             :                         } else {
    7347           0 :                                 sql_subfunc *isnil = sql_bind_func(sql, "sys", "isnull", &c->type, NULL, F_FUNC, true, true);
    7348             : 
    7349           0 :                                 s = stmt_unop(be, updates[c->colnr], NULL, isnil);
    7350             :                         }
    7351         131 :                         msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: NOT NULL constraint violated for column '%s.%s'", c->t->base.name, c->base.name);
    7352         131 :                         (void)stmt_exception(be, s, msg, 00001);
    7353             :                 }
    7354             :         }
    7355        4309 : }
    7356             : 
    7357             : /* updates: an array of table width, per column holds the values for the to be updated rows  */
    7358             : static list *
    7359          43 : sql_update(backend *be, sql_table *t, stmt *rows, stmt **updates)
    7360             : {
    7361          43 :         mvc *sql = be->mvc;
    7362          43 :         list *idx_updates = NULL;
    7363          43 :         int i, nr_cols = ol_length(t->columns);
    7364          43 :         list *l = sa_list(sql->sa);
    7365          43 :         node *n;
    7366          43 :         stmt *cnt = NULL;
    7367             : 
    7368          43 :         sql_update_check_null(be, t, updates);
    7369             : 
    7370             :         /* check keys + get idx */
    7371          43 :         idx_updates = update_idxs_and_check_keys(be, t, rows, updates, l, NULL);
    7372          43 :         if (!idx_updates) {
    7373           0 :                 assert(0);
    7374             :                 return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: failed to update indexes for table '%s'", t->base.name);
    7375             :         }
    7376             : 
    7377             : /* before */
    7378          43 :         if (!sql_update_triggers(be, t, rows, updates, 0))
    7379           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    7380             : 
    7381             : /* apply updates */
    7382         131 :         for (i = 0, n = ol_first_node(t->columns); i < nr_cols && n; i++, n = n->next) {
    7383          88 :                 sql_column *c = n->data;
    7384             : 
    7385          88 :                 if (updates[i])
    7386          45 :                         append(l, stmt_update_col(be, c, rows, updates[i]));
    7387             :         }
    7388          43 :         if (cascade_updates(be, t, rows, updates))
    7389           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
    7390             : 
    7391             : /* after */
    7392          43 :         if (!sql_update_triggers(be, t, rows, updates, 1))
    7393           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    7394             : 
    7395          43 :         if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
    7396          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);
    7397          43 :         if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
    7398           0 :                 return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7399          43 :         if (t->s && isGlobal(t) && !isGlobalTemp(t))
    7400          43 :                 stmt_add_dependency_change(be, t, cnt);
    7401             : /* cascade ?? */
    7402             :         return l;
    7403             : }
    7404             : 
    7405             : /* updates with empty list is alter with create idx or keys */
    7406             : static stmt *
    7407        4407 : rel2bin_update(backend *be, sql_rel *rel, list *refs)
    7408             : {
    7409        4407 :         mvc *sql = be->mvc;
    7410        4407 :         stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL, *cnt;
    7411        4407 :         list *l = sa_list(sql->sa);
    7412        4407 :         int nr_cols, updcol, idx_ups = 0;
    7413        4407 :         node *m;
    7414        4407 :         sql_rel *tr = rel->l, *prel = rel->r;
    7415        4407 :         sql_table *t = NULL;
    7416        4407 :         bool needs_returning = rel->returning;
    7417             : 
    7418        4407 :         if ((rel->flag&UPD_COMP)) {  /* special case ! */
    7419        1166 :                 idx_ups = 1;
    7420        1166 :                 prel = rel->l;
    7421        1166 :                 rel = rel->r;
    7422        1166 :                 tr = rel->l;
    7423             :         }
    7424        4407 :         if (tr->op == op_basetable) {
    7425        3060 :                 t = tr->l;
    7426             :         } else {
    7427        1347 :                 ddl = subrel_bin(be, tr, refs);
    7428        1347 :                 ddl = subrel_project(be, ddl, refs, NULL);
    7429        1347 :                 if (!ddl)
    7430             :                         return NULL;
    7431        1347 :                 t = rel_ddl_table_get(tr);
    7432             : 
    7433             :                 /* no columns to update (probably an new pkey or ckey!) */
    7434        1347 :                 if (!rel->exps) {
    7435         141 :                         stmt *tids = stmt_tid(be, t, 0);
    7436         154 :                         for (m = ol_first_node(t->keys); m; m = m->next) {
    7437          13 :                                 sql_key * key = m->data;
    7438          13 :                                 if (key->type == ckey && key->base.new)
    7439          13 :                                         sql_update_check(be, NULL, key, tids);
    7440             :                         }
    7441             :                         return ddl;
    7442             :                 }
    7443             :         }
    7444             : 
    7445        4266 :         if (rel->r) /* first construct the update relation */
    7446        4266 :                 update = subrel_bin(be, rel->r, refs);
    7447        4266 :         update = subrel_project(be, update, refs, rel->r);
    7448             : 
    7449        4266 :         if (!update)
    7450             :                 return NULL;
    7451             : 
    7452        4266 :         if (idx_ups)
    7453        1166 :                 pup = refs_find_rel(refs, prel);
    7454             : 
    7455        4266 :         updates = table_update_stmts(sql, t, &nr_cols);
    7456        4266 :         tids = update->op4.lval->h->data;
    7457             : 
    7458             :         /* lookup the updates */
    7459       11725 :         for (m = rel->exps->h; m; m = m->next) {
    7460        7459 :                 sql_exp *ce = m->data;
    7461        7459 :                 sql_column *c = find_sql_column(t, exp_name(ce));
    7462             : 
    7463        7459 :                 if (c)
    7464        3219 :                         updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r);
    7465             :         }
    7466             : 
    7467        5173 :         for (m = ol_first_node(t->keys); m; m = m->next) {
    7468         907 :                 sql_key * key = m->data;
    7469         907 :                 if (key->type == ckey && is_check_updated(key, updates))
    7470          12 :                         sql_update_check(be, updates, key, tids);
    7471             :         }
    7472        4266 :         sql_update_check_null(be, t, updates);
    7473             : 
    7474             :         /* check keys + get idx */
    7475        4266 :         updcol = first_updated_col(updates, ol_length(t->columns));
    7476       11725 :         for (m = rel->exps->h; m; m = m->next) {
    7477        7459 :                 sql_exp *ce = m->data;
    7478        7459 :                 sql_idx *i = find_sql_idx(t, exp_name(ce)+1);
    7479        7459 :                 stmt *update_idx, *is = NULL;
    7480             : 
    7481        7459 :                 if (i) {
    7482        1180 :                         if (non_updatable_index(i->type)) /* Some indexes don't hold delta structures */
    7483         148 :                                 continue;
    7484             : 
    7485        1032 :                         update_idx = bin_find_column(be, update, ce->l, ce->r);
    7486        1032 :                         if (update_idx)
    7487             :                                 is = update_idx;
    7488        1032 :                         if (hash_index(i->type) && list_length(i->columns) <= 1) {
    7489        1032 :                                 is = NULL;
    7490        1032 :                                 update_idx = NULL;
    7491             :                         }
    7492        1032 :                         if (i->key)
    7493        1605 :                                 sql_update_check_key(be, (updcol>=0)?updates:NULL, i->key, tids, update_idx, updcol, l, pup);
    7494        1032 :                         if (is)
    7495         780 :                                 list_append(l, stmt_update_idx(be,  i, tids, is));
    7496             :                 }
    7497             :         }
    7498             : 
    7499             : /* before */
    7500        4266 :         if (!sql_update_triggers(be, t, tids, updates, 0)) {
    7501           0 :                 if (sql->cascade_action)
    7502           0 :                         sql->cascade_action = NULL;
    7503           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    7504             :         }
    7505             : 
    7506             : /* apply the update */
    7507       11725 :         for (m = rel->exps->h; m; m = m->next) {
    7508        7459 :                 sql_exp *ce = m->data;
    7509        7459 :                 sql_column *c = find_sql_column(t, exp_name(ce));
    7510             : 
    7511        7459 :                 if (c)
    7512        3219 :                         append(l, stmt_update_col(be,  c, tids, updates[c->colnr]));
    7513             :         }
    7514             : 
    7515        4266 :         stmt* returning = NULL;
    7516        4266 :         if (needs_returning) {
    7517           6 :                 sql_rel* b = rel->l;
    7518           6 :                 int refcnt = b->ref.refcnt; // HACK: forces recalculation of base columns since they are assumed to be updated
    7519           6 :                 b->ref.refcnt = 1;
    7520           6 :                 returning = subrel_bin(be, b, refs);
    7521           6 :                 b->ref.refcnt = refcnt;
    7522           6 :                 returning->cand = tids;
    7523           6 :                 returning = subrel_project(be, returning, refs, b);
    7524           6 :                 sql->type = Q_TABLE;
    7525             :         }
    7526             : 
    7527        4266 :         if (cascade_updates(be, t, tids, updates)) {
    7528           0 :                 if (sql->cascade_action)
    7529           0 :                         sql->cascade_action = NULL;
    7530           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "UPDATE: cascade failed for table '%s'", t->base.name);
    7531             :         }
    7532             : 
    7533             : /* after */
    7534        4266 :         if (!sql_update_triggers(be, t, tids, updates, 1)) {
    7535           0 :                 if (sql->cascade_action)
    7536           0 :                         sql->cascade_action = NULL;
    7537           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers failed for table '%s'", t->base.name);
    7538             :         }
    7539             : 
    7540        4266 :         if (ddl) {
    7541        1206 :                 list_prepend(l, ddl);
    7542        1206 :                 cnt = stmt_list(be, l);
    7543             :         } else {
    7544        3060 :                 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);
    7545        3060 :                 if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
    7546           0 :                         return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7547        3060 :                 if (t->s && isGlobal(t) && !isGlobalTemp(t))
    7548        3056 :                         stmt_add_dependency_change(be, t, cnt);
    7549             :         }
    7550             : 
    7551        4266 :         if (sql->cascade_action)
    7552          67 :                 sql->cascade_action = NULL;
    7553        4266 :         if (rel->r && !rel_predicates(be, rel->r))
    7554             :                 return NULL;
    7555        4266 :         return returning?returning:cnt;
    7556             : }
    7557             : 
    7558             : static int
    7559          20 : sql_stack_add_deleted(mvc *sql, const char *name, sql_table *t, stmt *tids, stmt **deleted_cols, int type)
    7560             : {
    7561             :         /* Put single relation of updates and old values on to the stack */
    7562          20 :         sql_rel *r = NULL;
    7563          20 :         node *n;
    7564          20 :         list *exps = sa_list(sql->sa);
    7565          20 :         trigger_input *ti = SA_NEW(sql->sa, trigger_input);
    7566             : 
    7567          20 :         ti->t = t;
    7568          20 :         ti->tids = tids;
    7569          20 :         ti->updates = deleted_cols;
    7570          20 :         ti->type = type;
    7571          20 :         ti->nn = name;
    7572          20 :         sql_alias *aname = a_create(sql->sa, name);
    7573          56 :         for (n = ol_first_node(t->columns); n; n = n->next) {
    7574          36 :                 sql_column *c = n->data;
    7575          36 :                 sql_exp *ne = exp_column(sql->sa, aname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
    7576          36 :                 ne->alias.label = -(sql->nid++);
    7577             : 
    7578          36 :                 append(exps, ne);
    7579             :         }
    7580          20 :         r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER);
    7581          20 :         r->l = ti;
    7582             : 
    7583          20 :         return stack_push_rel_view(sql, name, r) ? 1 : 0;
    7584             : }
    7585             : 
    7586             : static int
    7587       84024 : sql_delete_triggers(backend *be, sql_table *t, stmt *tids, stmt **deleted_cols, int time, int firing_type, int internal_type)
    7588             : {
    7589       84024 :         mvc *sql = be->mvc;
    7590       84024 :         node *n;
    7591       84024 :         int res = 1;
    7592             : 
    7593       84024 :         if (!ol_length(t->triggers))
    7594             :                 return res;
    7595             : 
    7596         188 :         for (n = ol_first_node(t->triggers); n; n = n->next) {
    7597         142 :                 sql_trigger *trigger = n->data;
    7598             : 
    7599         142 :                 if (!stack_push_frame(sql, "%OLD-NEW"))
    7600             :                         return 0;
    7601         142 :                 if (trigger->event == firing_type && trigger->time == time) {
    7602             :                         /* add name for the 'deleted' to the stack */
    7603          20 :                         const char *o = trigger->old_name;
    7604             : 
    7605          20 :                         if (!o) o = "old";
    7606             : 
    7607          20 :                         if(!sql_stack_add_deleted(sql, o, t, tids, deleted_cols, internal_type)) {
    7608           0 :                                 stack_pop_frame(sql);
    7609           0 :                                 return 0;
    7610             :                         }
    7611             : 
    7612          20 :                         if (!sql_parse(be, trigger->t->s, trigger->statement, m_instantiate)) {
    7613           0 :                                 stack_pop_frame(sql);
    7614           0 :                                 return 0;
    7615             :                         }
    7616             :                 }
    7617         142 :                 stack_pop_frame(sql);
    7618             :         }
    7619             :         return res;
    7620             : }
    7621             : 
    7622             : static stmt * sql_delete(backend *be, sql_table *t, stmt *rows);
    7623             : 
    7624             : static stmt *
    7625           9 : sql_delete_cascade_Fkeys(backend *be, sql_key *fk, stmt *ftids)
    7626             : {
    7627           9 :         sql_table *t = mvc_bind_table(be->mvc, fk->t->s, fk->t->base.name);
    7628           9 :         return sql_delete(be, t, ftids);
    7629             : }
    7630             : 
    7631             : static void
    7632         130 : sql_delete_ukey(backend *be, stmt *utids /* deleted tids from ukey table */, sql_key *k, list *l, char* which, int cascade)
    7633             : {
    7634         130 :         mvc *sql = be->mvc;
    7635         130 :         sql_subtype *lng = sql_bind_localtype("lng");
    7636         130 :         sql_subtype *bt = sql_bind_localtype("bit");
    7637         130 :         sql_trans *tr = be->mvc->session->tr;
    7638         130 :         list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    7639             : 
    7640         130 :         if (keys) {
    7641         190 :                 for (node *n = keys->h; n; n = n->next->next) {
    7642          60 :                         sqlid fkey_id = *(sqlid*)n->data;
    7643          60 :                         sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    7644          60 :                         sql_key *fk = (sql_key*)b;
    7645          60 :                         sql_fkey *rk = (sql_fkey*)b;
    7646             : 
    7647          60 :                         if (fk->type != fkey || rk->rkey != k->base.id)
    7648           0 :                                 continue;
    7649          60 :                         char *msg = NULL;
    7650          60 :                         sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true);
    7651          60 :                         sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true, bt, 2, lng, lng);
    7652          60 :                         stmt *s, *tids;
    7653             : 
    7654          60 :                         tids = stmt_tid(be, fk->idx->t, 0);
    7655          60 :                         s = stmt_idx(be, fk->idx, tids, tids->partition);
    7656          60 :                         s = stmt_join(be, s, utids, 0, cmp_equal, 0, 0, false); /* join over the join index */
    7657          60 :                         s = stmt_result(be, s, 0);
    7658          60 :                         tids = stmt_project(be, s, tids);
    7659          60 :                         if(cascade) { /* for truncate statements with the cascade option */
    7660           1 :                                 s = sql_delete_cascade_Fkeys(be, fk, tids);
    7661           1 :                                 list_prepend(l, s);
    7662             :                         } else {
    7663          59 :                                 switch (((sql_fkey*)fk)->on_delete) {
    7664             :                                         case ACT_NO_ACTION:
    7665             :                                                 break;
    7666          11 :                                         case ACT_SET_NULL:
    7667             :                                         case ACT_SET_DEFAULT:
    7668          11 :                                                 s = sql_delete_set_Fkeys(be, fk, tids, ((sql_fkey*)fk)->on_delete);
    7669          11 :                                                 list_prepend(l, s);
    7670          11 :                                                 break;
    7671           8 :                                         case ACT_CASCADE:
    7672           8 :                                                 s = sql_delete_cascade_Fkeys(be, fk, tids);
    7673           8 :                                                 list_prepend(l, s);
    7674           8 :                                                 break;
    7675          38 :                                         default:        /*RESTRICT*/
    7676             :                                                 /* The overlap between deleted primaries and foreign should be empty */
    7677          38 :                                                 s = stmt_binop(be, stmt_aggr(be, tids, NULL, NULL, cnt, 1, 0, 1), stmt_atom_lng(be, 0), NULL, ne);
    7678          38 :                                                 msg = sa_message(sql->sa, SQLSTATE(40002) "%s: FOREIGN KEY constraint '%s.%s' violated", which, fk->t->base.name, fk->base.name);
    7679          38 :                                                 s = stmt_exception(be, s, msg, 00001);
    7680          38 :                                                 list_prepend(l, s);
    7681             :                                 }
    7682             :                         }
    7683             :                 }
    7684         130 :                 list_destroy(keys);
    7685             :         }
    7686         130 : }
    7687             : 
    7688             : static int
    7689       42011 : sql_delete_keys(backend *be, sql_table *t, stmt *rows, list *l, char* which, int cascade)
    7690             : {
    7691       42011 :         mvc *sql = be->mvc;
    7692       42011 :         int res = 1;
    7693       42011 :         node *n;
    7694             : 
    7695       42011 :         if (!ol_length(t->keys))
    7696             :                 return res;
    7697             : 
    7698         304 :         for (n = ol_first_node(t->keys); n; n = n->next) {
    7699         173 :                 sql_key *k = n->data;
    7700             : 
    7701         173 :                 if (k->type == pkey || k->type == ukey) {
    7702         131 :                         if (!(sql->cascade_action && list_find_id(sql->cascade_action, k->base.id))) {
    7703         130 :                                 sqlid *local_id = SA_NEW(sql->sa, sqlid);
    7704         130 :                                 if (!sql->cascade_action)
    7705         120 :                                         sql->cascade_action = sa_list(sql->sa);
    7706             : 
    7707         130 :                                 *local_id = k->base.id;
    7708         130 :                                 list_append(sql->cascade_action, local_id);
    7709         130 :                                 sql_delete_ukey(be, rows, k, l, which, cascade);
    7710             :                         }
    7711             :                 }
    7712             :         }
    7713             :         return res;
    7714             : }
    7715             : 
    7716             : static stmt *
    7717         511 : sql_delete(backend *be, sql_table *t, stmt *rows)
    7718             : {
    7719         511 :         mvc *sql = be->mvc;
    7720         511 :         stmt *v = NULL, *s = NULL;
    7721         511 :         list *l = sa_list(sql->sa);
    7722         511 :         stmt **deleted_cols = NULL;
    7723             : 
    7724         511 :         if (rows) {
    7725             :                 v = rows;
    7726             :         } else { /* delete all */
    7727         128 :                 v = stmt_tid(be, t, 0);
    7728             :         }
    7729             : 
    7730             :         /*  project all columns */
    7731         511 :         if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
    7732          38 :                 int nr = 0;
    7733          38 :                 deleted_cols = table_update_stmts(sql, t, &nr);
    7734          38 :                 int i = 0;
    7735         105 :                 for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
    7736          67 :                         sql_column *c = n->data;
    7737          67 :                         stmt *s = stmt_col(be, c, v, v->partition);
    7738             : 
    7739          67 :                         deleted_cols[i] = s;
    7740          67 :                         list_append(l, s);
    7741             :                 }
    7742             :         }
    7743             : 
    7744             : /* before */
    7745         511 :         if (!sql_delete_triggers(be, t, v, deleted_cols, 0, 1, 3))
    7746           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
    7747             : 
    7748         511 :         if (!sql_delete_keys(be, t, v, l, "DELETE", 0))
    7749           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "DELETE: failed to delete indexes for table '%s'", t->base.name);
    7750             : 
    7751         511 :         if (rows) {
    7752         383 :                 s = stmt_delete(be, t, rows);
    7753         383 :                 if (!be->silent || (t->s && isGlobal(t) && !isGlobalTemp(t)))
    7754         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);
    7755             :         } else { /* delete all */
    7756         128 :                 s = stmt_table_clear(be, t, 0); /* first column */
    7757             :         }
    7758             : 
    7759             : /* after */
    7760         511 :         if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
    7761           0 :                 return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers failed for table '%s'", t->base.name);
    7762             : 
    7763         511 :         if (add_to_rowcount_accumulator(be, s->nr) < 0)
    7764           0 :                 return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7765         511 :         if (t->s && isGlobal(t) && !isGlobalTemp(t))
    7766         509 :                 stmt_add_dependency_change(be, t, s);
    7767             :         return s;
    7768             : }
    7769             : 
    7770             : static stmt *
    7771         502 : rel2bin_delete(backend *be, sql_rel *rel, list *refs)
    7772             : {
    7773         502 :         mvc *sql = be->mvc;
    7774         502 :         stmt *stdelete = NULL, *tids = NULL, *returning = NULL;
    7775         502 :         sql_rel *tr = rel->l;
    7776         502 :         sql_table *t = NULL;
    7777             : 
    7778         502 :         if (tr->op == op_basetable)
    7779         502 :                 t = tr->l;
    7780             :         else
    7781           0 :                 assert(0/*ddl statement*/);
    7782             : 
    7783         502 :         if (rel->r) { /* first construct the deletes relation */
    7784         374 :                 stmt *rows = subrel_bin(be, rel->r, refs);
    7785         374 :                 rows = subrel_project(be, rows, refs, rel->r);
    7786         374 :                 if (!rows)
    7787             :                         return NULL;
    7788         374 :                 assert(rows->type == st_list);
    7789         374 :                 tids = rows->op4.lval->h->data; /* TODO this should be the candidate list instead */
    7790             :         }
    7791             : 
    7792         502 :         if (rel->returning) {
    7793           4 :                 returning = subrel_bin(be, rel->l, refs);
    7794           4 :                 returning->cand = tids;
    7795           4 :                 returning = subrel_project(be, returning, refs, rel->l);
    7796           4 :                 sql->type = Q_TABLE;
    7797             :         }
    7798             : 
    7799         502 :         stdelete = sql_delete(be, t, tids);
    7800         502 :         if (sql->cascade_action)
    7801         107 :                 sql->cascade_action = NULL;
    7802         502 :         if (!stdelete)
    7803             :                 return NULL;
    7804             : 
    7805         502 :         if (rel->r && !rel_predicates(be, rel->r))
    7806             :                 return NULL;
    7807         502 :         return returning?returning:stdelete;
    7808             : }
    7809             : 
    7810             : struct tablelist {
    7811             :         sql_table *table;
    7812             :         struct tablelist* next;
    7813             : };
    7814             : 
    7815             : static sql_table * /* inspect the other tables recursively for foreign key dependencies */
    7816       41674 : check_for_foreign_key_references(mvc *sql, struct tablelist* tlist, struct tablelist* next_append, sql_table *t, int cascade)
    7817             : {
    7818       41674 :         struct tablelist* new_node;
    7819       41674 :         sql_trans *tr = sql->session->tr;
    7820       41674 :         sqlstore *store = sql->session->tr->store;
    7821             : 
    7822       41674 :         if (mvc_highwater(sql))
    7823           0 :                 return sql_error(sql, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    7824             : 
    7825       41694 :         if (t->keys) { /* Check for foreign key references */
    7826       41712 :                 for (node *n = ol_first_node(t->keys); n; n = n->next) {
    7827          35 :                         sql_key *k = n->data;
    7828             : 
    7829          35 :                         if (k->type == ukey || k->type == pkey) {
    7830          17 :                                 list *keys = sql_trans_get_dependents(tr, k->base.id, FKEY_DEPENDENCY, NULL);
    7831             : 
    7832           2 :                                 if (keys) {
    7833          21 :                                         for (node *nn = keys->h; nn; nn = nn->next->next) {
    7834           6 :                                                 sqlid fkey_id = *(sqlid*)nn->data;
    7835           6 :                                                 sql_base *b = os_find_id(tr->cat->objects, tr, fkey_id);
    7836           6 :                                                 sql_key *fk = (sql_key*)b;
    7837           6 :                                                 sql_fkey *rk = (sql_fkey*)b;
    7838             : 
    7839           6 :                                                 if (fk->type != fkey || rk->rkey != k->base.id)
    7840           1 :                                                         continue;
    7841           5 :                                                 k = fk;
    7842             :                                                 /* make sure it is not a self referencing key */
    7843           5 :                                                 if (k->t != t && !cascade && isTable(t)) {
    7844           4 :                                                         node *nnn = ol_first_node(t->columns);
    7845           4 :                                                         sql_column *c = nnn->data;
    7846           4 :                                                         size_t n_rows = store->storage_api.count_col(sql->session->tr, c, 10);
    7847           4 :                                                         if (n_rows > 0) {
    7848           2 :                                                                 list_destroy(keys);
    7849           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);
    7850             :                                                         }
    7851           1 :                                                 } else if (k->t != t) {
    7852             :                                                         int found = 0;
    7853           2 :                                                         for (struct tablelist *node_check = tlist; node_check; node_check = node_check->next) {
    7854           1 :                                                                 if (node_check->table == k->t)
    7855           0 :                                                                         found = 1;
    7856             :                                                         }
    7857           1 :                                                         if (!found) {
    7858           2 :                                                                 if ((new_node = SA_NEW(sql->ta, struct tablelist)) == NULL) {
    7859           0 :                                                                         list_destroy(keys);
    7860           0 :                                                                         return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7861             :                                                                 }
    7862           1 :                                                                 new_node->table = k->t;
    7863           1 :                                                                 new_node->next = NULL;
    7864           1 :                                                                 next_append->next = new_node;
    7865           1 :                                                                 if (!check_for_foreign_key_references(sql, tlist, new_node, k->t, cascade)) {
    7866           0 :                                                                         list_destroy(keys);
    7867           0 :                                                                         return NULL;
    7868             :                                                                 }
    7869             :                                                         }
    7870             :                                                 }
    7871             :                                         }
    7872          15 :                                         list_destroy(keys);
    7873             :                                 }
    7874             :                         }
    7875             :                 }
    7876             :         }
    7877             :         return t;
    7878             : }
    7879             : 
    7880             : static stmt *
    7881       41677 : sql_truncate(backend *be, sql_table *t, int restart_sequences, int cascade)
    7882             : {
    7883       41677 :         mvc *sql = be->mvc;
    7884       41677 :         list *l = sa_list(sql->sa);
    7885       41677 :         if (t->multiset) {
    7886           3 :                 for (node *n = t->columns->l->h; n; n = n->next) {
    7887           2 :                         sql_column *c = n->data;
    7888             : 
    7889           2 :                         if (c->type.multiset) {
    7890           1 :                                 sql_table *st = mvc_bind_table(sql, c->t->s, c->storage_type);
    7891           1 :                                 if (st) {
    7892           1 :                                         stmt *trunc = sql_truncate(be, st, restart_sequences, cascade);
    7893           1 :                                         if (!trunc)
    7894             :                                                 return trunc;
    7895           1 :                                         append(l, trunc);
    7896             :                                 }
    7897             :                         }
    7898             :                 }
    7899             :         }
    7900       41677 :         stmt *ret = NULL, *other = NULL;
    7901       41677 :         struct tablelist *new_list = SA_NEW(sql->ta, struct tablelist);
    7902       41696 :         stmt **deleted_cols = NULL;
    7903             : 
    7904       41696 :         if (!new_list)
    7905           0 :                 return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7906       41696 :         new_list->table = t;
    7907       41696 :         new_list->next = NULL;
    7908       41696 :         if (!check_for_foreign_key_references(sql, new_list, new_list, t, cascade))
    7909           2 :                 goto finalize;
    7910             : 
    7911       83329 :         for (struct tablelist *list_node = new_list; list_node; list_node = list_node->next) {
    7912       41628 :                 sql_table *next = list_node->table;
    7913       41628 :                 stmt *v = stmt_tid(be, next, 0);
    7914             : 
    7915             :                 /* project all columns */
    7916       41594 :                 if (ol_length(t->triggers) || partition_find_part(sql->session->tr, t, NULL)) {
    7917          18 :                         int nr = 0;
    7918          18 :                         deleted_cols = table_update_stmts(sql, t, &nr);
    7919          18 :                         int i = 0;
    7920          50 :                         for (node *n = ol_first_node(t->columns); n; n = n->next, i++) {
    7921          32 :                                 sql_column *c = n->data;
    7922          32 :                                 stmt *s = stmt_col(be, c, v, v->partition);
    7923             : 
    7924          32 :                                 deleted_cols[i] = s;
    7925          32 :                                 list_append(l, s);
    7926             :                         }
    7927             :                 }
    7928             : 
    7929             :                 /* before */
    7930       41683 :                 if (!sql_delete_triggers(be, next, v, deleted_cols, 0, 3, 4)) {
    7931           0 :                         (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
    7932           0 :                         ret = NULL;
    7933           0 :                         goto finalize;
    7934             :                 }
    7935             : 
    7936       41590 :                 if (!sql_delete_keys(be, next, v, l, "TRUNCATE", cascade)) {
    7937           0 :                         (void) sql_error(sql, 10, SQLSTATE(42000) "TRUNCATE: failed to delete indexes for table '%s'", next->base.name);
    7938           0 :                         ret = NULL;
    7939           0 :                         goto finalize;
    7940             :                 }
    7941             : 
    7942       41394 :                 other = stmt_table_clear(be, next, restart_sequences);
    7943       41562 :                 list_append(l, other);
    7944       41475 :                 if (next && t && next->base.id == t->base.id)
    7945       41475 :                         ret = other;
    7946             : 
    7947             :                 /* after */
    7948       41475 :                 if (!sql_delete_triggers(be, next, v, deleted_cols, 1, 3, 4)) {
    7949           0 :                         (void) sql_error(sql, 10, SQLSTATE(27000) "TRUNCATE: triggers failed for table '%s'", next->base.name);
    7950           0 :                         ret = NULL;
    7951           0 :                         goto finalize;
    7952             :                 }
    7953             : 
    7954       41542 :                 if (add_to_rowcount_accumulator(be, other->nr) < 0) {
    7955           0 :                         (void) sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    7956           0 :                         ret = NULL;
    7957           0 :                         goto finalize;
    7958             :                 }
    7959       41466 :                 if (next->s && isGlobal(next) && !isGlobalTemp(next))
    7960       41508 :                         stmt_add_dependency_change(be, next, other);
    7961             :         }
    7962             : 
    7963       41701 : finalize:
    7964       41703 :         sa_reset(sql->ta);
    7965       41703 :         return ret;
    7966             : }
    7967             : 
    7968             : #define E_ATOM_INT(e) ((atom*)((sql_exp*)e)->l)->data.val.ival
    7969             : #define E_ATOM_STRING(e) ((atom*)((sql_exp*)e)->l)->data.val.sval
    7970             : 
    7971             : static stmt *
    7972       41678 : rel2bin_truncate(backend *be, sql_rel *rel)
    7973             : {
    7974       41678 :         mvc *sql = be->mvc;
    7975       41678 :         stmt *truncate = NULL;
    7976       41678 :         sql_rel *tr = rel->l;
    7977       41678 :         sql_table *t = NULL;
    7978       41678 :         node *n = NULL;
    7979       41678 :         int restart_sequences, cascade;
    7980             : 
    7981       41678 :         if (tr->op == op_basetable)
    7982       41678 :                 t = tr->l;
    7983             :         else
    7984           0 :                 assert(0/*ddl statement*/);
    7985             : 
    7986       41678 :         n = rel->exps->h;
    7987       41678 :         restart_sequences = E_ATOM_INT(n->data);
    7988       41678 :         cascade = E_ATOM_INT(n->next->data);
    7989       41678 :         truncate = sql_truncate(be, t, restart_sequences, cascade);
    7990       41641 :         if (sql->cascade_action)
    7991          13 :                 sql->cascade_action = NULL;
    7992       41641 :         return truncate;
    7993             : }
    7994             : 
    7995         234 : static ValPtr take_atom_arg(node **n, int expected_type) {
    7996         234 :         sql_exp *e = (*n)->data;
    7997         234 :         atom *a = e->l;
    7998         234 :         assert(a->tpe.type->localtype == expected_type); (void) expected_type;
    7999         234 :         assert(!a->isnull);
    8000         234 :         *n = (*n)->next;
    8001         234 :         return &a->data;
    8002             : }
    8003             : 
    8004             : static stmt *
    8005          74 : rel2bin_output(backend *be, sql_rel *rel, list *refs)
    8006             : {
    8007          74 :         mvc *sql = be->mvc;
    8008          74 :         stmt *sub = NULL, *fns = NULL, *res = NULL;
    8009          74 :         list *slist = sa_list(sql->sa);
    8010             : 
    8011          74 :         if (rel->l)  /* first construct the sub relation */
    8012          74 :                 sub = subrel_bin(be, rel->l, refs);
    8013          74 :         sub = subrel_project(be, sub, refs, rel->l);
    8014          74 :         if (!sub)
    8015             :                 return NULL;
    8016             : 
    8017          74 :         if (!rel->exps)
    8018             :                 return sub;
    8019             : 
    8020          74 :         list *arglist = rel->exps;
    8021          74 :         node *argnode = arglist->h;
    8022          74 :         atom *a = ((sql_exp*)argnode->data)->l;
    8023          74 :         int tpe = a->tpe.type->localtype;
    8024             : 
    8025             :         // With regular COPY INTO <file>, the first argument is a string.
    8026             :         // With COPY INTO BINARY, it is an int.
    8027          74 :         if (tpe == TYPE_str) {
    8028          32 :                 atom *tatom = ((sql_exp*) argnode->data)->l;
    8029          32 :                 const char *tsep  = sa_strdup(sql->sa, tatom->isnull ? "" : tatom->data.val.sval);
    8030          32 :                 atom *ratom = ((sql_exp*) argnode->next->data)->l;
    8031          32 :                 const char *rsep  = sa_strdup(sql->sa, ratom->isnull ? "" : ratom->data.val.sval);
    8032          32 :                 atom *satom = ((sql_exp*) argnode->next->next->data)->l;
    8033          32 :                 const char *ssep  = sa_strdup(sql->sa, satom->isnull ? "" : satom->data.val.sval);
    8034          32 :                 atom *natom = ((sql_exp*) argnode->next->next->next->data)->l;
    8035          32 :                 const char *ns = sa_strdup(sql->sa, natom->isnull ? "" : natom->data.val.sval);
    8036             : 
    8037          32 :                 const char *fn = NULL;
    8038          32 :                 int onclient = 0;
    8039          32 :                 if (argnode->next->next->next->next) {
    8040          23 :                         fn = E_ATOM_STRING(argnode->next->next->next->next->data);
    8041          23 :                         fns = stmt_atom_string(be, sa_strdup(sql->sa, fn));
    8042          23 :                         onclient = E_ATOM_INT(argnode->next->next->next->next->next->data);
    8043             :                 }
    8044          32 :                 stmt *export = stmt_export(be, sub, tsep, rsep, ssep, ns, onclient, fns);
    8045          32 :                 list_append(slist, export);
    8046          42 :         } else if (tpe == TYPE_int) {
    8047          42 :                 endianness endian = take_atom_arg(&argnode, TYPE_int)->val.ival;
    8048          42 :                 bool do_byteswap = (endian != endian_native && endian != OUR_ENDIANNESS);
    8049          42 :                 int on_client = take_atom_arg(&argnode, TYPE_int)->val.ival;
    8050          42 :                 assert(sub->type == st_list);
    8051          42 :                 list *collist = sub->op4.lval;
    8052         192 :                 for (node *colnode = collist->h; colnode; colnode = colnode->next) {
    8053         150 :                         stmt *colstmt = colnode->data;
    8054         150 :                         assert(argnode != NULL);
    8055         150 :                         const char *filename = take_atom_arg(&argnode, TYPE_str)->val.sval;
    8056         150 :                         stmt *export = stmt_export_bin(be, colstmt, do_byteswap, filename, on_client);
    8057         150 :                         list_append(slist, export);
    8058             :                 }
    8059          42 :                 assert(argnode == NULL);
    8060             : 
    8061             :         } else {
    8062           0 :                 assert(0 && "unimplemented export statement type");
    8063             :                 return sub;
    8064             :         }
    8065             : 
    8066          74 :         if (sub->type == st_list && ((stmt*)sub->op4.lval->h->data)->nrcols != 0) {
    8067          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);
    8068             :         } else {
    8069           1 :                 res = stmt_atom_lng(be, 1);
    8070             :         }
    8071          74 :         if (add_to_rowcount_accumulator(be, res->nr) < 0)
    8072           0 :                 return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
    8073             :         return res;
    8074             : }
    8075             : 
    8076             : static list *
    8077          54 : merge_stmt_join_projections(backend *be, stmt *left, stmt *right, stmt *jl, stmt *jr, stmt *diff)
    8078             : {
    8079          54 :         mvc *sql = be->mvc;
    8080          54 :         list *l = sa_list(sql->sa);
    8081             : 
    8082          54 :         if (left)
    8083         117 :                 for (node *n = left->op4.lval->h; n; n = n->next) {
    8084          89 :                         stmt *c = n->data;
    8085          89 :                         assert(c->type == st_alias);
    8086          89 :                         sql_alias *rnme = table_name(sql->sa, c);
    8087          89 :                         const char *nme = column_name(sql->sa, c);
    8088          89 :                         stmt *s = stmt_project(be, jl ? jl : diff, column(be, c));
    8089             : 
    8090          89 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    8091          89 :                         list_append(l, s);
    8092             :                 }
    8093          54 :         if (right)
    8094         154 :                 for (node *n = right->op4.lval->h; n; n = n->next) {
    8095         110 :                         stmt *c = n->data;
    8096         110 :                         assert(c->type == st_alias);
    8097         110 :                         sql_alias *rnme = table_name(sql->sa, c);
    8098         110 :                         const char *nme = column_name(sql->sa, c);
    8099         170 :                         stmt *s = stmt_project(be, jr ? jr : diff, column(be, c));
    8100             : 
    8101         110 :                         s = stmt_alias(be, s, c->label, rnme, nme);
    8102         110 :                         list_append(l, s);
    8103             :                 }
    8104          54 :         return l;
    8105             : }
    8106             : 
    8107             : static void
    8108          28 : validate_merge_delete_update(backend *be, bool delete, stmt *bt_stmt, sql_rel *bt, stmt *jl, stmt *ld)
    8109             : {
    8110          28 :         mvc *sql = be->mvc;
    8111          28 :         str msg;
    8112          28 :         sql_table *t = bt->l;
    8113          28 :         sql_alias *alias = rel_name(bt);
    8114          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);
    8115          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);
    8116          28 :         sql_subfunc *add = sql_bind_func(sql, "sys", "sql_add", tail_type(cnt1), tail_type(cnt2), F_FUNC, true, true);
    8117          28 :         stmt *s1 = stmt_binop(be, cnt1, cnt2, NULL, add);
    8118          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);
    8119          28 :         sql_subfunc *bf = sql_bind_func(sql, "sys", ">", tail_type(s1), tail_type(cnt3), F_FUNC, true, true);
    8120          28 :         stmt *s2 = stmt_binop(be, s1, cnt3, NULL, bf);
    8121             : 
    8122          28 :         if (alias && a_cmp_obj_name(alias, t->base.name)) /* detect if alias is present */
    8123             :                 alias = NULL;
    8124          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'",
    8125             :                                          delete ? "DELETE" : "UPDATE",
    8126             :                                          alias ? "relation" : "table",
    8127          22 :                                          alias ? alias->name : t->s ? t->s->base.name : "", alias ? "" : ".", alias ? "" : t->base.name);
    8128          28 :         (void)stmt_exception(be, s2, msg, 00001);
    8129          28 : }
    8130             : 
    8131             : static stmt *
    8132          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)
    8133             : {
    8134          54 :         if (is_insert(upd->op)) {
    8135          26 :                 if (!*rd) {
    8136          26 :                         *rd = stmt_tdiff(be, stmt_mirror(be, bin_find_smallest_column(be, target_stmt)), jr, NULL);
    8137             :                 }
    8138          26 :                 stmt *s = stmt_list(be, merge_stmt_join_projections(be, NULL, target_stmt, NULL, NULL, *rd));
    8139          26 :                 refs_update_stmt(refs, join, s); /* project the differences on the target side for inserts */
    8140             : 
    8141          26 :                 return rel2bin_insert(be, upd, refs);
    8142             :         } else {
    8143          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));
    8144          28 :                 refs_update_stmt(refs, join, s); /* project the matched values on both sides for updates and deletes */
    8145             : 
    8146          28 :                 assert(is_update(upd->op) || is_delete(upd->op));
    8147             :                 /* the left joined values + left difference must be smaller than the table count */
    8148          28 :                 validate_merge_delete_update(be, is_update(upd->op), bt_stmt, join->l, jl, ld);
    8149             : 
    8150          28 :                 return is_update(upd->op) ? rel2bin_update(be, upd, refs) : rel2bin_delete(be, upd, refs);
    8151             :         }
    8152             : }
    8153             : 
    8154             : static stmt *
    8155          44 : rel2bin_merge(backend *be, sql_rel *rel, list *refs)
    8156             : {
    8157          44 :         mvc *sql = be->mvc;
    8158          44 :         sql_rel *join;
    8159             : 
    8160          44 :         if (is_project(((sql_rel*)rel->l)->op)) {
    8161           0 :                 join = ((sql_rel*)rel->l)->l;
    8162             :         } else {
    8163             :                 join = rel->l;
    8164             :         }
    8165             : 
    8166          44 :         sql_rel *r = rel->r;
    8167          44 :         stmt *join_st, *bt_stmt, *target_stmt, *jl, *jr, *ld, *rd = NULL, *ns;
    8168          44 :         list *slist = sa_list(sql->sa);
    8169             : 
    8170          44 :         assert(rel_is_ref(join) && is_left(join->op));
    8171          44 :         join_st = subrel_bin(be, join, refs);
    8172          44 :         if (!join_st)
    8173             :                 return NULL;
    8174             : 
    8175             :         /* grab generated left join outputs and generate updates accordingly to matched and not matched values */
    8176          44 :         assert(join_st->type == st_list && list_length(join_st->extra) == 5);
    8177          44 :         bt_stmt = join_st->extra->h->data;
    8178          44 :         target_stmt = join_st->extra->h->next->data;
    8179          44 :         jl = join_st->extra->h->next->next->data;
    8180          44 :         jr = join_st->extra->h->next->next->next->data;
    8181          44 :         ld = join_st->extra->h->next->next->next->next->data;
    8182             : 
    8183          44 :         if (is_ddl(r->op)) {
    8184          44 :                 assert(r->flag == ddl_list);
    8185          44 :                 if (r->l) {
    8186          44 :                         if ((ns = rel2bin_merge_apply_update(be, join, r->l, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
    8187             :                                 return NULL;
    8188          44 :                         list_append(slist, ns);
    8189             :                 }
    8190          44 :                 if (r->r) {
    8191          10 :                         if ((ns = rel2bin_merge_apply_update(be, join, r->r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)) == NULL)
    8192             :                                 return NULL;
    8193          10 :                         list_append(slist, ns);
    8194             :                 }
    8195             :         } else {
    8196           0 :                 if (!(ns = rel2bin_merge_apply_update(be, join, r, refs, bt_stmt, target_stmt, jl, jr, ld, &rd)))
    8197             :                         return NULL;
    8198           0 :                 list_append(slist, ns);
    8199             :         }
    8200          44 :         return stmt_list(be, slist);
    8201             : }
    8202             : 
    8203             : static stmt *
    8204         521 : rel2bin_list(backend *be, sql_rel *rel, list *refs)
    8205             : {
    8206         521 :         mvc *sql = be->mvc;
    8207         521 :         stmt *l = NULL, *r = NULL;
    8208         521 :         list *slist = sa_list(sql->sa);
    8209             : 
    8210         521 :         if (rel->l)  /* first construct the sub relation */
    8211         521 :                 l = subrel_bin(be, rel->l, refs);
    8212         521 :         if (rel->r)  /* first construct the sub relation */
    8213         521 :                 r = subrel_bin(be, rel->r, refs);
    8214         521 :         l = subrel_project(be, l, refs, rel->l);
    8215         521 :         r = subrel_project(be, r, refs, rel->r);
    8216         521 :         if (!l || !r)
    8217             :                 return NULL;
    8218         521 :         list_append(slist, l);
    8219         521 :         list_append(slist, r);
    8220         521 :         return stmt_list(be, slist);
    8221             : }
    8222             : 
    8223             : static stmt *
    8224       47772 : rel2bin_psm(backend *be, sql_rel *rel)
    8225             : {
    8226       47772 :         mvc *sql = be->mvc;
    8227       47772 :         node *n;
    8228       47772 :         list *l = sa_list(sql->sa);
    8229       47774 :         stmt *sub = NULL;
    8230             : 
    8231       91160 :         for (n = rel->exps->h; n; n = n->next) {
    8232       48291 :                 sql_exp *e = n->data;
    8233       48291 :                 stmt *s = exp_bin(be, e, sub, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8234       48275 :                 if (!s)
    8235             :                         return NULL;
    8236             : 
    8237       43382 :                 if (s && s->type == st_table) /* relational statement */
    8238          37 :                         sub = s->op1;
    8239             :                 else
    8240       43345 :                         append(l, s);
    8241             :         }
    8242       42869 :         return stmt_list(be, l);
    8243             : }
    8244             : 
    8245             : static stmt *
    8246         285 : rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs)
    8247             : {
    8248         285 :         stmt *l = NULL, *r = NULL;
    8249         285 :         node *n = NULL;
    8250         285 :         list *slist = sa_list(be->mvc->sa);
    8251             : 
    8252         285 :         if (rel->l)  /* first construct the sub relation */
    8253           0 :                 l = subrel_bin(be, rel->l, refs);
    8254         285 :         if (rel->r)  /* first construct the sub relation */
    8255           0 :                 r = subrel_bin(be, rel->r, refs);
    8256         285 :         l = subrel_project(be, l, refs, rel->l);
    8257         285 :         r = subrel_project(be, r, refs, rel->r);
    8258         285 :         if ((rel->l && !l) || (rel->r && !r))
    8259             :                 return NULL;
    8260             : 
    8261         285 :         assert(rel->exps);
    8262         285 :         assert(rel->flag == ddl_alter_table_add_range_partition || rel->flag == ddl_alter_table_add_list_partition);
    8263             : 
    8264         285 :         if (rel->exps) {
    8265        2909 :                 for (n = rel->exps->h; n; n = n->next) {
    8266        2624 :                         sql_exp *e = n->data;
    8267        2624 :                         stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
    8268        2624 :                         if (!s)
    8269             :                                 return NULL;
    8270        2624 :                         append(slist, s);
    8271             :                 }
    8272             :         }
    8273         285 :         return stmt_catalog(be, rel->flag, stmt_list(be, slist));
    8274             : }
    8275             : 
    8276             : static stmt *
    8277         157 : rel2bin_exception(backend *be, sql_rel *rel, list *refs)
    8278             : {
    8279         157 :         stmt *l = NULL, *r = NULL;
    8280         157 :         list *slist = sa_list(be->mvc->sa);
    8281             : 
    8282         157 :         if (rel->l)  /* first construct the sub relation */
    8283           0 :                 l = subrel_bin(be, rel->l, refs);
    8284         157 :         if (rel->r)  /* first construct the sub relation */
    8285         157 :                 r = subrel_bin(be, rel->r, refs);
    8286         157 :         l = subrel_project(be, l, refs, rel->l);
    8287         157 :         r = subrel_project(be, r, refs, rel->r);
    8288         157 :         if ((rel->l && !l) || (rel->r && !r))
    8289             :                 return NULL;
    8290             : 
    8291         157 :         assert(rel->exps);
    8292         314 :         for (node *n = rel->exps->h; n; n = n->next) {
    8293         157 :                 sql_exp *e = n->data;
    8294         157 :                 stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL, 0, 0, 0);
    8295         157 :                 if (!s)
    8296             :                         return NULL;
    8297         157 :                 list_append(slist, s);
    8298             :         }
    8299         157 :         return stmt_list(be, slist);
    8300             : }
    8301             : 
    8302             : static stmt *
    8303         363 : rel2bin_seq(backend *be, sql_rel *rel, list *refs)
    8304             : {
    8305         363 :         mvc *sql = be->mvc;
    8306         363 :         node *en = rel->exps->h;
    8307         363 :         stmt *restart, *sname, *seq, *seqname, *sl = NULL;
    8308         363 :         list *l = sa_list(sql->sa);
    8309             : 
    8310         363 :         if (rel->l) { /* first construct the sub relation */
    8311           0 :                 sl = subrel_bin(be, rel->l, refs);
    8312           0 :                 sl = subrel_project(be, sl, refs, rel->l);
    8313           0 :                 if (!sl)
    8314             :                         return NULL;
    8315             :         }
    8316             : 
    8317         363 :         restart = exp_bin(be, en->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8318         363 :         sname = exp_bin(be, en->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8319         363 :         seqname = exp_bin(be, en->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8320         363 :         seq = exp_bin(be, en->next->next->next->data, sl, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8321         363 :         if (!restart || !sname || !seqname || !seq)
    8322             :                 return NULL;
    8323             : 
    8324         363 :         (void)refs;
    8325         363 :         append(l, sname);
    8326         363 :         append(l, seqname);
    8327         363 :         append(l, seq);
    8328         363 :         append(l, restart);
    8329         363 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    8330             : }
    8331             : 
    8332             : static stmt *
    8333        3160 : rel2bin_trans(backend *be, sql_rel *rel, list *refs)
    8334             : {
    8335        3160 :         node *en = rel->exps->h;
    8336        3160 :         stmt *chain = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8337        3160 :         stmt *name = NULL;
    8338             : 
    8339        3160 :         if (!chain)
    8340             :                 return NULL;
    8341             : 
    8342        3160 :         (void)refs;
    8343        3160 :         if (en->next) {
    8344          79 :                 name = exp_bin(be, en->next->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8345          79 :                 if (!name)
    8346             :                         return NULL;
    8347             :         }
    8348        3160 :         return stmt_trans(be, rel->flag, chain, name);
    8349             : }
    8350             : 
    8351             : static stmt *
    8352        1297 : rel2bin_catalog_schema(backend *be, sql_rel *rel, list *refs)
    8353             : {
    8354        1297 :         mvc *sql = be->mvc;
    8355        1297 :         node *en = rel->exps->h;
    8356        1297 :         stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8357        1297 :         stmt *sname = NULL, *name = NULL, *ifexists = NULL;
    8358        1297 :         list *l = sa_list(sql->sa);
    8359             : 
    8360        1297 :         if (!action)
    8361             :                 return NULL;
    8362             : 
    8363        1297 :         (void)refs;
    8364        1297 :         en = en->next;
    8365        1297 :         sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8366        1297 :         if (!sname)
    8367             :                 return NULL;
    8368        1297 :         append(l, sname);
    8369        1297 :         en = en->next;
    8370        1297 :         if (rel->flag == ddl_create_schema) {
    8371        1104 :                 if (en) {
    8372          38 :                         name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8373          38 :                         if (!name)
    8374             :                                 return NULL;
    8375             :                 } else {
    8376        1066 :                         name = stmt_atom_string_nil(be);
    8377             :                 }
    8378        1104 :                 append(l, name);
    8379             :         } else {
    8380         193 :                 assert(rel->flag == ddl_drop_schema);
    8381         193 :                 ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8382         193 :                 if (!ifexists)
    8383             :                         return NULL;
    8384         193 :                 append(l, ifexists);
    8385             :         }
    8386        1297 :         append(l, action);
    8387        1297 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    8388             : }
    8389             : 
    8390             : static stmt *
    8391       39031 : rel2bin_catalog_table(backend *be, sql_rel *rel, list *refs)
    8392             : {
    8393       39031 :         mvc *sql = be->mvc;
    8394       39031 :         node *en = rel->exps->h;
    8395       39031 :         stmt *action = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8396       39031 :         stmt *table = NULL, *sname, *tname = NULL, *kname = NULL, *ifexists = NULL, *replace = NULL;
    8397       39031 :         list *l = sa_list(sql->sa);
    8398             : 
    8399       39031 :         if (!action)
    8400             :                 return NULL;
    8401             : 
    8402       39031 :         (void)refs;
    8403       39031 :         en = en->next;
    8404       39031 :         sname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8405       39031 :         if (!sname)
    8406             :                 return NULL;
    8407       39031 :         en = en->next;
    8408       39031 :         if (en) {
    8409       39031 :                 tname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8410       39031 :                 if (!tname)
    8411             :                         return NULL;
    8412       39031 :                 en = en->next;
    8413             :         }
    8414       39031 :         append(l, sname);
    8415       39031 :         assert(tname);
    8416       39031 :         append(l, tname);
    8417       39031 :         if (rel->flag == ddl_drop_constraint) { /* needs extra string parameter for constraint name */
    8418         150 :                 if (en) {
    8419         150 :                         kname = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8420         150 :                         if (!kname)
    8421             :                                 return NULL;
    8422         150 :                         en = en->next;
    8423             :                 }
    8424         150 :                 append(l, kname);
    8425             :         }
    8426       39031 :         if (rel->flag != ddl_drop_table && rel->flag != ddl_drop_view && rel->flag != ddl_drop_constraint) {
    8427       34648 :                 if (en) {
    8428       34648 :                         table = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8429       34648 :                         if (!table)
    8430             :                                 return NULL;
    8431       34648 :                         en = en->next;
    8432             :                 }
    8433       34648 :                 append(l, table);
    8434             :         } else {
    8435        4383 :                 if (en) {
    8436        4383 :                         ifexists = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8437        4383 :                         if (!ifexists)
    8438             :                                 return NULL;
    8439        4383 :                         en = en->next;
    8440             :                 } else {
    8441           0 :                         ifexists = stmt_atom_int(be, 0);
    8442             :                 }
    8443        4383 :                 append(l, ifexists);
    8444             :         }
    8445       39031 :         append(l, action);
    8446       39031 :         if (rel->flag == ddl_create_view) {
    8447       23007 :                 if (en) {
    8448       23007 :                         replace = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8449       23007 :                         if (!replace)
    8450             :                                 return NULL;
    8451             :                 } else {
    8452           0 :                         replace = stmt_atom_int(be, 0);
    8453             :                 }
    8454       23007 :                 append(l, replace);
    8455       16024 :         } else if (rel->flag == ddl_create_table && en) {
    8456         101 :                 stmt *name = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8457         101 :                 if (!name)
    8458             :                         return NULL;
    8459         101 :                 en = en->next;
    8460         101 :                 append(l, name);
    8461         101 :                 if (!en)
    8462             :                         return NULL;
    8463         101 :                 stmt *passwd = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8464         101 :                 if (!passwd)
    8465             :                         return NULL;
    8466         101 :                 append(l, passwd);
    8467             :         }
    8468       39031 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    8469             : }
    8470             : 
    8471             : static stmt *
    8472      251912 : rel2bin_catalog2(backend *be, sql_rel *rel, list *refs)
    8473             : {
    8474      251912 :         mvc *sql = be->mvc;
    8475      251912 :         node *en;
    8476      251912 :         list *l = sa_list(sql->sa);
    8477             : 
    8478      251912 :         (void)refs;
    8479     1522205 :         for (en = rel->exps->h; en; en = en->next) {
    8480     1270293 :                 stmt *es = NULL;
    8481             : 
    8482     1270293 :                 if (en->data) {
    8483     1251348 :                         es = exp_bin(be, en->data, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0);
    8484     1251348 :                         if (!es)
    8485             :                                 return NULL;
    8486             :                 } else {
    8487       18945 :                         es = stmt_atom_string_nil(be);
    8488             :                 }
    8489     1270293 :                 append(l,es);
    8490             :         }
    8491      251912 :         return stmt_catalog(be, rel->flag, stmt_list(be, l));
    8492             : }
    8493             : 
    8494             : static stmt *
    8495      344572 : rel2bin_ddl(backend *be, sql_rel *rel, list *refs)
    8496             : {
    8497      344572 :         mvc *sql = be->mvc;
    8498      344572 :         stmt *s = NULL;
    8499             : 
    8500      344572 :         switch (rel->flag) {
    8501          74 :                 case ddl_output:
    8502          74 :                         s = rel2bin_output(be, rel, refs);
    8503          74 :                         sql->type = Q_TABLE;
    8504          74 :                         break;
    8505         521 :                 case ddl_list:
    8506         521 :                         s = rel2bin_list(be, rel, refs);
    8507         521 :                         break;
    8508       47772 :                 case ddl_psm:
    8509       47772 :                         s = rel2bin_psm(be, rel);
    8510       47772 :                         break;
    8511         157 :                 case ddl_exception:
    8512         157 :                         s = rel2bin_exception(be, rel, refs);
    8513         157 :                         break;
    8514         363 :                 case ddl_create_seq:
    8515             :                 case ddl_alter_seq:
    8516         363 :                         s = rel2bin_seq(be, rel, refs);
    8517         363 :                         sql->type = Q_SCHEMA;
    8518         363 :                         break;
    8519         285 :                 case ddl_alter_table_add_range_partition:
    8520             :                 case ddl_alter_table_add_list_partition:
    8521         285 :                         s = rel2bin_partition_limits(be, rel, refs);
    8522         285 :                         sql->type = Q_SCHEMA;
    8523         285 :                         break;
    8524        3160 :                 case ddl_release:
    8525             :                 case ddl_commit:
    8526             :                 case ddl_rollback:
    8527             :                 case ddl_trans:
    8528        3160 :                         s = rel2bin_trans(be, rel, refs);
    8529        3160 :                         sql->type = Q_TRANS;
    8530        3160 :                         break;
    8531        1297 :                 case ddl_create_schema:
    8532             :                 case ddl_drop_schema:
    8533        1297 :                         s = rel2bin_catalog_schema(be, rel, refs);
    8534        1297 :                         sql->type = Q_SCHEMA;
    8535        1297 :                         break;
    8536       39031 :                 case ddl_create_table:
    8537             :                 case ddl_drop_table:
    8538             :                 case ddl_create_view:
    8539             :                 case ddl_drop_view:
    8540             :                 case ddl_drop_constraint:
    8541             :                 case ddl_alter_table:
    8542       39031 :                         s = rel2bin_catalog_table(be, rel, refs);
    8543       39031 :                         sql->type = Q_SCHEMA;
    8544       39031 :                         break;
    8545      251912 :                 case ddl_drop_seq:
    8546             :                 case ddl_create_type:
    8547             :                 case ddl_drop_type:
    8548             :                 case ddl_drop_index:
    8549             :                 case ddl_create_function:
    8550             :                 case ddl_drop_function:
    8551             :                 case ddl_create_trigger:
    8552             :                 case ddl_drop_trigger:
    8553             :                 case ddl_grant_roles:
    8554             :                 case ddl_revoke_roles:
    8555             :                 case ddl_grant:
    8556             :                 case ddl_revoke:
    8557             :                 case ddl_grant_func:
    8558             :                 case ddl_revoke_func:
    8559             :                 case ddl_create_user:
    8560             :                 case ddl_drop_user:
    8561             :                 case ddl_alter_user:
    8562             :                 case ddl_rename_user:
    8563             :                 case ddl_create_role:
    8564             :                 case ddl_drop_role:
    8565             :                 case ddl_alter_table_add_table:
    8566             :                 case ddl_alter_table_del_table:
    8567             :                 case ddl_alter_table_set_access:
    8568             :                 case ddl_comment_on:
    8569             :                 case ddl_rename_schema:
    8570             :                 case ddl_rename_table:
    8571             :                 case ddl_rename_column:
    8572      251912 :                         s = rel2bin_catalog2(be, rel, refs);
    8573      251912 :                         sql->type = Q_SCHEMA;
    8574      251912 :                         break;
    8575             :                 default:
    8576           0 :                         assert(0);
    8577             :         }
    8578      344556 :         return s;
    8579             : }
    8580             : 
    8581             : static stmt *
    8582     1252345 : subrel_bin(backend *be, sql_rel *rel, list *refs)
    8583             : {
    8584     1252345 :         mvc *sql = be->mvc;
    8585     1252345 :         stmt *s = NULL;
    8586             : 
    8587     1252345 :         if (mvc_highwater(sql))
    8588           0 :                 return sql_error(be->mvc, 10, SQLSTATE(42000) "Query too complex: running out of stack space");
    8589             : 
    8590     1252368 :         if (!rel)
    8591             :                 return s;
    8592     1252368 :         if (rel_is_ref(rel)) {
    8593       15621 :                 s = refs_find_rel(refs, rel);
    8594             :                 /* needs a proper fix!! */
    8595       15621 :                 if (s)
    8596             :                         return s;
    8597             :         }
    8598     1246225 :         switch (rel->op) {
    8599      148847 :         case op_basetable:
    8600      148847 :                 s = rel2bin_basetable(be, rel);
    8601      148851 :                 sql->type = Q_TABLE;
    8602      148851 :                 break;
    8603        3193 :         case op_table:
    8604        3193 :                 s = rel2bin_table(be, rel, refs);
    8605        3193 :                 sql->type = Q_TABLE;
    8606        3193 :                 break;
    8607       76655 :         case op_join:
    8608             :         case op_left:
    8609             :         case op_right:
    8610             :         case op_full:
    8611       76655 :                 s = rel2bin_join(be, rel, refs);
    8612       76655 :                 sql->type = Q_TABLE;
    8613       76655 :                 break;
    8614        3206 :         case op_semi:
    8615        3206 :                 s = rel2bin_semijoin(be, rel, refs);
    8616        3206 :                 sql->type = Q_TABLE;
    8617        3206 :                 break;
    8618        1531 :         case op_anti:
    8619        1531 :                 s = rel2bin_antijoin(be, rel, refs);
    8620        1531 :                 sql->type = Q_TABLE;
    8621        1531 :                 break;
    8622         303 :         case op_union:
    8623         303 :                 s = rel2bin_union(be, rel, refs);
    8624         303 :                 sql->type = Q_TABLE;
    8625         303 :                 break;
    8626        4319 :         case op_munion:
    8627        4319 :                 s = rel2bin_munion(be, rel, refs);
    8628        4319 :                 sql->type = Q_TABLE;
    8629        4319 :                 break;
    8630        2025 :         case op_except:
    8631        2025 :                 s = rel2bin_except(be, rel, refs);
    8632        2025 :                 sql->type = Q_TABLE;
    8633        2025 :                 break;
    8634         375 :         case op_inter:
    8635         375 :                 s = rel2bin_inter(be, rel, refs);
    8636         375 :                 sql->type = Q_TABLE;
    8637         375 :                 break;
    8638      400575 :         case op_project:
    8639      400575 :                 s = rel2bin_project(be, rel, refs, NULL);
    8640      400491 :                 sql->type = Q_TABLE;
    8641      400491 :                 break;
    8642       73597 :         case op_select:
    8643       73597 :                 s = rel2bin_select(be, rel, refs);
    8644       73597 :                 sql->type = Q_TABLE;
    8645       73597 :                 break;
    8646       13620 :         case op_groupby:
    8647       13620 :                 s = rel2bin_groupby(be, rel, refs);
    8648       13620 :                 sql->type = Q_TABLE;
    8649       13620 :                 break;
    8650       16589 :         case op_topn:
    8651       16589 :                 s = rel2bin_topn(be, rel, refs);
    8652       16599 :                 sql->type = Q_TABLE;
    8653       16599 :                 break;
    8654          21 :         case op_sample:
    8655          21 :                 s = rel2bin_sample(be, rel, refs);
    8656          21 :                 sql->type = Q_TABLE;
    8657          21 :                 break;
    8658      110194 :         case op_insert:
    8659      110194 :                 s = rel2bin_insert(be, rel, refs);
    8660      110203 :                 if (!(rel->returning) && sql->type == Q_TABLE)
    8661      105308 :                         sql->type = Q_UPDATE;
    8662             :                 break;
    8663        4389 :         case op_update:
    8664        4389 :                 s = rel2bin_update(be, rel, refs);
    8665        4389 :                 if (!(rel->returning) && sql->type == Q_TABLE)
    8666        4230 :                         sql->type = Q_UPDATE;
    8667             :                 break;
    8668         492 :         case op_delete:
    8669         492 :                 s = rel2bin_delete(be, rel, refs);
    8670         492 :                 if (!(rel->returning) && sql->type == Q_TABLE)
    8671         357 :                         sql->type = Q_UPDATE;
    8672             :                 break;
    8673       41675 :         case op_truncate:
    8674       41675 :                 s = rel2bin_truncate(be, rel);
    8675       41628 :                 if (sql->type == Q_TABLE)
    8676           5 :                         sql->type = Q_UPDATE;
    8677             :                 break;
    8678          44 :         case op_merge:
    8679          44 :                 s = rel2bin_merge(be, rel, refs);
    8680          44 :                 if (sql->type == Q_TABLE)
    8681          44 :                         sql->type = Q_UPDATE;
    8682             :                 break;
    8683      344575 :         case op_ddl:
    8684      344575 :                 s = rel2bin_ddl(be, rel, refs);
    8685      344575 :                 break;
    8686             :         }
    8687     1246094 :         if (s && rel_is_ref(rel)) {
    8688        9478 :                 list_append(refs, rel);
    8689        9478 :                 list_append(refs, s);
    8690             :         }
    8691             :         return s;
    8692             : }
    8693             : 
    8694             : stmt *
    8695       10956 : rel_bin(backend *be, sql_rel *rel)
    8696             : {
    8697       10956 :         mvc *sql = be->mvc;
    8698       10956 :         list *refs = sa_list(sql->sa);
    8699       10956 :         mapi_query_t sqltype = sql->type;
    8700       10956 :         stmt *s = subrel_bin(be, rel, refs);
    8701             : 
    8702       10956 :         s = subrel_project(be, s, refs, rel);
    8703       10956 :         if (sqltype == Q_SCHEMA)
    8704         317 :                 sql->type = sqltype;  /* reset */
    8705             : 
    8706       10956 :         if (be->mb->errors) {
    8707           0 :                 if (be->mvc->sa->eb.enabled)
    8708           0 :                         eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : be->mb->errors, 1000);
    8709             :                 return NULL;
    8710             :         }
    8711             :         return s;
    8712             : }
    8713             : 
    8714             : stmt *
    8715      617383 : output_rel_bin(backend *be, sql_rel *rel, int top)
    8716             : {
    8717      617383 :         mvc *sql = be->mvc;
    8718      617383 :         list *refs = sa_list(sql->sa);
    8719      617351 :         mapi_query_t sqltype = sql->type;
    8720      617351 :         stmt *s = NULL;
    8721             : 
    8722      617351 :         be->join_idx = 0;
    8723      617351 :         be->rowcount = 0;
    8724      617351 :         be->silent = !top;
    8725             : 
    8726      617351 :         s = subrel_bin(be, rel, refs);
    8727      617204 :         s = subrel_project(be, s, refs, rel);
    8728             : 
    8729      617214 :         if (!s)
    8730             :                 return NULL;
    8731      617206 :         if (sqltype == Q_SCHEMA)
    8732      293020 :                 sql->type = sqltype; /* reset */
    8733             : 
    8734      617206 :         if (!be->silent) { /* don't generate outputs when we are silent */
    8735      610822 :                 if (!is_ddl(rel->op) && sql->type == Q_TABLE && stmt_output(be, s) < 0) {
    8736             :                         return NULL;
    8737      610798 :                 } else if (be->rowcount > 0 && sqltype == Q_UPDATE && stmt_affected_rows(be, be->rowcount) < 0) {
    8738             :                         /* only call stmt_affected_rows outside functions and ddl */
    8739             :                         return NULL;
    8740             :                 }
    8741             :         }
    8742             :         return s;
    8743             : }

Generated by: LCOV version 1.14