LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2898 3499 82.8 %
Date: 2024-12-19 23:10:26 Functions: 109 113 96.5 %

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

Generated by: LCOV version 1.14