LCOV - code coverage report
Current view: top level - sql/backends/monet5 - rel_bin.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4499 4867 92.4 %
Date: 2024-12-20 21:24:02 Functions: 130 133 97.7 %

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

Generated by: LCOV version 1.14