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

Generated by: LCOV version 1.14