LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3072 3777 81.3 %
Date: 2025-03-24 21:28:01 Functions: 118 125 94.4 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024, 2025 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "sql_mem.h"
      15             : #include "sql_stack.h"
      16             : #include "sql_statement.h"
      17             : #include "sql_gencode.h"
      18             : #include "rel_rel.h"
      19             : #include "rel_exp.h"
      20             : #include "rel_prop.h"
      21             : 
      22             : #include "mal_namespace.h"
      23             : #include "mal_builder.h"
      24             : 
      25             : /*
      26             :  * Some utility routines to generate code
      27             :  * The equality operator in MAL is '==' instead of '='.
      28             :  */
      29             : static const char *
      30       18072 : convertMultiplexMod(const char *mod, const char *op)
      31             : {
      32       18072 :         if (strcmp(op, "=") == 0)
      33           0 :                 return "calc";
      34             :         return mod;
      35             : }
      36             : 
      37             : static const char *
      38      328035 : convertMultiplexFcn(const char *op)
      39             : {
      40      328035 :         if (strcmp(op, "=") == 0)
      41       52447 :                 return "==";
      42             :         return op;
      43             : }
      44             : 
      45             : static InstrPtr
      46       17996 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
      47             : {
      48       17996 :         InstrPtr q = NULL;
      49             : 
      50       17996 :         q = newStmt(mb, malRef, multiplexRef);
      51       17996 :         if (q == NULL)
      52             :                 return NULL;
      53       17996 :         setVarType(mb, getArg(q, 0), newBatType(rtype));
      54       17996 :         q = pushStr(mb, q, convertMultiplexMod(mod, name));
      55       17996 :         q = pushStr(mb, q, convertMultiplexFcn(name));
      56       17996 :         q = pushArgument(mb, q, o1);
      57       17996 :         q = pushArgument(mb, q, o2);
      58       17996 :         pushInstruction(mb, q);
      59       17996 :         return q;
      60             : }
      61             : 
      62             : static InstrPtr
      63       51665 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
      64             : {
      65       51665 :         InstrPtr q = NULL;
      66             : 
      67       51665 :         if (o1 == NULL || o1->nr < 0)
      68             :                 return NULL;
      69       51665 :         q = newStmt(mb, mod, name);
      70       51665 :         q = pushArgument(mb, q, o1->nr);
      71       51665 :         pushInstruction(mb, q);
      72       51665 :         return q;
      73             : }
      74             : 
      75             : static InstrPtr
      76      181365 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
      77             : {
      78      181365 :         InstrPtr q = NULL;
      79             : 
      80      181365 :         if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
      81             :                 return NULL;
      82      181365 :         q = newStmt(mb, mod, name);
      83      181365 :         q = pushArgument(mb, q, o1->nr);
      84      181365 :         q = pushArgument(mb, q, o2->nr);
      85      181365 :         pushInstruction(mb, q);
      86      181365 :         return q;
      87             : }
      88             : 
      89             : InstrPtr
      90         346 : pushPtr(MalBlkPtr mb, InstrPtr q, ptr val)
      91             : {
      92         346 :         int _t;
      93         346 :         ValRecord cst;
      94             : 
      95         346 :         if (q == NULL || mb->errors)
      96             :                 return q;
      97         346 :         cst.vtype= TYPE_ptr;
      98         346 :         cst.val.pval = val;
      99         346 :         cst.len = 0;
     100         346 :         _t = defConstant(mb, TYPE_ptr, &cst);
     101         346 :         if( _t >= 0)
     102         346 :                 return pushArgument(mb, q, _t);
     103             :         return q;
     104             : }
     105             : 
     106             : static InstrPtr
     107     2250854 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
     108             : {
     109     2250854 :         if (t->s)
     110     2250854 :                 return pushArgument(mb, q, getStrConstant(mb,t->s->base.name));
     111             :         else
     112           0 :                 return pushNil(mb, q, TYPE_str);
     113             : }
     114             : 
     115             : int
     116           0 : stmt_key(stmt *s)
     117             : {
     118           0 :         const char *nme = column_name(NULL, s);
     119             : 
     120           0 :         return hash_key(nme);
     121             : }
     122             : 
     123             : /* #TODO make proper traversal operations */
     124             : stmt *
     125         211 : stmt_atom_string(backend *be, const char *S)
     126             : {
     127         211 :         const char *s = sa_strdup(be->mvc->sa, S);
     128         211 :         sql_subtype t;
     129             : 
     130         211 :         if (s == NULL)
     131             :                 return NULL;
     132         211 :         sql_find_subtype(&t, "varchar", _strlen(s), 0);
     133         211 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, s));
     134             : }
     135             : 
     136             : stmt *
     137       19926 : stmt_atom_string_nil(backend *be)
     138             : {
     139       19926 :         sql_subtype t;
     140             : 
     141       19926 :         sql_find_subtype(&t, "varchar", 0, 0);
     142       19926 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
     143             : }
     144             : 
     145             : stmt *
     146        6075 : stmt_atom_int(backend *be, int i)
     147             : {
     148        6075 :         sql_subtype t;
     149             : 
     150        6075 :         sql_find_subtype(&t, "int", 32, 0);
     151        6075 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     152             : }
     153             : 
     154             : stmt *
     155      117703 : stmt_atom_lng(backend *be, lng i)
     156             : {
     157      117703 :         sql_subtype t;
     158             : 
     159      117703 :         sql_find_subtype(&t, "bigint", 64, 0);
     160      117724 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     161             : }
     162             : 
     163             : stmt *
     164          26 : stmt_atom_lng_nil(backend *be)
     165             : {
     166          26 :         sql_subtype t;
     167             : 
     168          26 :         sql_find_subtype(&t, "bigint", 64, 0);
     169          26 :         return stmt_atom(be, atom_general(be->mvc->sa, &t, NULL, 0));
     170             : }
     171             : 
     172             : stmt *
     173       43132 : stmt_bool(backend *be, int b)
     174             : {
     175       43132 :         sql_subtype t;
     176             : 
     177       43132 :         sql_find_subtype(&t, "boolean", 0, 0);
     178             : 
     179       43132 :         if (b == bit_nil) {
     180           0 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
     181       43132 :         } else if (b) {
     182       42003 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
     183             :         } else {
     184        1129 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
     185             :         }
     186             : }
     187             : 
     188             : static stmt *
     189    18353567 : stmt_create(allocator *sa, st_type type)
     190             : {
     191    18353567 :         stmt *s = SA_NEW(sa, stmt);
     192             : 
     193    18353208 :         if (!s)
     194             :                 return NULL;
     195    18353208 :         *s = (stmt) {
     196             :                 .type = type,
     197             :         };
     198    18353208 :         return s;
     199             : }
     200             : 
     201             : stmt *
     202       28178 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
     203             : {
     204       28178 :         MalBlkPtr mb = be->mb;
     205       28178 :         InstrPtr q = NULL;
     206             : 
     207       28178 :         if (s == NULL || s->nr < 0)
     208           0 :                 goto bailout;
     209       28178 :         if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
     210           0 :                 goto bailout;
     211             : 
     212       49953 :         q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
     213       28178 :         if (q == NULL)
     214           0 :                 goto bailout;
     215             : 
     216             :         /* output variables extent and hist */
     217       28178 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     218       28178 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     219       28178 :         q = pushArgument(mb, q, s->nr);
     220       28178 :         if (grp)
     221        6403 :                 q = pushArgument(mb, q, grp->nr);
     222             : 
     223       28178 :         bool enabled = be->mvc->sa->eb.enabled;
     224       28178 :         be->mvc->sa->eb.enabled = false;
     225       28178 :         stmt *ns = stmt_create(be->mvc->sa, st_group);
     226       28178 :         be->mvc->sa->eb.enabled = enabled;
     227       28178 :         if (ns == NULL) {
     228           0 :                 freeInstruction(q);
     229           0 :                 goto bailout;
     230             :         }
     231             : 
     232       28178 :         ns->op1 = s;
     233             : 
     234       28178 :         if (grp) {
     235        6403 :                 ns->op2 = grp;
     236        6403 :                 ns->op3 = ext;
     237        6403 :                 ns->op4.stval = cnt;
     238             :         }
     239       28178 :         ns->nrcols = s->nrcols;
     240       28178 :         ns->key = 0;
     241       28178 :         ns->q = q;
     242       28178 :         ns->nr = getDestVar(q);
     243       28178 :         pushInstruction(mb, q);
     244       28178 :         return ns;
     245             : 
     246           0 :   bailout:
     247           0 :         if (be->mvc->sa->eb.enabled)
     248           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     249             :         return NULL;
     250             : }
     251             : 
     252             : stmt *
     253          76 : stmt_unique(backend *be, stmt *s)
     254             : {
     255          76 :         MalBlkPtr mb = be->mb;
     256          76 :         InstrPtr q = NULL;
     257             : 
     258          76 :         if (s == NULL || s->nr < 0)
     259           0 :                 goto bailout;
     260             : 
     261          76 :         q = newStmt(mb, algebraRef, uniqueRef);
     262          76 :         if (q == NULL)
     263           0 :                 goto bailout;
     264             : 
     265          76 :         q = pushArgument(mb, q, s->nr);
     266          76 :         q = pushNilBat(mb, q); /* candidate list */
     267             : 
     268          76 :         bool enabled = be->mvc->sa->eb.enabled;
     269          76 :         be->mvc->sa->eb.enabled = false;
     270          76 :         stmt *ns = stmt_create(be->mvc->sa, st_unique);
     271          76 :         be->mvc->sa->eb.enabled = enabled;
     272          76 :         if (ns == NULL) {
     273           0 :                 freeInstruction(q);
     274           0 :                 goto bailout;
     275             :         }
     276             : 
     277          76 :         ns->op1 = s;
     278          76 :         ns->nrcols = s->nrcols;
     279          76 :         ns->key = 1;
     280          76 :         ns->q = q;
     281          76 :         ns->nr = getDestVar(q);
     282          76 :         pushInstruction(mb, q);
     283          76 :         return ns;
     284             : 
     285           0 :   bailout:
     286           0 :         if (be->mvc->sa->eb.enabled)
     287           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     288             :         return NULL;
     289             : }
     290             : 
     291             : stmt *
     292           6 : stmt_none(backend *be)
     293             : {
     294           6 :         return stmt_create(be->mvc->sa, st_none);
     295             : }
     296             : 
     297             : static int
     298          55 : create_bat(MalBlkPtr mb, int tt)
     299             : {
     300          55 :         InstrPtr q = newStmt(mb, batRef, newRef);
     301             : 
     302          55 :         if (q == NULL)
     303             :                 return -1;
     304          55 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     305          55 :         q = pushType(mb, q, tt);
     306          55 :         pushInstruction(mb, q);
     307          55 :         return getDestVar(q);
     308             : }
     309             : 
     310             : stmt *
     311         116 : stmt_bat_new(backend *be, sql_subtype *tpe, lng estimate)
     312             : {
     313         116 :         InstrPtr q = newStmt(be->mb, batRef, newRef);
     314         116 :         int tt = tpe->type->localtype;
     315             : 
     316         116 :         if (q == NULL)
     317             :                 return NULL;
     318         116 :         if (tt == TYPE_void)
     319           1 :                 tt = TYPE_bte;
     320         116 :         setVarType(be->mb, getArg(q, 0), newBatType(tt));
     321         116 :         q = pushType(be->mb, q, tt);
     322         116 :         if (estimate > 0)
     323           0 :                 q = pushInt(be->mb, q, (int)estimate);
     324         116 :         pushInstruction(be->mb, q);
     325             : 
     326         116 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
     327         116 :         s->subtype = *tpe;
     328         116 :         s->q = q;
     329         116 :         s->nr = q->argv[0];
     330         116 :         s->nrcols = 2;
     331         116 :         return s;
     332             : }
     333             : 
     334             : static int *
     335          20 : dump_table(allocator *sa, MalBlkPtr mb, sql_table *t)
     336             : {
     337          20 :         int i = 0;
     338          20 :         node *n;
     339          20 :         int *l = SA_NEW_ARRAY(sa, int, ol_length(t->columns) + 1);
     340             : 
     341          20 :         if (!l)
     342             :                 return NULL;
     343             : 
     344             :         /* tid column */
     345          20 :         if ((l[i++] = create_bat(mb, TYPE_oid)) < 0)
     346             :                 return NULL;
     347             : 
     348          55 :         for (n = ol_first_node(t->columns); n; n = n->next) {
     349          35 :                 sql_column *c = n->data;
     350             : 
     351          35 :                 if ((l[i++] = create_bat(mb, c->type.type->localtype)) < 0)
     352             :                         return NULL;
     353             :         }
     354             :         return l;
     355             : }
     356             : 
     357             : stmt *
     358        2780 : stmt_var(backend *be, sql_alias *sname, const char *varname, sql_subtype *t, int declare, int level)
     359             : {
     360        2780 :         MalBlkPtr mb = be->mb;
     361        2780 :         InstrPtr q = NULL;
     362        2780 :         char *buf;
     363             : 
     364        2780 :         if (level == 0) { /* global */
     365         431 :                 int tt = t->type->localtype;
     366             : 
     367         431 :                 assert(sname);
     368         431 :                 q = newStmt(mb, sqlRef, getVariableRef);
     369         431 :                 if (q == NULL)
     370           0 :                         goto bailout;
     371         431 :                 q = pushArgument(mb, q, be->mvc_var);
     372         431 :                 q = pushStr(mb, q, sname->name); /* all global variables have a schema */
     373         431 :                 q = pushStr(mb, q, varname);
     374         431 :                 setVarType(mb, getArg(q, 0), tt);
     375        2349 :         } else if (!declare) {
     376        1959 :                 char levelstr[16];
     377             : 
     378        1959 :                 assert(!sname);
     379        1959 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     380        1959 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     381        1959 :                 if (!buf)
     382           1 :                         goto bailout;
     383        1959 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     384        1959 :                 q = newAssignment(mb);
     385        1959 :                 if (q == NULL)
     386           1 :                         goto bailout;
     387        1958 :                 q = pushArgumentId(mb, q, buf);
     388             :         } else {
     389         390 :                 int tt = t->type->localtype;
     390         390 :                 char levelstr[16];
     391             : 
     392         390 :                 assert(!sname);
     393         390 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     394         390 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     395         390 :                 if (!buf)
     396           0 :                         goto bailout;
     397         390 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     398             : 
     399         390 :                 q = newInstruction(mb, NULL, NULL);
     400         390 :                 if (q == NULL) {
     401           0 :                         goto bailout;
     402             :                 }
     403         390 :                 q->argc = q->retc = 0;
     404         390 :                 q = pushArgumentId(mb, q, buf);
     405         390 :                 q = pushNil(mb, q, tt);
     406         390 :                 q->retc++;
     407             :         }
     408        2779 :         bool enabled = be->mvc->sa->eb.enabled;
     409        2779 :         be->mvc->sa->eb.enabled = false;
     410        2779 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     411        2779 :         be->mvc->sa->eb.enabled = enabled;
     412        2779 :         if (s == NULL) {
     413           0 :                 freeInstruction(q);
     414           0 :                 goto bailout;
     415             :         }
     416             : 
     417        2779 :         if (t)
     418        2779 :                 s->subtype = *t;
     419             :         else
     420           0 :                 s->subtype.type = NULL;
     421        2779 :         s->flag = declare + (level << 1);
     422        2779 :         s->key = 1;
     423        2779 :         s->q = q;
     424        2779 :         s->nr = getDestVar(q);
     425        2779 :         pushInstruction(mb, q);
     426        2779 :         return s;
     427             : 
     428           1 :   bailout:
     429           1 :         if (be->mvc->sa->eb.enabled)
     430           1 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     431             :         return NULL;
     432             : }
     433             : 
     434             : stmt *
     435          20 : stmt_vars(backend *be, const char *varname, sql_table *t, int declare, int level)
     436             : {
     437          20 :         MalBlkPtr mb = be->mb;
     438          20 :         int *l;
     439             : 
     440          20 :         (void)varname;
     441             :         /* declared table */
     442          20 :         if ((l = dump_table(be->mvc->sa, mb, t)) != NULL) {
     443          20 :                 stmt *s = stmt_create(be->mvc->sa, st_var);
     444             : 
     445          20 :                 if (s == NULL) {
     446             :                         return NULL;
     447             :                 }
     448             : 
     449          20 :                 ATOMIC_PTR_SET(&t->data, l);
     450             :                 /*
     451             :                 s->op2 = (stmt*)l;
     452             :                 s->op3 = (stmt*)t;
     453             :                 */
     454          20 :                 s->flag = declare + (level << 1);
     455          20 :                 s->key = 1;
     456          20 :                 s->nr = l[0];
     457          20 :                 return s;
     458             :         }
     459           0 :         if (be->mvc->sa->eb.enabled)
     460           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     461             :         return NULL;
     462             : }
     463             : 
     464             : stmt *
     465        2050 : stmt_varnr(backend *be, int nr, sql_subtype *t)
     466             : {
     467        2050 :         MalBlkPtr mb = be->mb;
     468        2050 :         InstrPtr q = newAssignment(mb);
     469        2050 :         char buf[IDLENGTH];
     470             : 
     471        2050 :         if (q == NULL)
     472           0 :                 goto bailout;
     473             : 
     474        2050 :         (void) snprintf(buf, sizeof(buf), "A%d", nr);
     475        2050 :         q = pushArgumentId(mb, q, buf);
     476             : 
     477        2050 :         bool enabled = be->mvc->sa->eb.enabled;
     478        2050 :         be->mvc->sa->eb.enabled = false;
     479        2050 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     480        2050 :         be->mvc->sa->eb.enabled = enabled;
     481        2050 :         if (s == NULL) {
     482           0 :                 freeInstruction(q);
     483           0 :                 goto bailout;
     484             :         }
     485             : 
     486        2050 :         s->op1 = NULL;
     487        2050 :         if (t)
     488        2050 :                 s->subtype = *t;
     489             :         else
     490           0 :                 s->subtype.type = NULL;
     491        2050 :         s->flag = nr;
     492        2050 :         s->key = 1;
     493        2050 :         s->q = q;
     494        2050 :         s->nr = getDestVar(q);
     495        2050 :         pushInstruction(mb, q);
     496        2050 :         return s;
     497             : 
     498           0 :   bailout:
     499           0 :         if (be->mvc->sa->eb.enabled)
     500           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     501             :         return NULL;
     502             : }
     503             : 
     504             : stmt *
     505         690 : stmt_table(backend *be, stmt *cols, int temp)
     506             : {
     507         690 :         MalBlkPtr mb = be->mb;
     508             : 
     509         690 :         if (cols == NULL || cols->nr < 0)
     510           0 :                 goto bailout;
     511             : 
     512         690 :         stmt *s = stmt_create(be->mvc->sa, st_table);
     513             : 
     514         690 :         if (s == NULL)
     515           0 :                 goto bailout;
     516             : 
     517         690 :         if (cols->type != st_list) {
     518           0 :             InstrPtr q = newAssignment(mb);
     519           0 :                 if (q == NULL)
     520           0 :                         goto bailout;
     521           0 :                 pushInstruction(mb, q);
     522           0 :                 q = newStmt(mb, sqlRef, printRef);
     523           0 :                 if (q == NULL)
     524           0 :                         goto bailout;
     525           0 :                 q = pushStr(mb, q, "not a valid output list\n");
     526           0 :                 pushInstruction(mb, q);
     527             :         }
     528         690 :         s->op1 = cols;
     529         690 :         s->flag = temp;
     530         690 :         s->nr = cols->nr;
     531         690 :         s->nrcols = cols->nrcols;
     532         690 :         return s;
     533             : 
     534           0 :   bailout:
     535           0 :         if (be->mvc->sa->eb.enabled)
     536           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     537             :         return NULL;
     538             : }
     539             : 
     540             : stmt *
     541      223114 : stmt_temp(backend *be, sql_subtype *t)
     542             : {
     543      223114 :         int tt = t->type->localtype;
     544      223114 :         MalBlkPtr mb = be->mb;
     545      223114 :         InstrPtr q = newStmt(mb, batRef, newRef);
     546             : 
     547      224073 :         if (q == NULL)
     548           0 :                 goto bailout;
     549      224073 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     550      224073 :         q = pushType(mb, q, tt);
     551      223936 :         bool enabled = be->mvc->sa->eb.enabled;
     552      223936 :         be->mvc->sa->eb.enabled = false;
     553      223936 :         stmt *s = stmt_create(be->mvc->sa, st_temp);
     554      223846 :         be->mvc->sa->eb.enabled = enabled;
     555             : 
     556      223846 :         if (s == NULL) {
     557           0 :                 freeInstruction(q);
     558           0 :                 goto bailout;
     559             :         }
     560      223846 :         s->subtype = *t;
     561      223846 :         s->nrcols = 1;
     562      223846 :         s->q = q;
     563      223846 :         s->nr = getDestVar(q);
     564      223846 :         pushInstruction(mb, q);
     565      223846 :         return s;
     566             : 
     567           0 :   bailout:
     568           0 :         if (be->mvc->sa->eb.enabled)
     569           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     570             :         return NULL;
     571             : }
     572             : 
     573             : stmt *
     574         557 : stmt_blackbox_result(backend *be, InstrPtr q, int retnr, sql_subtype *t)
     575             : {
     576         557 :         if (q == NULL)
     577             :                 return NULL;
     578         557 :         stmt *s = stmt_create(be->mvc->sa, st_result);
     579         557 :         if (s == NULL)
     580             :                 return NULL;
     581         557 :         s->subtype = *t;
     582         557 :         s->nrcols = 2;
     583         557 :         s->q = q;
     584         557 :         s->nr = getArg(q, retnr);
     585         557 :         s->flag = retnr;
     586         557 :         return s;
     587             : }
     588             : 
     589             : 
     590             : stmt *
     591      205485 : stmt_tid(backend *be, sql_table *t, int partition)
     592             : {
     593      205485 :         int tt = TYPE_oid;
     594      205485 :         MalBlkPtr mb = be->mb;
     595      205485 :         InstrPtr q;
     596             : 
     597      205485 :         if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
     598          16 :                 stmt *s = stmt_create(be->mvc->sa, st_tid);
     599          16 :                 int *l = ATOMIC_PTR_GET(&t->data);
     600             : 
     601          16 :                 if (s == NULL) {
     602           0 :                         goto bailout;
     603             :                 }
     604          16 :                 assert(partition == 0);
     605          16 :                 s->partition = partition;
     606          16 :                 s->op4.tval = t;
     607          16 :                 s->nrcols = 1;
     608          16 :                 s->nr = l[0];
     609          16 :                 return s;
     610             :         }
     611      205469 :         q = newStmt(mb, sqlRef, tidRef);
     612      205629 :         if (q == NULL)
     613           0 :                 goto bailout;
     614      205629 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     615      205629 :         q = pushArgument(mb, q, be->mvc_var);
     616      205628 :         q = pushSchema(mb, q, t);
     617      205603 :         q = pushStr(mb, q, t->base.name);
     618      205618 :         if (t && isTable(t) && partition) {
     619       77060 :                 sql_trans *tr = be->mvc->session->tr;
     620       77060 :                 sqlstore *store = tr->store;
     621       77060 :                 BUN rows = (BUN) store->storage_api.count_del(tr, t, CNT_RDONLY);
     622       77060 :                 setRowCnt(mb,getArg(q,0),rows);
     623             :         }
     624             : 
     625      205618 :         bool enabled = be->mvc->sa->eb.enabled;
     626      205618 :         be->mvc->sa->eb.enabled = false;
     627      205618 :         stmt *s = stmt_create(be->mvc->sa, st_tid);
     628      205493 :         be->mvc->sa->eb.enabled = enabled;
     629      205493 :         if (s == NULL) {
     630           0 :                 freeInstruction(q);
     631           0 :                 goto bailout;
     632             :         }
     633             : 
     634      205493 :         s->tname = table_alias(be->mvc->sa, t, NULL);
     635      205443 :         s->partition = partition;
     636      205443 :         s->op4.tval = t;
     637      205443 :         s->nrcols = 1;
     638      205443 :         s->nr = getDestVar(q);
     639      205443 :         s->q = q;
     640      205443 :         pushInstruction(mb, q);
     641      205443 :         return s;
     642             : 
     643           0 :   bailout:
     644           0 :         if (be->mvc->sa->eb.enabled)
     645           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     646             :         return NULL;
     647             : }
     648             : 
     649             : static sql_column *
     650     1011951 : find_real_column(backend *be, sql_column *c)
     651             : {
     652     1011951 :         if (c && c->t && c->t->s && c->t->persistence == SQL_DECLARED_TABLE) {
     653       36780 :                 sql_table *nt = find_sql_table_id(be->mvc->session->tr, c->t->s, c->t->base.id);
     654       36780 :                 if (nt) {
     655       36780 :                         node *n = ol_find_id(nt->columns, c->base.id);
     656       36780 :                         if (n)
     657       36780 :                                 return n->data;
     658             :                 }
     659             :         }
     660             :         return c;
     661             : }
     662             : 
     663             : stmt *
     664     1011951 : stmt_bat(backend *be, sql_column *c, sql_alias *tname, int access, int partition)
     665             : {
     666     1011951 :         int tt = c->type.type->localtype;
     667     1011951 :         MalBlkPtr mb = be->mb;
     668     1011951 :         InstrPtr q;
     669             : 
     670     1011951 :         c = find_real_column(be, c);
     671             : 
     672     1011974 :         if (access == RD_EXT)
     673         176 :                 partition = 0;
     674             : 
     675             :         /* for read access tid.project(col) */
     676     1011974 :         if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
     677          23 :                 stmt *s = stmt_create(be->mvc->sa, st_bat);
     678          23 :                 int *l = ATOMIC_PTR_GET(&c->t->data);
     679             : 
     680          23 :                 if (s == NULL) {
     681           0 :                         goto bailout;
     682             :                 }
     683          23 :                 assert(partition == 0);
     684          23 :                 s->partition = partition;
     685          23 :                 s->op4.cval = c;
     686          23 :                 s->nrcols = 1;
     687          23 :                 s->flag = access;
     688          23 :                 s->nr = l[c->colnr+1];
     689          23 :                 s->tname = tname;
     690          23 :                 s->cname = c->base.name;
     691          23 :                 return s;
     692             :         }
     693     1011951 :         q = newStmtArgs(mb, sqlRef, bindRef, 9);
     694     1012011 :         if (q == NULL)
     695           0 :                 goto bailout;
     696     1012011 :         if (c->storage_type && access != RD_EXT) {
     697         422 :                 sql_trans *tr = be->mvc->session->tr;
     698         422 :                 sqlstore *store = tr->store;
     699         422 :                 BAT *b = store->storage_api.bind_col(tr, c, QUICK);
     700         422 :                 if (!b) {
     701           0 :                         freeInstruction(q);
     702           0 :                         goto bailout;
     703             :                 }
     704         422 :                 tt = b->ttype;
     705             :         }
     706     1011835 :         if (access == RD_UPD_ID) {
     707      491739 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     708             :         } else {
     709      520272 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     710             :         }
     711     1012010 :         q = pushArgument(mb, q, be->mvc_var);
     712     1011992 :         q = pushSchema(mb, q, c->t);
     713     1011994 :         q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
     714     1011982 :         q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
     715     1011970 :         q = pushArgument(mb, q, getIntConstant(mb,access));
     716             : 
     717     1011936 :         if (access == RD_UPD_ID) {
     718      491715 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     719             :         }
     720     1011936 :         if (partition) {
     721      560923 :                 sql_trans *tr = be->mvc->session->tr;
     722      560923 :                 sqlstore *store = tr->store;
     723             : 
     724      560923 :                 if (c && isTable(c->t)) {
     725      560915 :                         BUN rows = (BUN) store->storage_api.count_del(tr, c->t, CNT_RDONLY);
     726      561008 :                         setRowCnt(mb,getArg(q,0),rows);
     727             :                 }
     728             :         }
     729             : 
     730     1012029 :         bool enabled = be->mvc->sa->eb.enabled;
     731     1012029 :         be->mvc->sa->eb.enabled = false;
     732     1012029 :         stmt *s = stmt_create(be->mvc->sa, st_bat);
     733     1012008 :         be->mvc->sa->eb.enabled = enabled;
     734     1012008 :         if (s == NULL) {
     735           0 :                 freeInstruction(q);
     736           0 :                 goto bailout;
     737             :         }
     738             : 
     739     1012008 :         s->partition = partition;
     740     1012008 :         s->op4.cval = c;
     741     1012008 :         s->nrcols = 1;
     742     1012008 :         s->flag = access;
     743     1012008 :         s->nr = getDestVar(q);
     744     1012008 :         s->q = q;
     745     1012008 :         s->tname = tname;
     746     1012008 :         s->cname = c->base.name;
     747     1012008 :         pushInstruction(mb, q);
     748     1012008 :         return s;
     749             : 
     750           0 :   bailout:
     751           0 :         if (be->mvc->sa->eb.enabled)
     752           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     753             :         return NULL;
     754             : }
     755             : 
     756             : stmt *
     757        6472 : stmt_idxbat(backend *be, sql_idx *i, sql_alias *tname, int access, int partition)
     758             : {
     759        6472 :         int tt = hash_index(i->type)?TYPE_lng:TYPE_oid;
     760        6472 :         MalBlkPtr mb = be->mb;
     761        6472 :         InstrPtr q = newStmtArgs(mb, sqlRef, bindidxRef, 9);
     762             : 
     763        6472 :         if (q == NULL)
     764           0 :                 goto bailout;
     765             : 
     766        6472 :         if (access == RD_UPD_ID) {
     767        2871 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     768             :         } else {
     769        3601 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     770             :         }
     771             : 
     772        6472 :         q = pushArgument(mb, q, be->mvc_var);
     773        6472 :         q = pushSchema(mb, q, i->t);
     774        6472 :         q = pushArgument(mb, q, getStrConstant(mb, i->t->base.name));
     775        6472 :         q = pushArgument(mb, q, getStrConstant(mb, i->base.name));
     776        6472 :         q = pushArgument(mb, q, getIntConstant(mb, access));
     777             : 
     778        6472 :         if (access == RD_UPD_ID) {
     779        2871 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     780             :         }
     781        6472 :         if (partition) {
     782        3529 :                 sql_trans *tr = be->mvc->session->tr;
     783        3529 :                 sqlstore *store = tr->store;
     784             : 
     785        3529 :                 if (i && isTable(i->t)) {
     786        3529 :                         BUN rows = (BUN) store->storage_api.count_idx(tr, i, QUICK);
     787        3529 :                         setRowCnt(mb,getArg(q,0),rows);
     788             :                 }
     789             :         }
     790             : 
     791        6472 :         bool enabled = be->mvc->sa->eb.enabled;
     792        6472 :         be->mvc->sa->eb.enabled = false;
     793        6472 :         stmt *s = stmt_create(be->mvc->sa, st_idxbat);
     794        6472 :         be->mvc->sa->eb.enabled = enabled;
     795        6472 :         if (s == NULL) {
     796           0 :                 freeInstruction(q);
     797           0 :                 goto bailout;
     798             :         }
     799             : 
     800        6472 :         s->partition = partition;
     801        6472 :         s->op4.idxval = i;
     802        6472 :         s->nrcols = 1;
     803        6472 :         s->flag = access;
     804        6472 :         s->nr = getDestVar(q);
     805        6472 :         s->q = q;
     806        6472 :         s->tname = tname;
     807        6472 :         s->cname = i->base.name;
     808        6472 :         pushInstruction(mb, q);
     809        6472 :         return s;
     810             : 
     811           0 :   bailout:
     812           0 :         if (be->mvc->sa->eb.enabled)
     813           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     814             :         return NULL;
     815             : }
     816             : 
     817             : stmt *
     818      706398 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
     819             : {
     820      706398 :         MalBlkPtr mb = be->mb;
     821      706398 :         InstrPtr q = NULL;
     822             : 
     823      706398 :         if (b == NULL || b->nr < 0)
     824           0 :                 goto bailout;
     825             : 
     826      706398 :         if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
     827          23 :                 int *l = ATOMIC_PTR_GET(&c->t->data);
     828             : 
     829          23 :                 if (c->colnr == 0) { /* append to tid column */
     830          18 :                         q = newStmt(mb, sqlRef, growRef);
     831          18 :                         if (q == NULL)
     832           0 :                                 goto bailout;
     833          18 :                         q = pushArgument(mb, q, l[0]);
     834          18 :                         q = pushArgument(mb, q, b->nr);
     835          18 :                         pushInstruction(mb, q);
     836             :                 }
     837          23 :                 q = newStmt(mb, batRef, appendRef);
     838          23 :                 if (q == NULL)
     839           0 :                         goto bailout;
     840          23 :                 q = pushArgument(mb, q, l[c->colnr+1]);
     841          23 :                 q = pushArgument(mb, q, b->nr);
     842          23 :                 q = pushBit(mb, q, TRUE);
     843          23 :                 getArg(q,0) = l[c->colnr+1];
     844      706375 :         } else if (!fake) {     /* fake append */
     845      706375 :                 if (offset == NULL || offset->nr < 0)
     846           0 :                         goto bailout;
     847      706375 :                 q = newStmt(mb, sqlRef, appendRef);
     848      706921 :                 if (q == NULL)
     849           0 :                         goto bailout;
     850      706921 :                 q = pushArgument(mb, q, be->mvc_var);
     851      706918 :                 int tmpvar = newTmpVariable(mb, TYPE_int);
     852      706911 :                 getArg(q, 0) = tmpvar;
     853      706911 :                 if (mvc_var_update != NULL)
     854      706911 :                         *mvc_var_update = tmpvar;
     855      706911 :                 q = pushSchema(mb, q, c->t);
     856      706903 :                 q = pushStr(mb, q, c->t->base.name);
     857      706923 :                 if (c->column_type != column_plain)
     858         185 :                         q = pushInt(mb, q, c->base.id);
     859             :                 else
     860      706738 :                         q = pushStr(mb, q, c->base.name);
     861      706783 :                 q = pushArgument(mb, q, offset->nr);
     862             :                 /* also the offsets */
     863      706811 :                 assert(offset->q->retc == 2);
     864      706811 :                 q = pushArgument(mb, q, getArg(offset->q, 1));
     865      706821 :                 q = pushArgument(mb, q, b->nr);
     866      706814 :                 if (mvc_var_update != NULL)
     867      706814 :                         *mvc_var_update = getDestVar(q);
     868             :         } else {
     869             :                 return b;
     870             :         }
     871      706837 :         bool enabled = be->mvc->sa->eb.enabled;
     872      706837 :         be->mvc->sa->eb.enabled = false;
     873      706837 :         stmt *s = stmt_create(be->mvc->sa, st_append_col);
     874      706650 :         be->mvc->sa->eb.enabled = enabled;
     875             : 
     876      706650 :         if (s == NULL) {
     877           0 :                 freeInstruction(q);
     878           0 :                 goto bailout;
     879             :         }
     880      706650 :         s->op1 = b;
     881      706650 :         s->op2 = offset;
     882      706650 :         s->op4.cval = c;
     883      706650 :         s->q = q;
     884      706650 :         s->nr = getDestVar(q);
     885      706650 :         pushInstruction(mb, q);
     886      706650 :         return s;
     887             : 
     888           0 :   bailout:
     889           0 :         if (be->mvc->sa->eb.enabled)
     890           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     891             :         return NULL;
     892             : }
     893             : 
     894             : stmt *
     895        2225 : stmt_append_idx(backend *be, sql_idx *i, stmt *offset, stmt *b)
     896             : {
     897        2225 :         MalBlkPtr mb = be->mb;
     898        2225 :         InstrPtr q = NULL;
     899             : 
     900        2225 :         if (offset == NULL || b == NULL || offset->nr < 0 || b->nr < 0)
     901           0 :                 goto bailout;
     902             : 
     903        2225 :         q = newStmt(mb, sqlRef, appendRef);
     904        2225 :         if (q == NULL)
     905           0 :                 goto bailout;
     906        2225 :         q = pushArgument(mb, q, be->mvc_var);
     907        2225 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     908        2225 :         q = pushSchema(mb, q, i->t);
     909        2225 :         q = pushStr(mb, q, i->t->base.name);
     910        2225 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
     911        2225 :         q = pushArgument(mb, q, offset->nr);
     912             :         /* also the offsets */
     913        2225 :         assert(offset->q->retc == 2);
     914        2225 :         q = pushArgument(mb, q, getArg(offset->q, 1));
     915        2225 :         q = pushArgument(mb, q, b->nr);
     916        2225 :         be->mvc_var = getDestVar(q);
     917             : 
     918        2225 :         bool enabled = be->mvc->sa->eb.enabled;
     919        2225 :         be->mvc->sa->eb.enabled = false;
     920        2225 :         stmt *s = stmt_create(be->mvc->sa, st_append_idx);
     921        2225 :         be->mvc->sa->eb.enabled = enabled;
     922        2225 :         if (s == NULL) {
     923           0 :                 freeInstruction(q);
     924           0 :                 goto bailout;
     925             :         }
     926             : 
     927        2225 :         s->op1 = b;
     928        2225 :         s->op2 = offset;
     929        2225 :         s->op4.idxval = i;
     930        2225 :         s->q = q;
     931        2225 :         s->nr = getDestVar(q);
     932        2225 :         pushInstruction(mb, q);
     933        2225 :         return s;
     934             : 
     935           0 :   bailout:
     936           0 :         if (be->mvc->sa->eb.enabled)
     937           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     938             :         return NULL;
     939             : }
     940             : 
     941             : stmt *
     942        3259 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
     943             : {
     944        3259 :         MalBlkPtr mb = be->mb;
     945        3259 :         InstrPtr q = NULL;
     946             : 
     947        3259 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     948           0 :                 goto bailout;
     949             : 
     950        3260 :         if (!c->t->s && ATOMIC_PTR_GET(&c->t->data)) { /* declared table */
     951           1 :                 int *l = ATOMIC_PTR_GET(&c->t->data);
     952             : 
     953           1 :                 q = newStmt(mb, batRef, replaceRef);
     954           1 :                 if (q == NULL)
     955           0 :                         goto bailout;
     956           1 :                 q = pushArgument(mb, q, l[c->colnr+1]);
     957           1 :                 q = pushArgument(mb, q, tids->nr);
     958           1 :                 q = pushArgument(mb, q, upd->nr);
     959             :         } else {
     960        3258 :                 q = newStmt(mb, sqlRef, updateRef);
     961        3258 :                 if (q == NULL)
     962           0 :                         goto bailout;
     963        3258 :                 q = pushArgument(mb, q, be->mvc_var);
     964        3258 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     965        3258 :                 q = pushSchema(mb, q, c->t);
     966        3258 :                 q = pushStr(mb, q, c->t->base.name);
     967        3258 :                 q = pushStr(mb, q, c->base.name);
     968        3258 :                 q = pushArgument(mb, q, tids->nr);
     969        3258 :                 q = pushArgument(mb, q, upd->nr);
     970        3258 :                 be->mvc_var = getDestVar(q);
     971             :         }
     972        3259 :         bool enabled = be->mvc->sa->eb.enabled;
     973        3259 :         be->mvc->sa->eb.enabled = false;
     974        3259 :         stmt *s = stmt_create(be->mvc->sa, st_update_col);
     975        3259 :         be->mvc->sa->eb.enabled = enabled;
     976             : 
     977        3259 :         if (s == NULL) {
     978           0 :                 freeInstruction(q);
     979           0 :                 goto bailout;
     980             :         }
     981        3259 :         s->op1 = tids;
     982        3259 :         s->op2 = upd;
     983        3259 :         s->op4.cval = c;
     984        3259 :         s->q = q;
     985        3259 :         s->nr = getDestVar(q);
     986        3259 :         pushInstruction(mb, q);
     987        3259 :         return s;
     988             : 
     989           0 :   bailout:
     990           0 :         if (be->mvc->sa->eb.enabled)
     991           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     992             :         return NULL;
     993             : }
     994             : 
     995             : 
     996             : stmt *
     997         823 : stmt_update_idx(backend *be, sql_idx *i, stmt *tids, stmt *upd)
     998             : {
     999         823 :         MalBlkPtr mb = be->mb;
    1000         823 :         InstrPtr q = NULL;
    1001             : 
    1002         823 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
    1003           0 :                 goto bailout;
    1004             : 
    1005         823 :         q = newStmt(mb, sqlRef, updateRef);
    1006         823 :         if (q == NULL)
    1007           0 :                 goto bailout;
    1008         823 :         q = pushArgument(mb, q, be->mvc_var);
    1009         823 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    1010         823 :         q = pushSchema(mb, q, i->t);
    1011         823 :         q = pushStr(mb, q, i->t->base.name);
    1012         823 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
    1013         823 :         q = pushArgument(mb, q, tids->nr);
    1014         823 :         q = pushArgument(mb, q, upd->nr);
    1015         823 :         be->mvc_var = getDestVar(q);
    1016         823 :         bool enabled = be->mvc->sa->eb.enabled;
    1017         823 :         be->mvc->sa->eb.enabled = false;
    1018         823 :         stmt *s = stmt_create(be->mvc->sa, st_update_idx);
    1019         823 :         be->mvc->sa->eb.enabled = enabled;
    1020         823 :         if (s == NULL) {
    1021           0 :                 freeInstruction(q);
    1022           0 :                 goto bailout;
    1023             :         }
    1024             : 
    1025         823 :         s->op1 = tids;
    1026         823 :         s->op2 = upd;
    1027         823 :         s->op4.idxval = i;
    1028         823 :         s->q = q;
    1029         823 :         s->nr = getDestVar(q);
    1030         823 :         pushInstruction(mb, q);
    1031         823 :         return s;
    1032             : 
    1033           0 :   bailout:
    1034           0 :         if (be->mvc->sa->eb.enabled)
    1035           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1036             :         return NULL;
    1037             : }
    1038             : 
    1039             : stmt *
    1040         383 : stmt_delete(backend *be, sql_table *t, stmt *tids)
    1041             : {
    1042         383 :         MalBlkPtr mb = be->mb;
    1043         383 :         InstrPtr q = NULL;
    1044             : 
    1045         383 :         if (tids == NULL || tids->nr < 0)
    1046           0 :                 goto bailout;
    1047             : 
    1048         384 :         if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
    1049           1 :                 int *l = ATOMIC_PTR_GET(&t->data);
    1050             : 
    1051           1 :                 q = newStmt(mb, batRef, deleteRef);
    1052           1 :                 if (q == NULL)
    1053           0 :                         goto bailout;
    1054           1 :                 q = pushArgument(mb, q, l[0]);
    1055           1 :                 q = pushArgument(mb, q, tids->nr);
    1056             :         } else {
    1057         382 :                 q = newStmt(mb, sqlRef, deleteRef);
    1058         382 :                 if (q == NULL)
    1059           0 :                         goto bailout;
    1060         382 :                 q = pushArgument(mb, q, be->mvc_var);
    1061         382 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    1062         382 :                 q = pushSchema(mb, q, t);
    1063         382 :                 q = pushStr(mb, q, t->base.name);
    1064         382 :                 q = pushArgument(mb, q, tids->nr);
    1065         382 :                 be->mvc_var = getDestVar(q);
    1066             :         }
    1067         383 :         bool enabled = be->mvc->sa->eb.enabled;
    1068         383 :         be->mvc->sa->eb.enabled = false;
    1069         383 :         stmt *s = stmt_create(be->mvc->sa, st_delete);
    1070         383 :         be->mvc->sa->eb.enabled = enabled;
    1071         383 :         if (s == NULL) {
    1072           0 :                 freeInstruction(q);
    1073           0 :                 goto bailout;
    1074             :         }
    1075             : 
    1076         383 :         s->op1 = tids;
    1077         383 :         s->op4.tval = t;
    1078         383 :         s->q = q;
    1079         383 :         s->nr = getDestVar(q);
    1080         383 :         pushInstruction(mb, q);
    1081         383 :         return s;
    1082             : 
    1083           0 :   bailout:
    1084           0 :         if (be->mvc->sa->eb.enabled)
    1085           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1086             :         return NULL;
    1087             : }
    1088             : 
    1089             : stmt *
    1090      127617 : stmt_const(backend *be, stmt *s, stmt *val)
    1091             : {
    1092      127617 :         InstrPtr q = NULL;
    1093      127617 :         MalBlkPtr mb = be->mb;
    1094             : 
    1095      127617 :         if (s == NULL)
    1096           0 :                 goto bailout;
    1097      127617 :         if (val)
    1098      127617 :                 q = dump_2(mb, algebraRef, projectRef, s, val);
    1099             :         else
    1100           0 :                 q = dump_1(mb, algebraRef, projectRef, s);
    1101      127617 :         if (q) {
    1102      127617 :                 stmt *ns = stmt_create(be->mvc->sa, st_const);
    1103      127617 :                 if (ns == NULL) {
    1104           0 :                         goto bailout;
    1105             :                 }
    1106             : 
    1107      127617 :                 ns->op1 = s;
    1108      127617 :                 ns->op2 = val;
    1109      127617 :                 ns->nrcols = s->nrcols;
    1110      127617 :                 ns->key = s->key;
    1111      127617 :                 ns->aggr = s->aggr;
    1112      127617 :                 ns->q = q;
    1113      127617 :                 ns->nr = getDestVar(q);
    1114      127617 :                 ns->tname = val->tname;
    1115      127617 :                 ns->cname = val->cname;
    1116      127617 :                 return ns;
    1117             :         }
    1118           0 :   bailout:
    1119           0 :         if (be->mvc->sa->eb.enabled)
    1120           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1121             :         return NULL;
    1122             : }
    1123             : 
    1124             : stmt *
    1125        2400 : stmt_gen_group(backend *be, stmt *gids, stmt *cnts)
    1126             : {
    1127        2400 :         MalBlkPtr mb = be->mb;
    1128             : 
    1129        2400 :         if (gids == NULL || cnts == NULL)
    1130           0 :                 goto bailout;
    1131             : 
    1132        2400 :         InstrPtr q = dump_2(mb, algebraRef, groupbyRef, gids, cnts);
    1133             : 
    1134        2400 :         if (q) {
    1135        2400 :                 stmt *ns = stmt_create(be->mvc->sa, st_gen_group);
    1136        2400 :                 if (ns == NULL) {
    1137           0 :                         goto bailout;
    1138             :                 }
    1139             : 
    1140        2400 :                 ns->op1 = gids;
    1141        2400 :                 ns->op2 = cnts;
    1142             : 
    1143        2400 :                 ns->nrcols = gids->nrcols;
    1144        2400 :                 ns->key = 0;
    1145        2400 :                 ns->aggr = 0;
    1146        2400 :                 ns->q = q;
    1147        2400 :                 ns->nr = getDestVar(q);
    1148        2400 :                 return ns;
    1149             :         }
    1150           0 :   bailout:
    1151           0 :         if (be->mvc->sa->eb.enabled)
    1152           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1153             :         return NULL;
    1154             : }
    1155             : 
    1156             : stmt *
    1157       51665 : stmt_mirror(backend *be, stmt *s)
    1158             : {
    1159       51665 :         MalBlkPtr mb = be->mb;
    1160             : 
    1161       51665 :         if (s == NULL)
    1162           0 :                 goto bailout;
    1163             : 
    1164       51665 :         InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
    1165             : 
    1166       51665 :         if (q) {
    1167       51665 :                 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
    1168       51665 :                 if (ns == NULL) {
    1169           0 :                         goto bailout;
    1170             :                 }
    1171             : 
    1172       51665 :                 ns->op1 = s;
    1173       51665 :                 ns->nrcols = 2;
    1174       51665 :                 ns->key = s->key;
    1175       51665 :                 ns->aggr = s->aggr;
    1176       51665 :                 ns->q = q;
    1177       51665 :                 ns->nr = getDestVar(q);
    1178       51665 :                 return ns;
    1179             :         }
    1180           0 :   bailout:
    1181           0 :         if (be->mvc->sa->eb.enabled)
    1182           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1183             :         return NULL;
    1184             : }
    1185             : 
    1186             : #define MARKJOIN 100
    1187             : stmt *
    1188      330164 : stmt_result(backend *be, stmt *s, int nr)
    1189             : {
    1190      330164 :         stmt *ns;
    1191             : 
    1192      330164 :         if (s == NULL)
    1193             :                 return NULL;
    1194             : 
    1195      330164 :         if (s->type == st_join && s->flag == cmp_joined) {
    1196        5562 :                 if (nr)
    1197        2324 :                         return s->op2;
    1198        3238 :                 return s->op1;
    1199             :         }
    1200             : 
    1201      324602 :         if (s->op1->nr < 0)
    1202             :                 return NULL;
    1203             : 
    1204      324602 :         ns = stmt_create(be->mvc->sa, st_result);
    1205      324602 :         if(!ns) {
    1206             :                 return NULL;
    1207             :         }
    1208      324602 :         if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
    1209           0 :                 assert(0);
    1210      324602 :         } else if (nr) {
    1211      186292 :                 int v = getArg(s->q, nr);
    1212             : 
    1213      186292 :                 assert(s->q->retc > nr);
    1214      186292 :                 ns->nr = v;
    1215             :         } else {
    1216      138310 :                 ns->nr = s->nr;
    1217             :         }
    1218      324602 :         ns->op1 = s;
    1219      324602 :         if (!nr && (s->type == st_order || s->type == st_reorder))
    1220       26283 :                 ns->subtype = *tail_type(s->op1);
    1221      186292 :         else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
    1222        2986 :                 ns->subtype = *sql_bind_localtype("bit");
    1223             :         else
    1224      295333 :                 ns->subtype = *sql_bind_localtype("oid");
    1225      324602 :         ns->flag = nr;
    1226      324602 :         ns->nrcols = s->nrcols;
    1227      324602 :         ns->key = s->key;
    1228      324602 :         ns->aggr = s->aggr;
    1229      324602 :         return ns;
    1230             : }
    1231             : 
    1232             : 
    1233             : /* limit maybe atom nil */
    1234             : stmt *
    1235       17659 : stmt_limit(backend *be, stmt *col, stmt *piv, stmt *gid, stmt *offset, stmt *limit, int distinct, int dir, int nullslast, int nr_obe, int order)
    1236             : {
    1237       17659 :         MalBlkPtr mb = be->mb;
    1238       17659 :         InstrPtr q = NULL;
    1239       17659 :         int l, g, c;
    1240             : 
    1241       17659 :         if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
    1242           0 :                 goto bailout;
    1243       17659 :         if (piv && (piv->nr < 0 || (gid && gid->nr < 0)))
    1244           0 :                 goto bailout;
    1245             : 
    1246       17659 :         c = (col) ? col->nr : 0;
    1247       17659 :         g = (gid) ? gid->nr : 0;
    1248             : 
    1249             :         /* first insert single value into a bat */
    1250       17659 :         if (col->nrcols == 0) {
    1251           0 :                 int k, tt = tail_type(col)->type->localtype;
    1252             : 
    1253           0 :                 q = newStmt(mb, batRef, newRef);
    1254           0 :                 if (q == NULL)
    1255           0 :                         goto bailout;
    1256           0 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
    1257           0 :                 q = pushType(mb, q, tt);
    1258           0 :                 k = getDestVar(q);
    1259           0 :                 pushInstruction(mb, q);
    1260             : 
    1261           0 :                 q = newStmt(mb, batRef, appendRef);
    1262           0 :                 if (q == NULL)
    1263           0 :                         goto bailout;
    1264           0 :                 q = pushArgument(mb, q, k);
    1265           0 :                 q = pushArgument(mb, q, c);
    1266           0 :                 pushInstruction(mb, q);
    1267           0 :                 c = k;
    1268             :         }
    1269       17659 :         if (order) {
    1270         592 :                 if (piv && piv->q) {
    1271           0 :                         q = piv->q;
    1272           0 :                         q = pushArgument(mb, q, c);
    1273           0 :                         q = pushBit(mb, q, dir);
    1274           0 :                         q = pushBit(mb, q, nullslast);
    1275           0 :                         return piv;
    1276             :                 } else {
    1277         592 :                         int topn = 0;
    1278             : 
    1279         592 :                         q = newStmt(mb, calcRef, plusRef);
    1280         592 :                         if (q == NULL)
    1281           0 :                                 goto bailout;
    1282         592 :                         q = pushArgument(mb, q, offset->nr);
    1283         592 :                         q = pushArgument(mb, q, limit->nr);
    1284         592 :                         topn = getDestVar(q);
    1285         592 :                         pushInstruction(mb, q);
    1286             : 
    1287        1178 :                         if (!gid || (piv && !piv->q)) { /* use algebra.firstn (possibly concurrently) */
    1288         586 :                                 int p = (piv) ? piv->nr : 0;
    1289         586 :                                 q = newStmtArgs(mb, algebraRef, firstnRef, 9);
    1290         586 :                                 if (q == NULL)
    1291           0 :                                         goto bailout;
    1292         586 :                                 if (nr_obe > 1) /* we need the groups for the next firstn */
    1293         310 :                                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1294         586 :                                 q = pushArgument(mb, q, c);
    1295         586 :                                 if (p)
    1296         310 :                                         q = pushArgument(mb, q, p);
    1297             :                                 else
    1298         276 :                                         q = pushNilBat(mb, q);
    1299         586 :                                 if (g)
    1300         310 :                                         q = pushArgument(mb, q, g);
    1301             :                                 else
    1302         276 :                                         q = pushNilBat(mb, q);
    1303         586 :                                 q = pushArgument(mb, q, topn);
    1304         586 :                                 q = pushBit(mb, q, dir);
    1305         586 :                                 q = pushBit(mb, q, nullslast);
    1306         586 :                                 q = pushBit(mb, q, distinct != 0);
    1307             : 
    1308         586 :                                 l = getArg(q, 0);
    1309         586 :                                 l = getDestVar(q);
    1310         586 :                                 pushInstruction(mb, q);
    1311             :                         } else {
    1312           6 :                                 q = newStmtArgs(mb, algebraRef, groupedfirstnRef, (nr_obe*3)+6);
    1313           6 :                                 if (q == NULL)
    1314           0 :                                         goto bailout;
    1315           6 :                                 q = pushArgument(mb, q, topn);
    1316           6 :                                 q = pushNilBat(mb, q);  /* candidates */
    1317           6 :                                 if (g)                                  /* grouped case */
    1318           6 :                                         q = pushArgument(mb, q, g);
    1319             :                                 else
    1320           0 :                                         q = pushNilBat(mb, q);
    1321             : 
    1322           6 :                                 q = pushArgument(mb, q, c);
    1323           6 :                                 q = pushBit(mb, q, dir);
    1324           6 :                                 q = pushBit(mb, q, nullslast);
    1325             : 
    1326           6 :                                 l = getArg(q, 0);
    1327           6 :                                 l = getDestVar(q);
    1328           6 :                                 pushInstruction(mb, q);
    1329             :                         }
    1330             :                 }
    1331             :         } else {
    1332       17067 :                 int len;
    1333             : 
    1334       17067 :                 q = newStmt(mb, calcRef, plusRef);
    1335       17088 :                 if (q == NULL)
    1336           0 :                         goto bailout;
    1337       17088 :                 q = pushArgument(mb, q, offset->nr);
    1338       17088 :                 q = pushArgument(mb, q, limit->nr);
    1339       17088 :                 len = getDestVar(q);
    1340       17088 :                 pushInstruction(mb, q);
    1341             : 
    1342             :                 /* since both arguments of algebra.subslice are
    1343             :                    inclusive correct the LIMIT value by
    1344             :                    subtracting 1 */
    1345       17087 :                 q = newStmt(mb, calcRef, minusRef);
    1346       17089 :                 if (q == NULL)
    1347           0 :                         goto bailout;
    1348       17089 :                 q = pushArgument(mb, q, len);
    1349       17089 :                 q = pushInt(mb, q, 1);
    1350       17088 :                 len = getDestVar(q);
    1351       17088 :                 pushInstruction(mb, q);
    1352             : 
    1353       17088 :                 q = newStmt(mb, algebraRef, subsliceRef);
    1354       17089 :                 if (q == NULL)
    1355           0 :                         goto bailout;
    1356       17089 :                 q = pushArgument(mb, q, c);
    1357       17089 :                 q = pushArgument(mb, q, offset->nr);
    1358       17089 :                 q = pushArgument(mb, q, len);
    1359       17087 :                 l = getDestVar(q);
    1360       17087 :                 pushInstruction(mb, q);
    1361             :         }
    1362             :         /* retrieve the single values again */
    1363       17679 :         if (col->nrcols == 0) {
    1364           0 :                 q = newStmt(mb, algebraRef, findRef);
    1365           0 :                 if (q == NULL)
    1366           0 :                         goto bailout;
    1367           0 :                 q = pushArgument(mb, q, l);
    1368           0 :                 q = pushOid(mb, q, 0);
    1369           0 :                 l = getDestVar(q);
    1370           0 :                 pushInstruction(mb, q);
    1371             :         }
    1372             : 
    1373       35048 :         stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
    1374       17679 :         if (ns == NULL) {
    1375           0 :                 goto bailout;
    1376             :         }
    1377             : 
    1378       17679 :         ns->op1 = col;
    1379       17679 :         ns->op2 = offset;
    1380       17679 :         ns->op3 = limit;
    1381       17679 :         ns->nrcols = col->nrcols;
    1382       17679 :         ns->key = col->key;
    1383       17679 :         ns->aggr = col->aggr;
    1384       17679 :         ns->q = q;
    1385       17679 :         ns->nr = l;
    1386       17679 :         return ns;
    1387             : 
    1388           0 :   bailout:
    1389           0 :         if (be->mvc->sa->eb.enabled)
    1390           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1391             :         return NULL;
    1392             : }
    1393             : 
    1394             : stmt *
    1395          21 : stmt_sample(backend *be, stmt *s, stmt *sample, stmt *seed)
    1396             : {
    1397          21 :         MalBlkPtr mb = be->mb;
    1398          21 :         InstrPtr q = NULL;
    1399             : 
    1400          21 :         if (s == NULL || sample == NULL || s->nr < 0 || sample->nr < 0)
    1401           0 :                 goto bailout;
    1402          21 :         q = newStmt(mb, sampleRef, subuniformRef);
    1403          21 :         if (q == NULL)
    1404           0 :                 goto bailout;
    1405          21 :         q = pushArgument(mb, q, s->nr);
    1406          21 :         q = pushArgument(mb, q, sample->nr);
    1407             : 
    1408          21 :         if (seed) {
    1409          12 :                 if (seed->nr < 0)
    1410           0 :                         goto bailout;
    1411             : 
    1412          12 :                 q = pushArgument(mb, q, seed->nr);
    1413             :         }
    1414             : 
    1415          21 :         bool enabled = be->mvc->sa->eb.enabled;
    1416          21 :         be->mvc->sa->eb.enabled = false;
    1417          21 :         stmt *ns = stmt_create(be->mvc->sa, st_sample);
    1418          21 :         be->mvc->sa->eb.enabled = enabled;
    1419          21 :         if (ns == NULL) {
    1420           0 :                 freeInstruction(q);
    1421           0 :                 goto bailout;
    1422             :         }
    1423             : 
    1424          21 :         ns->op1 = s;
    1425          21 :         ns->op2 = sample;
    1426             : 
    1427          21 :         if (seed) {
    1428          12 :                 ns->op3 = seed;
    1429             :         }
    1430             : 
    1431          21 :         ns->nrcols = s->nrcols;
    1432          21 :         ns->key = s->key;
    1433          21 :         ns->aggr = s->aggr;
    1434          21 :         ns->flag = 0;
    1435          21 :         ns->q = q;
    1436          21 :         ns->nr = getDestVar(q);
    1437          21 :         pushInstruction(mb, q);
    1438          21 :         return ns;
    1439             : 
    1440           0 :   bailout:
    1441           0 :         if (be->mvc->sa->eb.enabled)
    1442           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1443             :         return NULL;
    1444             : }
    1445             : 
    1446             : 
    1447             : stmt *
    1448       12984 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
    1449             : {
    1450       12984 :         MalBlkPtr mb = be->mb;
    1451       12984 :         InstrPtr q = NULL;
    1452             : 
    1453       12984 :         if (s == NULL || s->nr < 0)
    1454           0 :                 goto bailout;
    1455       12984 :         q = newStmt(mb, algebraRef, sortRef);
    1456       12984 :         if (q == NULL)
    1457           0 :                 goto bailout;
    1458             :         /* both ordered result and oid's order en subgroups */
    1459       12984 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1460       12984 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1461       12984 :         q = pushArgument(mb, q, s->nr);
    1462       12984 :         q = pushBit(mb, q, !direction);
    1463       12984 :         q = pushBit(mb, q, nullslast);
    1464       12984 :         q = pushBit(mb, q, FALSE);
    1465             : 
    1466       12984 :         bool enabled = be->mvc->sa->eb.enabled;
    1467       12984 :         be->mvc->sa->eb.enabled = false;
    1468       12984 :         stmt *ns = stmt_create(be->mvc->sa, st_order);
    1469       12984 :         be->mvc->sa->eb.enabled = enabled;
    1470       12984 :         if (ns == NULL) {
    1471           0 :                 freeInstruction(q);
    1472           0 :                 goto bailout;
    1473             :         }
    1474             : 
    1475       12984 :         ns->op1 = s;
    1476       12984 :         ns->flag = direction;
    1477       12984 :         ns->nrcols = s->nrcols;
    1478       12984 :         ns->key = s->key;
    1479       12984 :         ns->aggr = s->aggr;
    1480       12984 :         ns->q = q;
    1481       12984 :         ns->nr = getDestVar(q);
    1482       12984 :         pushInstruction(mb, q);
    1483       12984 :         return ns;
    1484             : 
    1485           0 :   bailout:
    1486           0 :         if (be->mvc->sa->eb.enabled)
    1487           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1488             :         return NULL;
    1489             : }
    1490             : 
    1491             : stmt *
    1492       13824 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
    1493             : {
    1494       13824 :         MalBlkPtr mb = be->mb;
    1495       13824 :         InstrPtr q = NULL;
    1496             : 
    1497       13824 :         if (s == NULL || orderby_ids == NULL || orderby_grp == NULL || s->nr < 0 || orderby_ids->nr < 0 || orderby_grp->nr < 0)
    1498           0 :                 goto bailout;
    1499       13824 :         q = newStmtArgs(mb, algebraRef, sortRef, 9);
    1500       13824 :         if (q == NULL)
    1501           0 :                 goto bailout;
    1502             :         /* both ordered result and oid's order en subgroups */
    1503       13824 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1504       13824 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1505       13824 :         q = pushArgument(mb, q, s->nr);
    1506       13824 :         q = pushArgument(mb, q, orderby_ids->nr);
    1507       13824 :         q = pushArgument(mb, q, orderby_grp->nr);
    1508       13824 :         q = pushBit(mb, q, !direction);
    1509       13824 :         q = pushBit(mb, q, nullslast);
    1510       13824 :         q = pushBit(mb, q, FALSE);
    1511             : 
    1512       13824 :         bool enabled = be->mvc->sa->eb.enabled;
    1513       13824 :         be->mvc->sa->eb.enabled = false;
    1514       13824 :         stmt *ns = stmt_create(be->mvc->sa, st_reorder);
    1515       13824 :         be->mvc->sa->eb.enabled = enabled;
    1516       13824 :         if (ns == NULL) {
    1517           0 :                 freeInstruction(q);
    1518           0 :                 goto bailout;
    1519             :         }
    1520             : 
    1521       13824 :         ns->op1 = s;
    1522       13824 :         ns->op2 = orderby_ids;
    1523       13824 :         ns->op3 = orderby_grp;
    1524       13824 :         ns->flag = direction;
    1525       13824 :         ns->nrcols = s->nrcols;
    1526       13824 :         ns->key = s->key;
    1527       13824 :         ns->aggr = s->aggr;
    1528       13824 :         ns->nr = getDestVar(q);
    1529       13824 :         ns->q = q;
    1530       13824 :         pushInstruction(mb, q);
    1531       13824 :         return ns;
    1532             : 
    1533           0 :   bailout:
    1534           0 :         if (be->mvc->sa->eb.enabled)
    1535           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1536             :         return NULL;
    1537             : }
    1538             : 
    1539             : stmt *
    1540     3539400 : stmt_atom(backend *be, atom *a)
    1541             : {
    1542             :         /* TODO handle tuples of values for composite types */
    1543     3539400 :         MalBlkPtr mb = be->mb;
    1544             : 
    1545     3539400 :         if (a == NULL)
    1546           0 :                 goto bailout;
    1547             : 
    1548     3539400 :         InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->d.impl) : newAssignment(mb);
    1549             : 
    1550     3540159 :         if (q == NULL)
    1551           0 :                 goto bailout;
    1552     3540159 :         if (atom_null(a)) {
    1553      158106 :                 q = pushNil(mb, q, atom_type(a)->type->localtype);
    1554             :         } else {
    1555     3382053 :                 int k;
    1556     3382053 :                 if ((k = constantAtom(be, mb, a)) == -1) {
    1557           0 :                         freeInstruction(q);
    1558           0 :                         goto bailout;
    1559             :                 }
    1560     3381587 :                 q = pushArgument(mb, q, k);
    1561             :         }
    1562             :         /* digits of the result timestamp/daytime */
    1563     3539735 :         if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
    1564       47397 :                 q = pushInt(mb, q, atom_type(a)->digits);
    1565     3540103 :         bool enabled = be->mvc->sa->eb.enabled;
    1566     3540103 :         be->mvc->sa->eb.enabled = false;
    1567     3540103 :         stmt *s = stmt_create(be->mvc->sa, st_atom);
    1568     3539185 :         be->mvc->sa->eb.enabled = enabled;
    1569     3539185 :         if (s == NULL) {
    1570           0 :                 freeInstruction(q);
    1571           0 :                 goto bailout;
    1572             :         }
    1573             : 
    1574     3539185 :         s->op4.aval = a;
    1575     3539185 :         s->key = 1;          /* values are also unique */
    1576     3539185 :         s->q = q;
    1577     3539185 :         s->nr = getDestVar(q);
    1578     3539185 :         pushInstruction(mb, q);
    1579     3539185 :         return s;
    1580             : 
    1581           0 :   bailout:
    1582           0 :         if (be->mvc->sa->eb.enabled)
    1583           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1584             :         return NULL;
    1585             : }
    1586             : 
    1587             : stmt *
    1588        4117 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
    1589             : {
    1590        4117 :         MalBlkPtr mb = be->mb;
    1591        4117 :         InstrPtr q = NULL;
    1592        4117 :         const char *mod, *op;
    1593        4117 :         node *n;
    1594        4117 :         int k;
    1595             : 
    1596        4117 :         if (lops == NULL || rops == NULL)
    1597           0 :                 goto bailout;
    1598             : 
    1599        4117 :         if (backend_create_subfunc(be, f, NULL) < 0)
    1600           0 :                 goto bailout;
    1601        4117 :         op = backend_function_imp(be, f->func);
    1602        4117 :         mod = sql_func_mod(f->func);
    1603             : 
    1604        4117 :         if (rops->nrcols >= 1) {
    1605          55 :                 bit need_not = FALSE;
    1606             : 
    1607          55 :                 int narg = 3;
    1608         110 :                 for (n = lops->op4.lval->h; n; n = n->next)
    1609          55 :                         narg++;
    1610         174 :                 for (n = rops->op4.lval->h; n; n = n->next)
    1611         119 :                         narg++;
    1612          55 :                 q = newStmtArgs(mb, malRef, multiplexRef, narg);
    1613          55 :                 if (q == NULL)
    1614           0 :                         goto bailout;
    1615          55 :                 setVarType(mb, getArg(q, 0), newBatType(TYPE_bit));
    1616          55 :                 q = pushStr(mb, q, convertMultiplexMod(mod, op));
    1617          55 :                 q = pushStr(mb, q, convertMultiplexFcn(op));
    1618         110 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1619          55 :                         stmt *op = n->data;
    1620             : 
    1621          55 :                         q = pushArgument(mb, q, op->nr);
    1622             :                 }
    1623         174 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1624         119 :                         stmt *op = n->data;
    1625             : 
    1626         119 :                         q = pushArgument(mb, q, op->nr);
    1627             :                 }
    1628          55 :                 k = getDestVar(q);
    1629          55 :                 pushInstruction(mb, q);
    1630             : 
    1631          55 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1632          55 :                 if (q == NULL)
    1633           0 :                         goto bailout;
    1634          55 :                 q = pushArgument(mb, q, k);
    1635          55 :                 if (sub)
    1636          35 :                         q = pushArgument(mb, q, sub->nr);
    1637          55 :                 q = pushBit(mb, q, !need_not);
    1638          55 :                 q = pushBit(mb, q, !need_not);
    1639          55 :                 q = pushBit(mb, q, TRUE);
    1640          55 :                 q = pushBit(mb, q, TRUE);
    1641          55 :                 q = pushBit(mb, q, anti);
    1642             :         } else {
    1643        4062 :                 node *n;
    1644             : 
    1645        4062 :                 op = sa_strconcat(be->mvc->sa, op, selectRef);
    1646        4062 :                 q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
    1647        4062 :                 if (q == NULL)
    1648           0 :                         goto bailout;
    1649             :                 // push pointer to the SQL structure into the MAL call
    1650             :                 // allows getting argument names for example
    1651        4062 :                 if (LANG_EXT(f->func->lang))
    1652           0 :                         q = pushPtr(mb, q, f->func); // nothing to see here, please move along
    1653             :                 // f->query contains the R code to be run
    1654        4062 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
    1655           0 :                         q = pushStr(mb, q, f->func->query);
    1656             : 
    1657        8124 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1658        4062 :                         stmt *op = n->data;
    1659             : 
    1660        4062 :                         q = pushArgument(mb, q, op->nr);
    1661             :                 }
    1662             :                 /* candidate lists */
    1663        4062 :                 if (sub)
    1664        3994 :                         q = pushArgument(mb, q, sub->nr);
    1665             :                 else
    1666          68 :                         q = pushNilBat(mb, q);
    1667             : 
    1668       15995 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1669       11933 :                         stmt *op = n->data;
    1670             : 
    1671       11933 :                         q = pushArgument(mb, q, op->nr);
    1672             :                 }
    1673             : 
    1674        4062 :                 q = pushBit(mb, q, anti);
    1675             :         }
    1676             : 
    1677        4117 :         bool enabled = be->mvc->sa->eb.enabled;
    1678        4117 :         be->mvc->sa->eb.enabled = false;
    1679        4117 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1680        4117 :         be->mvc->sa->eb.enabled = enabled;
    1681        4117 :         if (s == NULL) {
    1682           0 :                 freeInstruction(q);
    1683           0 :                 goto bailout;
    1684             :         }
    1685             : 
    1686        4117 :         s->op1 = lops;
    1687        4117 :         s->op2 = rops;
    1688        4117 :         s->op3 = sub;
    1689        4117 :         s->key = lops->nrcols == 0 && rops->nrcols == 0;
    1690        4117 :         s->flag = cmp_filter;
    1691        4117 :         s->nrcols = lops->nrcols;
    1692        4117 :         s->nr = getDestVar(q);
    1693        4117 :         s->q = q;
    1694        4117 :         s->cand = sub;
    1695        4117 :         pushInstruction(mb, q);
    1696        4117 :         return s;
    1697             : 
    1698           0 :   bailout:
    1699           0 :         if (be->mvc->sa->eb.enabled)
    1700           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1701             :         return NULL;
    1702             : }
    1703             : 
    1704             : stmt *
    1705      204568 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
    1706             : {
    1707      204568 :         MalBlkPtr mb = be->mb;
    1708      204568 :         InstrPtr q = NULL;
    1709      204568 :         int l, r;
    1710      204568 :         stmt *sel = sub;
    1711             : 
    1712      204568 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
    1713           0 :                 goto bailout;
    1714      204568 :         l = op1->nr;
    1715      204568 :         r = op2->nr;
    1716             : 
    1717      204568 :         if (op2->nrcols >= 1 && op1->nrcols == 0) { /* swap */
    1718          79 :                 stmt *v = op1;
    1719          79 :                 op1 = op2;
    1720          79 :                 op2 = v;
    1721          79 :                 int n = l;
    1722          79 :                 l = r;
    1723          79 :                 r = n;
    1724          79 :                 cmptype = swap_compare(cmptype);
    1725             :         }
    1726      204568 :         if (op2->nrcols >= 1) {
    1727       17996 :                 bit need_not = FALSE;
    1728       17996 :                 const char *mod = calcRef;
    1729       17996 :                 const char *op = "=";
    1730       17996 :                 int k;
    1731             : 
    1732       17996 :                 switch (cmptype) {
    1733             :                 case cmp_equal:
    1734             :                         op = "=";
    1735             :                         break;
    1736             :                 case cmp_notequal:
    1737       17996 :                         op = "!=";
    1738             :                         break;
    1739         917 :                 case cmp_lt:
    1740         917 :                         op = "<";
    1741         917 :                         break;
    1742         775 :                 case cmp_lte:
    1743         775 :                         op = "<=";
    1744         775 :                         break;
    1745        4831 :                 case cmp_gt:
    1746        4831 :                         op = ">";
    1747        4831 :                         break;
    1748         800 :                 case cmp_gte:
    1749         800 :                         op = ">=";
    1750         800 :                         break;
    1751           0 :                 default:
    1752           0 :                         TRC_ERROR(SQL_EXECUTION, "Unknown operator\n");
    1753             :                 }
    1754             : 
    1755       28405 :                 if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
    1756           0 :                         goto bailout;
    1757       17996 :                 if (sub && (op1->cand || op2->cand)) {
    1758        1756 :                         if (op1->cand && !op2->cand) {
    1759          30 :                                 if (op1->nrcols > 0)
    1760          30 :                                         q = pushNilBat(mb, q);
    1761          30 :                                 q = pushArgument(mb, q, sub->nr);
    1762        1726 :                         } else if (!op1->cand && op2->cand) {
    1763        1692 :                                 q = pushArgument(mb, q, sub->nr);
    1764        1692 :                                 if (op2->nrcols > 0)
    1765        1692 :                                         q = pushNilBat(mb, q);
    1766             :                         }
    1767             :                         sub = NULL;
    1768             :                 }
    1769       17996 :                 if (is_semantics)
    1770        2998 :                         q = pushBit(mb, q, TRUE);
    1771       17996 :                 k = getDestVar(q);
    1772             : 
    1773       17996 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1774       17996 :                 if (q == NULL)
    1775           0 :                         goto bailout;
    1776       17996 :                 q = pushArgument(mb, q, k);
    1777       17996 :                 if (sub)
    1778        4362 :                         q = pushArgument(mb, q, sub->nr);
    1779       17996 :                 q = pushBit(mb, q, !need_not);
    1780       17996 :                 q = pushBit(mb, q, !need_not);
    1781       17996 :                 q = pushBit(mb, q, TRUE);
    1782       17996 :                 q = pushBit(mb, q, TRUE);
    1783       17996 :                 q = pushBit(mb, q, anti);
    1784       17996 :                 k = getDestVar(q);
    1785             :         } else {
    1786      186572 :                 assert (cmptype != cmp_filter);
    1787      186572 :                 q = newStmt(mb, algebraRef, thetaselectRef);
    1788      186586 :                 if (q == NULL)
    1789           0 :                         goto bailout;
    1790      186586 :                 q = pushArgument(mb, q, l);
    1791      186584 :                 if (sub && !op1->cand) {
    1792      112690 :                         q = pushArgument(mb, q, sub->nr);
    1793             :                 } else {
    1794        2631 :                         assert(!sub || op1->cand == sub);
    1795       73894 :                         q = pushNilBat(mb, q);
    1796       73894 :                         sub = NULL;
    1797             :                 }
    1798      186586 :                 q = pushArgument(mb, q, r);
    1799      186573 :                 switch (cmptype) {
    1800      168374 :                 case cmp_equal:
    1801      168374 :                         if (is_semantics)
    1802       35060 :                                 q = pushStr(mb, q, anti?"ne":"eq");
    1803             :                         else
    1804      296612 :                                 q = pushStr(mb, q, anti?"!=":"==");
    1805             :                         break;
    1806       15124 :                 case cmp_notequal:
    1807       15124 :                         if (is_semantics)
    1808         153 :                                 q = pushStr(mb, q, anti?"eq":"ne");
    1809             :                         else
    1810       30090 :                                 q = pushStr(mb, q, anti?"==":"!=");
    1811             :                         break;
    1812         436 :                 case cmp_lt:
    1813         436 :                         q = pushStr(mb, q, anti?">=":"<");
    1814         436 :                         break;
    1815          71 :                 case cmp_lte:
    1816          71 :                         q = pushStr(mb, q, anti?">":"<=");
    1817          71 :                         break;
    1818        2289 :                 case cmp_gt:
    1819        2289 :                         q = pushStr(mb, q, anti?"<=":">");
    1820        2289 :                         break;
    1821         279 :                 case cmp_gte:
    1822         279 :                         q = pushStr(mb, q, anti?"<":">=");
    1823         279 :                         break;
    1824           0 :                 default:
    1825           0 :                         TRC_ERROR(SQL_EXECUTION, "Impossible select compare\n");
    1826           0 :                         if (q)
    1827           0 :                                 freeInstruction(q);
    1828           0 :                         q = NULL;
    1829           0 :                         goto bailout;
    1830             :                 }
    1831             :         }
    1832             : 
    1833      204578 :         bool enabled = be->mvc->sa->eb.enabled;
    1834      204578 :         be->mvc->sa->eb.enabled = false;
    1835      204578 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1836      204574 :         be->mvc->sa->eb.enabled = enabled;
    1837      204574 :         if (s == NULL) {
    1838           0 :                 freeInstruction(q);
    1839           0 :                 goto bailout;
    1840             :         }
    1841             : 
    1842      204574 :         s->op1 = op1;
    1843      204574 :         s->op2 = op2;
    1844      204574 :         s->op3 = sub;
    1845      204574 :         s->flag = cmptype;
    1846      204574 :         s->key = op1->nrcols == 0 && op2->nrcols == 0;
    1847      204574 :         s->nrcols = op1->nrcols;
    1848      204574 :         s->nr = getDestVar(q);
    1849      204574 :         s->q = q;
    1850      204574 :         s->cand = sub;
    1851      204574 :         pushInstruction(mb, q);
    1852      204580 :         if (!sub && sel) /* project back the old ids */
    1853        4387 :                 return stmt_project(be, s, sel);
    1854             :         return s;
    1855             : 
    1856           0 :   bailout:
    1857           0 :         if (be->mvc->sa->eb.enabled)
    1858           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1859             :         return NULL;
    1860             : }
    1861             : 
    1862             : /*
    1863             : static int
    1864             : range_join_convertable(stmt *s, stmt **base, stmt **L, stmt **H)
    1865             : {
    1866             :         int ls = 0, hs = 0;
    1867             :         stmt *l = NULL, *h = NULL;
    1868             :         stmt *bl = s->op2, *bh = s->op3;
    1869             :         int tt = tail_type(s->op2)->type->localtype;
    1870             : 
    1871             : #ifdef HAVE_HGE
    1872             :         if (tt > TYPE_hge)
    1873             : #else
    1874             :         if (tt > TYPE_lng)
    1875             : #endif
    1876             :                 return 0;
    1877             :         if (s->op2->type == st_Nop && list_length(s->op2->op1->op4.lval) == 2) {
    1878             :                 bl = s->op2->op1->op4.lval->h->data;
    1879             :                 l = s->op2->op1->op4.lval->t->data;
    1880             :         }
    1881             :         if (s->op3->type == st_Nop && list_length(s->op3->op1->op4.lval) == 2) {
    1882             :                 bh = s->op3->op1->op4.lval->h->data;
    1883             :                 h = s->op3->op1->op4.lval->t->data;
    1884             :         }
    1885             : 
    1886             :         if (((ls = (l && strcmp(s->op2->op4.funcval->func->base.name, "sql_sub") == 0 && l->nrcols == 0)) || (hs = (h && strcmp(s->op3->op4.funcval->func->base.name, "sql_add") == 0 && h->nrcols == 0))) && (ls || hs) && bl == bh) {
    1887             :                 *base = bl;
    1888             :                 *L = l;
    1889             :                 *H = h;
    1890             :                 return 1;
    1891             :         }
    1892             :         return 0;
    1893             : }
    1894             : 
    1895             : static int
    1896             : argumentZero(MalBlkPtr mb, int tpe)
    1897             : {
    1898             :         ValRecord cst;
    1899             :         str msg;
    1900             : 
    1901             :         cst.vtype = TYPE_int;
    1902             :         cst.val.ival = 0;
    1903             :         msg = convertConstant(tpe, &cst);
    1904             :         if( msg)
    1905             :                 freeException(msg); // will not be called
    1906             :         return defConstant(mb, tpe, &cst);
    1907             : }
    1908             : */
    1909             : 
    1910             : static InstrPtr
    1911        5113 : select2_join2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt **Sub, int anti, int symmetric, int swapped, int type, int reduce)
    1912             : {
    1913        5113 :         MalBlkPtr mb = be->mb;
    1914        5113 :         InstrPtr p, q;
    1915        5113 :         int l;
    1916        5113 :         const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
    1917        5113 :         stmt *sub = (Sub)?*Sub:NULL;
    1918             : 
    1919        5113 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
    1920           0 :                 goto bailout;
    1921        5113 :         l = op1->nr;
    1922        8475 :         if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
    1923        3610 :                 int k;
    1924        3610 :                 int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
    1925             : 
    1926        3610 :                 if (op2->nr < 0 || op3->nr < 0)
    1927           0 :                         goto bailout;
    1928             : 
    1929        3610 :                 if (nrcols)
    1930        3567 :                         p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
    1931             :                 else
    1932          43 :                         p = newStmtArgs(mb, calcRef, betweenRef, 9);
    1933        3610 :                 if (p == NULL)
    1934           0 :                         goto bailout;
    1935        3610 :                 p = pushArgument(mb, p, l);
    1936        3610 :                 p = pushArgument(mb, p, op2->nr);
    1937        3610 :                 p = pushArgument(mb, p, op3->nr);
    1938             : 
    1939             :                 /* cands */
    1940        3610 :                 if ((sub && !reduce) || op1->cand || op2->cand || op3->cand) { /* some already handled the previous selection */
    1941        1576 :                         if (op1->cand && op1->nrcols)
    1942        1290 :                                 p = pushNilBat(mb, p);
    1943         286 :                         else if (op1->nrcols)
    1944         286 :                                 p = pushArgument(mb, p, sub->nr);
    1945        1576 :                         if (op2->nrcols) {
    1946        1466 :                                 if (op2->cand)
    1947        1220 :                                         p = pushNilBat(mb, p);
    1948         246 :                                 else if (op2->nrcols)
    1949         246 :                                         p = pushArgument(mb, p, sub->nr);
    1950             :                         }
    1951        1576 :                         if (op3->nrcols) {
    1952        1461 :                                 if (op3->cand)
    1953        1336 :                                         p = pushNilBat(mb, p);
    1954         125 :                                 else if (op3->nrcols)
    1955         125 :                                         p = pushArgument(mb, p, sub->nr);
    1956             :                         }
    1957             :                         sub = NULL;
    1958             :                 }
    1959             : 
    1960        3610 :                 p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
    1961        3610 :                 p = pushBit(mb, p, (cmp & 1) != 0);     /* lo inclusive */
    1962        3610 :                 p = pushBit(mb, p, (cmp & 2) != 0);     /* hi inclusive */
    1963        3610 :                 p = pushBit(mb, p, FALSE);                  /* nils_false */
    1964        3610 :                 p = pushBit(mb, p, (anti)?TRUE:FALSE);      /* anti */
    1965        3610 :                 pushInstruction(mb, p);
    1966        3610 :                 if (!reduce)
    1967             :                         return p;
    1968        3362 :                 k = getDestVar(p);
    1969             : 
    1970        3362 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1971        3362 :                 if (q == NULL)
    1972           0 :                         goto bailout;
    1973        3362 :                 q = pushArgument(mb, q, k);
    1974        3362 :                 if (sub)
    1975         896 :                         q = pushArgument(mb, q, sub->nr);
    1976        3362 :                 q = pushBit(mb, q, TRUE);
    1977        3362 :                 q = pushBit(mb, q, TRUE);
    1978        3362 :                 q = pushBit(mb, q, TRUE);
    1979        3362 :                 q = pushBit(mb, q, TRUE);
    1980        3362 :                 q = pushBit(mb, q, FALSE);
    1981        3362 :                 pushInstruction(mb, q);
    1982             :         } else {
    1983             :                 /* if st_join2 try to convert to bandjoin */
    1984             :                 /* ie check if we subtract/add a constant, to the
    1985             :                 same column */
    1986             :                 /* move this optimization into the relational phase! */
    1987             :         /*
    1988             :                 stmt *base, *low = NULL, *high = NULL;
    1989             :                 if (type == st_join2 && range_join_convertable(s, &base, &low, &high)) {
    1990             :                         int tt = tail_type(base)->type->localtype;
    1991             : 
    1992             :                         if ((rs = _dumpstmt(sql, mb, base)) < 0)
    1993             :                                 return -1;
    1994             :                         if (low) {
    1995             :                                 if ((r1 = _dumpstmt(sql, mb, low)) < 0)
    1996             :                                         return -1;
    1997             :                         } else
    1998             :                                 r1 = argumentZero(mb, tt);
    1999             :                         if (high) {
    2000             :                                 if ((r2 = _dumpstmt(sql, mb, high)) < 0)
    2001             :                                         return -1;
    2002             :                         } else
    2003             :                                 r2 = argumentZero(mb, tt);
    2004             :                         cmd = bandjoinRef;
    2005             :                 }
    2006             :         */
    2007             : 
    2008        1503 :                 int r1 = op2->nr;
    2009        1503 :                 int r2 = op3->nr;
    2010        1503 :                 int rs = 0;
    2011        1503 :                 q = newStmtArgs(mb, algebraRef, cmd, 12);
    2012        1503 :                 if (q == NULL)
    2013           0 :                         goto bailout;
    2014        1503 :                 if (type == st_join2)
    2015          54 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2016        1503 :                 q = pushArgument(mb, q, l);
    2017        1503 :                 if (sub) {
    2018        1185 :                         int cand = op1->cand || op2->cand || op3->cand;
    2019        1179 :                         if (cand) {
    2020           6 :                                 assert(!op1->nrcols || op1->cand);
    2021           6 :                                 assert(!op2->nrcols || op2->cand);
    2022           6 :                                 assert(!op3->nrcols || op3->cand);
    2023             :                                 sub = NULL;
    2024             :                         }
    2025             :                 }
    2026        1179 :                 if (sub) /* only for uselect2 */
    2027        1179 :                         q = pushArgument(mb, q, sub->nr);
    2028        1503 :                 if (rs) {
    2029             :                         q = pushArgument(mb, q, rs);
    2030             :                 } else {
    2031        1503 :                         q = pushArgument(mb, q, r1);
    2032        1503 :                         q = pushArgument(mb, q, r2);
    2033             :                 }
    2034        1503 :                 if (type == st_join2) {
    2035          54 :                         q = pushNilBat(mb, q);
    2036          54 :                         q = pushNilBat(mb, q);
    2037             :                 }
    2038             : 
    2039        1503 :                 switch (cmp & 3) {
    2040          61 :                 case 0:
    2041          61 :                         q = pushBit(mb, q, FALSE);
    2042          61 :                         q = pushBit(mb, q, FALSE);
    2043          61 :                         break;
    2044         228 :                 case 1:
    2045         228 :                         q = pushBit(mb, q, TRUE);
    2046         228 :                         q = pushBit(mb, q, FALSE);
    2047         228 :                         break;
    2048          11 :                 case 2:
    2049          11 :                         q = pushBit(mb, q, FALSE);
    2050          11 :                         q = pushBit(mb, q, TRUE);
    2051          11 :                         break;
    2052        1203 :                 case 3:
    2053        1203 :                         q = pushBit(mb, q, TRUE);
    2054        1203 :                         q = pushBit(mb, q, TRUE);
    2055        1203 :                         break;
    2056             :                 }
    2057        1503 :                 q = pushBit(mb, q, anti);
    2058        1503 :                 if (type == st_uselect2) {
    2059        1449 :                         q = pushBit(mb, q, TRUE); /* all nil's are != */
    2060             :                 } else {
    2061          54 :                         q = pushBit(mb, q, (symmetric)?TRUE:FALSE);
    2062             :                 }
    2063        1503 :                 if (type == st_join2)
    2064          54 :                         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2065        1503 :                 pushInstruction(mb, q);
    2066        1503 :                 if (swapped) {
    2067           2 :                         InstrPtr r = newInstruction(mb,  NULL, NULL);
    2068           2 :                         if (r == NULL)
    2069           0 :                                 goto bailout;
    2070           2 :                         getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2071           2 :                         r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2072           2 :                         r = pushArgument(mb, r, getArg(q,1));
    2073           2 :                         r = pushArgument(mb, r, getArg(q,0));
    2074           2 :                         pushInstruction(mb, r);
    2075           2 :                         q = r;
    2076             :                 }
    2077             :         }
    2078        4865 :         if (Sub)
    2079        4811 :                 *Sub = sub;
    2080             :         return q;
    2081             : 
    2082           0 :   bailout:
    2083           0 :         if (be->mvc->sa->eb.enabled)
    2084           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2085             :         return NULL;
    2086             : }
    2087             : 
    2088             : stmt *
    2089          38 : stmt_outerselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2090             : {
    2091          38 :         MalBlkPtr mb = be->mb;
    2092          38 :         InstrPtr q;
    2093             : 
    2094          38 :         q = newStmtArgs(mb, algebraRef, outerselectRef, 6);
    2095          38 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2096          38 :         q = pushArgument(mb, q, g->nr); /* group ids */
    2097          38 :         q = pushArgument(mb, q, m->nr); /* mark flag */
    2098          38 :         q = pushArgument(mb, q, p->nr); /* predicate */
    2099          38 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2100          38 :         pushInstruction(mb, q);
    2101             : 
    2102          38 :         if (!q)
    2103             :                 return NULL;
    2104          38 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2105          38 :         if (s == NULL) {
    2106           0 :                 freeInstruction(q);
    2107           0 :                 return NULL;
    2108             :         }
    2109             : 
    2110          38 :         s->op1 = g;
    2111          38 :         s->op2 = m;
    2112          38 :         s->flag = MARKJOIN;
    2113          38 :         s->key = 0;
    2114          38 :         s->nrcols = g->nrcols;
    2115          38 :         s->nr = getDestVar(q);
    2116          38 :         s->q = q;
    2117          38 :         return s;
    2118             : }
    2119             : 
    2120             : stmt *
    2121         402 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2122             : {
    2123         402 :         MalBlkPtr mb = be->mb;
    2124         402 :         InstrPtr q;
    2125             : 
    2126         402 :         q = newStmtArgs(mb, algebraRef, markselectRef, 6);
    2127         402 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2128         402 :         q = pushArgument(mb, q, g->nr); /* left ids */
    2129         402 :         q = pushArgument(mb, q, m->nr); /* mark info mask */
    2130         402 :         q = pushArgument(mb, q, p->nr);      /* predicate */
    2131         402 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2132         402 :         pushInstruction(mb, q);
    2133             : 
    2134         402 :         if (!q)
    2135             :                 return NULL;
    2136         402 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2137         402 :         if (s == NULL) {
    2138           0 :                 freeInstruction(q);
    2139           0 :                 return NULL;
    2140             :         }
    2141             : 
    2142         402 :         s->op1 = g;
    2143         402 :         s->op2 = m;
    2144         402 :         s->flag = MARKJOIN;
    2145         402 :         s->key = 0;
    2146         402 :         s->nrcols = g->nrcols;
    2147         402 :         s->nr = getDestVar(q);
    2148         402 :         s->q = q;
    2149         402 :         return s;
    2150             : }
    2151             : 
    2152             : stmt *
    2153        2541 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
    2154             : {
    2155        2541 :         MalBlkPtr mb = be->mb;
    2156        2541 :         InstrPtr q;
    2157             : 
    2158        2541 :         q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
    2159        2541 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2160        2541 :         if (!final)
    2161           5 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2162        2541 :         q = pushArgument(mb, q, l->nr); /* left ids */
    2163        2541 :         q = pushArgument(mb, q, r->nr); /* mark info mask */
    2164        2541 :         q = pushNilBat(mb, q);
    2165        2541 :         q = pushNilBat(mb, q);
    2166        2541 :         q = pushNil(mb, q, TYPE_lng);
    2167        2541 :         pushInstruction(mb, q);
    2168             : 
    2169        2541 :         if (!q)
    2170             :                 return NULL;
    2171        2541 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2172        2541 :         if (s == NULL) {
    2173           0 :                 freeInstruction(q);
    2174           0 :                 return NULL;
    2175             :         }
    2176             : 
    2177        2541 :         s->op1 = l;
    2178        2541 :         s->op2 = r;
    2179        2541 :         s->flag = MARKJOIN;
    2180        2541 :         s->key = 0;
    2181        2541 :         s->nrcols = l->nrcols;
    2182        2541 :         s->nr = getDestVar(q);
    2183        2541 :         s->q = q;
    2184        2541 :         return s;
    2185             : }
    2186             : 
    2187             : stmt *
    2188        5059 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
    2189             : {
    2190        5059 :         stmt *sel = sub;
    2191        5059 :         InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
    2192             : 
    2193        5059 :         if (q == NULL)
    2194             :                 return NULL;
    2195             : 
    2196        5059 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2197        5059 :         if (s == NULL) {
    2198             :                 return NULL;
    2199             :         }
    2200             : 
    2201        5059 :         s->op1 = op1;
    2202        5059 :         s->op2 = op2;
    2203        5059 :         s->op3 = op3;
    2204        5059 :         s->op4.stval = sub;
    2205        5059 :         s->flag = cmp;
    2206        5059 :         s->nrcols = op1->nrcols;
    2207        5059 :         s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
    2208        5059 :         s->nr = getDestVar(q);
    2209        5059 :         s->q = q;
    2210        5059 :         s->cand = sub;
    2211        5059 :         s->reduce = reduce;
    2212        5059 :         if (!sub && sel) /* project back the old ids */
    2213        1451 :                 return stmt_project(be, s, sel);
    2214             :         return s;
    2215             : }
    2216             : 
    2217             : stmt *
    2218       51348 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
    2219             : {
    2220       51348 :         InstrPtr q = NULL;
    2221       51348 :         MalBlkPtr mb = be->mb;
    2222             : 
    2223       51348 :         q = dump_2(mb, batRef, mergecandRef, op1, op2);
    2224       51348 :         if (q) {
    2225       51348 :                 stmt *s = stmt_create(be->mvc->sa, st_tunion);
    2226       51348 :                 if (s == NULL) {
    2227             :                         return NULL;
    2228             :                 }
    2229             : 
    2230       51348 :                 s->op1 = op1;
    2231       51348 :                 s->op2 = op2;
    2232       51348 :                 s->nrcols = op1->nrcols;
    2233       51348 :                 s->key = op1->key;
    2234       51348 :                 s->aggr = op1->aggr;
    2235       51348 :                 s->nr = getDestVar(q);
    2236       51348 :                 s->q = q;
    2237       51348 :                 return s;
    2238             :         }
    2239             : 
    2240           0 :         if (be->mvc->sa->eb.enabled)
    2241           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2242             :         return NULL;
    2243             : }
    2244             : 
    2245             : stmt *
    2246       44989 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2247             : {
    2248       44989 :         InstrPtr q = NULL;
    2249       44989 :         MalBlkPtr mb = be->mb;
    2250             : 
    2251       44989 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2252           0 :                 goto bailout;
    2253       44989 :         q = newStmt(mb, algebraRef, differenceRef);
    2254       44989 :         if (q == NULL)
    2255           0 :                 goto bailout;
    2256       44989 :         q = pushArgument(mb, q, op1->nr); /* left */
    2257       44989 :         q = pushArgument(mb, q, op2->nr); /* right */
    2258       44989 :         if (lcand)
    2259           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2260             :         else
    2261       44989 :                 q = pushNilBat(mb, q); /* left candidate */
    2262       44989 :         q = pushNilBat(mb, q); /* right candidate */
    2263       44989 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2264       44989 :         q = pushBit(mb, q, FALSE);    /* do not clear nils */
    2265       44989 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2266             : 
    2267       44989 :         bool enabled = be->mvc->sa->eb.enabled;
    2268       44989 :         be->mvc->sa->eb.enabled = false;
    2269       44989 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2270       44989 :         be->mvc->sa->eb.enabled = enabled;
    2271       44989 :         if (s == NULL) {
    2272           0 :                 freeInstruction(q);
    2273           0 :                 goto bailout;
    2274             :         }
    2275             : 
    2276       44989 :         s->op1 = op1;
    2277       44989 :         s->op2 = op2;
    2278       44989 :         s->nrcols = op1->nrcols;
    2279       44989 :         s->key = op1->key;
    2280       44989 :         s->aggr = op1->aggr;
    2281       44989 :         s->nr = getDestVar(q);
    2282       44989 :         s->q = q;
    2283       44989 :         pushInstruction(mb, q);
    2284       44989 :         return s;
    2285             : 
    2286           0 :   bailout:
    2287           0 :         if (be->mvc->sa->eb.enabled)
    2288           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2289             :         return NULL;
    2290             : }
    2291             : 
    2292             : stmt *
    2293        1378 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2294             : {
    2295        1378 :         InstrPtr q = NULL;
    2296        1378 :         MalBlkPtr mb = be->mb;
    2297             : 
    2298        1378 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2299           0 :                 goto bailout;
    2300        1378 :         q = newStmt(mb, algebraRef, differenceRef);
    2301        1378 :         if (q == NULL)
    2302           0 :                 goto bailout;
    2303        1378 :         q = pushArgument(mb, q, op1->nr); /* left */
    2304        1378 :         q = pushArgument(mb, q, op2->nr); /* right */
    2305        1378 :         if (lcand)
    2306           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2307             :         else
    2308        1378 :                 q = pushNilBat(mb, q); /* left candidate */
    2309        1378 :         q = pushNilBat(mb, q); /* right candidate */
    2310        1378 :         q = pushBit(mb, q, FALSE);     /* nil matches */
    2311        1378 :         q = pushBit(mb, q, TRUE);     /* not in */
    2312        1378 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2313             : 
    2314        1378 :         bool enabled = be->mvc->sa->eb.enabled;
    2315        1378 :         be->mvc->sa->eb.enabled = false;
    2316        1378 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2317        1378 :         be->mvc->sa->eb.enabled = enabled;
    2318        1378 :         if (s == NULL) {
    2319           0 :                 freeInstruction(q);
    2320           0 :                 goto bailout;
    2321             :         }
    2322             : 
    2323        1378 :         s->op1 = op1;
    2324        1378 :         s->op2 = op2;
    2325        1378 :         s->nrcols = op1->nrcols;
    2326        1378 :         s->key = op1->key;
    2327        1378 :         s->aggr = op1->aggr;
    2328        1378 :         s->nr = getDestVar(q);
    2329        1378 :         s->q = q;
    2330        1378 :         pushInstruction(mb, q);
    2331        1378 :         return s;
    2332             : 
    2333           0 :   bailout:
    2334           0 :         if (be->mvc->sa->eb.enabled)
    2335           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2336             :         return NULL;
    2337             : }
    2338             : 
    2339             : stmt *
    2340        2115 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
    2341             : {
    2342        2115 :         InstrPtr q = NULL;
    2343        2115 :         MalBlkPtr mb = be->mb;
    2344             : 
    2345        2115 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2346           0 :                 goto bailout;
    2347        2115 :         q = newStmt(mb, algebraRef, intersectRef);
    2348        2115 :         if (q == NULL)
    2349           0 :                 goto bailout;
    2350        2115 :         q = pushArgument(mb, q, op1->nr); /* left */
    2351        2115 :         q = pushArgument(mb, q, op2->nr); /* right */
    2352        2115 :         q = pushNilBat(mb, q); /* left candidate */
    2353        2115 :         q = pushNilBat(mb, q); /* right candidate */
    2354        2115 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2355        2115 :         q = pushBit(mb, q, single?TRUE:FALSE);    /* max_one */
    2356        2115 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2357             : 
    2358        2115 :         bool enabled = be->mvc->sa->eb.enabled;
    2359        2115 :         be->mvc->sa->eb.enabled = false;
    2360        2115 :         stmt *s = stmt_create(be->mvc->sa, st_tinter);
    2361        2115 :         be->mvc->sa->eb.enabled = enabled;
    2362        2115 :         if (s == NULL) {
    2363           0 :                 freeInstruction(q);
    2364           0 :                 goto bailout;
    2365             :         }
    2366             : 
    2367        2115 :         s->op1 = op1;
    2368        2115 :         s->op2 = op2;
    2369        2115 :         s->nrcols = op1->nrcols;
    2370        2115 :         s->key = op1->key;
    2371        2115 :         s->aggr = op1->aggr;
    2372        2115 :         s->nr = getDestVar(q);
    2373        2115 :         s->q = q;
    2374        2115 :         pushInstruction(mb, q);
    2375        2115 :         return s;
    2376             : 
    2377           0 :   bailout:
    2378           0 :         if (be->mvc->sa->eb.enabled)
    2379           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2380             :         return NULL;
    2381             : }
    2382             : 
    2383             : stmt *
    2384       95223 : stmt_join_cand(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int anti, comp_type cmptype, int need_left, int is_semantics, bool single, bool inner)
    2385             : {
    2386       95223 :         MalBlkPtr mb = be->mb;
    2387       95223 :         InstrPtr q = NULL;
    2388       95223 :         const char *sjt = inner?joinRef:outerjoinRef;
    2389             : 
    2390       95223 :         (void)anti;
    2391       95223 :         (void)inner;
    2392             : 
    2393       95223 :         if (need_left) {
    2394         653 :                 cmptype = cmp_equal;
    2395         653 :                 sjt = leftjoinRef;
    2396             :         }
    2397       95223 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2398           0 :                 goto bailout;
    2399             : 
    2400       95223 :         assert (!single || cmptype == cmp_all);
    2401             : 
    2402       95223 :         switch (cmptype) {
    2403       77295 :         case cmp_equal:
    2404       77295 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2405       77295 :                 if (q == NULL)
    2406           0 :                         goto bailout;
    2407       77295 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2408       77295 :                 q = pushArgument(mb, q, op1->nr);
    2409       77295 :                 q = pushArgument(mb, q, op2->nr);
    2410       77295 :                 if (!lcand)
    2411       76192 :                         q = pushNilBat(mb, q);
    2412             :                 else
    2413        1103 :                         q = pushArgument(mb, q, lcand->nr);
    2414       77295 :                 if (!rcand)
    2415       77295 :                         q = pushNilBat(mb, q);
    2416             :                 else
    2417           0 :                         q = pushArgument(mb, q, rcand->nr);
    2418       77295 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2419       77295 :                 if (!inner)
    2420          76 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2421       77295 :                 q = pushNil(mb, q, TYPE_lng);
    2422       77295 :                 pushInstruction(mb, q);
    2423       77295 :                 break;
    2424          31 :         case cmp_notequal:
    2425          31 :                 if (inner)
    2426          31 :                         sjt = thetajoinRef;
    2427          31 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2428          31 :                 if (q == NULL)
    2429           0 :                         goto bailout;
    2430          31 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2431          31 :                 q = pushArgument(mb, q, op1->nr);
    2432          31 :                 q = pushArgument(mb, q, op2->nr);
    2433          31 :                 if (!lcand)
    2434          31 :                         q = pushNilBat(mb, q);
    2435             :                 else
    2436           0 :                         q = pushArgument(mb, q, lcand->nr);
    2437          31 :                 if (!rcand)
    2438          31 :                         q = pushNilBat(mb, q);
    2439             :                 else
    2440           0 :                         q = pushArgument(mb, q, rcand->nr);
    2441          31 :                 if (inner)
    2442          31 :                         q = pushInt(mb, q, JOIN_NE);
    2443          31 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2444          31 :                 if (!inner)
    2445           0 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2446          31 :                 q = pushNil(mb, q, TYPE_lng);
    2447          31 :                 pushInstruction(mb, q);
    2448          31 :                 break;
    2449        2584 :         case cmp_lt:
    2450             :         case cmp_lte:
    2451             :         case cmp_gt:
    2452             :         case cmp_gte:
    2453        2584 :                 q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
    2454        2584 :                 if (q == NULL)
    2455           0 :                         goto bailout;
    2456        2584 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2457        2584 :                 q = pushArgument(mb, q, op1->nr);
    2458        2584 :                 q = pushArgument(mb, q, op2->nr);
    2459        2584 :                 if (!lcand)
    2460        2584 :                         q = pushNilBat(mb, q);
    2461             :                 else
    2462           0 :                         q = pushArgument(mb, q, lcand->nr);
    2463        2584 :                 if (!rcand)
    2464        2584 :                         q = pushNilBat(mb, q);
    2465             :                 else
    2466           0 :                         q = pushArgument(mb, q, rcand->nr);
    2467        2584 :                 if (cmptype == cmp_lt)
    2468        2068 :                         q = pushInt(mb, q, JOIN_LT);
    2469         516 :                 else if (cmptype == cmp_lte)
    2470           8 :                         q = pushInt(mb, q, JOIN_LE);
    2471         508 :                 else if (cmptype == cmp_gt)
    2472         503 :                         q = pushInt(mb, q, JOIN_GT);
    2473           5 :                 else if (cmptype == cmp_gte)
    2474           5 :                         q = pushInt(mb, q, JOIN_GE);
    2475        2584 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2476        2584 :                 q = pushNil(mb, q, TYPE_lng);
    2477        2584 :                 pushInstruction(mb, q);
    2478        2584 :                 break;
    2479       12075 :         case cmp_all:   /* aka cross table */
    2480       12510 :                 q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
    2481       12075 :                 if (q == NULL)
    2482           0 :                         goto bailout;
    2483       12075 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2484       12075 :                 q = pushArgument(mb, q, op1->nr);
    2485       12075 :                 q = pushArgument(mb, q, op2->nr);
    2486       12075 :                 if (!inner) {
    2487         435 :                         q = pushNilBat(mb, q);
    2488         435 :                         q = pushNilBat(mb, q);
    2489             :                 }
    2490       12075 :                 q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2491       12075 :                 assert(!lcand && !rcand);
    2492       12075 :                 pushInstruction(mb, q);
    2493       12075 :                 break;
    2494        3238 :         case cmp_joined:
    2495        3238 :                 q = op1->q;
    2496        3238 :                 if (q == NULL)
    2497           0 :                         goto bailout;
    2498             :                 break;
    2499           0 :         default:
    2500           0 :                 TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
    2501             :         }
    2502             : 
    2503       95223 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2504       95223 :         if (s == NULL) {
    2505           0 :                 goto bailout;
    2506             :         }
    2507             : 
    2508       95223 :         s->op1 = op1;
    2509       95223 :         s->op2 = op2;
    2510       95223 :         s->flag = cmptype;
    2511       95223 :         s->key = 0;
    2512       95223 :         s->nrcols = 2;
    2513       95223 :         s->nr = getDestVar(q);
    2514       95223 :         s->q = q;
    2515       95223 :         return s;
    2516             : 
    2517           0 :   bailout:
    2518           0 :         if (be->mvc->sa->eb.enabled)
    2519           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2520             :         return NULL;
    2521             : }
    2522             : 
    2523             : stmt *
    2524       90974 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
    2525             : {
    2526       90974 :         return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
    2527             : }
    2528             : 
    2529             : stmt *
    2530        1469 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
    2531             : {
    2532        1469 :         MalBlkPtr mb = be->mb;
    2533        1469 :         InstrPtr q = NULL;
    2534             : 
    2535        1469 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2536           0 :                 goto bailout;
    2537             : 
    2538        1469 :         if (single) {
    2539         284 :                 q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
    2540         284 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2541             :         } else
    2542        1185 :                 q = newStmt(mb, algebraRef, intersectRef);
    2543        1469 :         if (q == NULL)
    2544           0 :                 goto bailout;
    2545        1469 :         q = pushArgument(mb, q, op1->nr);
    2546        1469 :         q = pushArgument(mb, q, op2->nr);
    2547        1469 :         if (lcand)
    2548        1182 :                 q = pushArgument(mb, q, lcand->nr);
    2549             :         else
    2550         287 :                 q = pushNilBat(mb, q);
    2551        1469 :         if (rcand)
    2552           0 :                 q = pushArgument(mb, q, rcand->nr);
    2553             :         else
    2554        1469 :                 q = pushNilBat(mb, q);
    2555        1469 :         q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2556        1469 :         q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2557        1469 :         q = pushNil(mb, q, TYPE_lng);
    2558             : 
    2559        1469 :         bool enabled = be->mvc->sa->eb.enabled;
    2560        1469 :         be->mvc->sa->eb.enabled = false;
    2561        1469 :         stmt *s = stmt_create(be->mvc->sa, st_semijoin);
    2562        1469 :         be->mvc->sa->eb.enabled = enabled;
    2563        1469 :         if (s == NULL) {
    2564           0 :                 freeInstruction(q);
    2565           0 :                 goto bailout;
    2566             :         }
    2567             : 
    2568        1469 :         s->op1 = op1;
    2569        1469 :         s->op2 = op2;
    2570        1469 :         s->flag = cmp_equal;
    2571        1469 :         s->key = 0;
    2572        1469 :         s->nrcols = 1;
    2573        1469 :         if (single)
    2574         284 :                 s->nrcols = 2;
    2575        1469 :         s->nr = getDestVar(q);
    2576        1469 :         s->q = q;
    2577        1469 :         pushInstruction(mb, q);
    2578        1469 :         return s;
    2579             : 
    2580           0 :   bailout:
    2581           0 :         if (be->mvc->sa->eb.enabled)
    2582           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2583             :         return NULL;
    2584             : }
    2585             : 
    2586             : static InstrPtr
    2587     3565501 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
    2588             : {
    2589     3565501 :         MalBlkPtr mb = be->mb;
    2590     3565501 :         InstrPtr q = NULL;
    2591             : 
    2592     3565501 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2593             :                 return NULL;
    2594             :         /* delta bat */
    2595     3565501 :         if (delta) {
    2596      494582 :                 int uval = getArg(op2->q, 1);
    2597             : 
    2598      494582 :                 q = newStmt(mb, sqlRef, deltaRef);
    2599      494611 :                 q = pushArgument(mb, q, op1->nr);
    2600      494611 :                 q = pushArgument(mb, q, op2->nr);
    2601      494611 :                 q = pushArgument(mb, q, uval);
    2602             :         } else {
    2603             :                 /* projections, ie left is void headed */
    2604     3070919 :                 q = newStmt(mb, algebraRef, projectionRef);
    2605     3070955 :                 q = pushArgument(mb, q, op1->nr);
    2606     3070948 :                 q = pushArgument(mb, q, op2->nr);
    2607             :         }
    2608     3565560 :         pushInstruction(mb, q);
    2609     3565560 :         return q;
    2610             : }
    2611             : 
    2612             : static list *
    2613          62 : unnest_stmt(stmt *o)
    2614             : {
    2615         156 :         while (o->type == st_alias)
    2616          94 :                 o = o->op1;
    2617          62 :         assert(o && o->type == st_list);
    2618          62 :         return o->op4.lval;
    2619             : }
    2620             : 
    2621             : static stmt *
    2622           0 : stmt_nest2(backend *be, stmt *op1, stmt *op2, fstmt call)
    2623             : {
    2624           0 :         list *ops1 = unnest_stmt(op1);
    2625           0 :         list *ops2 = unnest_stmt(op2);
    2626           0 :         list *nops = sa_list(be->mvc->sa);
    2627           0 :         sql_subtype *st = tail_type(op2);
    2628           0 :         bool propagate = !st->multiset && st->type->composite;
    2629           0 :         for(node *n = ops1->h, *m = ops2->h; n && m; n = n->next, m = m->next) {
    2630           0 :                 stmt *i1 = n->data;
    2631           0 :                 stmt *i2 = m->data;
    2632           0 :                 stmt *i = i2;
    2633           0 :                 if (propagate || (st->multiset && n == ops1->t)) {
    2634           0 :                         stmt *oi = i;
    2635           0 :                         i = call(be, i1, oi);
    2636           0 :                         i->nested = oi->nested;
    2637           0 :                         i->subtype = *tail_type(oi);
    2638           0 :                         i->tname = oi->tname;
    2639           0 :                         i->cname = oi->cname;
    2640           0 :                         i->label = oi->label;
    2641             :                 }
    2642           0 :                 append(nops, i);
    2643             :         }
    2644           0 :         stmt *s = stmt_list(be, nops);
    2645           0 :         if (s == NULL)
    2646             :                 return NULL;
    2647           0 :         s->nested = true;
    2648           0 :         s->subtype = *st;
    2649           0 :         s->tname = op2->tname;
    2650           0 :         s->cname = op2->cname;
    2651           0 :         s->label = op2->label;
    2652           0 :         if (op2->type == st_alias)
    2653           0 :                 return stmt_alias(be, s, op2->label, op2->tname, op2->cname);
    2654             :         return s;
    2655             : }
    2656             : 
    2657             : static stmt *
    2658           0 : stmt_nest1(backend *be, stmt *op1, stmt *op2, fstmt call)
    2659             : {
    2660           0 :         assert(op1->nested);
    2661           0 :         list *ops = unnest_stmt(op1);
    2662           0 :         list *nops = sa_list(be->mvc->sa);
    2663           0 :         sql_subtype *st = tail_type(op1);
    2664           0 :         bool propagate = !st->multiset && st->type->composite;
    2665           0 :         for(node *n = ops->h; n; n = n->next) {
    2666           0 :                 stmt *i = n->data;
    2667           0 :                 if (propagate || (st->multiset && n == ops->t)) {
    2668           0 :                         stmt *oi = i;
    2669           0 :                         i = call(be, oi, op2);
    2670           0 :                         i->nested = oi->nested;
    2671           0 :                         i->subtype = *tail_type(oi);
    2672           0 :                         i->tname = oi->tname;
    2673           0 :                         i->cname = oi->cname;
    2674           0 :                         i->label = oi->label;
    2675             :                 }
    2676           0 :                 append(nops, i);
    2677             :         }
    2678           0 :         stmt *s = stmt_list(be, nops);
    2679           0 :         if (s == NULL)
    2680             :                 return NULL;
    2681           0 :         s->nested = true;
    2682           0 :         s->subtype = *st;
    2683           0 :         s->tname = op1->tname;
    2684           0 :         s->cname = op1->cname;
    2685           0 :         s->label = op1->label;
    2686           0 :         if (op1->type == st_alias)
    2687           0 :                 return stmt_alias(be, s, op1->label, op1->tname, op1->cname);
    2688             :         return s;
    2689             : }
    2690             : 
    2691             : stmt *
    2692          36 : stmt_nest(backend *be, stmt *op1, stmt *op2, fstmt call)
    2693             : {
    2694          36 :         if (!op2)
    2695           0 :                 op2 = op1;
    2696          36 :         if (op1->nested && op2->nested)
    2697           0 :                 return stmt_nest2(be, op1, op2, call);
    2698          36 :         if (op1->nested && !op2->nested)
    2699           0 :                 return stmt_nest1(be, op1, op2, call);
    2700          36 :         assert(op2->nested);
    2701          36 :         list *ops = unnest_stmt(op2);
    2702          36 :         list *nops = sa_list(be->mvc->sa);
    2703          36 :         sql_subtype *st = tail_type(op2);
    2704          36 :         bool propagate = !st->multiset && st->type->composite;
    2705         172 :         for(node *n = ops->h; n; n = n->next) {
    2706         136 :                 stmt *i = n->data;
    2707         136 :                 if (propagate || (st->multiset && n == ops->t)) {
    2708          82 :                         stmt *oi = i;
    2709          82 :                         i = call(be, op1, oi);
    2710          82 :                         i->nested = oi->nested;
    2711          82 :                         i->subtype = *tail_type(oi);
    2712          82 :                         i->tname = oi->tname;
    2713          82 :                         i->cname = oi->cname;
    2714          82 :                         i->label = oi->label;
    2715             :                 }
    2716         136 :                 append(nops, i);
    2717             :         }
    2718          36 :         stmt *s = stmt_list(be, nops);
    2719          36 :         if (s == NULL)
    2720             :                 return NULL;
    2721          36 :         s->nested = true;
    2722          36 :         s->subtype = *st;
    2723          36 :         s->tname = op2->tname;
    2724          36 :         s->cname = op2->cname;
    2725          36 :         s->label = op2->label;
    2726          36 :         if (op2->type == st_alias)
    2727          32 :                 return stmt_alias(be, s, op2->label, op2->tname, op2->cname);
    2728             :         return s;
    2729             : }
    2730             : 
    2731             : stmt *
    2732     3080247 : stmt_project(backend *be, stmt *op1, stmt *op2)
    2733             : {
    2734     3080247 :         if (op1 == NULL || op2 == NULL)
    2735             :                 return NULL;
    2736     3080247 :         if (!op2->nrcols)
    2737        9287 :                 return stmt_const(be, op1, op2);
    2738     3070960 :         if (op2->nested)
    2739          36 :                 return stmt_nest(be, op1, op2, &stmt_project);
    2740     3070924 :         InstrPtr q = stmt_project_join(be, op1, op2, false);
    2741     3070953 :         if (q) {
    2742     3070953 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2743     3070931 :                 if (s == NULL) {
    2744             :                         return NULL;
    2745             :                 }
    2746             : 
    2747     3070931 :                 s->op1 = op1;
    2748     3070931 :                 s->op2 = op2;
    2749     3070931 :                 s->flag = cmp_project;
    2750     3070931 :                 s->key = 0;
    2751     3070931 :                 s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2752     3070931 :                 s->nr = getDestVar(q);
    2753     3070931 :                 s->q = q;
    2754     3070931 :                 s->tname = op2->tname;
    2755     3070931 :                 s->cname = op2->cname;
    2756     3070931 :                 s->label = op2->label;
    2757     3070931 :                 return s;
    2758             :         }
    2759           0 :         if (be->mvc->sa->eb.enabled)
    2760           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);
    2761             :         return NULL;
    2762             : }
    2763             : 
    2764             : stmt *
    2765      494582 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
    2766             : {
    2767      494582 :         InstrPtr q = stmt_project_join(be, col, upd, true);
    2768      494610 :         if (q) {
    2769      494610 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2770      494603 :                 if (s == NULL) {
    2771             :                         return NULL;
    2772             :                 }
    2773             : 
    2774      494603 :                 s->op1 = col;
    2775      494603 :                 s->op2 = upd;
    2776      494603 :                 s->flag = cmp_project;
    2777      494603 :                 s->key = 0;
    2778      494603 :                 s->nrcols = 2;
    2779      494603 :                 s->nr = getDestVar(q);
    2780      494603 :                 s->q = q;
    2781      494603 :                 s->tname = col->tname;
    2782      494603 :                 s->cname = col->cname;
    2783      494603 :                 return s;
    2784             :         }
    2785             : 
    2786           0 :         if (be->mvc->sa->eb.enabled)
    2787           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);
    2788             :         return NULL;
    2789             : }
    2790             : 
    2791             : stmt *
    2792          43 : stmt_left_project(backend *be, stmt *op1, stmt *op2, stmt *op3)
    2793             : {
    2794          43 :         MalBlkPtr mb = be->mb;
    2795          43 :         InstrPtr q = NULL;
    2796          43 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || op2->nr < 0 || op3->nr < 0)
    2797           0 :                 goto bailout;
    2798             : 
    2799          43 :         q = newStmt(mb, sqlRef, projectRef);
    2800          43 :         if (q == NULL)
    2801           0 :                 goto bailout;
    2802          43 :         q = pushArgument(mb, q, op1->nr);
    2803          43 :         q = pushArgument(mb, q, op2->nr);
    2804          43 :         q = pushArgument(mb, q, op3->nr);
    2805             : 
    2806          43 :         bool enabled = be->mvc->sa->eb.enabled;
    2807          43 :         be->mvc->sa->eb.enabled = false;
    2808          43 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2809          43 :         be->mvc->sa->eb.enabled = enabled;
    2810          43 :         if (s == NULL) {
    2811           0 :                 freeInstruction(q);
    2812           0 :                 goto bailout;
    2813             :         }
    2814             : 
    2815          43 :         s->op1 = op1;
    2816          43 :         s->op2 = op2;
    2817          43 :         s->op3 = op3;
    2818          43 :         s->flag = cmp_left_project;
    2819          43 :         s->key = 0;
    2820          43 :         s->nrcols = 2;
    2821          43 :         s->nr = getDestVar(q);
    2822          43 :         s->q = q;
    2823          43 :         pushInstruction(mb, q);
    2824          43 :         return s;
    2825             : 
    2826           0 :   bailout:
    2827           0 :         if (be->mvc->sa->eb.enabled)
    2828           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2829             :         return NULL;
    2830             : }
    2831             : 
    2832             : stmt *
    2833         176 : stmt_dict(backend *be, stmt *op1, stmt *op2)
    2834             : {
    2835         176 :         MalBlkPtr mb = be->mb;
    2836         176 :         InstrPtr q = NULL;
    2837             : 
    2838         176 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2839             :                 return NULL;
    2840             : 
    2841         176 :         q = newStmt(mb, dictRef, decompressRef);
    2842         176 :         if (q == NULL)
    2843           0 :                 goto bailout;
    2844         176 :         q = pushArgument(mb, q, op1->nr);
    2845         176 :         q = pushArgument(mb, q, op2->nr);
    2846             : 
    2847         176 :         bool enabled = be->mvc->sa->eb.enabled;
    2848         176 :         be->mvc->sa->eb.enabled = false;
    2849         176 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2850         176 :         be->mvc->sa->eb.enabled = enabled;
    2851         176 :         if (s == NULL) {
    2852           0 :                 freeInstruction(q);
    2853           0 :                 return NULL;
    2854             :         }
    2855             : 
    2856         176 :         s->op1 = op1;
    2857         176 :         s->op2 = op2;
    2858         176 :         s->flag = cmp_project;
    2859         176 :         s->key = 0;
    2860         176 :         s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2861         176 :         s->nr = getDestVar(q);
    2862         176 :         s->q = q;
    2863         176 :         s->tname = op1->tname;
    2864         176 :         s->cname = op1->cname;
    2865         176 :         pushInstruction(mb, q);
    2866         176 :         return s;
    2867             : 
    2868           0 :   bailout:
    2869           0 :         if (be->mvc->sa->eb.enabled)
    2870           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2871             :         return NULL;
    2872             : }
    2873             : 
    2874             : stmt *
    2875           8 : stmt_for(backend *be, stmt *op1, stmt *min_val)
    2876             : {
    2877           8 :         MalBlkPtr mb = be->mb;
    2878           8 :         InstrPtr q = NULL;
    2879             : 
    2880           8 :         if (op1 == NULL || min_val == NULL || op1->nr < 0)
    2881             :                 return NULL;
    2882             : 
    2883           8 :         q = newStmt(mb, forRef, decompressRef);
    2884           8 :         if (q == NULL)
    2885           0 :                 goto bailout;
    2886           8 :         q = pushArgument(mb, q, op1->nr);
    2887           8 :         q = pushArgument(mb, q, min_val->nr);
    2888             : 
    2889           8 :         bool enabled = be->mvc->sa->eb.enabled;
    2890           8 :         be->mvc->sa->eb.enabled = false;
    2891           8 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2892           8 :         be->mvc->sa->eb.enabled = enabled;
    2893           8 :         if (s == NULL) {
    2894           0 :                 freeInstruction(q);
    2895           0 :                 return NULL;
    2896             :         }
    2897             : 
    2898           8 :         s->op1 = op1;
    2899           8 :         s->op2 = min_val;
    2900           8 :         s->flag = cmp_project;
    2901           8 :         s->key = 0;
    2902           8 :         s->nrcols = op1->nrcols;
    2903           8 :         s->nr = getDestVar(q);
    2904           8 :         s->q = q;
    2905           8 :         s->tname = op1->tname;
    2906           8 :         s->cname = op1->cname;
    2907           8 :         pushInstruction(mb, q);
    2908           8 :         return s;
    2909             : 
    2910           0 :   bailout:
    2911           0 :         if (be->mvc->sa->eb.enabled)
    2912           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2913             :         return NULL;
    2914             : }
    2915             : 
    2916             : stmt *
    2917          54 : stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int symmetric, int swapped)
    2918             : {
    2919          54 :         InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, swapped, st_join2, 1/*reduce semantics*/);
    2920          54 :         if (q == NULL)
    2921             :                 return NULL;
    2922             : 
    2923          54 :         stmt *s = stmt_create(be->mvc->sa, st_join2);
    2924          54 :         if (s == NULL) {
    2925             :                 return NULL;
    2926             :         }
    2927             : 
    2928          54 :         s->op1 = l;
    2929          54 :         s->op2 = ra;
    2930          54 :         s->op3 = rb;
    2931          54 :         s->flag = cmp;
    2932          54 :         s->nrcols = 2;
    2933          54 :         s->nr = getDestVar(q);
    2934          54 :         s->q = q;
    2935          54 :         s->reduce = 1;
    2936          54 :         return s;
    2937             : }
    2938             : 
    2939             : stmt *
    2940          48 : stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
    2941             : {
    2942          48 :         MalBlkPtr mb = be->mb;
    2943          48 :         InstrPtr q = NULL;
    2944          48 :         const char *mod, *fimp;
    2945          48 :         node *n;
    2946             : 
    2947          48 :         if (l == NULL || r == NULL)
    2948           0 :                 goto bailout;
    2949          48 :         if (backend_create_subfunc(be, op, NULL) < 0)
    2950           0 :                 goto bailout;
    2951          48 :         mod = sql_func_mod(op->func);
    2952          48 :         fimp = backend_function_imp(be, op->func);
    2953          48 :         fimp = sa_strconcat(be->mvc->sa, fimp, "join");
    2954             : 
    2955             :         /* filter qualifying tuples, return oids of h and tail */
    2956          48 :         q = newStmtArgs(mb, mod, fimp, list_length(l->op4.lval) + list_length(r->op4.lval) + 7);
    2957          48 :         if (q == NULL)
    2958           0 :                 goto bailout;
    2959          48 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2960          96 :         for (n = l->op4.lval->h; n; n = n->next) {
    2961          48 :                 stmt *op = n->data;
    2962             : 
    2963          48 :                 q = pushArgument(mb, q, op->nr);
    2964             :         }
    2965             : 
    2966         158 :         for (n = r->op4.lval->h; n; n = n->next) {
    2967         110 :                 stmt *op = n->data;
    2968             : 
    2969         110 :                 q = pushArgument(mb, q, op->nr);
    2970             :         }
    2971          48 :         q = pushNilBat(mb, q); /* candidate lists */
    2972          48 :         q = pushNilBat(mb, q); /* candidate lists */
    2973          48 :         q = pushBit(mb, q, TRUE);     /* nil_matches */
    2974          48 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2975          48 :         q = pushBit(mb, q, anti?TRUE:FALSE); /* 'not' matching */
    2976          48 :         pushInstruction(mb, q);
    2977             : 
    2978          48 :         if (swapped) {
    2979           2 :                 InstrPtr r = newInstruction(mb,  NULL, NULL);
    2980           2 :                 if (r == NULL)
    2981           0 :                         goto bailout;
    2982           2 :                 getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2983           2 :                 r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2984           2 :                 r = pushArgument(mb, r, getArg(q,1));
    2985           2 :                 r = pushArgument(mb, r, getArg(q,0));
    2986           2 :                 pushInstruction(mb, r);
    2987           2 :                 q = r;
    2988             :         }
    2989             : 
    2990          48 :         stmt *s = stmt_create(be->mvc->sa, st_joinN);
    2991          48 :         if (s == NULL) {
    2992           0 :                 goto bailout;
    2993             :         }
    2994             : 
    2995          48 :         s->op1 = l;
    2996          48 :         s->op2 = r;
    2997          48 :         s->op4.funcval = op;
    2998          48 :         s->nrcols = 2;
    2999          48 :         if (swapped)
    3000           2 :                 s->flag |= SWAPPED;
    3001          48 :         s->nr = getDestVar(q);
    3002          48 :         s->q = q;
    3003          48 :         return s;
    3004             : 
    3005           0 :   bailout:
    3006           0 :         if (be->mvc->sa->eb.enabled)
    3007           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3008             :         return NULL;
    3009             : }
    3010             : 
    3011             : stmt *
    3012       26023 : stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
    3013             : {
    3014       26023 :         InstrPtr q = NULL;
    3015             : 
    3016       26023 :         if (rs == NULL || rs->nr < 0)
    3017             :                 return NULL;
    3018       26023 :         q = rs->q;
    3019       26023 :         if (q) {
    3020       25615 :                 stmt *s = stmt_create(be->mvc->sa, st_rs_column);
    3021       25615 :                 if (s == NULL) {
    3022             :                         return NULL;
    3023             :                 }
    3024             : 
    3025       25615 :                 s->op1 = rs;
    3026       25615 :                 s->subtype = *tpe;
    3027       25615 :                 s->flag = i;
    3028       25615 :                 s->nrcols = 1;
    3029       25615 :                 s->key = 0;
    3030       25615 :                 s->q = q;
    3031       25615 :                 s->nr = getArg(q, s->flag);
    3032       25615 :                 return s;
    3033         408 :         } else if (rs->type == st_list) {
    3034         408 :                 list *cols = rs->op4.lval;
    3035         408 :                 if (i < list_length(cols))
    3036         408 :                         return list_fetch(cols, i);
    3037             :         }
    3038             :         return NULL;
    3039             : }
    3040             : 
    3041             : /*
    3042             :  * The dump_header produces a sequence of instructions for
    3043             :  * the front-end to prepare presentation of a result table.
    3044             :  *
    3045             :  * A secondary scheme is added to assemble all information
    3046             :  * in columns first. Then it can be returned to the environment.
    3047             :  */
    3048             : #define NEWRESULTSET
    3049             : 
    3050             : #define meta(P, Id, Tpe, Args)                                          \
    3051             :         do {                                                                                    \
    3052             :                 P = newStmtArgs(mb, batRef, packRef, Args);     \
    3053             :                 if (P) {                                                                        \
    3054             :                         Id = getArg(P,0);                                               \
    3055             :                         setVarType(mb, Id, newBatType(Tpe));    \
    3056             :                         setVarFixed(mb, Id);                                    \
    3057             :                         list = pushArgument(mb, list, Id);              \
    3058             :                         pushInstruction(mb, P);                                 \
    3059             :                 }                                                                                       \
    3060             :         } while (0)
    3061             : 
    3062             : static int
    3063          32 : dump_export_header(mvc *sql, MalBlkPtr mb, list *l, int file, const char * format, const char * sep,const char * rsep,const char * ssep,const char * ns, int onclient)
    3064             : {
    3065          32 :         node *n;
    3066          32 :         int ret = -1;
    3067          32 :         int args;
    3068             : 
    3069             :         // gather the meta information
    3070          32 :         int tblId, nmeId, tpeId, lenId, scaleId;
    3071          32 :         InstrPtr list;
    3072          32 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    3073             : 
    3074          32 :         args = list_length(l) + 1;
    3075             : 
    3076          32 :         list = newInstructionArgs(mb, sqlRef, export_tableRef, args + 13);
    3077          32 :         if (list == NULL)
    3078             :                 return -1;
    3079          32 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3080          32 :         if( file >= 0){
    3081          32 :                 list = pushArgument(mb, list, file);
    3082          32 :                 list = pushStr(mb, list, format);
    3083          32 :                 list = pushStr(mb, list, sep);
    3084          32 :                 list = pushStr(mb, list, rsep);
    3085          32 :                 list = pushStr(mb, list, ssep);
    3086          32 :                 list = pushStr(mb, list, ns);
    3087          32 :                 list = pushInt(mb, list, onclient);
    3088             :         }
    3089          32 :         meta(tblPtr, tblId, TYPE_str, args);
    3090          32 :         meta(nmePtr, nmeId, TYPE_str, args);
    3091          32 :         meta(tpePtr, tpeId, TYPE_str, args);
    3092          32 :         meta(lenPtr, lenId, TYPE_int, args);
    3093          32 :         meta(scalePtr, scaleId, TYPE_int, args);
    3094          32 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    3095             :                 return -1;
    3096             : 
    3097         172 :         for (n = l->h; n; n = n->next) {
    3098         140 :                 stmt *c = n->data;
    3099         140 :                 sql_subtype *t = tail_type(c);
    3100         140 :                 sql_alias *tname = table_name(sql->sa, c);
    3101             : 
    3102         140 :                 const char *_empty = "";
    3103         140 :                 const char *tn = (tname) ? tname->name : _empty;
    3104         140 :                 const char *sn = (tname && tname->parent) ? tname->parent->name : _empty;
    3105         140 :                 const char *cn = column_name(sql->sa, c);
    3106         140 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3107         140 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3108         140 :                 size_t fqtnl;
    3109         140 :                 char *fqtn = NULL;
    3110             : 
    3111         140 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3112         140 :                         fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3113         140 :                         if (fqtn == NULL)
    3114             :                                 return -1;
    3115         140 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3116         140 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3117         140 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3118         140 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3119         140 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3120         140 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3121         140 :                         list = pushArgument(mb, list, c->nr);
    3122             :                 } else
    3123             :                         return -1;
    3124             :         }
    3125          32 :         sa_reset(sql->ta);
    3126          32 :         ret = getArg(list,0);
    3127          32 :         pushInstruction(mb,list);
    3128          32 :         return ret;
    3129             : }
    3130             : 
    3131             : 
    3132             : stmt *
    3133          32 : stmt_export(backend *be, stmt *t, const char *sep, const char *rsep, const char *ssep, const char *null_string, int onclient, stmt *file)
    3134             : {
    3135          32 :         MalBlkPtr mb = be->mb;
    3136          32 :         InstrPtr q = NULL;
    3137          32 :         int fnr;
    3138          32 :         list *l;
    3139             : 
    3140          32 :         if (t == NULL || t->nr < 0)
    3141           0 :                 goto bailout;
    3142          32 :         l = t->op4.lval;
    3143          32 :         if (file) {
    3144          23 :                 if (file->nr < 0)
    3145           0 :                         goto bailout;
    3146             :                 fnr = file->nr;
    3147             :         } else {
    3148           9 :                 q = newAssignment(mb);
    3149           9 :                 if (q == NULL)
    3150           0 :                         goto bailout;
    3151           9 :                 q = pushStr(mb,q,"stdout");
    3152           9 :                 fnr = getArg(q,0);
    3153           9 :                 pushInstruction(mb, q);
    3154             :         }
    3155          32 :         if (t->type == st_list) {
    3156          32 :                 if (dump_export_header(be->mvc, mb, l, fnr, "csv", sep, rsep, ssep, null_string, onclient) < 0)
    3157           0 :                         goto bailout;
    3158             :         } else {
    3159           0 :                 q = newStmt(mb, sqlRef, raiseRef);
    3160           0 :                 if (q == NULL)
    3161           0 :                         goto bailout;
    3162           0 :                 q = pushStr(mb, q, "not a valid output list\n");
    3163           0 :                 pushInstruction(mb, q);
    3164             :         }
    3165          32 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3166          32 :         if(!s) {
    3167           0 :                 goto bailout;
    3168             :         }
    3169          32 :         s->op1 = t;
    3170          32 :         s->op2 = file;
    3171          32 :         s->q = q;
    3172          32 :         s->nr = 1;
    3173          32 :         return s;
    3174             : 
    3175           0 :   bailout:
    3176           0 :         if (be->mvc->sa->eb.enabled)
    3177           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3178             :         return NULL;
    3179             : }
    3180             : 
    3181             : stmt *
    3182         150 : stmt_export_bin(backend *be, stmt *colstmt, bool byteswap, const char *filename, int on_client)
    3183             : {
    3184         150 :         MalBlkPtr mb = be->mb;
    3185         150 :         InstrPtr q;
    3186             : 
    3187         150 :         if (colstmt == NULL)
    3188           0 :                 goto bailout;
    3189         150 :         q = newStmt(mb, sqlRef, export_bin_columnRef);
    3190         150 :         if (q == NULL)
    3191           0 :                 goto bailout;
    3192         150 :         pushArgument(mb, q, colstmt->nr);
    3193         150 :         pushBit(mb, q, byteswap);
    3194         150 :         pushStr(mb, q, filename);
    3195         150 :         pushInt(mb, q, on_client);
    3196         150 :         pushInstruction(mb, q);
    3197             : 
    3198         150 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3199         150 :         if (!s)
    3200           0 :                 goto bailout;
    3201             : 
    3202         150 :         s->q = q;
    3203         150 :         return s;
    3204             : 
    3205           0 :   bailout:
    3206           0 :         if (be->mvc->sa->eb.enabled)
    3207           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3208             :         return NULL;
    3209             : }
    3210             : 
    3211             : stmt *
    3212        3160 : stmt_trans(backend *be, int type, stmt *chain, stmt *name)
    3213             : {
    3214        3160 :         MalBlkPtr mb = be->mb;
    3215        3160 :         InstrPtr q = NULL;
    3216             : 
    3217        3160 :         if (chain == NULL || chain->nr < 0)
    3218           0 :                 goto bailout;
    3219             : 
    3220        3160 :         switch(type){
    3221          13 :         case ddl_release:
    3222          13 :                 q = newStmt(mb, sqlRef, transaction_releaseRef);
    3223          13 :                 break;
    3224         556 :         case ddl_commit:
    3225         556 :                 q = newStmt(mb, sqlRef, transaction_commitRef);
    3226         556 :                 break;
    3227        1084 :         case ddl_rollback:
    3228        1084 :                 q = newStmt(mb, sqlRef, transaction_rollbackRef);
    3229        1084 :                 break;
    3230        1507 :         case ddl_trans:
    3231        1507 :                 q = newStmt(mb, sqlRef, transaction_beginRef);
    3232        1507 :                 break;
    3233           0 :         default:
    3234           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown transaction type\n");
    3235           0 :                 goto bailout;
    3236             :         }
    3237        3160 :         if (q == NULL)
    3238           0 :                 goto bailout;
    3239        3160 :         q = pushArgument(mb, q, chain->nr);
    3240        3160 :         if (name)
    3241          79 :                 q = pushArgument(mb, q, name->nr);
    3242             :         else
    3243        3081 :                 q = pushNil(mb, q, TYPE_str);
    3244             : 
    3245        3160 :         bool enabled = be->mvc->sa->eb.enabled;
    3246        3160 :         be->mvc->sa->eb.enabled = false;
    3247        3160 :         stmt *s = stmt_create(be->mvc->sa, st_trans);
    3248        3160 :         be->mvc->sa->eb.enabled = enabled;
    3249        3160 :         if(!s) {
    3250           0 :                 freeInstruction(q);
    3251           0 :                 goto bailout;
    3252             :         }
    3253        3160 :         s->op1 = chain;
    3254        3160 :         s->op2 = name;
    3255        3160 :         s->flag = type;
    3256        3160 :         s->q = q;
    3257        3160 :         s->nr = getDestVar(q);
    3258        3160 :         pushInstruction(mb, q);
    3259        3160 :         return s;
    3260             : 
    3261           0 :   bailout:
    3262           0 :         if (be->mvc->sa->eb.enabled)
    3263           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3264             :         return NULL;
    3265             : }
    3266             : 
    3267             : stmt *
    3268      291655 : stmt_catalog(backend *be, int type, stmt *args)
    3269             : {
    3270      291655 :         MalBlkPtr mb = be->mb;
    3271      291655 :         InstrPtr q = NULL;
    3272      291655 :         node *n;
    3273             : 
    3274      291655 :         if (args == NULL || args->nr < 0)
    3275           0 :                 goto bailout;
    3276             : 
    3277             :         /* cast them into properly named operations */
    3278      291655 :         const char *ref;
    3279      291655 :         switch(type){
    3280             :         case ddl_create_seq:                    ref = create_seqRef;            break;
    3281          47 :         case ddl_alter_seq:                             ref = alter_seqRef;                     break;
    3282          32 :         case ddl_drop_seq:                              ref = drop_seqRef;                      break;
    3283        1100 :         case ddl_create_schema:                 ref = create_schemaRef;         break;
    3284         193 :         case ddl_drop_schema:                   ref = drop_schemaRef;           break;
    3285       10242 :         case ddl_create_table:                  ref = create_tableRef;          break;
    3286       22911 :         case ddl_create_view:                   ref = create_viewRef;           break;
    3287        3753 :         case ddl_drop_table:                    ref = drop_tableRef;            break;
    3288         475 :         case ddl_drop_view:                             ref = drop_viewRef;                     break;
    3289         150 :         case ddl_drop_constraint:               ref = drop_constraintRef;       break;
    3290        1372 :         case ddl_alter_table:                   ref = alter_tableRef;           break;
    3291         944 :         case ddl_create_type:                   ref = create_typeRef;           break;
    3292          36 :         case ddl_drop_type:                             ref = drop_typeRef;                     break;
    3293          40 :         case ddl_grant_roles:                   ref = grant_rolesRef;           break;
    3294          10 :         case ddl_revoke_roles:                  ref = revoke_rolesRef;          break;
    3295       18907 :         case ddl_grant:                                 ref = grantRef;                         break;
    3296          15 :         case ddl_revoke:                                ref = revokeRef;                        break;
    3297      101527 :         case ddl_grant_func:                    ref = grant_functionRef;        break;
    3298           1 :         case ddl_revoke_func:                   ref = revoke_functionRef;       break;
    3299         362 :         case ddl_create_user:                   ref = create_userRef;           break;
    3300         107 :         case ddl_drop_user:                             ref = drop_userRef;                     break;
    3301          83 :         case ddl_alter_user:                    ref = alter_userRef;            break;
    3302           5 :         case ddl_rename_user:                   ref = rename_userRef;           break;
    3303          26 :         case ddl_create_role:                   ref = create_roleRef;           break;
    3304          19 :         case ddl_drop_role:                             ref = drop_roleRef;                     break;
    3305         160 :         case ddl_drop_index:                    ref = drop_indexRef;            break;
    3306         688 :         case ddl_drop_function:                 ref = drop_functionRef;         break;
    3307      124150 :         case ddl_create_function:               ref = create_functionRef;       break;
    3308         349 :         case ddl_create_trigger:                ref = create_triggerRef;        break;
    3309          84 :         case ddl_drop_trigger:                  ref = drop_triggerRef;          break;
    3310         312 :         case ddl_alter_table_add_table: ref = alter_add_tableRef;       break;
    3311         180 :         case ddl_alter_table_del_table: ref = alter_del_tableRef;       break;
    3312        2350 :         case ddl_alter_table_set_access:ref = alter_set_tableRef;       break;
    3313         225 :         case ddl_alter_table_add_range_partition: ref = alter_add_range_partitionRef; break;
    3314          60 :         case ddl_alter_table_add_list_partition: ref = alter_add_value_partitionRef; break;
    3315         358 :         case ddl_comment_on:                    ref = comment_onRef;            break;
    3316           8 :         case ddl_rename_schema:                 ref = rename_schemaRef;         break;
    3317          45 :         case ddl_rename_table:                  ref = rename_tableRef;          break;
    3318          13 :         case ddl_rename_column:                 ref = rename_columnRef;         break;
    3319           0 :         default:
    3320           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown catalog operation\n");
    3321           0 :                 goto bailout;
    3322             :         }
    3323      291655 :         q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
    3324      291656 :         if (q == NULL)
    3325           0 :                 goto bailout;
    3326             :         // pass all arguments as before
    3327     1743271 :         for (n = args->op4.lval->h; n; n = n->next) {
    3328     1451615 :                 stmt *c = n->data;
    3329             : 
    3330     1451615 :                 q = pushArgument(mb, q, c->nr);
    3331             :         }
    3332             : 
    3333      291656 :         bool enabled = be->mvc->sa->eb.enabled;
    3334      291656 :         be->mvc->sa->eb.enabled = false;
    3335      291656 :         stmt *s = stmt_create(be->mvc->sa, st_catalog);
    3336      291656 :         be->mvc->sa->eb.enabled = enabled;
    3337      291656 :         if(!s) {
    3338           0 :                 freeInstruction(q);
    3339           0 :                 goto bailout;
    3340             :         }
    3341      291656 :         s->op1 = args;
    3342      291656 :         s->flag = type;
    3343      291656 :         s->q = q;
    3344      291656 :         s->nr = getDestVar(q);
    3345      291656 :         pushInstruction(mb, q);
    3346      291656 :         return s;
    3347             : 
    3348           0 :   bailout:
    3349           0 :         if (be->mvc->sa->eb.enabled)
    3350           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3351             :         return NULL;
    3352             : }
    3353             : 
    3354             : void
    3355     1996050 : stmt_set_nrcols(stmt *s)
    3356             : {
    3357     1996050 :         unsigned nrcols = 0;
    3358     1996050 :         int key = 1;
    3359     1996050 :         node *n;
    3360     1996050 :         list *l = s->op4.lval;
    3361             : 
    3362     1996050 :         assert(s->type == st_list);
    3363     9481111 :         for (n = l->h; n; n = n->next) {
    3364     7485061 :                 stmt *f = n->data;
    3365             : 
    3366     7485061 :                 if (!f)
    3367           0 :                         continue;
    3368     7485061 :                 if (f->nrcols > nrcols)
    3369             :                         nrcols = f->nrcols;
    3370     7485061 :                 key &= f->key;
    3371     7485061 :                 s->nr = f->nr;
    3372             :         }
    3373     1996050 :         s->nrcols = nrcols;
    3374     1996050 :         s->key = key;
    3375     1996050 : }
    3376             : 
    3377             : stmt *
    3378     1581748 : stmt_list(backend *be, list *l)
    3379             : {
    3380     1581748 :         if (l == NULL)
    3381             :                 return NULL;
    3382     1581748 :         stmt *s = stmt_create(be->mvc->sa, st_list);
    3383     1581782 :         if(!s) {
    3384             :                 return NULL;
    3385             :         }
    3386     1581782 :         s->op4.lval = l;
    3387     1581782 :         stmt_set_nrcols(s);
    3388     1581782 :         return s;
    3389             : }
    3390             : 
    3391             : static InstrPtr
    3392       68610 : nested_dump_header(mvc *sql, MalBlkPtr mb, InstrPtr instrlist, InstrPtr tblPtr, InstrPtr nmePtr, InstrPtr tpePtr, InstrPtr lenPtr, InstrPtr scalePtr, InstrPtr multisetPtr, list *l)
    3393             : {
    3394       68610 :         if (list_empty(l))
    3395             :                 return instrlist;
    3396      354148 :         for (node *n = l->h; n; n = n->next) {
    3397      285539 :                 stmt *c = n->data;
    3398      285539 :                 sql_subtype *t = tail_type(c);
    3399      285545 :                 bool virt = (!c->q && c->type == st_alias && !c->op1 && c->multiset);
    3400      285545 :                 if (!c->nested && c->virt)
    3401           0 :                         continue;
    3402             : 
    3403      285545 :                 sql_alias *tname = table_name(sql->sa, c);
    3404      285547 :                 const char *_empty = "";
    3405      285547 :                 const char *tn = (tname) ? tname->name : _empty;
    3406             :                 //const char *sn = (sname) ? sname : _empty;
    3407      276514 :                 const char *sn = (tname && tname->parent) ? tname->parent->name : _empty;
    3408      285547 :                 const char *cn = column_name(sql->sa, c);
    3409      285541 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3410      285541 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3411      285555 :                 size_t fqtnl;
    3412             : 
    3413      285555 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3414      285555 :                         char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3415      285557 :                         if (fqtn == NULL)
    3416             :                                 return NULL;
    3417      285557 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3418      285557 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3419      285537 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3420      285534 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3421      285548 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3422      285536 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3423      285537 :                         if (virt || c->nested) {
    3424          13 :                                 multisetPtr = pushInt(mb, multisetPtr, c->subtype.multiset + ((virt || c->nested)?4:0));
    3425          13 :                                 InstrPtr q = newStmt(mb, batRef, newRef);
    3426             : 
    3427          13 :                                 if (q == NULL)
    3428             :                                         return NULL;
    3429          13 :                                 setVarType(mb, getArg(q, 0), newBatType(TYPE_void));
    3430          13 :                                 q = pushType(mb, q, TYPE_void);
    3431          13 :                                 pushInstruction(mb, q);
    3432          13 :                                 instrlist = pushArgument(mb, instrlist, getArg(q, 0));
    3433             : 
    3434          13 :                                 instrlist = nested_dump_header(sql, mb, instrlist, tblPtr, nmePtr, tpePtr, lenPtr, scalePtr, multisetPtr, unnest_stmt(c));
    3435          13 :                                 if (!instrlist)
    3436             :                                         return NULL;
    3437             :                         } else {
    3438      285524 :                                 multisetPtr = pushInt(mb, multisetPtr, 0);
    3439      285518 :                                 instrlist = pushArgument(mb, instrlist,c->nr);
    3440             :                         }
    3441             :                 } else {
    3442             :                         return NULL;
    3443             :                 }
    3444             :         }
    3445             :         return instrlist;
    3446             : }
    3447             : 
    3448             : static int
    3449       68594 : nested_len(list *l)
    3450             : {
    3451       68594 :         int nr = 0;
    3452       68594 :         if (list_empty(l))
    3453             :                 return 0;
    3454      354153 :         for(node *n = l->h; n; n = n->next) {
    3455      285547 :                 stmt *s = n->data;
    3456      285547 :                 if (s->nested)
    3457          13 :                         nr += nested_len(unnest_stmt(s)) + 1;
    3458             :                 else
    3459      285534 :                         nr++;
    3460             :         }
    3461             :         return nr;
    3462             : }
    3463             : 
    3464             : static InstrPtr
    3465       68582 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
    3466             : {
    3467             :         // gather the meta information
    3468       68582 :         int tblId, nmeId, tpeId, lenId, scaleId, multisetId;
    3469       68582 :         int args;
    3470       68582 :         InstrPtr list;
    3471       68582 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr, multisetPtr;
    3472             : 
    3473       68582 :         args = 1 + nested_len(l);
    3474             : 
    3475       68596 :         list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 6);
    3476       68591 :         if(!list)
    3477             :                 return NULL;
    3478             : 
    3479       68591 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3480       68589 :         meta(tblPtr, tblId, TYPE_str, args);
    3481       68596 :         meta(nmePtr, nmeId, TYPE_str, args);
    3482       68597 :         meta(tpePtr, tpeId, TYPE_str, args);
    3483       68597 :         meta(lenPtr, lenId, TYPE_int, args);
    3484       68597 :         meta(scalePtr, scaleId, TYPE_int, args);
    3485       68597 :         meta(multisetPtr, multisetId, TYPE_int, args);
    3486       68597 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL || multisetPtr == NULL)
    3487             :                 return NULL;
    3488       68597 :         list = nested_dump_header(sql, mb, list, tblPtr, nmePtr, tpePtr, lenPtr, scalePtr, multisetPtr, l);
    3489       68595 :         sa_reset(sql->ta);
    3490       68574 :         if (list)
    3491       68574 :                 pushInstruction(mb, list);
    3492             :         return list;
    3493             : }
    3494             : 
    3495             : int
    3496      128978 : stmt_output(backend *be, stmt *lst)
    3497             : {
    3498      128978 :         MalBlkPtr mb = be->mb;
    3499      128978 :         InstrPtr q = NULL;
    3500      128978 :         list *l = lst->op4.lval;
    3501      128978 :         int cnt = list_length(l), ok = 0;
    3502      129054 :         node *n = l->h;
    3503      129054 :         stmt *first = n->data;
    3504             : 
    3505             :         /* single value result, has a fast exit */
    3506      129054 :         if (cnt == 1 && first->nrcols <= 0 ){
    3507       60428 :                 stmt *c = n->data;
    3508       60428 :                 sql_subtype *t = tail_type(c);
    3509       60440 :                 sql_alias *tname = table_name(be->mvc->sa, c);
    3510       60394 :                 const char *_empty = "";
    3511       60394 :                 const char *tn = (tname) ? tname->name : _empty;
    3512       59968 :                 const char *sn = (tname && tname->parent) ? tname->parent->name : _empty;
    3513       60394 :                 const char *cn = column_name(be->mvc->sa, c);
    3514       60385 :                 const char *ntn = sql_escape_ident(be->mvc->ta, tn);
    3515       60497 :                 const char *nsn = sql_escape_ident(be->mvc->ta, sn);
    3516             : 
    3517       60506 :                 if (ntn && nsn) {
    3518       60506 :                         size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
    3519       60506 :                         char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
    3520       60505 :                         if (fqtn == NULL)
    3521             :                                 return -1;
    3522       60505 :                         ok = 1;
    3523       60505 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3524             : 
    3525       60505 :                         q = newStmt(mb, sqlRef, resultSetRef);
    3526       60506 :                         if (q == NULL)
    3527             :                                 return -1;
    3528       60506 :                         getArg(q,0) = newTmpVariable(mb,TYPE_int);
    3529       60507 :                         q = pushStr(mb, q, fqtn);
    3530       60505 :                         q = pushStr(mb, q, cn);
    3531       60507 :                         q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
    3532       60506 :                         q = pushInt(mb, q, t->digits);
    3533       60497 :                         q = pushInt(mb, q, t->scale);
    3534       60506 :                         q = pushInt(mb, q, t->type->eclass);
    3535       60502 :                         q = pushInt(mb, q, t->multiset);
    3536       60494 :                         q = pushArgument(mb, q, c->nr);
    3537       60510 :                         pushInstruction(mb, q);
    3538             :                 }
    3539       60500 :                 sa_reset(be->mvc->ta);
    3540       60490 :                 if (!ok)
    3541             :                         return -1;
    3542             :         } else {
    3543       68626 :                 if ((q = dump_header(be->mvc, mb, l)) == NULL)
    3544             :                         return -1;
    3545             :         }
    3546             :         return 0;
    3547             : }
    3548             : 
    3549             : int
    3550      149571 : stmt_affected_rows(backend *be, int lastnr)
    3551             : {
    3552      149571 :         MalBlkPtr mb = be->mb;
    3553      149571 :         InstrPtr q = NULL;
    3554             : 
    3555      149571 :         q = newStmt(mb, sqlRef, affectedRowsRef);
    3556      149817 :         if (q == NULL)
    3557             :                 return -1;
    3558      149817 :         q = pushArgument(mb, q, be->mvc_var);
    3559      149815 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    3560      149817 :         q = pushArgument(mb, q, lastnr);
    3561      149819 :         pushInstruction(mb, q);
    3562      149827 :         be->mvc_var = getDestVar(q);
    3563      149827 :         return 0;
    3564             : }
    3565             : 
    3566             : stmt *
    3567      178079 : stmt_append(backend *be, stmt *c, stmt *a)
    3568             : {
    3569      178079 :         MalBlkPtr mb = be->mb;
    3570      178079 :         InstrPtr q = NULL;
    3571             : 
    3572      178079 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3573           0 :                 goto bailout;
    3574      178079 :         if (c->nested)
    3575           0 :                 return stmt_nest(be, c, a, &stmt_append);
    3576      178079 :         q = newStmt(mb, batRef, appendRef);
    3577      178079 :         if (q == NULL)
    3578           0 :                 goto bailout;
    3579      178079 :         q = pushArgument(mb, q, c->nr);
    3580      178079 :         q = pushArgument(mb, q, a->nr);
    3581      178079 :         q = pushBit(mb, q, TRUE);
    3582      178079 :         bool enabled = be->mvc->sa->eb.enabled;
    3583      178079 :         be->mvc->sa->eb.enabled = false;
    3584      178079 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3585      178079 :         be->mvc->sa->eb.enabled = enabled;
    3586      178079 :         if(!s) {
    3587           0 :                 freeInstruction(q);
    3588           0 :                 goto bailout;
    3589             :         }
    3590      178079 :         s->op1 = c;
    3591      178079 :         s->op2 = a;
    3592      178079 :         s->nrcols = c->nrcols;
    3593      178079 :         s->key = c->key;
    3594      178079 :         s->nr = getDestVar(q);
    3595      178079 :         s->q = q;
    3596      178079 :         pushInstruction(mb, q);
    3597      178079 :         return s;
    3598             : 
    3599           0 :   bailout:
    3600           0 :         if (be->mvc->sa->eb.enabled)
    3601           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3602             :         return NULL;
    3603             : }
    3604             : 
    3605             : stmt *
    3606      137888 : stmt_append_bulk(backend *be, stmt *c, list *l)
    3607             : {
    3608      137888 :         MalBlkPtr mb = be->mb;
    3609      137888 :         InstrPtr q = NULL;
    3610      137888 :         bool needs_columns = false;
    3611      137888 :         bool ms = false;
    3612             : 
    3613      137888 :         if (c->nr < 0)
    3614           0 :                 goto bailout;
    3615             : 
    3616             :         /* currently appendBulk accepts its inputs all either scalar or vectors
    3617             :            if there is one vector and any scala, then the scalars mut be upgraded to vectors */
    3618      890712 :         for (node *n = l->h; n; n = n->next) {
    3619      752824 :                 stmt *t = n->data;
    3620      752824 :                 needs_columns |= t->nrcols > 0;
    3621             :         }
    3622      137888 :         if (needs_columns) {
    3623         122 :                 for (node *n = l->h; n; n = n->next) {
    3624          84 :                         stmt *t = n->data;
    3625          84 :                         if (t->nrcols == 0)
    3626           0 :                                 n->data = const_column(be, t);
    3627          84 :                         if (t->multiset)
    3628          36 :                                 ms = true;
    3629             :                 }
    3630             :         }
    3631             : 
    3632      137888 :         q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3 + (ms?1:0));
    3633      138221 :         if (q == NULL)
    3634           0 :                 goto bailout;
    3635      138221 :         q = pushArgument(mb, q, c->nr);
    3636      138219 :         q = pushBit(mb, q, TRUE);
    3637      138108 :         if (ms)
    3638          16 :                 q = pushBit(mb, q, TRUE);
    3639      890995 :         for (node *n = l->h ; n ; n = n->next) {
    3640      752857 :                 stmt *a = n->data;
    3641      752857 :                 q = pushArgument(mb, q, a->nr);
    3642             :         }
    3643      138138 :         bool enabled = be->mvc->sa->eb.enabled;
    3644      138138 :         be->mvc->sa->eb.enabled = false;
    3645      138138 :         stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
    3646      137971 :         be->mvc->sa->eb.enabled = enabled;
    3647      137971 :         if(!s) {
    3648           0 :                 freeInstruction(q);
    3649           0 :                 goto bailout;
    3650             :         }
    3651      137971 :         s->op1 = c;
    3652      137971 :         s->op4.lval = l;
    3653      137971 :         s->nrcols = c->nrcols;
    3654      137971 :         s->key = c->key;
    3655      137971 :         s->nr = getDestVar(q);
    3656      137971 :         s->q = q;
    3657      137971 :         pushInstruction(mb, q);
    3658      137971 :         return s;
    3659             : 
    3660           0 :   bailout:
    3661           0 :         if (be->mvc->sa->eb.enabled)
    3662           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3663             :         return NULL;
    3664             : }
    3665             : 
    3666             : stmt *
    3667       16470 : stmt_pack(backend *be, stmt *c, int n)
    3668             : {
    3669       16470 :         MalBlkPtr mb = be->mb;
    3670       16470 :         InstrPtr q = NULL;
    3671             : 
    3672       16470 :         if (c == NULL || c->nr < 0)
    3673           0 :                 goto bailout;
    3674       16470 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3675       16470 :         if (q == NULL)
    3676           0 :                 goto bailout;
    3677       16470 :         q = pushArgument(mb, q, c->nr);
    3678       16470 :         q = pushInt(mb, q, n);
    3679       16470 :         bool enabled = be->mvc->sa->eb.enabled;
    3680       16470 :         be->mvc->sa->eb.enabled = false;
    3681       16470 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3682       16470 :         be->mvc->sa->eb.enabled = enabled;
    3683       16470 :         if(!s) {
    3684           0 :                 freeInstruction(q);
    3685           0 :                 goto bailout;
    3686             :         }
    3687       16470 :         s->op1 = c;
    3688       16470 :         s->nrcols = c->nrcols;
    3689       16470 :         s->key = c->key;
    3690       16470 :         s->nr = getDestVar(q);
    3691       16470 :         s->q = q;
    3692       16470 :         pushInstruction(mb, q);
    3693       16470 :         return s;
    3694             : 
    3695           0 :   bailout:
    3696           0 :         if (be->mvc->sa->eb.enabled)
    3697           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3698             :         return NULL;
    3699             : 
    3700             : }
    3701             : 
    3702             : stmt *
    3703       30169 : stmt_pack_add(backend *be, stmt *c, stmt *a)
    3704             : {
    3705       30169 :         MalBlkPtr mb = be->mb;
    3706       30169 :         InstrPtr q = NULL;
    3707             : 
    3708       30169 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3709           0 :                 goto bailout;
    3710       30169 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3711       30169 :         if (q == NULL)
    3712           0 :                 goto bailout;
    3713       30169 :         q = pushArgument(mb, q, c->nr);
    3714       30169 :         q = pushArgument(mb, q, a->nr);
    3715       30169 :         bool enabled = be->mvc->sa->eb.enabled;
    3716       30169 :         be->mvc->sa->eb.enabled = false;
    3717       30169 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3718       30169 :         be->mvc->sa->eb.enabled = enabled;
    3719       30169 :         if(!s) {
    3720           0 :                 freeInstruction(q);
    3721           0 :                 goto bailout;
    3722             :         }
    3723       30169 :         s->op1 = c;
    3724       30169 :         s->op2 = a;
    3725       30169 :         s->nrcols = c->nrcols;
    3726       30169 :         s->key = c->key;
    3727       30169 :         s->nr = getDestVar(q);
    3728       30169 :         s->q = q;
    3729       30169 :         pushInstruction(mb, q);
    3730       30169 :         return s;
    3731             : 
    3732           0 :   bailout:
    3733           0 :         if (be->mvc->sa->eb.enabled)
    3734           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3735             :         return NULL;
    3736             : }
    3737             : 
    3738             : stmt *
    3739      106528 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
    3740             : {
    3741      106528 :         MalBlkPtr mb = be->mb;
    3742      106528 :         InstrPtr q = NULL;
    3743             : 
    3744      106528 :         if (!t || cnt->nr < 0)
    3745           0 :                 goto bailout;
    3746      106528 :         assert(t->s);                                /* declared table */
    3747      106528 :         q = newStmtArgs(mb, sqlRef, claimRef, 6);
    3748      106588 :         if (q == NULL)
    3749           0 :                 goto bailout;
    3750             :         /* returns offset or offsets */
    3751      106588 :         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
    3752      106579 :         q = pushArgument(mb, q, be->mvc_var);
    3753      106574 :         q = pushSchema(mb, q, t);
    3754      106547 :         q = pushStr(mb, q, t->base.name);
    3755      106567 :         q = pushArgument(mb, q, cnt->nr);
    3756      106570 :         bool enabled = be->mvc->sa->eb.enabled;
    3757      106570 :         be->mvc->sa->eb.enabled = false;
    3758      106570 :         stmt *s = stmt_create(be->mvc->sa, st_claim);
    3759      106518 :         be->mvc->sa->eb.enabled = enabled;
    3760      106518 :         if(!s) {
    3761           0 :                 freeInstruction(q);
    3762           0 :                 goto bailout;
    3763             :         }
    3764      106518 :         s->op1 = cnt;
    3765      106518 :         s->op4.tval = t;
    3766      106518 :         s->nr = getDestVar(q);
    3767      106518 :         s->q = q;
    3768      106518 :         pushInstruction(mb, q);
    3769      106518 :         return s;
    3770             : 
    3771           0 :   bailout:
    3772           0 :         if (be->mvc->sa->eb.enabled)
    3773           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3774             :         return NULL;
    3775             : }
    3776             : 
    3777             : void
    3778      149578 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
    3779             : {
    3780      149578 :         MalBlkPtr mb = be->mb;
    3781      149578 :         InstrPtr q = NULL;
    3782             : 
    3783      149578 :         if (!t || cnt->nr < 0)
    3784           0 :                 goto bailout;
    3785      149578 :         q = newStmtArgs(mb, sqlRef, dependRef, 4);
    3786      150056 :         if (q == NULL)
    3787           0 :                 goto bailout;
    3788      150056 :         q = pushSchema(mb, q, t);
    3789      150048 :         q = pushStr(mb, q, t->base.name);
    3790      150057 :         q = pushArgument(mb, q, cnt->nr);
    3791      150060 :         pushInstruction(mb, q);
    3792      150060 :         return;
    3793             : 
    3794           0 :   bailout:
    3795           0 :         if (be->mvc->sa->eb.enabled)
    3796           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);
    3797             : }
    3798             : 
    3799             : void
    3800       14936 : stmt_add_column_predicate(backend *be, sql_column *c)
    3801             : {
    3802       14936 :         MalBlkPtr mb = be->mb;
    3803       14936 :         InstrPtr q = NULL;
    3804             : 
    3805       14936 :         if (!c)
    3806           0 :                 goto bailout;
    3807       14936 :         q = newStmtArgs(mb, sqlRef, predicateRef, 4);
    3808       14980 :         if (q == NULL)
    3809           0 :                 goto bailout;
    3810       14980 :         q = pushSchema(mb, q, c->t);
    3811       14978 :         q = pushStr(mb, q, c->t->base.name);
    3812       14978 :         q = pushStr(mb, q, c->base.name);
    3813       14980 :         pushInstruction(mb, q);
    3814       14980 :         return;
    3815             : 
    3816           0 :   bailout:
    3817           0 :         if (be->mvc->sa->eb.enabled)
    3818           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);
    3819             : }
    3820             : 
    3821             : stmt *
    3822       55832 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
    3823             : {
    3824       55832 :         MalBlkPtr mb = be->mb;
    3825       55832 :         InstrPtr q = NULL;
    3826             : 
    3827       55832 :         if (r->nr < 0)
    3828           0 :                 goto bailout;
    3829             : 
    3830       55832 :         q = newStmt(mb, batRef, replaceRef);
    3831       55832 :         if (q == NULL)
    3832           0 :                 goto bailout;
    3833       55832 :         q = pushArgument(mb, q, r->nr);
    3834       55832 :         q = pushArgument(mb, q, id->nr);
    3835       55832 :         q = pushArgument(mb, q, val->nr);
    3836       55832 :         q = pushBit(mb, q, TRUE); /* forced */
    3837       55832 :         bool enabled = be->mvc->sa->eb.enabled;
    3838       55832 :         be->mvc->sa->eb.enabled = false;
    3839       55832 :         stmt *s = stmt_create(be->mvc->sa, st_replace);
    3840       55832 :         be->mvc->sa->eb.enabled = enabled;
    3841       55832 :         if(!s) {
    3842           0 :                 freeInstruction(q);
    3843           0 :                 goto bailout;
    3844             :         }
    3845       55832 :         s->op1 = r;
    3846       55832 :         s->op2 = id;
    3847       55832 :         s->op3 = val;
    3848       55832 :         s->nrcols = r->nrcols;
    3849       55832 :         s->key = r->key;
    3850       55832 :         s->nr = getDestVar(q);
    3851       55832 :         s->q = q;
    3852       55832 :         s->cand = r->cand;
    3853       55832 :         pushInstruction(mb, q);
    3854       55832 :         return s;
    3855             : 
    3856           0 :   bailout:
    3857           0 :         if (be->mvc->sa->eb.enabled)
    3858           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3859             :         return NULL;
    3860             : }
    3861             : 
    3862             : stmt *
    3863       41425 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
    3864             : {
    3865       41425 :         MalBlkPtr mb = be->mb;
    3866       41425 :         InstrPtr q = NULL;
    3867             : 
    3868       41425 :         if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
    3869           2 :                 int *l = ATOMIC_PTR_GET(&t->data), cnt = ol_length(t->columns)+1;
    3870             : 
    3871           6 :                 for (int i = 0; i < cnt; i++) {
    3872           4 :                         q = newStmt(mb, batRef, deleteRef);
    3873           4 :                         if (q == NULL)
    3874           0 :                                 goto bailout;
    3875           4 :                         q = pushArgument(mb, q, l[i]);
    3876           4 :                         pushInstruction(mb, q);
    3877             :                 }
    3878             :                 /* declared tables don't have sequences */
    3879             :         } else {
    3880       41423 :                 q = newStmt(mb, sqlRef, clear_tableRef);
    3881       41825 :                 if (q == NULL)
    3882           0 :                         goto bailout;
    3883       41825 :                 q = pushSchema(mb, q, t);
    3884       41816 :                 q = pushStr(mb, q, t->base.name);
    3885       41776 :                 q = pushInt(mb, q, restart_sequences);
    3886       41751 :                 pushInstruction(mb, q);
    3887             :         }
    3888       41767 :         stmt *s = stmt_create(be->mvc->sa, st_table_clear);
    3889             : 
    3890       41673 :         if(!s) {
    3891           0 :                 goto bailout;
    3892             :         }
    3893       41673 :         s->op4.tval = t;
    3894       41673 :         s->nrcols = 0;
    3895       41673 :         s->nr = getDestVar(q);
    3896       41673 :         s->q = q;
    3897       41673 :         return s;
    3898             : 
    3899           0 :   bailout:
    3900           0 :         if (be->mvc->sa->eb.enabled)
    3901           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3902             :         return NULL;
    3903             : }
    3904             : 
    3905             : stmt *
    3906       39659 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
    3907             : {
    3908       39659 :         MalBlkPtr mb = be->mb;
    3909       39659 :         InstrPtr q = NULL;
    3910             : 
    3911       39659 :         if (cond->nr < 0)
    3912             :                 return NULL;
    3913             : 
    3914             :         /* if(bit(l)) { error(r);}  ==raising an exception */
    3915       39659 :         q = newStmt(mb, sqlRef, assertRef);
    3916       39702 :         if (q == NULL)
    3917           0 :                 goto bailout;
    3918       39702 :         q = pushArgument(mb, q, cond->nr);
    3919       39702 :         q = pushStr(mb, q, errstr);
    3920       39702 :         bool enabled = be->mvc->sa->eb.enabled;
    3921       39702 :         be->mvc->sa->eb.enabled = false;
    3922       39702 :         stmt *s = stmt_create(be->mvc->sa, st_exception);
    3923       39701 :         be->mvc->sa->eb.enabled = enabled;
    3924       39701 :         if(!s) {
    3925           0 :                 freeInstruction(q);
    3926           0 :                 return NULL;
    3927             :         }
    3928       39701 :         assert(cond);
    3929       39701 :         s->op1 = cond;
    3930       39701 :         (void)errcode;
    3931       39701 :         s->nrcols = 0;
    3932       39701 :         s->q = q;
    3933       39701 :         s->nr = getDestVar(q);
    3934       39701 :         pushInstruction(mb, q);
    3935       39701 :         return s;
    3936             : 
    3937           0 :   bailout:
    3938           0 :         if (be->mvc->sa->eb.enabled)
    3939           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3940             :         return NULL;
    3941             : }
    3942             : 
    3943             : /* The type setting is not propagated to statements such as st_bat and st_append,
    3944             :         because they are not considered projections */
    3945             : static void
    3946       18024 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
    3947             : {
    3948       44557 :         for (;;) {
    3949       44557 :                 switch (st->type) {
    3950        3689 :                 case st_const:
    3951        3689 :                         st = st->op2;
    3952        3689 :                         continue;
    3953       18749 :                 case st_alias:
    3954             :                 case st_gen_group:
    3955             :                 case st_order:
    3956       18749 :                         st = st->op1;
    3957       18749 :                         continue;
    3958           0 :                 case st_list:
    3959           0 :                         st = st->op4.lval->h->data;
    3960           0 :                         continue;
    3961        4095 :                 case st_join:
    3962             :                 case st_join2:
    3963             :                 case st_joinN:
    3964        4095 :                         if (st->flag == cmp_project) {
    3965        4095 :                                 st = st->op2;
    3966        4095 :                                 continue;
    3967             :                         }
    3968             :                         return;
    3969        2782 :                 case st_aggr:
    3970             :                 case st_Nop: {
    3971        2782 :                         list *res = st->op4.funcval->res;
    3972             : 
    3973        2782 :                         if (res && list_length(res) == 1)
    3974        2782 :                                 res->h->data = t;
    3975             :                         return;
    3976             :                 }
    3977        9193 :                 case st_atom:
    3978        9193 :                         st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
    3979        9193 :                         return;
    3980          60 :                 case st_convert:
    3981             :                 case st_temp:
    3982             :                 case st_single:
    3983          60 :                         st->subtype = *t;
    3984          60 :                         return;
    3985          86 :                 case st_var:
    3986          86 :                         if (st->subtype.type)
    3987          86 :                                 st->subtype = *t;
    3988             :                         return;
    3989             :                 default:
    3990             :                         return;
    3991             :                 }
    3992             :         }
    3993             : }
    3994             : 
    3995             : #define trivial_string_conversion(x) ((x) == EC_BIT || (x) == EC_CHAR || (x) == EC_STRING || (x) == EC_NUM || (x) == EC_POS || (x) == EC_FLT \
    3996             :                                                                           || (x) == EC_DATE || (x) == EC_BLOB || (x) == EC_MONTH)
    3997             : 
    3998             : static stmt *
    3999         352 : temporal_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t, bool before)
    4000             : {
    4001         352 :         MalBlkPtr mb = be->mb;
    4002         352 :         InstrPtr q = NULL;
    4003         352 :         const char *convert = t->type->d.impl, *mod = mtimeRef;
    4004         352 :         bool add_tz = false, pushed = (v->cand && v->cand == sel), cand = 0;
    4005             : 
    4006         352 :         if (before) {
    4007         291 :                 if (f->type->eclass == EC_TIMESTAMP_TZ && (t->type->eclass == EC_TIMESTAMP || t->type->eclass == EC_TIME)) {
    4008             :                         /* call timestamp+local_timezone */
    4009             :                         convert = "timestamp_add_msec_interval";
    4010             :                         add_tz = true;
    4011         211 :                 } else if (f->type->eclass == EC_TIMESTAMP_TZ && t->type->eclass == EC_DATE) {
    4012             :                         /* call convert timestamp with tz to date */
    4013             :                         convert = "datetz";
    4014             :                         mod = calcRef;
    4015             :                         add_tz = true;
    4016         198 :                 } else if (f->type->eclass == EC_TIMESTAMP && t->type->eclass == EC_TIMESTAMP_TZ) {
    4017             :                         /* call timestamp+local_timezone */
    4018             :                         convert = "timestamp_sub_msec_interval";
    4019             :                         add_tz = true;
    4020         159 :                 } else if (f->type->eclass == EC_TIME_TZ && (t->type->eclass == EC_TIME || t->type->eclass == EC_TIMESTAMP)) {
    4021             :                         /* call times+local_timezone */
    4022             :                         convert = "time_add_msec_interval";
    4023             :                         add_tz = true;
    4024         146 :                 } else if (f->type->eclass == EC_TIME && t->type->eclass == EC_TIME_TZ) {
    4025             :                         /* call times+local_timezone */
    4026             :                         convert = "time_sub_msec_interval";
    4027             :                         add_tz = true;
    4028         131 :                 } else if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass)) {
    4029         124 :                         if (t->type->eclass == EC_TIME_TZ)
    4030             :                                 convert = "daytimetz";
    4031             :                         else
    4032         100 :                                 convert = "timestamptz";
    4033             :                         mod = calcRef;
    4034             :                         add_tz = true;
    4035             :                         cand = 1;
    4036             :                 } else {
    4037             :                         return v;
    4038             :                 }
    4039             :         } else {
    4040          61 :                 if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIMESTAMP_TZ) {
    4041             :                         convert = "timestamp_sub_msec_interval";
    4042             :                         add_tz = true;
    4043          56 :                 } else if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIME_TZ) {
    4044             :                         convert = "time_sub_msec_interval";
    4045             :                         add_tz = true;
    4046             :                 } else {
    4047             :                         return v;
    4048             :                 }
    4049             :         }
    4050             : 
    4051         289 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    4052         171 :                 q = newStmtArgs(mb, mod, convert, 13);
    4053         171 :                 if (q == NULL)
    4054           0 :                         goto bailout;
    4055             :         } else {
    4056         118 :                 if (sel && !pushed && v->nrcols == 0) {
    4057           1 :                         pushed = 1;
    4058           1 :                         v = stmt_project(be, sel, v);
    4059           1 :                         v->cand = sel;
    4060             :                 }
    4061         193 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    4062         118 :                 if (q == NULL)
    4063           0 :                         goto bailout;
    4064             :         }
    4065         289 :         q = pushArgument(mb, q, v->nr);
    4066             : 
    4067         289 :         if (cand) {
    4068         124 :                 if (sel && !pushed && !v->cand) {
    4069          14 :                         q = pushArgument(mb, q, sel->nr);
    4070          14 :                         pushed = 1;
    4071         110 :                 } else if (v->nrcols > 0) {
    4072          18 :                         q = pushNilBat(mb, q);
    4073             :                 }
    4074             :         }
    4075             : 
    4076         289 :         if (EC_VARCHAR(f->type->eclass))
    4077         124 :                 q = pushInt(mb, q, t->digits);
    4078             : 
    4079         289 :         if (add_tz)
    4080         289 :                         q = pushLng(mb, q, be->mvc->timezone);
    4081             : 
    4082         289 :         if (!cand) {
    4083         165 :                 if (sel && !pushed && !v->cand) {
    4084           2 :                         q = pushArgument(mb, q, sel->nr);
    4085           2 :                         pushed = 1;
    4086         163 :                 } else if (v->nrcols > 0) {
    4087          84 :                         q = pushNilBat(mb, q);
    4088             :                 }
    4089             :         }
    4090             : 
    4091         289 :         bool enabled = be->mvc->sa->eb.enabled;
    4092         289 :         be->mvc->sa->eb.enabled = false;
    4093         289 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4094         289 :         be->mvc->sa->eb.enabled = enabled;
    4095         289 :         if(!s) {
    4096           0 :                 freeInstruction(q);
    4097           0 :                 goto bailout;
    4098             :         }
    4099         289 :         s->op1 = v;
    4100         289 :         s->nrcols = 0;       /* function without arguments returns single value */
    4101         289 :         s->key = v->key;
    4102         289 :         s->nrcols = v->nrcols;
    4103         289 :         s->aggr = v->aggr;
    4104         289 :         s->subtype = *t;
    4105         289 :         s->nr = getDestVar(q);
    4106         289 :         s->q = q;
    4107         289 :         s->cand = pushed ? sel : NULL;
    4108         289 :         pushInstruction(mb, q);
    4109         289 :         return s;
    4110             : 
    4111           0 :   bailout:
    4112           0 :         if (be->mvc->sa->eb.enabled)
    4113           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4114             :         return NULL;
    4115             : }
    4116             : 
    4117             : static int
    4118         106 : composite_type_resultsize(sql_subtype *t)
    4119             : {
    4120         106 :         int nr = 0;
    4121             : 
    4122         106 :         if (t->multiset)
    4123          27 :                 nr += 2 + (t->multiset == MS_ARRAY);
    4124         106 :         if (t->type->composite) {
    4125         117 :                 for (node *n = t->type->d.fields->h; n; n = n->next) {
    4126          79 :                         sql_arg *a = n->data;
    4127          79 :                         nr += composite_type_resultsize(&a->type);
    4128             :                 }
    4129             :         } else {
    4130          68 :                 nr++;
    4131             :         }
    4132         106 :         return nr;
    4133             : }
    4134             : 
    4135             : typedef struct result_subtype {
    4136             :         sql_subtype st;
    4137             :         bool multiset; /* multiset id */
    4138             : } result_subtype;
    4139             : 
    4140             : /* mark multiset rowid and msid as multiset, for later id correction */
    4141             : static int
    4142         106 : composite_type_result(backend *be, InstrPtr q, sql_subtype *t, result_subtype *tps)
    4143             : {
    4144         106 :         int i = 0;
    4145         106 :         if (t->multiset || t->type->composite) {
    4146          51 :                 if (t->type->composite) {
    4147         117 :                         for (node *n = t->type->d.fields->h; n; n = n->next) {
    4148          79 :                                 sql_arg *a = n->data;
    4149          79 :                                 int r = 0;
    4150          79 :                                 if ((r = composite_type_result(be, q, &a->type, tps+i)) < 0)
    4151             :                                         return -1;
    4152          79 :                                 i += r;
    4153             :                         }
    4154             :                 } else {
    4155          13 :                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, newBatType(t->type->localtype)));
    4156          13 :                         tps[i].st = *t;
    4157          13 :                         tps[i++].multiset = false;
    4158             :                 }
    4159          51 :                 if (t->multiset) { /* msid */
    4160          27 :                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, newBatType(TYPE_int)));
    4161          27 :                         tps[i].st = *sql_bind_localtype("int");
    4162          27 :                         tps[i++].multiset = true;
    4163             :                 }
    4164          51 :                 if (t->multiset == MS_ARRAY) { /* msnr */
    4165          27 :                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, newBatType(TYPE_int)));
    4166          27 :                         tps[i].st = *sql_bind_localtype("int");
    4167          27 :                         tps[i++].multiset = false;
    4168             :                 }
    4169             :                 /* end with the rowid */
    4170          51 :                 if (t->multiset) { /* id col : rowid */
    4171          27 :                         q = pushReturn(be->mb, q, newTmpVariable(be->mb, newBatType(TYPE_int)));
    4172          27 :                         tps[i].st = *sql_bind_localtype("int");
    4173          27 :                         tps[i++].multiset = true;
    4174             :                 }
    4175             :         } else {
    4176          55 :                 q = pushReturn(be->mb, q, newTmpVariable(be->mb, newBatType(t->type->localtype)));
    4177          55 :                 tps[i].st = *t;
    4178          55 :                 tps[i++].multiset = false;
    4179             :         }
    4180             :         return i;
    4181             : }
    4182             : 
    4183             : static void
    4184           0 : nested_to_json(backend *be, InstrPtr q, list *l)
    4185             : {
    4186           0 :         for(node *n = l->h; n; n = n->next) {
    4187           0 :                 stmt *s = n->data;
    4188           0 :                 if (s->nested) {
    4189           0 :                         nested_to_json(be, q, unnest_stmt(s));
    4190             :                 } else {
    4191           0 :                         pushArgument(be->mb, q, s->nr);
    4192             :                 }
    4193             :         }
    4194           0 : }
    4195             : 
    4196             : static stmt *
    4197           0 : stmt_to_json(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    4198             : {
    4199             :         /* to_json(json res, ptr st, bats vararg) 1, 3 */
    4200           0 :         int nrcols = nested_len(unnest_stmt(v));
    4201           0 :         (void)sel;
    4202             : 
    4203           0 :         InstrPtr q = newStmtArgs(be->mb, "sql", "to_json", nrcols + 2);
    4204           0 :         setVarType(be->mb, getArg(q, 0), t->type->localtype);
    4205           0 :         q = pushPtr(be->mb, q, f);
    4206           0 :         nested_to_json(be, q, unnest_stmt(v));
    4207             : 
    4208           0 :         bool enabled = be->mvc->sa->eb.enabled;
    4209           0 :         be->mvc->sa->eb.enabled = false;
    4210           0 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4211           0 :         be->mvc->sa->eb.enabled = enabled;
    4212           0 :         if(!s) {
    4213           0 :                 freeInstruction(q);
    4214           0 :                 goto bailout;
    4215             :         }
    4216           0 :         s->op1 = v;
    4217           0 :         s->nrcols = 2;
    4218           0 :         s->key = v->key;
    4219           0 :         s->aggr = v->aggr;
    4220           0 :         s->subtype = *t;
    4221           0 :         s->nr = getDestVar(q);
    4222           0 :         s->q = q;
    4223             :         //s->cand = pushed ? sel : NULL;
    4224           0 :         pushInstruction(be->mb, q);
    4225           0 :         return s;
    4226           0 : bailout:
    4227           0 :         if (be->mvc->sa->eb.enabled)
    4228           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);
    4229             :         return NULL;
    4230             : }
    4231             : 
    4232             : /* for each result create stmt_result and return stmt list */
    4233             : static stmt *
    4234          27 : result_list(backend *be, InstrPtr q, int cur, result_subtype *tps, int nrcols)
    4235             : {
    4236          27 :         list *r = sa_list(be->mvc->sa);
    4237         176 :         for(int i = cur; i < nrcols; i++) {
    4238         149 :                 stmt *br = stmt_blackbox_result(be, q, i, &tps[i].st);
    4239         149 :                 append(r, br);
    4240         149 :                 if (tps[i].multiset)
    4241          54 :                         br->multiset = true;
    4242             :         }
    4243          27 :         return stmt_list(be, r);
    4244             : }
    4245             : 
    4246             : static stmt *
    4247           7 : stmt_from_json(backend *be, stmt *v, stmt *sel, sql_subtype *t)
    4248             : {
    4249           7 :         (void)sel;
    4250           7 :         int nrcols = composite_type_resultsize(t);
    4251           7 :         result_subtype *tps = SA_NEW_ARRAY(be->mvc->sa, result_subtype, nrcols);
    4252             : 
    4253           7 :         InstrPtr q = newStmtArgs(be->mb, "sql", "from_json", nrcols + 2);
    4254           7 :         if (q == NULL)
    4255           0 :                 goto bailout;
    4256             : 
    4257           7 :         q->retc = q->argc = 0;
    4258           7 :         if (composite_type_result(be, q, t, tps) < 0) {
    4259           0 :                 freeInstruction(q);
    4260           0 :                 goto bailout;
    4261             :         }
    4262             : 
    4263           7 :         q = pushArgument(be->mb, q, v->nr);
    4264           7 :         q = pushPtr(be->mb, q, t);
    4265             : 
    4266           7 :         bool enabled = be->mvc->sa->eb.enabled;
    4267           7 :         be->mvc->sa->eb.enabled = false;
    4268           7 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4269           7 :         be->mvc->sa->eb.enabled = enabled;
    4270           7 :         if(!s) {
    4271           0 :                 freeInstruction(q);
    4272           0 :                 goto bailout;
    4273             :         }
    4274           7 :         s->op1 = v;
    4275           7 :         s->nrcols = 2;
    4276           7 :         s->key = v->key;
    4277           7 :         s->aggr = v->aggr;
    4278           7 :         s->subtype = *t;
    4279           7 :         s->nr = getDestVar(q);
    4280           7 :         s->q = q;
    4281             :         //s->cand = pushed ? sel : NULL;
    4282           7 :         pushInstruction(be->mb, q);
    4283           7 :         s = result_list(be, s->q, 0, tps, nrcols);
    4284           7 :         s->subtype = *t;
    4285           7 :         s->nested = true;
    4286           7 :         s->multiset = t->multiset;
    4287           7 :         return s;
    4288           0 : bailout:
    4289           0 :         if (be->mvc->sa->eb.enabled)
    4290           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);
    4291             :         return NULL;
    4292             : }
    4293             : 
    4294             : static stmt *
    4295          20 : stmt_from_varchar(backend *be, stmt *v, stmt *sel, sql_subtype *t)
    4296             : {
    4297          20 :         (void)sel;
    4298          20 :         int nrcols = composite_type_resultsize(t);
    4299          20 :         result_subtype *tps = SA_NEW_ARRAY(be->mvc->sa, result_subtype, nrcols);
    4300             : 
    4301          20 :         InstrPtr q = newStmtArgs(be->mb, "sql", "from_varchar", nrcols + 2);
    4302          20 :         if (q == NULL)
    4303           0 :                 goto bailout;
    4304             : 
    4305          20 :         q->retc = q->argc = 0;
    4306          20 :         if (composite_type_result(be, q, t, tps) < 0) {
    4307           0 :                 freeInstruction(q);
    4308           0 :                 goto bailout;
    4309             :         }
    4310             : 
    4311          20 :         q = pushArgument(be->mb, q, v->nr);
    4312          20 :         q = pushPtr(be->mb, q, t);
    4313             : 
    4314          20 :         bool enabled = be->mvc->sa->eb.enabled;
    4315          20 :         be->mvc->sa->eb.enabled = false;
    4316          20 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4317          20 :         be->mvc->sa->eb.enabled = enabled;
    4318          20 :         if(!s) {
    4319           0 :                 freeInstruction(q);
    4320           0 :                 goto bailout;
    4321             :         }
    4322          20 :         s->op1 = v;
    4323          20 :         s->nrcols = 2;
    4324          20 :         s->key = v->key;
    4325          20 :         s->aggr = v->aggr;
    4326          20 :         s->subtype = *t;
    4327          20 :         s->nr = getDestVar(q);
    4328          20 :         s->q = q;
    4329             :         //s->cand = pushed ? sel : NULL;
    4330          20 :         pushInstruction(be->mb, q);
    4331          20 :         s = result_list(be, s->q, 0, tps, nrcols);
    4332          20 :         s->subtype = *t;
    4333          20 :         s->nested = true;
    4334          20 :         s->multiset = t->multiset;
    4335          20 :         return s;
    4336           0 : bailout:
    4337           0 :         if (be->mvc->sa->eb.enabled)
    4338           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);
    4339             :         return NULL;
    4340             : }
    4341             : 
    4342             : stmt *
    4343       55220 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    4344             : {
    4345       55220 :         MalBlkPtr mb = be->mb;
    4346       55220 :         InstrPtr q = NULL;
    4347       55220 :         const char *convert = t->type->d.impl, *mod = calcRef;
    4348       55220 :         int pushed = (v->cand && v->cand == sel), no_candidates = 0;
    4349       55220 :         bool add_tz = false;
    4350             :         /* convert types and make sure they are rounded up correctly */
    4351             : 
    4352       55220 :         if (v->nr < 0)
    4353           0 :                 goto bailout;
    4354             : 
    4355       55220 :         if (f->type->eclass == EC_EXTERNAL && t->type->composite && strcmp(f->type->base.name, "json") == 0)
    4356           7 :                 return stmt_from_json(be, v, sel, t);
    4357       55213 :         if (t->type->eclass == EC_EXTERNAL && f->type->composite && strcmp(t->type->base.name, "json") == 0)
    4358           0 :                 return stmt_to_json(be, v, sel, f, t);
    4359       55213 :         if (EC_VARCHAR(f->type->eclass) && (t->type->composite || t->multiset))
    4360          20 :                 return stmt_from_varchar(be, v, sel, t);
    4361       55193 :         if (f->type == t->type && t->multiset && v->subtype.multiset)
    4362             :                 return v;
    4363       55192 :         if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
    4364             :                 /* general cases */
    4365       54817 :                 ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
    4366       54817 :                 !EC_INTERVAL(f->type->eclass) && f->type->eclass != EC_DEC && (t->digits == 0 || f->digits == t->digits) && type_has_tz(t) == type_has_tz(f)) ||
    4367             :                 /* trivial decimal cases */
    4368       45074 :                 (f->type->eclass == EC_DEC && t->type->eclass == EC_DEC && f->scale == t->scale && f->type->localtype == t->type->localtype) ||
    4369             :                 /* trivial string cases */
    4370       11133 :                 (EC_VARCHAR(f->type->eclass) && EC_VARCHAR(t->type->eclass) && (t->digits == 0 || (f->digits > 0 && t->digits >= f->digits))))) {
    4371             :                 /* set output type. Despite the MAL code already being generated, the output type may still be checked */
    4372       18024 :                 tail_set_type(be->mvc, v, t);
    4373       18024 :                 return v;
    4374             :         }
    4375             : 
    4376             :         /* external types have sqlname convert functions,
    4377             :            these can generate errors (fromstr cannot) */
    4378       37168 :         if (t->type->eclass == EC_EXTERNAL)
    4379         347 :                 convert = t->type->base.name;
    4380       36821 :         else if (t->type->eclass == EC_MONTH)
    4381             :                 convert = "month_interval";
    4382       36771 :         else if (t->type->eclass == EC_SEC)
    4383         194 :                 convert = "second_interval";
    4384             : 
    4385       37168 :         no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
    4386             : 
    4387       37168 :         if ((type_has_tz(f) && !type_has_tz(t) && !EC_VARCHAR(t->type->eclass)) || (!type_has_tz(f) && type_has_tz(t))) {
    4388         291 :                 v = temporal_convert(be, v, sel, f, t, true);
    4389         291 :                 sel = NULL;
    4390         291 :                 pushed = 0;
    4391         291 :                 if (EC_VARCHAR(f->type->eclass))
    4392             :                         return v;
    4393             :         }
    4394             : 
    4395             :         /* Lookup the sql convert function, there is no need
    4396             :          * for single value vs bat, this is handled by the
    4397             :          * mal function resolution */
    4398       37044 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    4399        8481 :                 q = newStmtArgs(mb, mod, convert, 13);
    4400        8481 :                 if (q == NULL)
    4401           0 :                         goto bailout;
    4402       28584 :         } else if ((v->nrcols > 0 || (sel && sel->nrcols > 0)) && no_candidates) {
    4403          21 :                 int type = t->type->localtype;
    4404             : 
    4405             :                 /* with our current implementation, all internal SQL types have candidate list support on their conversions */
    4406          21 :                 if (sel && !pushed) {
    4407           0 :                         pushed = 1;
    4408           0 :                         v = stmt_project(be, sel, v);
    4409           0 :                         v->cand = sel;
    4410             :                 }
    4411          21 :                 q = newStmtArgs(mb, malRef, multiplexRef, 15);
    4412          21 :                 if (q == NULL)
    4413           0 :                         goto bailout;
    4414          21 :                 setVarType(mb, getArg(q, 0), newBatType(type));
    4415          21 :                 q = pushStr(mb, q, convertMultiplexMod(mod, convert));
    4416          21 :                 q = pushStr(mb, q, convertMultiplexFcn(convert));
    4417             :         } else {
    4418       28542 :                 if (v->nrcols == 0 && sel && !pushed) {
    4419         877 :                         pushed = 1;
    4420         877 :                         v = stmt_project(be, sel, v);
    4421         877 :                         v->cand = sel;
    4422             :                 }
    4423       28542 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    4424       28542 :                 if (q == NULL)
    4425           0 :                         goto bailout;
    4426             :         }
    4427             : 
    4428             :         /* convert to string is complex, we need full type info and mvc for the timezone */
    4429       37210 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
    4430        1925 :                 q = pushInt(mb, q, f->type->eclass);
    4431        1925 :                 q = pushInt(mb, q, f->digits);
    4432        1925 :                 q = pushInt(mb, q, f->scale);
    4433        1925 :                 q = pushInt(mb, q, type_has_tz(f));
    4434       35119 :         } else if (f->type->eclass == EC_DEC) {
    4435             :                 /* scale of the current decimal */
    4436        1566 :                 q = pushInt(mb, q, f->scale);
    4437       33553 :         } else if (f->type->eclass == EC_SEC && (EC_COMPUTE(t->type->eclass) || t->type->eclass == EC_DEC)) {
    4438             :                 /* scale of the current decimal */
    4439           0 :                 q = pushInt(mb, q, 3);
    4440             :         }
    4441       37044 :         q = pushArgument(mb, q, v->nr);
    4442       37044 :         if (add_tz)
    4443             :                         q = pushLng(mb, q, be->mvc->timezone);
    4444       37044 :         if (sel && !pushed && !v->cand) {
    4445        3578 :                 q = pushArgument(mb, q, sel->nr);
    4446        3578 :                 pushed = 1;
    4447       33466 :         } else if (v->nrcols > 0 && !no_candidates) {
    4448       24964 :                 q = pushNilBat(mb, q);
    4449             :         }
    4450       37043 :         if (!add_tz && (t->type->eclass == EC_DEC || EC_TEMP_FRAC(t->type->eclass) || EC_INTERVAL(t->type->eclass))) {
    4451             :                 /* digits, scale of the result decimal */
    4452        3197 :                 q = pushInt(mb, q, t->digits);
    4453        3197 :                 if (!EC_TEMP_FRAC(t->type->eclass))
    4454        2857 :                         q = pushInt(mb, q, t->scale);
    4455             :         }
    4456             :         /* convert to string, give error on to large strings */
    4457       37209 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
    4458        1925 :                 q = pushInt(mb, q, t->digits);
    4459             :         /* convert a string to a time(stamp) with time zone */
    4460       37043 :         if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass))
    4461             :                 //q = pushInt(mb, q, type_has_tz(t));
    4462           0 :                 q = pushLng(mb, q, be->mvc->timezone);
    4463       37043 :         if (t->type->eclass == EC_GEOM) {
    4464             :                 /* push the type and coordinates of the column */
    4465         687 :                 q = pushInt(mb, q, t->digits);
    4466             :                 /* push the SRID of the whole columns */
    4467         687 :                 q = pushInt(mb, q, t->scale);
    4468             :                 /* push the type and coordinates of the inserted value */
    4469             :                 //q = pushInt(mb, q, f->digits);
    4470             :                 /* push the SRID of the inserted value */
    4471             :                 //q = pushInt(mb, q, f->scale);
    4472             :                 /* we decided to create the EWKB type also used by PostGIS and has the SRID provided by the user inside already */
    4473             :                 /* push the SRID provided for this value */
    4474             :                 /* GEOS library is able to store in the returned wkb the type an
    4475             :                  * number if coordinates but not the SRID so SRID should be provided
    4476             :                  * from this level */
    4477             : /*              if(be->argc > 1)
    4478             :                         f->scale = ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival;
    4479             : 
    4480             :                         q = pushInt(mb, q, f->digits);
    4481             :                         q = pushInt(mb, q, f->scale);
    4482             : */                      //q = pushInt(mb, q, ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival);
    4483             :         }
    4484             : 
    4485       37043 :         bool enabled = be->mvc->sa->eb.enabled;
    4486       37043 :         be->mvc->sa->eb.enabled = false;
    4487       37043 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4488       37043 :         be->mvc->sa->eb.enabled = enabled;
    4489       37043 :         if(!s) {
    4490           0 :                 freeInstruction(q);
    4491           0 :                 goto bailout;
    4492             :         }
    4493       37043 :         s->op1 = v;
    4494       37043 :         s->nrcols = 0;       /* function without arguments returns single value */
    4495       37043 :         s->key = v->key;
    4496       37043 :         s->nrcols = v->nrcols;
    4497       37043 :         s->aggr = v->aggr;
    4498       37043 :         s->subtype = *t;
    4499       37043 :         s->nr = getDestVar(q);
    4500       37043 :         s->q = q;
    4501       37043 :         s->cand = pushed ? sel : NULL;
    4502       37043 :         pushInstruction(mb, q);
    4503       37044 :         if ((!type_has_tz(f) && type_has_tz(t)))
    4504          61 :                 return temporal_convert(be, s, NULL, f, t, false);
    4505             :         return s;
    4506             : 
    4507           0 :   bailout:
    4508           0 :         if (be->mvc->sa->eb.enabled)
    4509           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4510             :         return NULL;
    4511             : }
    4512             : 
    4513             : stmt *
    4514       27197 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
    4515             : {
    4516       27197 :         list *ops = sa_list(be->mvc->sa);
    4517       27218 :         list_append(ops, op1);
    4518       27234 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4519       27237 :         if (r && !r->cand)
    4520       27237 :                 r->cand = op1->cand;
    4521       27237 :         return r;
    4522             : }
    4523             : 
    4524             : stmt *
    4525       47493 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
    4526             : {
    4527       47493 :         list *ops = sa_list(be->mvc->sa);
    4528       47497 :         list_append(ops, op1);
    4529       47501 :         list_append(ops, op2);
    4530       47501 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4531       47502 :         if (r && !r->cand)
    4532       47502 :                 r->cand = op1->cand?op1->cand:op2->cand;
    4533       47502 :         return r;
    4534             : }
    4535             : 
    4536             : #define LANG_INT_OR_MAL(l)  ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
    4537             : 
    4538             : stmt *
    4539      287872 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
    4540             : {
    4541      287872 :         MalBlkPtr mb = be->mb;
    4542      287872 :         InstrPtr q = NULL;
    4543      287872 :         const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
    4544      287955 :         sql_subtype *tpe = NULL;
    4545      287955 :         int push_cands = 0, default_nargs;
    4546      287955 :         stmt *o = NULL, *card = NULL;
    4547             : 
    4548      287955 :         if (ops == NULL)
    4549           0 :                 goto bailout;
    4550             : 
    4551      287955 :         if (rows) {
    4552         105 :                 if (sel) /* if there's a candidate list, use it instead of 'rows' */
    4553           0 :                         rows = sel;
    4554             :                 o = rows;
    4555      287850 :         } else if (list_length(ops->op4.lval)) {
    4556      285951 :                 o = ops->op4.lval->h->data;
    4557      821950 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4558      535999 :                         stmt *c = n->data;
    4559             : 
    4560      535999 :                         if (c && o->nrcols < c->nrcols)
    4561      535999 :                                 o = c;
    4562             :                 }
    4563             :         }
    4564             : 
    4565             :         /* handle nullif */
    4566      287948 :         if (list_length(ops->op4.lval) == 2 &&
    4567      172769 :                 strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
    4568          95 :                 stmt *e1 = ops->op4.lval->h->data;
    4569          95 :                 stmt *e2 = ops->op4.lval->h->next->data;
    4570          95 :                 int nrcols = 0;
    4571             : 
    4572          95 :                 nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols;
    4573             :                 /* nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) */
    4574          95 :                 if (strcmp(f->func->base.name, "nullif") == 0) {
    4575          95 :                         const char *mod = (!nrcols)?calcRef:batcalcRef;
    4576          95 :                         sql_subtype *t = tail_type(e1);
    4577          95 :                         int tt = t->type->localtype;
    4578          95 :                         q = newStmt(mb, mod, "==");
    4579          95 :                         if (q == NULL)
    4580           0 :                                 goto bailout;
    4581          95 :                         q = pushArgument(mb, q, e1->nr);
    4582          95 :                         q = pushArgument(mb, q, e2->nr);
    4583          95 :                         int nr = getDestVar(q);
    4584          95 :                         pushInstruction(mb, q);
    4585             : 
    4586          95 :                         q = newStmt(mb, mod, ifthenelseRef);
    4587          95 :                         if (q == NULL)
    4588           0 :                                 goto bailout;
    4589          95 :                         q = pushArgument(mb, q, nr);
    4590          95 :                         q = pushNil(mb, q, tt);
    4591          95 :                         q = pushArgument(mb, q, e1->nr);
    4592          95 :                         pushInstruction(mb, q);
    4593             :                 }
    4594          95 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4595             :         }
    4596          95 :         if (q == NULL) {
    4597      287826 :                 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
    4598           2 :                         goto bailout;
    4599      287870 :                 mod = sql_func_mod(f->func);
    4600      287930 :                 fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
    4601      287905 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4602      329734 :                 default_nargs = (f->res && list_length(f->res) ? list_length(f->res) : 1) + list_length(ops->op4.lval) + (o && o->nrcols > 0 ? 6 : 4);
    4603      287889 :                 if (rows) {
    4604         105 :                         card = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(be->mvc, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
    4605         105 :                         default_nargs++;
    4606             :                 }
    4607             : 
    4608      287889 :                 if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
    4609      174729 :                         sql_subtype *res = f->res->h->data;
    4610             : 
    4611      349442 :                         q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
    4612      174729 :                         if (q == NULL)
    4613           0 :                                 goto bailout;
    4614      174729 :                         if (rows)
    4615         105 :                                 q = pushArgument(mb, q, card->nr);
    4616      174729 :                         q = pushStr(mb, q, mod);
    4617      174729 :                         q = pushStr(mb, q, fimp);
    4618      174729 :                         setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
    4619             :                 } else {
    4620      113160 :                         q = newStmtArgs(mb, mod, fimp, default_nargs);
    4621      113223 :                         if (q == NULL)
    4622           0 :                                 goto bailout;
    4623             : 
    4624      113223 :                         if (rows)
    4625           0 :                                 q = pushArgument(mb, q, card->nr);
    4626      113225 :                         if (f->res && list_length(f->res)) {
    4627       71374 :                                 sql_subtype *res = f->res->h->data;
    4628             : 
    4629       71374 :                                 setVarType(mb, getArg(q, 0), res->type->localtype);
    4630             :                         }
    4631             :                 }
    4632      287954 :                 if (LANG_EXT(f->func->lang)) {
    4633             :                         /* TODO LOADER functions still use information in sql_subfunc struct
    4634             :                            that won't be visible to other sessions if another function uses them.
    4635             :                            It has to be cleaned up */
    4636         221 :                         if (f->func->type == F_LOADER)
    4637          25 :                                 q = pushPtr(mb, q, f);
    4638             :                         else
    4639         196 :                                 q = pushPtr(mb, q, f->func);
    4640             :                 }
    4641      287954 :                 if (f->func->lang == FUNC_LANG_C) {
    4642          35 :                         q = pushBit(mb, q, 0);
    4643      287919 :                 } else if (f->func->lang == FUNC_LANG_CPP) {
    4644           1 :                         q = pushBit(mb, q, 1);
    4645             :                 }
    4646      287954 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY ||
    4647             :                         f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) {
    4648         221 :                         q = pushStr(mb, q, f->func->query);
    4649             :                 }
    4650             :                 /* first dynamic output of copy* functions */
    4651      287954 :                 if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
    4652        2787 :                         q = table_func_create_result(mb, q, f->func, f->res);
    4653      287954 :                 if (list_length(ops->op4.lval))
    4654      286067 :                         tpe = tail_type(ops->op4.lval->h->data);
    4655             : 
    4656      824111 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4657      536161 :                         stmt *op = n->data;
    4658      536161 :                         q = pushArgument(mb, q, op->nr);
    4659             :                 }
    4660             :                 /* push candidate lists if that's the case */
    4661      287950 :                 if (push_cands) {
    4662      178404 :                         for (node *n = ops->op4.lval->h; n; n = n->next) {
    4663      118396 :                                 stmt *op = n->data;
    4664             : 
    4665      118396 :                                 if (op->nrcols > 0) {
    4666       78132 :                                         if (op->cand && op->cand == sel) {
    4667       35479 :                                                 q = pushNilBat(mb, q);
    4668             :                                         } else {
    4669       42653 :                                                 q = pushArgument(mb, q, sel->nr);
    4670             :                                         }
    4671             :                                 }
    4672             :                         }
    4673             :                 }
    4674             :                 /* special case for round function on decimals */
    4675      287950 :                 if (LANG_INT_OR_MAL(f->func->lang) && strcmp(fimp, "round") == 0 && tpe && tpe->type->eclass == EC_DEC && ops->op4.lval->h && ops->op4.lval->h->data) {
    4676          48 :                         q = pushInt(mb, q, tpe->digits);
    4677          48 :                         q = pushInt(mb, q, tpe->scale);
    4678             :                 }
    4679      287950 :                 pushInstruction(mb, q);
    4680             :         }
    4681             : 
    4682      288047 :         stmt *s = stmt_create(be->mvc->sa, st_Nop);
    4683      288046 :         if(!s) {
    4684           0 :                 goto bailout;
    4685             :         }
    4686      288046 :         s->op1 = ops;
    4687      288046 :         if (o) {
    4688      286177 :                 s->nrcols = o->nrcols;
    4689      286177 :                 s->key = o->key;
    4690      286177 :                 s->aggr = o->aggr;
    4691             :         } else {
    4692        1869 :                 s->nrcols = 0;
    4693        1869 :                 s->key = 1;
    4694             :         }
    4695      288046 :         s->op4.funcval = f;
    4696      288046 :         s->nr = getDestVar(q);
    4697      288046 :         s->q = q;
    4698      288046 :         if (sel && push_cands && s->nrcols)
    4699       58487 :                 s->cand = sel;
    4700             :         return s;
    4701             : 
    4702           2 :   bailout:
    4703           2 :         if (be->mvc->sa->eb.enabled)
    4704           2 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4705             :         return NULL;
    4706             : }
    4707             : 
    4708             : stmt *
    4709          23 : stmt_direct_func(backend *be, InstrPtr q)
    4710             : {
    4711          23 :         if (q) {
    4712          23 :                 stmt *s = stmt_create(be->mvc->sa, st_func);
    4713          23 :                 if(!s) {
    4714             :                         return NULL;
    4715             :                 }
    4716          23 :                 s->flag = op_union;
    4717          23 :                 s->nrcols = 3;
    4718          23 :                 s->nr = getDestVar(q);
    4719          23 :                 s->q = q;
    4720          23 :                 return s;
    4721             :         }
    4722             :         return NULL;
    4723             : }
    4724             : 
    4725             : stmt *
    4726         188 : stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
    4727             : {
    4728         188 :         MalBlkPtr mb = be->mb;
    4729         188 :         InstrPtr q = NULL;
    4730         188 :         prop *p = NULL;
    4731             : 
    4732             :         /* dump args */
    4733         188 :         if (ops && ops->nr < 0)
    4734           0 :                 goto bailout;
    4735             : 
    4736         188 :         if ((p = find_prop(rel->p, PROP_REMOTE)))
    4737         188 :                 rel->p = prop_remove(rel->p, p);
    4738             :         /* sql_processrelation may split projections, so make sure the topmost relation only contains references */
    4739         188 :         int opt = rel->opt;
    4740         188 :         rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 1, 1));
    4741         188 :         if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
    4742           0 :                 goto bailout;
    4743         188 :         if (p) {
    4744         188 :                 p->p = rel->p;
    4745         188 :                 rel->p = p;
    4746             :         }
    4747         188 :         rel->opt = opt;
    4748             : 
    4749         188 :         if (monet5_create_relational_function(be->mvc, sql_private_module_name, name, rel, ops, NULL, 1) < 0)
    4750           0 :                 goto bailout;
    4751             : 
    4752         188 :         int nargs;
    4753         188 :         sql_rel *r = relational_func_create_result_part1(be->mvc, rel, &nargs);
    4754         188 :         if (ops)
    4755         186 :                 nargs += list_length(ops->op4.lval);
    4756         188 :         if (f_union)
    4757           0 :                 q = newStmt(mb, batmalRef, multiplexRef);
    4758             :         else
    4759         188 :                 q = newStmt(mb, sql_private_module_name, name);
    4760         188 :         if (q == NULL)
    4761           0 :                 goto bailout;
    4762         188 :         q = relational_func_create_result_part2(mb, q, r);
    4763         188 :         if (f_union) {
    4764           0 :                 q = pushStr(mb, q, sql_private_module_name);
    4765           0 :                 q = pushStr(mb, q, name);
    4766             :         }
    4767         188 :         if (ops) {
    4768         208 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4769          22 :                         stmt *op = n->data;
    4770             : 
    4771          22 :                         q = pushArgument(mb, q, op->nr);
    4772             :                 }
    4773             :         }
    4774             : 
    4775         188 :         allocator *sa = be->mvc->sa;
    4776         188 :         bool enabled = be->mvc->sa->eb.enabled;
    4777         188 :         be->mvc->sa->eb.enabled = false;
    4778         188 :         stmt *o = NULL, *s = stmt_create(sa, st_func);
    4779         188 :         be->mvc->sa->eb.enabled = enabled;
    4780         188 :         if(!s) {
    4781           0 :                 freeInstruction(q);
    4782           0 :                 goto bailout;
    4783             :         }
    4784         188 :         s->op1 = ops;
    4785         188 :         s->op2 = stmt_atom_string(be, name);
    4786         188 :         s->op4.rel = rel;
    4787         188 :         s->flag = f_union;
    4788         188 :         if (ops && list_length(ops->op4.lval)) {
    4789          10 :                 node *n;
    4790          32 :                 for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
    4791          22 :                         stmt *c = n->data;
    4792             : 
    4793          22 :                         if (o->nrcols < c->nrcols)
    4794           0 :                                 o = c;
    4795             :                 }
    4796             :         }
    4797             : 
    4798          10 :         if (o) {
    4799          10 :                 s->nrcols = o->nrcols;
    4800          10 :                 s->key = o->key;
    4801          10 :                 s->aggr = o->aggr;
    4802             :         } else {
    4803         178 :                 s->nrcols = 0;
    4804         178 :                 s->key = 1;
    4805             :         }
    4806         188 :         s->nr = getDestVar(q);
    4807         188 :         s->q = q;
    4808         188 :         pushInstruction(mb, q);
    4809         188 :         return s;
    4810             : 
    4811           0 :   bailout:
    4812           0 :         if (be->mvc->sa->eb.enabled)
    4813           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4814             :         return NULL;
    4815             : }
    4816             : 
    4817             : stmt *
    4818       85489 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
    4819             : {
    4820       85489 :         MalBlkPtr mb = be->mb;
    4821       85489 :         InstrPtr q = NULL;
    4822       85489 :         const char *mod, *aggrfunc;
    4823       85489 :         sql_subtype *res = op->res->h->data;
    4824       85489 :         int restype = res->type->localtype;
    4825       85489 :         bool complex_aggr = false;
    4826       85489 :         int *stmt_nr = NULL;
    4827       85489 :         int avg = 0;
    4828             : 
    4829       85489 :         if (op1->nr < 0)
    4830           0 :                 goto bailout;
    4831       85489 :         if (backend_create_subfunc(be, op, NULL) < 0)
    4832           0 :                 goto bailout;
    4833       85710 :         mod = sql_func_mod(op->func);
    4834       85486 :         aggrfunc = backend_function_imp(be, op->func);
    4835             : 
    4836       85646 :         if (LANG_INT_OR_MAL(op->func->lang)) {
    4837       85523 :                 if (strcmp(aggrfunc, "avg") == 0)
    4838             :                         avg = 1;
    4839       84150 :                 if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
    4840       77036 :                         || strcmp(aggrfunc, "str_group_concat") == 0)
    4841             :                         complex_aggr = true;
    4842       85523 :                 if (restype == TYPE_dbl)
    4843        1564 :                         avg = 0;
    4844             :         }
    4845             : 
    4846      171292 :         int argc = 1
    4847       85646 :                 + 2 * avg
    4848       85646 :                 + (LANG_EXT(op->func->lang) != 0)
    4849       85646 :                 + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
    4850       85646 :                 + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
    4851       85646 :                 + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
    4852       85646 :                 + (grp ? 4 : avg + 1);
    4853             : 
    4854       85646 :         if (grp) {
    4855        6726 :                 char *aggrF = SA_NEW_ARRAY(be->mvc->sa, char, strlen(aggrfunc) + 4);
    4856        6726 :                 if (!aggrF)
    4857           0 :                         goto bailout;
    4858        6726 :                 stpcpy(stpcpy(aggrF, "sub"), aggrfunc);
    4859        6726 :                 aggrfunc = aggrF;
    4860        6726 :                 if ((grp && grp->nr < 0) || (ext && ext->nr < 0))
    4861           0 :                         goto bailout;
    4862             : 
    4863        6726 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4864        6726 :                 if (q == NULL)
    4865           0 :                         goto bailout;
    4866        6726 :                 setVarType(mb, getArg(q, 0), newBatType(restype));
    4867        6726 :                 if (avg) { /* for avg also return rest and count */
    4868          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4869          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4870             :                 }
    4871             :         } else {
    4872       78920 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4873       79180 :                 if (q == NULL)
    4874           0 :                         goto bailout;
    4875       79180 :                 if (complex_aggr) {
    4876        6783 :                         setVarType(mb, getArg(q, 0), restype);
    4877        6783 :                         if (avg) { /* for avg also return rest and count */
    4878          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4879          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4880             :                         }
    4881             :                 }
    4882             :         }
    4883             : 
    4884       85906 :         if (LANG_EXT(op->func->lang))
    4885          47 :                 q = pushPtr(mb, q, op->func);
    4886       85910 :         if (op->func->lang == FUNC_LANG_R ||
    4887       85875 :                 op->func->lang >= FUNC_LANG_PY ||
    4888             :                 op->func->lang == FUNC_LANG_C ||
    4889             :                 op->func->lang == FUNC_LANG_CPP) {
    4890          47 :                 if (!grp) {
    4891          20 :                         setVarType(mb, getArg(q, 0), restype);
    4892             :                 }
    4893          47 :                 if (op->func->lang == FUNC_LANG_C) {
    4894          12 :                         q = pushBit(mb, q, 0);
    4895          35 :                 } else if (op->func->lang == FUNC_LANG_CPP) {
    4896           0 :                         q = pushBit(mb, q, 1);
    4897             :                 }
    4898          47 :                 q = pushStr(mb, q, op->func->query);
    4899             :         }
    4900             : 
    4901       85909 :         if (op1->type != st_list) {
    4902       80129 :                 q = pushArgument(mb, q, op1->nr);
    4903             :         } else {
    4904        5780 :                 int i;
    4905        5780 :                 node *n;
    4906             : 
    4907       11982 :                 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
    4908        6201 :                         stmt *op = n->data;
    4909             : 
    4910        6201 :                         if (stmt_nr)
    4911             :                                 q = pushArgument(mb, q, stmt_nr[i]);
    4912             :                         else
    4913        6201 :                                 q = pushArgument(mb, q, op->nr);
    4914             :                 }
    4915             :         }
    4916       85908 :         if (grp) {
    4917        6726 :                 q = pushArgument(mb, q, grp->nr);
    4918        6726 :                 q = pushArgument(mb, q, ext->nr);
    4919        6726 :                 if (LANG_INT_OR_MAL(op->func->lang)) {
    4920        6699 :                         if (avg) /* push nil candidates */
    4921          96 :                                 q = pushNilBat(mb, q);
    4922        6699 :                         q = pushBit(mb, q, no_nil);
    4923             :                 }
    4924       79182 :         } else if (LANG_INT_OR_MAL(op->func->lang) && no_nil && strncmp(aggrfunc, "count", 5) == 0) {
    4925        1641 :                 q = pushBit(mb, q, no_nil);
    4926       77541 :         } else if (LANG_INT_OR_MAL(op->func->lang) && !nil_if_empty && strncmp(aggrfunc, "sum", 3) == 0) {
    4927           0 :                 q = pushBit(mb, q, FALSE);
    4928       77541 :         } else if (LANG_INT_OR_MAL(op->func->lang) && avg) { /* push candidates */
    4929          57 :                 q = pushNilBat(mb, q);
    4930          57 :                 q = pushBit(mb, q, no_nil);
    4931             :         }
    4932             : 
    4933       85908 :         bool enabled = be->mvc->sa->eb.enabled;
    4934       85908 :         be->mvc->sa->eb.enabled = false;
    4935       85908 :         stmt *s = stmt_create(be->mvc->sa, st_aggr);
    4936       85894 :         be->mvc->sa->eb.enabled = enabled;
    4937       85894 :         if(!s) {
    4938           0 :                 freeInstruction(q);
    4939           0 :                 goto bailout;
    4940             :         }
    4941       85894 :         s->op1 = op1;
    4942       85894 :         if (grp) {
    4943        6726 :                 s->op2 = grp;
    4944        6726 :                 s->op3 = ext;
    4945        6726 :                 s->nrcols = 1;
    4946             :         } else {
    4947       79168 :                 if (!reduce)
    4948           0 :                         s->nrcols = 1;
    4949             :         }
    4950       85894 :         s->key = reduce;
    4951       85894 :         s->aggr = reduce;
    4952       85894 :         s->flag = no_nil;
    4953       85894 :         s->op4.funcval = op;
    4954       85894 :         s->nr = getDestVar(q);
    4955       85894 :         s->q = q;
    4956       85894 :         pushInstruction(mb, q);
    4957       85894 :         return s;
    4958             : 
    4959           0 :   bailout:
    4960           0 :         if (be->mvc->sa->eb.enabled)
    4961           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4962             :         return NULL;
    4963             : }
    4964             : 
    4965             : static stmt *
    4966     5144466 : stmt_alias_(backend *be, stmt *op1, int label, sql_alias *tname, const char *alias)
    4967             : {
    4968     5144466 :         assert(label);
    4969     5144466 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
    4970     5145303 :         if(!s) {
    4971             :                 return NULL;
    4972             :         }
    4973     5145303 :         s->label = label;
    4974     5145303 :         s->op1 = op1;
    4975     5145303 :         s->nrcols = op1->nrcols;
    4976     5145303 :         s->key = op1->key;
    4977     5145303 :         s->aggr = op1->aggr;
    4978     5145303 :         s->multiset = op1->multiset;
    4979     5145303 :         s->nested = op1->nested;
    4980     5145303 :         s->virt = op1->virt;
    4981     5145303 :         s->subtype = op1->subtype;
    4982             : 
    4983     5145303 :         s->tname = tname;
    4984     5145303 :         s->cname = alias;
    4985     5145303 :         s->nr = op1->nr;
    4986     5145303 :         s->q = op1->q;
    4987     5145303 :         return s;
    4988             : }
    4989             : 
    4990             : stmt *
    4991     4562428 : stmt_alias(backend *be, stmt *op1, int label, sql_alias *tname, const char *alias)
    4992             : {
    4993             :         /*
    4994             :         if (((!op1->tname && !tname) ||
    4995             :             (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
    4996             :             op1->cname && strcmp(op1->cname, alias)==0)
    4997             :                 return op1;
    4998             :                 */
    4999     4562428 :         return stmt_alias_(be, op1, label, tname, alias);
    5000             : }
    5001             : 
    5002             : stmt *
    5003      582146 : stmt_as(backend *be, stmt *s, stmt *org)
    5004             : {
    5005      582146 :         assert(org->type == st_alias);
    5006      582146 :         return stmt_alias_(be, s, org->label, org->tname, org->cname);
    5007             : }
    5008             : 
    5009             : sql_subtype *
    5010     1659565 : tail_type(stmt *st)
    5011             : {
    5012     1659565 :         if (st->subtype.type)
    5013       82165 :                 return &st->subtype;
    5014     8639404 :         for (;;) {
    5015     8639404 :                 switch (st->type) {
    5016       37114 :                 case st_const:
    5017       37114 :                         st = st->op2;
    5018       37114 :                         continue;
    5019        3365 :                 case st_uselect:
    5020             :                 case st_semijoin:
    5021             :                 case st_limit:
    5022             :                 case st_limit2:
    5023             :                 case st_sample:
    5024             :                 case st_tunion:
    5025             :                 case st_tdiff:
    5026             :                 case st_tinter:
    5027        3365 :                         return sql_bind_localtype("oid");
    5028         594 :                 case st_uselect2:
    5029         594 :                         if (!st->reduce)
    5030          68 :                                 return sql_bind_localtype("bit");
    5031         526 :                         return sql_bind_localtype("oid");
    5032     3368583 :                 case st_alias:
    5033     3368583 :                         if (!st->op1)
    5034         175 :                                 return &st->subtype;
    5035             :                         /* fall through */
    5036             :                 case st_append:
    5037             :                 case st_append_bulk:
    5038             :                 case st_replace:
    5039             :                 case st_gen_group:
    5040             :                 case st_order:
    5041     3848306 :                         st = st->op1;
    5042     3848306 :                         continue;
    5043           0 :                 case st_list:
    5044           0 :                         st = st->op4.lval->t->data;
    5045           0 :                         continue;
    5046      934087 :                 case st_bat:
    5047      934087 :                         return &st->op4.cval->type;
    5048        1835 :                 case st_idxbat:
    5049        1835 :                         if (hash_index(st->op4.idxval->type)) {
    5050         239 :                                 return sql_bind_localtype("lng");
    5051        1596 :                         } else if (oid_index(st->op4.idxval->type)) {
    5052        1596 :                                 return sql_bind_localtype("oid");
    5053             :                         }
    5054             :                         /* fall through */
    5055             :                 case st_join:
    5056             :                 case st_join2:
    5057             :                 case st_joinN:
    5058     3176602 :                         if (st->flag == cmp_project) {
    5059     3176584 :                                 st = st->op2;
    5060     3176584 :                                 continue;
    5061             :                         }
    5062             :                         /* fall through */
    5063             :                 case st_reorder:
    5064             :                 case st_group:
    5065             :                 case st_tid:
    5066             :                 case st_mirror:
    5067       14582 :                         return sql_bind_localtype("oid");
    5068        3222 :                 case st_result:
    5069        3222 :                         return &st->subtype;
    5070           0 :                 case st_table_clear:
    5071           0 :                         return sql_bind_localtype("lng");
    5072      171194 :                 case st_aggr:
    5073             :                 case st_Nop: {
    5074      171194 :                         list *res = st->op4.funcval->res;
    5075             : 
    5076      171194 :                         if (res && list_length(res) == 1)
    5077      171194 :                                 return res->h->data;
    5078             : 
    5079             :                         return NULL;
    5080             :                 }
    5081      191815 :                 case st_atom:
    5082      191815 :                         return atom_type(st->op4.aval);
    5083      255973 :                 case st_convert:
    5084             :                 case st_temp:
    5085             :                 case st_single:
    5086             :                 case st_rs_column:
    5087      255973 :                         return &st->subtype;
    5088         550 :                 case st_var:
    5089         550 :                         if (st->subtype.type)
    5090         550 :                                 return &st->subtype;
    5091             :                         /* fall through */
    5092             :                 case st_exception:
    5093             :                         return NULL;
    5094           8 :                 case st_table:
    5095           8 :                         return sql_bind_localtype("bat");
    5096             :                 default:
    5097           0 :                         assert(0);
    5098             :                         return NULL;
    5099             :                 }
    5100             :         }
    5101             : }
    5102             : 
    5103             : int
    5104        6727 : stmt_has_null(stmt *s)
    5105             : {
    5106       21155 :         switch (s->type) {
    5107             :         case st_aggr:
    5108             :         case st_semijoin:
    5109             :         case st_uselect:
    5110             :         case st_uselect2:
    5111             :         case st_atom:
    5112             :                 return 0;
    5113        8252 :         case st_alias:
    5114        8252 :                 return stmt_has_null(s->op1);
    5115        6176 :         case st_join:
    5116        6176 :                 return stmt_has_null(s->op2);
    5117        4276 :         case st_bat:
    5118        4276 :                 return s->op4.cval->null;
    5119             : 
    5120        2451 :         default:
    5121        2451 :                 return 1;
    5122             :         }
    5123             : }
    5124             : 
    5125             : static const char *
    5126           0 : func_name(allocator *sa, const char *n1, const char *n2)
    5127             : {
    5128           0 :         size_t l1 = _strlen(n1), l2;
    5129             : 
    5130           0 :         if (!sa)
    5131             :                 return n1;
    5132           0 :         if (!n2)
    5133           0 :                 return sa_strdup(sa, n1);
    5134           0 :         l2 = _strlen(n2);
    5135             : 
    5136           0 :         if (l2 > 16) {               /* only support short names */
    5137           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l2 + 1);
    5138           0 :                 if(!ns)
    5139             :                         return NULL;
    5140           0 :                 snprintf(ns, l2 + 1, "%s", n2);
    5141           0 :                 return ns;
    5142             :         } else {
    5143           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l1 + l2 + 2), *s = ns;
    5144           0 :                 if(!ns)
    5145             :                         return NULL;
    5146           0 :                 snprintf(ns, l1 + l2 + 2, "%s_%s", n1, n2);
    5147           0 :                 return s;
    5148             :         }
    5149             : }
    5150             : 
    5151             : static const char *_column_name(allocator *sa, stmt *st);
    5152             : 
    5153             : const char *
    5154     2687127 : column_name(allocator *sa, stmt *st)
    5155             : {
    5156     2687127 :         if (!st->cname)
    5157           0 :                 st->cname = _column_name(sa, st);
    5158     2687127 :         return st->cname;
    5159             : }
    5160             : 
    5161             : static const char *
    5162           0 : _column_name(allocator *sa, stmt *st)
    5163             : {
    5164           0 :         switch (st->type) {
    5165           0 :         case st_order:
    5166             :         case st_reorder:
    5167           0 :                 return column_name(sa, st->op1);
    5168           0 :         case st_const:
    5169             :         case st_join:
    5170             :         case st_join2:
    5171             :         case st_joinN:
    5172           0 :                 return column_name(sa, st->op2);
    5173             : 
    5174           0 :         case st_mirror:
    5175             :         case st_group:
    5176             :         case st_result:
    5177             :         case st_append:
    5178             :         case st_append_bulk:
    5179             :         case st_replace:
    5180             :         case st_gen_group:
    5181             :         case st_semijoin:
    5182             :         case st_uselect:
    5183             :         case st_uselect2:
    5184             :         case st_limit:
    5185             :         case st_limit2:
    5186             :         case st_sample:
    5187             :         case st_tunion:
    5188             :         case st_tdiff:
    5189             :         case st_tinter:
    5190             :         case st_convert:
    5191           0 :                 return column_name(sa, st->op1);
    5192           0 :         case st_Nop:
    5193             :         case st_aggr:
    5194             :         {
    5195           0 :                 const char *cn = column_name(sa, st->op1);
    5196           0 :                 return func_name(sa, st->op4.funcval->func->base.name, cn);
    5197             :         }
    5198           0 :         case st_alias:
    5199           0 :                 if (st->op3)
    5200           0 :                         return column_name(sa, st->op3);
    5201             :                 break;
    5202           0 :         case st_bat:
    5203           0 :                 return st->op4.cval->base.name;
    5204           0 :         case st_atom:
    5205           0 :                 if (st->op4.aval->data.vtype == TYPE_str)
    5206           0 :                         return atom2string(sa, st->op4.aval);
    5207             :                 /* fall through */
    5208             :         case st_var:
    5209             :         case st_temp:
    5210             :         case st_single:
    5211           0 :                 if (sa)
    5212           0 :                         return sa_strdup(sa, "single_value");
    5213             :                 return "single_value";
    5214             : 
    5215           0 :         case st_list:
    5216           0 :                 if (list_length(st->op4.lval))
    5217           0 :                         return column_name(sa, st->op4.lval->h->data);
    5218             :                 /* fall through */
    5219             :         case st_rs_column:
    5220             :                 return NULL;
    5221             :         default:
    5222             :                 return NULL;
    5223             :         }
    5224             :         return NULL;
    5225             : }
    5226             : 
    5227             : sql_alias *
    5228     2671804 : table_name(allocator *sa, stmt *st)
    5229             : {
    5230     2671804 :         (void)sa;
    5231     2671804 :         return st->tname;
    5232             : }
    5233             : 
    5234             : stmt *
    5235        1120 : stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
    5236             : {
    5237        1120 :         MalBlkPtr mb = be->mb;
    5238        1120 :         InstrPtr q = NULL;
    5239             : 
    5240        1120 :         if (cond->nr < 0)
    5241           0 :                 goto bailout;
    5242        1120 :         if (anti) {
    5243          25 :                 sql_subtype *bt = sql_bind_localtype("bit");
    5244          25 :                 sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    5245          25 :                 sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    5246          25 :                 sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    5247          25 :                 cond = stmt_binop(be,
    5248             :                         stmt_unop(be, cond, NULL, not),
    5249             :                         stmt_unop(be, cond, NULL, isnull), NULL, or);
    5250             :         }
    5251        1120 :         if (!loop) {    /* if */
    5252        1103 :                 q = newAssignment(mb);
    5253        1103 :                 if (q == NULL)
    5254           0 :                         goto bailout;
    5255        1103 :                 q->barrier = BARRIERsymbol;
    5256        1103 :                 q = pushArgument(mb, q, cond->nr);
    5257             :         } else {        /* while */
    5258          17 :                 int c;
    5259             : 
    5260          17 :                 if (outer->nr < 0)
    5261           0 :                         goto bailout;
    5262             :                 /* leave barrier */
    5263          17 :                 q = newStmt(mb, calcRef, notRef);
    5264          17 :                 if (q == NULL)
    5265           0 :                         goto bailout;
    5266          17 :                 q = pushArgument(mb, q, cond->nr);
    5267          17 :                 c = getArg(q, 0);
    5268          17 :                 pushInstruction(mb, q);
    5269             : 
    5270          17 :                 q = newAssignment(mb);
    5271          17 :                 if (q == NULL)
    5272           0 :                         goto bailout;
    5273          17 :                 getArg(q, 0) = outer->nr;
    5274          17 :                 q->barrier = LEAVEsymbol;
    5275          17 :                 q = pushArgument(mb, q, c);
    5276             :         }
    5277             : 
    5278        1120 :         bool enabled = be->mvc->sa->eb.enabled;
    5279        1120 :         be->mvc->sa->eb.enabled = false;
    5280        1120 :         stmt *s = stmt_create(be->mvc->sa, st_cond);
    5281        1120 :         be->mvc->sa->eb.enabled = enabled;
    5282        1120 :         if(!s) {
    5283           0 :                 freeInstruction(q);
    5284           0 :                 goto bailout;
    5285             :         }
    5286        1120 :         s->flag = be->mvc_var; /* keep the mvc_var of the outer context */
    5287        1120 :         s->loop = loop;
    5288        1120 :         s->op1 = cond;
    5289        1120 :         s->nr = getArg(q, 0);
    5290        1120 :         pushInstruction(mb, q);
    5291        1120 :         return s;
    5292             : 
    5293           0 :   bailout:
    5294           0 :         if (be->mvc->sa->eb.enabled)
    5295           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5296             :         return NULL;
    5297             : }
    5298             : 
    5299             : stmt *
    5300        1120 : stmt_control_end(backend *be, stmt *cond)
    5301             : {
    5302        1120 :         MalBlkPtr mb = be->mb;
    5303        1120 :         InstrPtr q = NULL;
    5304             : 
    5305        1120 :         if (cond->nr < 0)
    5306           0 :                 goto bailout;
    5307             : 
    5308        1120 :         if (cond->loop) {    /* while */
    5309             :                 /* redo barrier */
    5310          17 :                 q = newAssignment(mb);
    5311          17 :                 if (q == NULL)
    5312           0 :                         goto bailout;
    5313          17 :                 getArg(q, 0) = cond->nr;
    5314          17 :                 q->argc = q->retc = 1;
    5315          17 :                 q->barrier = REDOsymbol;
    5316          17 :                 q = pushBit(mb, q, TRUE);
    5317             :         } else {
    5318        1103 :                 q = newAssignment(mb);
    5319        1103 :                 if (q == NULL)
    5320           0 :                         goto bailout;
    5321        1103 :                 getArg(q, 0) = cond->nr;
    5322        1103 :                 q->argc = q->retc = 1;
    5323        1103 :                 q->barrier = EXITsymbol;
    5324             :         }
    5325        1120 :         be->mvc_var = cond->flag; /* restore old mvc_var from before the barrier */
    5326        1120 :         bool enabled = be->mvc->sa->eb.enabled;
    5327        1120 :         be->mvc->sa->eb.enabled = false;
    5328        1120 :         stmt *s = stmt_create(be->mvc->sa, st_control_end);
    5329        1120 :         be->mvc->sa->eb.enabled = enabled;
    5330        1120 :         if(!s) {
    5331           0 :                 freeInstruction(q);
    5332           0 :                 goto bailout;
    5333             :         }
    5334        1120 :         s->op1 = cond;
    5335        1120 :         s->nr = getArg(q, 0);
    5336        1120 :         pushInstruction(mb, q);
    5337        1120 :         return s;
    5338             : 
    5339           0 :   bailout:
    5340           0 :         if (be->mvc->sa->eb.enabled)
    5341           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5342             :         return NULL;
    5343             : }
    5344             : 
    5345             : 
    5346             : static InstrPtr
    5347         208 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
    5348             : {
    5349         208 :         int i;
    5350         208 :         node *n;
    5351             : 
    5352         208 :         if (q == NULL)
    5353             :                 return NULL;
    5354         208 :         q->retc = q->argc = 0;
    5355        1670 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    5356        1462 :                 stmt *c = n->data;
    5357             : 
    5358        1462 :                 q = pushArgument(mb, q, c->nr);
    5359             :         }
    5360         208 :         if (q == NULL)
    5361             :                 return NULL;
    5362         208 :         q->retc = q->argc;
    5363             :         /* Let's make it a proper assignment */
    5364        1670 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    5365        1462 :                 stmt *c = n->data;
    5366             : 
    5367        1462 :                 q = pushArgument(mb, q, c->nr);
    5368             :         }
    5369             :         return q;
    5370             : }
    5371             : 
    5372             : stmt *
    5373         664 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
    5374             : {
    5375         664 :         MalBlkPtr mb = be->mb;
    5376         664 :         InstrPtr q = NULL;
    5377             : 
    5378         664 :         if (val->nr < 0)
    5379           0 :                 goto bailout;
    5380         664 :         int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
    5381         208 :         if (args < MAXARG)
    5382             :                 args = MAXARG;
    5383         664 :         q = newInstructionArgs(mb, NULL, NULL, args);
    5384         664 :         if (q == NULL)
    5385           0 :                 goto bailout;
    5386         664 :         q->barrier= RETURNsymbol;
    5387         664 :         if (val->type == st_table) {
    5388         208 :                 list *l = val->op1->op4.lval;
    5389             : 
    5390         208 :                 q = dump_cols(mb, l, q);
    5391             :         } else {
    5392         456 :                 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
    5393         456 :                 q = pushArgument(mb, q, val->nr);
    5394             :         }
    5395             : 
    5396         664 :         bool enabled = be->mvc->sa->eb.enabled;
    5397         664 :         be->mvc->sa->eb.enabled = false;
    5398         664 :         stmt *s = stmt_create(be->mvc->sa, st_return);
    5399         664 :         be->mvc->sa->eb.enabled = enabled;
    5400         664 :         if(!s) {
    5401           0 :                 freeInstruction(q);
    5402           0 :                 goto bailout;
    5403             :         }
    5404         664 :         s->op1 = val;
    5405         664 :         s->flag = nr_declared_tables;
    5406         664 :         s->nr = getDestVar(q);
    5407         664 :         s->q = q;
    5408         664 :         pushInstruction(mb, q);
    5409         664 :         return s;
    5410             : 
    5411           0 :   bailout:
    5412           0 :         if (be->mvc->sa->eb.enabled)
    5413           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5414             :         return NULL;
    5415             : }
    5416             : 
    5417             : stmt *
    5418        1422 : stmt_assign(backend *be, sql_alias *sname, const char *varname, stmt *val, int level)
    5419             : {
    5420        1422 :         MalBlkPtr mb = be->mb;
    5421        1422 :         InstrPtr q = NULL;
    5422             : 
    5423        1422 :         if (val && val->nr < 0)
    5424           0 :                 goto bailout;
    5425        1422 :         if (level != 0) {
    5426        1039 :                 char *buf,  levelstr[16];
    5427             : 
    5428        1039 :                 if (!val) {
    5429             :                         /* drop declared table */
    5430           0 :                         assert(0);
    5431             :                 }
    5432             : 
    5433        1039 :                 assert(!sname);
    5434        1039 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
    5435        1039 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
    5436        1039 :                 if (!buf)
    5437           0 :                         goto bailout;
    5438        1039 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
    5439        1039 :                 q = newInstruction(mb, NULL, NULL);
    5440        1039 :                 if (q == NULL) {
    5441           0 :                         goto bailout;
    5442             :                 }
    5443        1039 :                 q->argc = q->retc = 0;
    5444        1039 :                 q = pushArgumentId(mb, q, buf);
    5445        1039 :                 pushInstruction(mb, q);
    5446        1039 :                 q->retc++;
    5447             :         } else {
    5448         383 :                 assert(sname); /* all global variables have a schema */
    5449         383 :                 q = newStmt(mb, sqlRef, setVariableRef);
    5450         384 :                 if (q == NULL)
    5451           0 :                         goto bailout;
    5452         384 :                 q = pushArgument(mb, q, be->mvc_var);
    5453         384 :                 q = pushStr(mb, q, sname->name);
    5454         384 :                 q = pushStr(mb, q, varname);
    5455         384 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    5456         384 :                 pushInstruction(mb, q);
    5457         384 :                 be->mvc_var = getDestVar(q);
    5458             :         }
    5459        1423 :         q = pushArgument(mb, q, val->nr);
    5460             : 
    5461        1423 :         bool enabled = be->mvc->sa->eb.enabled;
    5462        1423 :         be->mvc->sa->eb.enabled = false;
    5463        1423 :         stmt *s = stmt_create(be->mvc->sa, st_assign);
    5464        1423 :         be->mvc->sa->eb.enabled = enabled;
    5465        1423 :         if(!s) {
    5466           0 :                 goto bailout;
    5467             :         }
    5468        1423 :         s->op2 = val;
    5469        1423 :         s->flag = (level << 1);
    5470        1423 :         s->q = q;
    5471        1423 :         s->nr = 1;
    5472        1423 :         return s;
    5473             : 
    5474           0 :   bailout:
    5475           0 :         if (be->mvc->sa->eb.enabled)
    5476           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5477             :         return NULL;
    5478             : }
    5479             : 
    5480             : stmt *
    5481       26580 : const_column(backend *be, stmt *val)
    5482             : {
    5483       26580 :         sql_subtype *ct = tail_type(val);
    5484       26580 :         MalBlkPtr mb = be->mb;
    5485       26580 :         InstrPtr q = NULL;
    5486       26580 :         int tt = ct->type->localtype;
    5487             : 
    5488       26580 :         if (val->nr < 0)
    5489           0 :                 goto bailout;
    5490       26580 :         q = newStmt(mb, batRef, singleRef);
    5491       26580 :         if (q == NULL)
    5492           0 :                 goto bailout;
    5493       26580 :         setVarType(mb, getArg(q, 0), newBatType(tt));
    5494       26580 :         q = pushArgument(mb, q, val->nr);
    5495             : 
    5496       26580 :         bool enabled = be->mvc->sa->eb.enabled;
    5497       26580 :         be->mvc->sa->eb.enabled = false;
    5498       26580 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5499       26580 :         be->mvc->sa->eb.enabled = enabled;
    5500       26580 :         if(!s) {
    5501           0 :                 freeInstruction(q);
    5502           0 :                 goto bailout;
    5503             :         }
    5504       26580 :         s->op1 = val;
    5505       26580 :         s->subtype = *ct;
    5506       26580 :         s->nrcols = 1;
    5507             : 
    5508       26580 :         s->tname = val->tname;
    5509       26580 :         s->cname = val->cname;
    5510       26580 :         s->nr = getDestVar(q);
    5511       26580 :         s->q = q;
    5512       26580 :         pushInstruction(mb, q);
    5513       26580 :         return s;
    5514             : 
    5515           0 :   bailout:
    5516           0 :         if (be->mvc->sa->eb.enabled)
    5517           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5518             :         return NULL;
    5519             : }
    5520             : 
    5521             : stmt *
    5522          10 : stmt_fetch(backend *be, stmt *val)
    5523             : {
    5524          10 :         sql_subtype *ct;
    5525          10 :         MalBlkPtr mb = be->mb;
    5526          10 :         InstrPtr q = NULL;
    5527          10 :         int tt;
    5528             : 
    5529          10 :         if (val->nr < 0)
    5530           0 :                 goto bailout;
    5531             :         /* pick from first column on a table case */
    5532          10 :         if (val->type == st_table) {
    5533           0 :                 if (list_length(val->op1->op4.lval) > 1)
    5534           0 :                         goto bailout;
    5535           0 :                 val = val->op1->op4.lval->h->data;
    5536             :         }
    5537          10 :         ct = tail_type(val);
    5538          10 :         tt = ct->type->localtype;
    5539             : 
    5540          10 :         q = newStmt(mb, algebraRef, fetchRef);
    5541          10 :         if (q == NULL)
    5542           0 :                 goto bailout;
    5543          10 :         setVarType(mb, getArg(q, 0), tt);
    5544          10 :         q = pushArgument(mb, q, val->nr);
    5545          10 :         q = pushOid(mb, q, 0);
    5546             : 
    5547          10 :         bool enabled = be->mvc->sa->eb.enabled;
    5548          10 :         be->mvc->sa->eb.enabled = false;
    5549          10 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5550          10 :         be->mvc->sa->eb.enabled = enabled;
    5551          10 :         if(!s) {
    5552           0 :                 freeInstruction(q);
    5553           0 :                 goto bailout;
    5554             :         }
    5555          10 :         s->op1 = val;
    5556          10 :         s->subtype = *ct;
    5557          10 :         s->nrcols = 0;
    5558             : 
    5559          10 :         s->tname = val->tname;
    5560          10 :         s->cname = val->cname;
    5561          10 :         s->nr = getDestVar(q);
    5562          10 :         s->q = q;
    5563          10 :         pushInstruction(mb, q);
    5564          10 :         return s;
    5565             : 
    5566           0 :   bailout:
    5567           0 :         if (be->mvc->sa->eb.enabled)
    5568           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5569             :         return NULL;
    5570             : }
    5571             : 
    5572             : stmt *
    5573     1674855 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    5574             : {
    5575     1674855 :         int label = exp_get_label(exp);
    5576     1674816 :         const char *name = exp_name(exp);
    5577     1675099 :         sql_alias *rname = exp_relname(exp);
    5578     1674787 :         stmt *o = s;
    5579             : 
    5580     1674787 :         if (!name && exp_is_atom(exp))
    5581           0 :                 name = sa_strdup(be->mvc->sa, "single_value");
    5582           0 :         assert(name);
    5583     1674787 :         s = stmt_alias(be, s, label, rname, name);
    5584     1675372 :         if (o->flag & OUTER_ZERO)
    5585         521 :                 s->flag |= OUTER_ZERO;
    5586     1675372 :         return s;
    5587             : }

Generated by: LCOV version 1.14