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-20 21:24:02 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       18213 : convertMultiplexMod(const char *mod, const char *op)
      31             : {
      32       18213 :         if (strcmp(op, "=") == 0)
      33           0 :                 return "calc";
      34             :         return mod;
      35             : }
      36             : 
      37             : static const char *
      38      260297 : convertMultiplexFcn(const char *op)
      39             : {
      40      260297 :         if (strcmp(op, "=") == 0)
      41       34662 :                 return "==";
      42             :         return op;
      43             : }
      44             : 
      45             : static InstrPtr
      46       18136 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
      47             : {
      48       18136 :         InstrPtr q = NULL;
      49             : 
      50       18136 :         q = newStmt(mb, malRef, multiplexRef);
      51       18136 :         if (q == NULL)
      52             :                 return NULL;
      53       18136 :         setVarType(mb, getArg(q, 0), newBatType(rtype));
      54       18136 :         q = pushStr(mb, q, convertMultiplexMod(mod, name));
      55       18136 :         q = pushStr(mb, q, convertMultiplexFcn(name));
      56       18136 :         q = pushArgument(mb, q, o1);
      57       18136 :         q = pushArgument(mb, q, o2);
      58       18136 :         pushInstruction(mb, q);
      59       18136 :         return q;
      60             : }
      61             : 
      62             : static InstrPtr
      63       51591 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
      64             : {
      65       51591 :         InstrPtr q = NULL;
      66             : 
      67       51591 :         if (o1 == NULL || o1->nr < 0)
      68             :                 return NULL;
      69       51591 :         q = newStmt(mb, mod, name);
      70       51591 :         q = pushArgument(mb, q, o1->nr);
      71       51591 :         pushInstruction(mb, q);
      72       51591 :         return q;
      73             : }
      74             : 
      75             : static InstrPtr
      76      181139 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
      77             : {
      78      181139 :         InstrPtr q = NULL;
      79             : 
      80      181139 :         if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
      81             :                 return NULL;
      82      181139 :         q = newStmt(mb, mod, name);
      83      181140 :         q = pushArgument(mb, q, o1->nr);
      84      181140 :         q = pushArgument(mb, q, o2->nr);
      85      181140 :         pushInstruction(mb, q);
      86      181140 :         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     2208240 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
     108             : {
     109     2208240 :         if (t->s)
     110     2208240 :                 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       19669 : stmt_atom_string_nil(backend *be)
     138             : {
     139       19669 :         sql_subtype t;
     140             : 
     141       19669 :         sql_find_subtype(&t, "varchar", 0, 0);
     142       19669 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
     143             : }
     144             : 
     145             : stmt *
     146        5890 : stmt_atom_int(backend *be, int i)
     147             : {
     148        5890 :         sql_subtype t;
     149             : 
     150        5890 :         sql_find_subtype(&t, "int", 32, 0);
     151        5890 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     152             : }
     153             : 
     154             : stmt *
     155      117246 : stmt_atom_lng(backend *be, lng i)
     156             : {
     157      117246 :         sql_subtype t;
     158             : 
     159      117246 :         sql_find_subtype(&t, "bigint", 64, 0);
     160      117277 :         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       40616 : stmt_bool(backend *be, int b)
     174             : {
     175       40616 :         sql_subtype t;
     176             : 
     177       40616 :         sql_find_subtype(&t, "boolean", 0, 0);
     178             : 
     179       40616 :         if (b == bit_nil) {
     180           0 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
     181       40616 :         } else if (b) {
     182       39485 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
     183             :         } else {
     184        1131 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
     185             :         }
     186             : }
     187             : 
     188             : static stmt *
     189    17903166 : stmt_create(allocator *sa, st_type type)
     190             : {
     191    17903166 :         stmt *s = SA_NEW(sa, stmt);
     192             : 
     193    17902668 :         if (!s)
     194             :                 return NULL;
     195    17902668 :         *s = (stmt) {
     196             :                 .type = type,
     197             :         };
     198    17902668 :         return s;
     199             : }
     200             : 
     201             : stmt *
     202       28202 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
     203             : {
     204       28202 :         MalBlkPtr mb = be->mb;
     205       28202 :         InstrPtr q = NULL;
     206             : 
     207       28202 :         if (s == NULL || s->nr < 0)
     208           0 :                 goto bailout;
     209       28202 :         if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
     210           0 :                 goto bailout;
     211             : 
     212       49981 :         q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
     213       28202 :         if (q == NULL)
     214           0 :                 goto bailout;
     215             : 
     216             :         /* output variables extent and hist */
     217       28202 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     218       28202 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     219       28202 :         q = pushArgument(mb, q, s->nr);
     220       28202 :         if (grp)
     221        6423 :                 q = pushArgument(mb, q, grp->nr);
     222             : 
     223       28202 :         bool enabled = be->mvc->sa->eb.enabled;
     224       28202 :         be->mvc->sa->eb.enabled = false;
     225       28202 :         stmt *ns = stmt_create(be->mvc->sa, st_group);
     226       28202 :         be->mvc->sa->eb.enabled = enabled;
     227       28202 :         if (ns == NULL) {
     228           0 :                 freeInstruction(q);
     229           0 :                 goto bailout;
     230             :         }
     231             : 
     232       28202 :         ns->op1 = s;
     233             : 
     234       28202 :         if (grp) {
     235        6423 :                 ns->op2 = grp;
     236        6423 :                 ns->op3 = ext;
     237        6423 :                 ns->op4.stval = cnt;
     238             :         }
     239       28202 :         ns->nrcols = s->nrcols;
     240       28202 :         ns->key = 0;
     241       28202 :         ns->q = q;
     242       28202 :         ns->nr = getDestVar(q);
     243       28202 :         pushInstruction(mb, q);
     244       28202 :         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         116 : stmt_bat_new(backend *be, sql_subtype *tpe, lng estimate)
     312             : {
     313         116 :         InstrPtr q = newStmt(be->mb, batRef, newRef);
     314         116 :         int tt = tpe->type->localtype;
     315             : 
     316         116 :         if (q == NULL)
     317             :                 return NULL;
     318         116 :         if (tt == TYPE_void)
     319           1 :                 tt = TYPE_bte;
     320         116 :         setVarType(be->mb, getArg(q, 0), newBatType(tt));
     321         116 :         q = pushType(be->mb, q, tt);
     322         116 :         if (estimate > 0)
     323           0 :                 q = pushInt(be->mb, q, (int)estimate);
     324         116 :         pushInstruction(be->mb, q);
     325             : 
     326         116 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
     327         116 :         s->op4.typeval = *tpe;
     328         116 :         s->q = q;
     329         116 :         s->nr = q->argv[0];
     330         116 :         s->nrcols = 2;
     331         116 :         return s;
     332             : }
     333             : 
     334             : static int *
     335          20 : dump_table(allocator *sa, MalBlkPtr mb, sql_table *t)
     336             : {
     337          20 :         int i = 0;
     338          20 :         node *n;
     339          20 :         int *l = SA_NEW_ARRAY(sa, int, ol_length(t->columns) + 1);
     340             : 
     341          20 :         if (!l)
     342             :                 return NULL;
     343             : 
     344             :         /* tid column */
     345          20 :         if ((l[i++] = create_bat(mb, TYPE_oid)) < 0)
     346             :                 return NULL;
     347             : 
     348          55 :         for (n = ol_first_node(t->columns); n; n = n->next) {
     349          35 :                 sql_column *c = n->data;
     350             : 
     351          35 :                 if ((l[i++] = create_bat(mb, c->type.type->localtype)) < 0)
     352             :                         return NULL;
     353             :         }
     354             :         return l;
     355             : }
     356             : 
     357             : stmt *
     358        2778 : stmt_var(backend *be, const char *sname, const char *varname, sql_subtype *t, int declare, int level)
     359             : {
     360        2778 :         MalBlkPtr mb = be->mb;
     361        2778 :         InstrPtr q = NULL;
     362        2778 :         char *buf;
     363             : 
     364        2778 :         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        2347 :         } else if (!declare) {
     376        1958 :                 char levelstr[16];
     377             : 
     378        1958 :                 assert(!sname);
     379        1958 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     380        1958 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     381        1958 :                 if (!buf)
     382           1 :                         goto bailout;
     383        1958 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     384        1958 :                 q = newAssignment(mb);
     385        1958 :                 if (q == NULL)
     386           1 :                         goto bailout;
     387        1957 :                 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        2777 :         bool enabled = be->mvc->sa->eb.enabled;
     409        2777 :         be->mvc->sa->eb.enabled = false;
     410        2777 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     411        2777 :         be->mvc->sa->eb.enabled = enabled;
     412        2777 :         if (s == NULL) {
     413           0 :                 freeInstruction(q);
     414           0 :                 goto bailout;
     415             :         }
     416             : 
     417        2777 :         if (t)
     418        2777 :                 s->op4.typeval = *t;
     419             :         else
     420           0 :                 s->op4.typeval.type = NULL;
     421        2777 :         s->flag = declare + (level << 1);
     422        2777 :         s->key = 1;
     423        2777 :         s->q = q;
     424        2777 :         s->nr = getDestVar(q);
     425        2777 :         pushInstruction(mb, q);
     426        2777 :         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      222125 : stmt_temp(backend *be, sql_subtype *t)
     542             : {
     543      222125 :         int tt = t->type->localtype;
     544      222125 :         MalBlkPtr mb = be->mb;
     545      222125 :         InstrPtr q = newStmt(mb, batRef, newRef);
     546             : 
     547      223126 :         if (q == NULL)
     548           0 :                 goto bailout;
     549      223126 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     550      223126 :         q = pushType(mb, q, tt);
     551      222947 :         bool enabled = be->mvc->sa->eb.enabled;
     552      222947 :         be->mvc->sa->eb.enabled = false;
     553      222947 :         stmt *s = stmt_create(be->mvc->sa, st_temp);
     554      222906 :         be->mvc->sa->eb.enabled = enabled;
     555             : 
     556      222906 :         if (s == NULL) {
     557           0 :                 freeInstruction(q);
     558           0 :                 goto bailout;
     559             :         }
     560      222906 :         s->op4.typeval = *t;
     561      222906 :         s->nrcols = 1;
     562      222906 :         s->q = q;
     563      222906 :         s->nr = getDestVar(q);
     564      222906 :         pushInstruction(mb, q);
     565      222906 :         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      204935 : stmt_tid(backend *be, sql_table *t, int partition)
     592             : {
     593      204935 :         int tt = TYPE_oid;
     594      204935 :         MalBlkPtr mb = be->mb;
     595      204935 :         InstrPtr q;
     596             : 
     597      204935 :         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      204919 :         q = newStmt(mb, sqlRef, tidRef);
     612      205104 :         if (q == NULL)
     613           0 :                 goto bailout;
     614      205104 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     615      205104 :         q = pushArgument(mb, q, be->mvc_var);
     616      205100 :         q = pushSchema(mb, q, t);
     617      205083 :         q = pushStr(mb, q, t->base.name);
     618      205089 :         if (t && isTable(t) && partition) {
     619       76841 :                 sql_trans *tr = be->mvc->session->tr;
     620       76841 :                 sqlstore *store = tr->store;
     621       76841 :                 BUN rows = (BUN) store->storage_api.count_col(tr, ol_first_node(t->columns)->data, RDONLY);
     622       76841 :                 setRowCnt(mb,getArg(q,0),rows);
     623             :         }
     624             : 
     625      205089 :         bool enabled = be->mvc->sa->eb.enabled;
     626      205089 :         be->mvc->sa->eb.enabled = false;
     627      205089 :         stmt *s = stmt_create(be->mvc->sa, st_tid);
     628      204931 :         be->mvc->sa->eb.enabled = enabled;
     629      204931 :         if (s == NULL) {
     630           0 :                 freeInstruction(q);
     631           0 :                 goto bailout;
     632             :         }
     633             : 
     634      204931 :         s->partition = partition;
     635      204931 :         s->op4.tval = t;
     636      204931 :         s->nrcols = 1;
     637      204931 :         s->nr = getDestVar(q);
     638      204931 :         s->q = q;
     639      204931 :         pushInstruction(mb, q);
     640      204931 :         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     1003062 : find_real_column(backend *be, sql_column *c)
     650             : {
     651     1003062 :         if (c && c->t && c->t->s && c->t->persistence == SQL_DECLARED_TABLE) {
     652       36774 :                 sql_table *nt = find_sql_table_id(be->mvc->session->tr, c->t->s, c->t->base.id);
     653       36774 :                 if (nt) {
     654       36774 :                         node *n = ol_find_id(nt->columns, c->base.id);
     655       36774 :                         if (n)
     656       36774 :                                 return n->data;
     657             :                 }
     658             :         }
     659             :         return c;
     660             : }
     661             : 
     662             : stmt *
     663     1003059 : stmt_bat(backend *be, sql_column *c, int access, int partition)
     664             : {
     665     1003059 :         int tt = c->type.type->localtype;
     666     1003059 :         MalBlkPtr mb = be->mb;
     667     1003059 :         InstrPtr q;
     668             : 
     669     1003059 :         c = find_real_column(be, c);
     670             : 
     671     1003093 :         if (access == RD_EXT)
     672         176 :                 partition = 0;
     673             : 
     674             :         /* for read access tid.project(col) */
     675     1003093 :         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     1003070 :         q = newStmtArgs(mb, sqlRef, bindRef, 9);
     693     1003150 :         if (q == NULL)
     694           0 :                 goto bailout;
     695     1003150 :         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     1002974 :         if (access == RD_UPD_ID) {
     706      487390 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     707             :         } else {
     708      515760 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     709             :         }
     710     1003153 :         q = pushArgument(mb, q, be->mvc_var);
     711     1003133 :         q = pushSchema(mb, q, c->t);
     712     1003137 :         q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
     713     1003141 :         q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
     714     1003088 :         q = pushArgument(mb, q, getIntConstant(mb,access));
     715             : 
     716     1003085 :         if (access == RD_UPD_ID) {
     717      487377 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     718             :         }
     719     1003085 :         if (partition) {
     720      555365 :                 sql_trans *tr = be->mvc->session->tr;
     721      555365 :                 sqlstore *store = tr->store;
     722             : 
     723      555365 :                 if (c && isTable(c->t)) {
     724      555369 :                         BUN rows = (BUN) store->storage_api.count_col(tr, c, RDONLY);
     725      555440 :                         setRowCnt(mb,getArg(q,0),rows);
     726             :                 }
     727             :         }
     728             : 
     729     1003156 :         bool enabled = be->mvc->sa->eb.enabled;
     730     1003156 :         be->mvc->sa->eb.enabled = false;
     731     1003156 :         stmt *s = stmt_create(be->mvc->sa, st_bat);
     732     1003145 :         be->mvc->sa->eb.enabled = enabled;
     733     1003145 :         if (s == NULL) {
     734           0 :                 freeInstruction(q);
     735           0 :                 goto bailout;
     736             :         }
     737             : 
     738     1003145 :         s->partition = partition;
     739     1003145 :         s->op4.cval = c;
     740     1003145 :         s->nrcols = 1;
     741     1003145 :         s->flag = access;
     742     1003145 :         s->nr = getDestVar(q);
     743     1003145 :         s->q = q;
     744     1003145 :         s->tname = c->t->base.name;
     745     1003145 :         s->cname = c->base.name;
     746     1003145 :         pushInstruction(mb, q);
     747     1003145 :         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      673994 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
     818             : {
     819      673994 :         MalBlkPtr mb = be->mb;
     820      673994 :         InstrPtr q = NULL;
     821             : 
     822      673994 :         if (b == NULL || b->nr < 0)
     823           0 :                 goto bailout;
     824             : 
     825      673994 :         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      673971 :         } else if (!fake) {     /* fake append */
     844      673971 :                 if (offset == NULL || offset->nr < 0)
     845           0 :                         goto bailout;
     846      673971 :                 q = newStmt(mb, sqlRef, appendRef);
     847      674504 :                 if (q == NULL)
     848           0 :                         goto bailout;
     849      674504 :                 q = pushArgument(mb, q, be->mvc_var);
     850      674500 :                 int tmpvar = newTmpVariable(mb, TYPE_int);
     851      674504 :                 getArg(q, 0) = tmpvar;
     852      674504 :                 if (mvc_var_update != NULL)
     853      674504 :                         *mvc_var_update = tmpvar;
     854      674504 :                 q = pushSchema(mb, q, c->t);
     855      674485 :                 q = pushStr(mb, q, c->t->base.name);
     856      674483 :                 q = pushStr(mb, q, c->base.name);
     857      674375 :                 q = pushArgument(mb, q, offset->nr);
     858             :                 /* also the offsets */
     859      674405 :                 assert(offset->q->retc == 2);
     860      674405 :                 q = pushArgument(mb, q, getArg(offset->q, 1));
     861      674371 :                 q = pushArgument(mb, q, b->nr);
     862      674309 :                 if (mvc_var_update != NULL)
     863      674309 :                         *mvc_var_update = getDestVar(q);
     864             :         } else {
     865             :                 return b;
     866             :         }
     867      674332 :         bool enabled = be->mvc->sa->eb.enabled;
     868      674332 :         be->mvc->sa->eb.enabled = false;
     869      674332 :         stmt *s = stmt_create(be->mvc->sa, st_append_col);
     870      674190 :         be->mvc->sa->eb.enabled = enabled;
     871             : 
     872      674190 :         if (s == NULL) {
     873           0 :                 freeInstruction(q);
     874           0 :                 goto bailout;
     875             :         }
     876      674190 :         s->op1 = b;
     877      674190 :         s->op2 = offset;
     878      674190 :         s->op4.cval = c;
     879      674190 :         s->q = q;
     880      674190 :         s->nr = getDestVar(q);
     881      674190 :         pushInstruction(mb, q);
     882      674190 :         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        3208 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
     939             : {
     940        3208 :         MalBlkPtr mb = be->mb;
     941        3208 :         InstrPtr q = NULL;
     942             : 
     943        3208 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     944           0 :                 goto bailout;
     945             : 
     946        3209 :         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        3207 :                 q = newStmt(mb, sqlRef, updateRef);
     957        3207 :                 if (q == NULL)
     958           0 :                         goto bailout;
     959        3207 :                 q = pushArgument(mb, q, be->mvc_var);
     960        3207 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     961        3207 :                 q = pushSchema(mb, q, c->t);
     962        3207 :                 q = pushStr(mb, q, c->t->base.name);
     963        3207 :                 q = pushStr(mb, q, c->base.name);
     964        3207 :                 q = pushArgument(mb, q, tids->nr);
     965        3207 :                 q = pushArgument(mb, q, upd->nr);
     966        3207 :                 be->mvc_var = getDestVar(q);
     967             :         }
     968        3208 :         bool enabled = be->mvc->sa->eb.enabled;
     969        3208 :         be->mvc->sa->eb.enabled = false;
     970        3208 :         stmt *s = stmt_create(be->mvc->sa, st_update_col);
     971        3208 :         be->mvc->sa->eb.enabled = enabled;
     972             : 
     973        3208 :         if (s == NULL) {
     974           0 :                 freeInstruction(q);
     975           0 :                 goto bailout;
     976             :         }
     977        3208 :         s->op1 = tids;
     978        3208 :         s->op2 = upd;
     979        3208 :         s->op4.cval = c;
     980        3208 :         s->q = q;
     981        3208 :         s->nr = getDestVar(q);
     982        3208 :         pushInstruction(mb, q);
     983        3208 :         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      124510 : stmt_const(backend *be, stmt *s, stmt *val)
    1087             : {
    1088      124510 :         InstrPtr q = NULL;
    1089      124510 :         MalBlkPtr mb = be->mb;
    1090             : 
    1091      124510 :         if (s == NULL)
    1092           0 :                 goto bailout;
    1093      124510 :         if (val)
    1094      124510 :                 q = dump_2(mb, algebraRef, projectRef, s, val);
    1095             :         else
    1096           0 :                 q = dump_1(mb, algebraRef, projectRef, s);
    1097      124511 :         if (q) {
    1098      124511 :                 stmt *ns = stmt_create(be->mvc->sa, st_const);
    1099      124511 :                 if (ns == NULL) {
    1100           0 :                         goto bailout;
    1101             :                 }
    1102             : 
    1103      124511 :                 ns->op1 = s;
    1104      124511 :                 ns->op2 = val;
    1105      124511 :                 ns->nrcols = s->nrcols;
    1106      124511 :                 ns->key = s->key;
    1107      124511 :                 ns->aggr = s->aggr;
    1108      124511 :                 ns->q = q;
    1109      124511 :                 ns->nr = getDestVar(q);
    1110      124511 :                 ns->tname = val->tname;
    1111      124511 :                 ns->cname = val->cname;
    1112      124511 :                 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       51591 : stmt_mirror(backend *be, stmt *s)
    1154             : {
    1155       51591 :         MalBlkPtr mb = be->mb;
    1156             : 
    1157       51591 :         if (s == NULL)
    1158           0 :                 goto bailout;
    1159             : 
    1160       51591 :         InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
    1161             : 
    1162       51591 :         if (q) {
    1163       51591 :                 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
    1164       51591 :                 if (ns == NULL) {
    1165           0 :                         goto bailout;
    1166             :                 }
    1167             : 
    1168       51591 :                 ns->op1 = s;
    1169       51591 :                 ns->nrcols = 2;
    1170       51591 :                 ns->key = s->key;
    1171       51591 :                 ns->aggr = s->aggr;
    1172       51591 :                 ns->q = q;
    1173       51591 :                 ns->nr = getDestVar(q);
    1174       51591 :                 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      322704 : stmt_result(backend *be, stmt *s, int nr)
    1185             : {
    1186      322704 :         stmt *ns;
    1187             : 
    1188      322704 :         if (s == NULL)
    1189             :                 return NULL;
    1190             : 
    1191      322704 :         if (s->type == st_join && s->flag == cmp_joined) {
    1192        5547 :                 if (nr)
    1193        2322 :                         return s->op2;
    1194        3225 :                 return s->op1;
    1195             :         }
    1196             : 
    1197      317157 :         if (s->op1->nr < 0)
    1198             :                 return NULL;
    1199             : 
    1200      317157 :         ns = stmt_create(be->mvc->sa, st_result);
    1201      317157 :         if(!ns) {
    1202             :                 return NULL;
    1203             :         }
    1204      317157 :         if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
    1205           0 :                 assert(0);
    1206      317157 :         } else if (nr) {
    1207      181363 :                 int v = getArg(s->q, nr);
    1208             : 
    1209      181363 :                 assert(s->q->retc > nr);
    1210      181363 :                 ns->nr = v;
    1211             :         } else {
    1212      135794 :                 ns->nr = s->nr;
    1213             :         }
    1214      317157 :         ns->op1 = s;
    1215      317157 :         if (!nr && (s->type == st_order || s->type == st_reorder))
    1216       23799 :                 ns->op4.typeval = *tail_type(s->op1);
    1217      181363 :         else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
    1218        2965 :                 ns->op4.typeval = *sql_bind_localtype("bit");
    1219             :         else
    1220      290393 :                 ns->op4.typeval = *sql_bind_localtype("oid");
    1221      317157 :         ns->flag = nr;
    1222      317157 :         ns->nrcols = s->nrcols;
    1223      317157 :         ns->key = s->key;
    1224      317157 :         ns->aggr = s->aggr;
    1225      317157 :         return ns;
    1226             : }
    1227             : 
    1228             : 
    1229             : /* limit maybe atom nil */
    1230             : stmt *
    1231       17658 : 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       17658 :         MalBlkPtr mb = be->mb;
    1234       17658 :         InstrPtr q = NULL;
    1235       17658 :         int l, g, c;
    1236             : 
    1237       17658 :         if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
    1238           0 :                 goto bailout;
    1239       17658 :         if (piv && (piv->nr < 0 || (gid && gid->nr < 0)))
    1240           0 :                 goto bailout;
    1241             : 
    1242       17658 :         c = (col) ? col->nr : 0;
    1243       17658 :         g = (gid) ? gid->nr : 0;
    1244             : 
    1245             :         /* first insert single value into a bat */
    1246       17658 :         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       17658 :         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       17068 :                 int len;
    1329             : 
    1330       17068 :                 q = newStmt(mb, calcRef, plusRef);
    1331       17092 :                 if (q == NULL)
    1332           0 :                         goto bailout;
    1333       17092 :                 q = pushArgument(mb, q, offset->nr);
    1334       17092 :                 q = pushArgument(mb, q, limit->nr);
    1335       17092 :                 len = getDestVar(q);
    1336       17092 :                 pushInstruction(mb, q);
    1337             : 
    1338             :                 /* since both arguments of algebra.subslice are
    1339             :                    inclusive correct the LIMIT value by
    1340             :                    subtracting 1 */
    1341       17092 :                 q = newStmt(mb, calcRef, minusRef);
    1342       17091 :                 if (q == NULL)
    1343           0 :                         goto bailout;
    1344       17091 :                 q = pushArgument(mb, q, len);
    1345       17092 :                 q = pushInt(mb, q, 1);
    1346       17092 :                 len = getDestVar(q);
    1347       17092 :                 pushInstruction(mb, q);
    1348             : 
    1349       17092 :                 q = newStmt(mb, algebraRef, subsliceRef);
    1350       17092 :                 if (q == NULL)
    1351           0 :                         goto bailout;
    1352       17092 :                 q = pushArgument(mb, q, c);
    1353       17091 :                 q = pushArgument(mb, q, offset->nr);
    1354       17091 :                 q = pushArgument(mb, q, len);
    1355       17092 :                 l = getDestVar(q);
    1356       17092 :                 pushInstruction(mb, q);
    1357             :         }
    1358             :         /* retrieve the single values again */
    1359       17681 :         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       35052 :         stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
    1370       17681 :         if (ns == NULL) {
    1371           0 :                 goto bailout;
    1372             :         }
    1373             : 
    1374       17681 :         ns->op1 = col;
    1375       17681 :         ns->op2 = offset;
    1376       17681 :         ns->op3 = limit;
    1377       17681 :         ns->nrcols = col->nrcols;
    1378       17681 :         ns->key = col->key;
    1379       17681 :         ns->aggr = col->aggr;
    1380       17681 :         ns->q = q;
    1381       17681 :         ns->nr = l;
    1382       17681 :         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       10520 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
    1445             : {
    1446       10520 :         MalBlkPtr mb = be->mb;
    1447       10520 :         InstrPtr q = NULL;
    1448             : 
    1449       10520 :         if (s == NULL || s->nr < 0)
    1450           0 :                 goto bailout;
    1451       10520 :         q = newStmt(mb, algebraRef, sortRef);
    1452       10520 :         if (q == NULL)
    1453           0 :                 goto bailout;
    1454             :         /* both ordered result and oid's order en subgroups */
    1455       10520 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1456       10520 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1457       10520 :         q = pushArgument(mb, q, s->nr);
    1458       10520 :         q = pushBit(mb, q, !direction);
    1459       10520 :         q = pushBit(mb, q, nullslast);
    1460       10520 :         q = pushBit(mb, q, FALSE);
    1461             : 
    1462       10520 :         bool enabled = be->mvc->sa->eb.enabled;
    1463       10520 :         be->mvc->sa->eb.enabled = false;
    1464       10520 :         stmt *ns = stmt_create(be->mvc->sa, st_order);
    1465       10520 :         be->mvc->sa->eb.enabled = enabled;
    1466       10520 :         if (ns == NULL) {
    1467           0 :                 freeInstruction(q);
    1468           0 :                 goto bailout;
    1469             :         }
    1470             : 
    1471       10520 :         ns->op1 = s;
    1472       10520 :         ns->flag = direction;
    1473       10520 :         ns->nrcols = s->nrcols;
    1474       10520 :         ns->key = s->key;
    1475       10520 :         ns->aggr = s->aggr;
    1476       10520 :         ns->q = q;
    1477       10520 :         ns->nr = getDestVar(q);
    1478       10520 :         pushInstruction(mb, q);
    1479       10520 :         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       13794 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
    1489             : {
    1490       13794 :         MalBlkPtr mb = be->mb;
    1491       13794 :         InstrPtr q = NULL;
    1492             : 
    1493       13794 :         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       13794 :         q = newStmtArgs(mb, algebraRef, sortRef, 9);
    1496       13794 :         if (q == NULL)
    1497           0 :                 goto bailout;
    1498             :         /* both ordered result and oid's order en subgroups */
    1499       13794 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1500       13794 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1501       13794 :         q = pushArgument(mb, q, s->nr);
    1502       13794 :         q = pushArgument(mb, q, orderby_ids->nr);
    1503       13794 :         q = pushArgument(mb, q, orderby_grp->nr);
    1504       13794 :         q = pushBit(mb, q, !direction);
    1505       13794 :         q = pushBit(mb, q, nullslast);
    1506       13794 :         q = pushBit(mb, q, FALSE);
    1507             : 
    1508       13794 :         bool enabled = be->mvc->sa->eb.enabled;
    1509       13794 :         be->mvc->sa->eb.enabled = false;
    1510       13794 :         stmt *ns = stmt_create(be->mvc->sa, st_reorder);
    1511       13794 :         be->mvc->sa->eb.enabled = enabled;
    1512       13794 :         if (ns == NULL) {
    1513           0 :                 freeInstruction(q);
    1514           0 :                 goto bailout;
    1515             :         }
    1516             : 
    1517       13794 :         ns->op1 = s;
    1518       13794 :         ns->op2 = orderby_ids;
    1519       13794 :         ns->op3 = orderby_grp;
    1520       13794 :         ns->flag = direction;
    1521       13794 :         ns->nrcols = s->nrcols;
    1522       13794 :         ns->key = s->key;
    1523       13794 :         ns->aggr = s->aggr;
    1524       13794 :         ns->nr = getDestVar(q);
    1525       13794 :         ns->q = q;
    1526       13794 :         pushInstruction(mb, q);
    1527       13794 :         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     3432734 : stmt_atom(backend *be, atom *a)
    1537             : {
    1538     3432734 :         MalBlkPtr mb = be->mb;
    1539             : 
    1540     3432734 :         if (a == NULL)
    1541           0 :                 goto bailout;
    1542             : 
    1543     3432734 :         InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->impl) : newAssignment(mb);
    1544             : 
    1545     3433955 :         if (q == NULL)
    1546           0 :                 goto bailout;
    1547     3433955 :         if (atom_null(a)) {
    1548      151902 :                 q = pushNil(mb, q, atom_type(a)->type->localtype);
    1549             :         } else {
    1550     3282053 :                 int k;
    1551     3282053 :                 if ((k = constantAtom(be, mb, a)) == -1) {
    1552           0 :                         freeInstruction(q);
    1553           0 :                         goto bailout;
    1554             :                 }
    1555     3281012 :                 q = pushArgument(mb, q, k);
    1556             :         }
    1557             :         /* digits of the result timestamp/daytime */
    1558     3432960 :         if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
    1559       47402 :                 q = pushInt(mb, q, atom_type(a)->digits);
    1560     3433145 :         bool enabled = be->mvc->sa->eb.enabled;
    1561     3433145 :         be->mvc->sa->eb.enabled = false;
    1562     3433145 :         stmt *s = stmt_create(be->mvc->sa, st_atom);
    1563     3432398 :         be->mvc->sa->eb.enabled = enabled;
    1564     3432398 :         if (s == NULL) {
    1565           0 :                 freeInstruction(q);
    1566           0 :                 goto bailout;
    1567             :         }
    1568             : 
    1569     3432398 :         s->op4.aval = a;
    1570     3432398 :         s->key = 1;          /* values are also unique */
    1571     3432398 :         s->q = q;
    1572     3432398 :         s->nr = getDestVar(q);
    1573     3432398 :         pushInstruction(mb, q);
    1574     3432398 :         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        3616 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
    1584             : {
    1585        3616 :         MalBlkPtr mb = be->mb;
    1586        3616 :         InstrPtr q = NULL;
    1587        3616 :         const char *mod, *op;
    1588        3616 :         node *n;
    1589        3616 :         int k;
    1590             : 
    1591        3616 :         if (lops == NULL || rops == NULL)
    1592           0 :                 goto bailout;
    1593             : 
    1594        3616 :         if (backend_create_subfunc(be, f, NULL) < 0)
    1595           0 :                 goto bailout;
    1596        3616 :         op = backend_function_imp(be, f->func);
    1597        3616 :         mod = sql_func_mod(f->func);
    1598             : 
    1599        3616 :         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        3560 :                 node *n;
    1639             : 
    1640        3560 :                 op = sa_strconcat(be->mvc->sa, op, selectRef);
    1641        3560 :                 q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
    1642        3560 :                 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        3560 :                 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        3560 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
    1650           0 :                         q = pushStr(mb, q, f->func->query);
    1651             : 
    1652        7120 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1653        3560 :                         stmt *op = n->data;
    1654             : 
    1655        3560 :                         q = pushArgument(mb, q, op->nr);
    1656             :                 }
    1657             :                 /* candidate lists */
    1658        3560 :                 if (sub)
    1659        3491 :                         q = pushArgument(mb, q, sub->nr);
    1660             :                 else
    1661          69 :                         q = pushNilBat(mb, q);
    1662             : 
    1663       13993 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1664       10433 :                         stmt *op = n->data;
    1665             : 
    1666       10433 :                         q = pushArgument(mb, q, op->nr);
    1667             :                 }
    1668             : 
    1669        3560 :                 q = pushBit(mb, q, anti);
    1670             :         }
    1671             : 
    1672        3616 :         bool enabled = be->mvc->sa->eb.enabled;
    1673        3616 :         be->mvc->sa->eb.enabled = false;
    1674        3616 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1675        3616 :         be->mvc->sa->eb.enabled = enabled;
    1676        3616 :         if (s == NULL) {
    1677           0 :                 freeInstruction(q);
    1678           0 :                 goto bailout;
    1679             :         }
    1680             : 
    1681        3616 :         s->op1 = lops;
    1682        3616 :         s->op2 = rops;
    1683        3616 :         s->op3 = sub;
    1684        3616 :         s->key = lops->nrcols == 0 && rops->nrcols == 0;
    1685        3616 :         s->flag = cmp_filter;
    1686        3616 :         s->nrcols = lops->nrcols;
    1687        3616 :         s->nr = getDestVar(q);
    1688        3616 :         s->q = q;
    1689        3616 :         s->cand = sub;
    1690        3616 :         pushInstruction(mb, q);
    1691        3616 :         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      216797 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
    1701             : {
    1702      216797 :         MalBlkPtr mb = be->mb;
    1703      216797 :         InstrPtr q = NULL;
    1704      216797 :         int l, r;
    1705      216797 :         stmt *sel = sub;
    1706             : 
    1707      216797 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
    1708           0 :                 goto bailout;
    1709      216797 :         l = op1->nr;
    1710      216797 :         r = op2->nr;
    1711             : 
    1712      216797 :         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      216797 :         if (op2->nrcols >= 1) {
    1722       18136 :                 bit need_not = FALSE;
    1723       18136 :                 const char *mod = calcRef;
    1724       18136 :                 const char *op = "=";
    1725       18136 :                 int k;
    1726             : 
    1727       18136 :                 switch (cmptype) {
    1728             :                 case cmp_equal:
    1729             :                         op = "=";
    1730             :                         break;
    1731             :                 case cmp_notequal:
    1732       18136 :                         op = "!=";
    1733             :                         break;
    1734         920 :                 case cmp_lt:
    1735         920 :                         op = "<";
    1736         920 :                         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       28679 :                 if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
    1751           0 :                         goto bailout;
    1752       18136 :                 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       18136 :                 if (is_semantics)
    1765        2988 :                         q = pushBit(mb, q, TRUE);
    1766       18136 :                 k = getDestVar(q);
    1767             : 
    1768       18136 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1769       18136 :                 if (q == NULL)
    1770           0 :                         goto bailout;
    1771       18136 :                 q = pushArgument(mb, q, k);
    1772       18136 :                 if (sub)
    1773        4363 :                         q = pushArgument(mb, q, sub->nr);
    1774       18136 :                 q = pushBit(mb, q, !need_not);
    1775       18136 :                 q = pushBit(mb, q, !need_not);
    1776       18136 :                 q = pushBit(mb, q, TRUE);
    1777       18136 :                 q = pushBit(mb, q, TRUE);
    1778       18136 :                 q = pushBit(mb, q, anti);
    1779       18136 :                 k = getDestVar(q);
    1780             :         } else {
    1781      198661 :                 assert (cmptype != cmp_filter);
    1782      198661 :                 q = newStmt(mb, algebraRef, thetaselectRef);
    1783      198667 :                 if (q == NULL)
    1784           0 :                         goto bailout;
    1785      198667 :                 q = pushArgument(mb, q, l);
    1786      198665 :                 if (sub && !op1->cand) {
    1787      129770 :                         q = pushArgument(mb, q, sub->nr);
    1788             :                 } else {
    1789         630 :                         assert(!sub || op1->cand == sub);
    1790       68895 :                         q = pushNilBat(mb, q);
    1791       68895 :                         sub = NULL;
    1792             :                 }
    1793      198668 :                 q = pushArgument(mb, q, r);
    1794      198642 :                 switch (cmptype) {
    1795      162725 :                 case cmp_equal:
    1796      162725 :                         if (is_semantics)
    1797       34875 :                                 q = pushStr(mb, q, anti?"ne":"eq");
    1798             :                         else
    1799      285530 :                                 q = pushStr(mb, q, anti?"!=":"==");
    1800             :                         break;
    1801       32838 :                 case cmp_notequal:
    1802       32838 :                         if (is_semantics)
    1803         150 :                                 q = pushStr(mb, q, anti?"eq":"ne");
    1804             :                         else
    1805       65526 :                                 q = pushStr(mb, q, anti?"==":"!=");
    1806             :                         break;
    1807         436 :                 case cmp_lt:
    1808         436 :                         q = pushStr(mb, q, anti?">=":"<");
    1809         436 :                         break;
    1810          74 :                 case cmp_lte:
    1811          74 :                         q = pushStr(mb, q, anti?">":"<=");
    1812          74 :                         break;
    1813        2290 :                 case cmp_gt:
    1814        2290 :                         q = pushStr(mb, q, anti?"<=":">");
    1815        2290 :                         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      216802 :         bool enabled = be->mvc->sa->eb.enabled;
    1829      216802 :         be->mvc->sa->eb.enabled = false;
    1830      216802 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1831      216782 :         be->mvc->sa->eb.enabled = enabled;
    1832      216782 :         if (s == NULL) {
    1833           0 :                 freeInstruction(q);
    1834           0 :                 goto bailout;
    1835             :         }
    1836             : 
    1837      216782 :         s->op1 = op1;
    1838      216782 :         s->op2 = op2;
    1839      216782 :         s->op3 = sub;
    1840      216782 :         s->flag = cmptype;
    1841      216782 :         s->key = op1->nrcols == 0 && op2->nrcols == 0;
    1842      216782 :         s->nrcols = op1->nrcols;
    1843      216782 :         s->nr = getDestVar(q);
    1844      216782 :         s->q = q;
    1845      216782 :         s->cand = sub;
    1846      216782 :         pushInstruction(mb, q);
    1847      216802 :         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        5110 : 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        5110 :         MalBlkPtr mb = be->mb;
    1909        5110 :         InstrPtr p, q;
    1910        5110 :         int l;
    1911        5110 :         const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
    1912        5110 :         stmt *sub = (Sub)?*Sub:NULL;
    1913             : 
    1914        5110 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
    1915           0 :                 goto bailout;
    1916        5110 :         l = op1->nr;
    1917        8482 :         if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
    1918        3602 :                 int k;
    1919        3602 :                 int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
    1920             : 
    1921        3602 :                 if (op2->nr < 0 || op3->nr < 0)
    1922           0 :                         goto bailout;
    1923             : 
    1924        3602 :                 if (nrcols)
    1925        3561 :                         p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
    1926             :                 else
    1927          41 :                         p = newStmtArgs(mb, calcRef, betweenRef, 9);
    1928        3602 :                 if (p == NULL)
    1929           0 :                         goto bailout;
    1930        3602 :                 p = pushArgument(mb, p, l);
    1931        3602 :                 p = pushArgument(mb, p, op2->nr);
    1932        3602 :                 p = pushArgument(mb, p, op3->nr);
    1933             : 
    1934             :                 /* cands */
    1935        3602 :                 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        3602 :                 p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
    1956        3602 :                 p = pushBit(mb, p, (cmp & 1) != 0);     /* lo inclusive */
    1957        3602 :                 p = pushBit(mb, p, (cmp & 2) != 0);     /* hi inclusive */
    1958        3602 :                 p = pushBit(mb, p, FALSE);                  /* nils_false */
    1959        3602 :                 p = pushBit(mb, p, (anti)?TRUE:FALSE);      /* anti */
    1960        3602 :                 pushInstruction(mb, p);
    1961        3602 :                 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         404 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2117             : {
    2118         404 :         MalBlkPtr mb = be->mb;
    2119         404 :         InstrPtr q;
    2120             : 
    2121         404 :         q = newStmtArgs(mb, algebraRef, markselectRef, 6);
    2122         404 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2123         404 :         q = pushArgument(mb, q, g->nr); /* left ids */
    2124         404 :         q = pushArgument(mb, q, m->nr); /* mark info mask */
    2125         404 :         q = pushArgument(mb, q, p->nr);      /* predicate */
    2126         404 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2127         404 :         pushInstruction(mb, q);
    2128             : 
    2129         404 :         if (!q)
    2130             :                 return NULL;
    2131         404 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2132         404 :         if (s == NULL) {
    2133           0 :                 freeInstruction(q);
    2134           0 :                 return NULL;
    2135             :         }
    2136             : 
    2137         404 :         s->op1 = g;
    2138         404 :         s->op2 = m;
    2139         404 :         s->flag = MARKJOIN;
    2140         404 :         s->key = 0;
    2141         404 :         s->nrcols = g->nrcols;
    2142         404 :         s->nr = getDestVar(q);
    2143         404 :         s->q = q;
    2144         404 :         return s;
    2145             : }
    2146             : 
    2147             : stmt *
    2148        2518 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
    2149             : {
    2150        2518 :         MalBlkPtr mb = be->mb;
    2151        2518 :         InstrPtr q;
    2152             : 
    2153        2518 :         q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
    2154        2518 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2155        2518 :         if (!final)
    2156           5 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2157        2518 :         q = pushArgument(mb, q, l->nr); /* left ids */
    2158        2518 :         q = pushArgument(mb, q, r->nr); /* mark info mask */
    2159        2518 :         q = pushNilBat(mb, q);
    2160        2518 :         q = pushNilBat(mb, q);
    2161        2518 :         q = pushNil(mb, q, TYPE_lng);
    2162        2518 :         pushInstruction(mb, q);
    2163             : 
    2164        2518 :         if (!q)
    2165             :                 return NULL;
    2166        2518 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2167        2518 :         if (s == NULL) {
    2168           0 :                 freeInstruction(q);
    2169           0 :                 return NULL;
    2170             :         }
    2171             : 
    2172        2518 :         s->op1 = l;
    2173        2518 :         s->op2 = r;
    2174        2518 :         s->flag = MARKJOIN;
    2175        2518 :         s->key = 0;
    2176        2518 :         s->nrcols = l->nrcols;
    2177        2518 :         s->nr = getDestVar(q);
    2178        2518 :         s->q = q;
    2179        2518 :         return s;
    2180             : }
    2181             : 
    2182             : stmt *
    2183        5056 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
    2184             : {
    2185        5056 :         stmt *sel = sub;
    2186        5056 :         InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
    2187             : 
    2188        5056 :         if (q == NULL)
    2189             :                 return NULL;
    2190             : 
    2191        5056 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2192        5056 :         if (s == NULL) {
    2193             :                 return NULL;
    2194             :         }
    2195             : 
    2196        5056 :         s->op1 = op1;
    2197        5056 :         s->op2 = op2;
    2198        5056 :         s->op3 = op3;
    2199        5056 :         s->op4.stval = sub;
    2200        5056 :         s->flag = cmp;
    2201        5056 :         s->nrcols = op1->nrcols;
    2202        5056 :         s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
    2203        5056 :         s->nr = getDestVar(q);
    2204        5056 :         s->q = q;
    2205        5056 :         s->cand = sub;
    2206        5056 :         s->reduce = reduce;
    2207        5056 :         if (!sub && sel) /* project back the old ids */
    2208        1458 :                 return stmt_project(be, s, sel);
    2209             :         return s;
    2210             : }
    2211             : 
    2212             : stmt *
    2213       54229 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
    2214             : {
    2215       54229 :         InstrPtr q = NULL;
    2216       54229 :         MalBlkPtr mb = be->mb;
    2217             : 
    2218       54229 :         q = dump_2(mb, batRef, mergecandRef, op1, op2);
    2219       54229 :         if (q) {
    2220       54229 :                 stmt *s = stmt_create(be->mvc->sa, st_tunion);
    2221       54229 :                 if (s == NULL) {
    2222             :                         return NULL;
    2223             :                 }
    2224             : 
    2225       54229 :                 s->op1 = op1;
    2226       54229 :                 s->op2 = op2;
    2227       54229 :                 s->nrcols = op1->nrcols;
    2228       54229 :                 s->key = op1->key;
    2229       54229 :                 s->aggr = op1->aggr;
    2230       54229 :                 s->nr = getDestVar(q);
    2231       54229 :                 s->q = q;
    2232       54229 :                 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       44838 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2242             : {
    2243       44838 :         InstrPtr q = NULL;
    2244       44838 :         MalBlkPtr mb = be->mb;
    2245             : 
    2246       44838 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2247           0 :                 goto bailout;
    2248       44838 :         q = newStmt(mb, algebraRef, differenceRef);
    2249       44838 :         if (q == NULL)
    2250           0 :                 goto bailout;
    2251       44838 :         q = pushArgument(mb, q, op1->nr); /* left */
    2252       44838 :         q = pushArgument(mb, q, op2->nr); /* right */
    2253       44838 :         if (lcand)
    2254           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2255             :         else
    2256       44838 :                 q = pushNilBat(mb, q); /* left candidate */
    2257       44838 :         q = pushNilBat(mb, q); /* right candidate */
    2258       44838 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2259       44838 :         q = pushBit(mb, q, FALSE);    /* do not clear nils */
    2260       44838 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2261             : 
    2262       44838 :         bool enabled = be->mvc->sa->eb.enabled;
    2263       44838 :         be->mvc->sa->eb.enabled = false;
    2264       44838 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2265       44838 :         be->mvc->sa->eb.enabled = enabled;
    2266       44838 :         if (s == NULL) {
    2267           0 :                 freeInstruction(q);
    2268           0 :                 goto bailout;
    2269             :         }
    2270             : 
    2271       44838 :         s->op1 = op1;
    2272       44838 :         s->op2 = op2;
    2273       44838 :         s->nrcols = op1->nrcols;
    2274       44838 :         s->key = op1->key;
    2275       44838 :         s->aggr = op1->aggr;
    2276       44838 :         s->nr = getDestVar(q);
    2277       44838 :         s->q = q;
    2278       44838 :         pushInstruction(mb, q);
    2279       44838 :         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        1378 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2289             : {
    2290        1378 :         InstrPtr q = NULL;
    2291        1378 :         MalBlkPtr mb = be->mb;
    2292             : 
    2293        1378 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2294           0 :                 goto bailout;
    2295        1378 :         q = newStmt(mb, algebraRef, differenceRef);
    2296        1378 :         if (q == NULL)
    2297           0 :                 goto bailout;
    2298        1378 :         q = pushArgument(mb, q, op1->nr); /* left */
    2299        1378 :         q = pushArgument(mb, q, op2->nr); /* right */
    2300        1378 :         if (lcand)
    2301           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2302             :         else
    2303        1378 :                 q = pushNilBat(mb, q); /* left candidate */
    2304        1378 :         q = pushNilBat(mb, q); /* right candidate */
    2305        1378 :         q = pushBit(mb, q, FALSE);     /* nil matches */
    2306        1378 :         q = pushBit(mb, q, TRUE);     /* not in */
    2307        1378 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2308             : 
    2309        1378 :         bool enabled = be->mvc->sa->eb.enabled;
    2310        1378 :         be->mvc->sa->eb.enabled = false;
    2311        1378 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2312        1378 :         be->mvc->sa->eb.enabled = enabled;
    2313        1378 :         if (s == NULL) {
    2314           0 :                 freeInstruction(q);
    2315           0 :                 goto bailout;
    2316             :         }
    2317             : 
    2318        1378 :         s->op1 = op1;
    2319        1378 :         s->op2 = op2;
    2320        1378 :         s->nrcols = op1->nrcols;
    2321        1378 :         s->key = op1->key;
    2322        1378 :         s->aggr = op1->aggr;
    2323        1378 :         s->nr = getDestVar(q);
    2324        1378 :         s->q = q;
    2325        1378 :         pushInstruction(mb, q);
    2326        1378 :         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        2109 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
    2336             : {
    2337        2109 :         InstrPtr q = NULL;
    2338        2109 :         MalBlkPtr mb = be->mb;
    2339             : 
    2340        2109 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2341           0 :                 goto bailout;
    2342        2109 :         q = newStmt(mb, algebraRef, intersectRef);
    2343        2109 :         if (q == NULL)
    2344           0 :                 goto bailout;
    2345        2109 :         q = pushArgument(mb, q, op1->nr); /* left */
    2346        2109 :         q = pushArgument(mb, q, op2->nr); /* right */
    2347        2109 :         q = pushNilBat(mb, q); /* left candidate */
    2348        2109 :         q = pushNilBat(mb, q); /* right candidate */
    2349        2109 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2350        2109 :         q = pushBit(mb, q, single?TRUE:FALSE);    /* max_one */
    2351        2109 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2352             : 
    2353        2109 :         bool enabled = be->mvc->sa->eb.enabled;
    2354        2109 :         be->mvc->sa->eb.enabled = false;
    2355        2109 :         stmt *s = stmt_create(be->mvc->sa, st_tinter);
    2356        2109 :         be->mvc->sa->eb.enabled = enabled;
    2357        2109 :         if (s == NULL) {
    2358           0 :                 freeInstruction(q);
    2359           0 :                 goto bailout;
    2360             :         }
    2361             : 
    2362        2109 :         s->op1 = op1;
    2363        2109 :         s->op2 = op2;
    2364        2109 :         s->nrcols = op1->nrcols;
    2365        2109 :         s->key = op1->key;
    2366        2109 :         s->aggr = op1->aggr;
    2367        2109 :         s->nr = getDestVar(q);
    2368        2109 :         s->q = q;
    2369        2109 :         pushInstruction(mb, q);
    2370        2109 :         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       95102 : 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       95102 :         MalBlkPtr mb = be->mb;
    2382       95102 :         InstrPtr q = NULL;
    2383       95102 :         const char *sjt = inner?joinRef:outerjoinRef;
    2384             : 
    2385       95102 :         (void)anti;
    2386       95102 :         (void)inner;
    2387             : 
    2388       95102 :         if (need_left) {
    2389         653 :                 cmptype = cmp_equal;
    2390         653 :                 sjt = leftjoinRef;
    2391             :         }
    2392       95102 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2393           0 :                 goto bailout;
    2394             : 
    2395       95102 :         assert (!single || cmptype == cmp_all);
    2396             : 
    2397       95102 :         switch (cmptype) {
    2398       77024 :         case cmp_equal:
    2399       77024 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2400       77024 :                 if (q == NULL)
    2401           0 :                         goto bailout;
    2402       77024 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2403       77024 :                 q = pushArgument(mb, q, op1->nr);
    2404       77024 :                 q = pushArgument(mb, q, op2->nr);
    2405       77024 :                 if (!lcand)
    2406       75936 :                         q = pushNilBat(mb, q);
    2407             :                 else
    2408        1088 :                         q = pushArgument(mb, q, lcand->nr);
    2409       77024 :                 if (!rcand)
    2410       77024 :                         q = pushNilBat(mb, q);
    2411             :                 else
    2412           0 :                         q = pushArgument(mb, q, rcand->nr);
    2413       77024 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2414       77024 :                 if (!inner)
    2415          75 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2416       77024 :                 q = pushNil(mb, q, TYPE_lng);
    2417       77024 :                 pushInstruction(mb, q);
    2418       77024 :                 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        2584 :         case cmp_lt:
    2445             :         case cmp_lte:
    2446             :         case cmp_gt:
    2447             :         case cmp_gte:
    2448        2584 :                 q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
    2449        2584 :                 if (q == NULL)
    2450           0 :                         goto bailout;
    2451        2584 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2452        2584 :                 q = pushArgument(mb, q, op1->nr);
    2453        2584 :                 q = pushArgument(mb, q, op2->nr);
    2454        2584 :                 if (!lcand)
    2455        2584 :                         q = pushNilBat(mb, q);
    2456             :                 else
    2457           0 :                         q = pushArgument(mb, q, lcand->nr);
    2458        2584 :                 if (!rcand)
    2459        2584 :                         q = pushNilBat(mb, q);
    2460             :                 else
    2461           0 :                         q = pushArgument(mb, q, rcand->nr);
    2462        2584 :                 if (cmptype == cmp_lt)
    2463        2068 :                         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        2584 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2471        2584 :                 q = pushNil(mb, q, TYPE_lng);
    2472        2584 :                 pushInstruction(mb, q);
    2473        2584 :                 break;
    2474       12235 :         case cmp_all:   /* aka cross table */
    2475       12673 :                 q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
    2476       12235 :                 if (q == NULL)
    2477           0 :                         goto bailout;
    2478       12235 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2479       12235 :                 q = pushArgument(mb, q, op1->nr);
    2480       12235 :                 q = pushArgument(mb, q, op2->nr);
    2481       12235 :                 if (!inner) {
    2482         438 :                         q = pushNilBat(mb, q);
    2483         438 :                         q = pushNilBat(mb, q);
    2484             :                 }
    2485       12235 :                 q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2486       12235 :                 assert(!lcand && !rcand);
    2487       12235 :                 pushInstruction(mb, q);
    2488       12235 :                 break;
    2489        3225 :         case cmp_joined:
    2490        3225 :                 q = op1->q;
    2491        3225 :                 if (q == NULL)
    2492           0 :                         goto bailout;
    2493             :                 break;
    2494           0 :         default:
    2495           0 :                 TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
    2496             :         }
    2497             : 
    2498       95102 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2499       95102 :         if (s == NULL) {
    2500           0 :                 goto bailout;
    2501             :         }
    2502             : 
    2503       95102 :         s->op1 = op1;
    2504       95102 :         s->op2 = op2;
    2505       95102 :         s->flag = cmptype;
    2506       95102 :         s->key = 0;
    2507       95102 :         s->nrcols = 2;
    2508       95102 :         s->nr = getDestVar(q);
    2509       95102 :         s->q = q;
    2510       95102 :         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       90882 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
    2520             : {
    2521       90882 :         return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
    2522             : }
    2523             : 
    2524             : stmt *
    2525        1454 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
    2526             : {
    2527        1454 :         MalBlkPtr mb = be->mb;
    2528        1454 :         InstrPtr q = NULL;
    2529             : 
    2530        1454 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2531           0 :                 goto bailout;
    2532             : 
    2533        1454 :         if (single) {
    2534         284 :                 q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
    2535         284 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2536             :         } else
    2537        1170 :                 q = newStmt(mb, algebraRef, intersectRef);
    2538        1454 :         if (q == NULL)
    2539           0 :                 goto bailout;
    2540        1454 :         q = pushArgument(mb, q, op1->nr);
    2541        1454 :         q = pushArgument(mb, q, op2->nr);
    2542        1454 :         if (lcand)
    2543        1167 :                 q = pushArgument(mb, q, lcand->nr);
    2544             :         else
    2545         287 :                 q = pushNilBat(mb, q);
    2546        1454 :         if (rcand)
    2547           0 :                 q = pushArgument(mb, q, rcand->nr);
    2548             :         else
    2549        1454 :                 q = pushNilBat(mb, q);
    2550        1454 :         q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2551        1454 :         q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2552        1454 :         q = pushNil(mb, q, TYPE_lng);
    2553             : 
    2554        1454 :         bool enabled = be->mvc->sa->eb.enabled;
    2555        1454 :         be->mvc->sa->eb.enabled = false;
    2556        1454 :         stmt *s = stmt_create(be->mvc->sa, st_semijoin);
    2557        1454 :         be->mvc->sa->eb.enabled = enabled;
    2558        1454 :         if (s == NULL) {
    2559           0 :                 freeInstruction(q);
    2560           0 :                 goto bailout;
    2561             :         }
    2562             : 
    2563        1454 :         s->op1 = op1;
    2564        1454 :         s->op2 = op2;
    2565        1454 :         s->flag = cmp_equal;
    2566        1454 :         s->key = 0;
    2567        1454 :         s->nrcols = 1;
    2568        1454 :         if (single)
    2569         284 :                 s->nrcols = 2;
    2570        1454 :         s->nr = getDestVar(q);
    2571        1454 :         s->q = q;
    2572        1454 :         pushInstruction(mb, q);
    2573        1454 :         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     3538527 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
    2583             : {
    2584     3538527 :         MalBlkPtr mb = be->mb;
    2585     3538527 :         InstrPtr q = NULL;
    2586             : 
    2587     3538527 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2588             :                 return NULL;
    2589             :         /* delta bat */
    2590     3538527 :         if (delta) {
    2591      490235 :                 int uval = getArg(op2->q, 1);
    2592             : 
    2593      490235 :                 q = newStmt(mb, sqlRef, deltaRef);
    2594      490263 :                 q = pushArgument(mb, q, op1->nr);
    2595      490263 :                 q = pushArgument(mb, q, op2->nr);
    2596      490263 :                 q = pushArgument(mb, q, uval);
    2597             :         } else {
    2598             :                 /* projections, ie left is void headed */
    2599     3048292 :                 q = newStmt(mb, algebraRef, projectionRef);
    2600     3048342 :                 q = pushArgument(mb, q, op1->nr);
    2601     3048340 :                 q = pushArgument(mb, q, op2->nr);
    2602             :         }
    2603     3538600 :         pushInstruction(mb, q);
    2604     3538600 :         return q;
    2605             : }
    2606             : 
    2607             : stmt *
    2608     3057578 : stmt_project(backend *be, stmt *op1, stmt *op2)
    2609             : {
    2610     3057578 :         if (op1 == NULL || op2 == NULL)
    2611             :                 return NULL;
    2612     3057578 :         if (!op2->nrcols)
    2613        9286 :                 return stmt_const(be, op1, op2);
    2614     3048292 :         InstrPtr q = stmt_project_join(be, op1, op2, false);
    2615     3048340 :         if (q) {
    2616     3048340 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2617     3048321 :                 if (s == NULL) {
    2618             :                         return NULL;
    2619             :                 }
    2620             : 
    2621     3048321 :                 s->op1 = op1;
    2622     3048321 :                 s->op2 = op2;
    2623     3048321 :                 s->flag = cmp_project;
    2624     3048321 :                 s->key = 0;
    2625     3048321 :                 s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2626     3048321 :                 s->nr = getDestVar(q);
    2627     3048321 :                 s->q = q;
    2628     3048321 :                 s->tname = op2->tname;
    2629     3048321 :                 s->cname = op2->cname;
    2630     3048321 :                 s->label = op2->label;
    2631     3048321 :                 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      490235 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
    2640             : {
    2641      490235 :         InstrPtr q = stmt_project_join(be, col, upd, true);
    2642      490261 :         if (q) {
    2643      490261 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2644      490258 :                 if (s == NULL) {
    2645             :                         return NULL;
    2646             :                 }
    2647             : 
    2648      490258 :                 s->op1 = col;
    2649      490258 :                 s->op2 = upd;
    2650      490258 :                 s->flag = cmp_project;
    2651      490258 :                 s->key = 0;
    2652      490258 :                 s->nrcols = 2;
    2653      490258 :                 s->nr = getDestVar(q);
    2654      490258 :                 s->q = q;
    2655      490258 :                 s->tname = col->tname;
    2656      490258 :                 s->cname = col->cname;
    2657      490258 :                 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      287219 : stmt_catalog(backend *be, int type, stmt *args)
    3143             : {
    3144      287219 :         MalBlkPtr mb = be->mb;
    3145      287219 :         InstrPtr q = NULL;
    3146      287219 :         node *n;
    3147             : 
    3148      287219 :         if (args == NULL || args->nr < 0)
    3149           0 :                 goto bailout;
    3150             : 
    3151             :         /* cast them into properly named operations */
    3152      287219 :         const char *ref;
    3153      287219 :         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        1086 :         case ddl_create_schema:                 ref = create_schemaRef;         break;
    3158         191 :         case ddl_drop_schema:                   ref = drop_schemaRef;           break;
    3159       10157 :         case ddl_create_table:                  ref = create_tableRef;          break;
    3160       22620 :         case ddl_create_view:                   ref = create_viewRef;           break;
    3161        3712 :         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        1369 :         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       99959 :         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      122071 :         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      287219 :         q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
    3198      287219 :         if (q == NULL)
    3199           0 :                 goto bailout;
    3200             :         // pass all arguments as before
    3201     1717004 :         for (n = args->op4.lval->h; n; n = n->next) {
    3202     1429786 :                 stmt *c = n->data;
    3203             : 
    3204     1429786 :                 q = pushArgument(mb, q, c->nr);
    3205             :         }
    3206             : 
    3207      287218 :         bool enabled = be->mvc->sa->eb.enabled;
    3208      287218 :         be->mvc->sa->eb.enabled = false;
    3209      287218 :         stmt *s = stmt_create(be->mvc->sa, st_catalog);
    3210      287218 :         be->mvc->sa->eb.enabled = enabled;
    3211      287218 :         if(!s) {
    3212           0 :                 freeInstruction(q);
    3213           0 :                 goto bailout;
    3214             :         }
    3215      287218 :         s->op1 = args;
    3216      287218 :         s->flag = type;
    3217      287218 :         s->q = q;
    3218      287218 :         s->nr = getDestVar(q);
    3219      287218 :         pushInstruction(mb, q);
    3220      287218 :         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     1869180 : stmt_set_nrcols(stmt *s)
    3230             : {
    3231     1869180 :         unsigned nrcols = 0;
    3232     1869180 :         int key = 1;
    3233     1869180 :         node *n;
    3234     1869180 :         list *l = s->op4.lval;
    3235             : 
    3236     1869180 :         assert(s->type == st_list);
    3237     9113518 :         for (n = l->h; n; n = n->next) {
    3238     7244338 :                 stmt *f = n->data;
    3239             : 
    3240     7244338 :                 if (!f)
    3241           0 :                         continue;
    3242     7244338 :                 if (f->nrcols > nrcols)
    3243             :                         nrcols = f->nrcols;
    3244     7244338 :                 key &= f->key;
    3245     7244338 :                 s->nr = f->nr;
    3246             :         }
    3247     1869180 :         s->nrcols = nrcols;
    3248     1869180 :         s->key = key;
    3249     1869180 : }
    3250             : 
    3251             : stmt *
    3252     1459902 : stmt_list(backend *be, list *l)
    3253             : {
    3254     1459902 :         if (l == NULL)
    3255             :                 return NULL;
    3256     1459902 :         stmt *s = stmt_create(be->mvc->sa, st_list);
    3257     1459972 :         if(!s) {
    3258             :                 return NULL;
    3259             :         }
    3260     1459972 :         s->op4.lval = l;
    3261     1459972 :         stmt_set_nrcols(s);
    3262     1459972 :         return s;
    3263             : }
    3264             : 
    3265             : static InstrPtr
    3266       65650 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
    3267             : {
    3268       65650 :         node *n;
    3269             :         // gather the meta information
    3270       65650 :         int tblId, nmeId, tpeId, lenId, scaleId;
    3271       65650 :         int args;
    3272       65650 :         InstrPtr list;
    3273       65650 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    3274             : 
    3275       65650 :         args = list_length(l) + 1;
    3276             : 
    3277       65658 :         list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 5);
    3278       65668 :         if(!list) {
    3279             :                 return NULL;
    3280             :         }
    3281       65668 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3282       65667 :         meta(tblPtr, tblId, TYPE_str, args);
    3283       65669 :         meta(nmePtr, nmeId, TYPE_str, args);
    3284       65670 :         meta(tpePtr, tpeId, TYPE_str, args);
    3285       65669 :         meta(lenPtr, lenId, TYPE_int, args);
    3286       65670 :         meta(scalePtr, scaleId, TYPE_int, args);
    3287       65670 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    3288             :                 return NULL;
    3289             : 
    3290      344821 :         for (n = l->h; n; n = n->next) {
    3291      279155 :                 stmt *c = n->data;
    3292      279155 :                 sql_subtype *t = tail_type(c);
    3293      279160 :                 const char *tname = table_name(sql->sa, c);
    3294      279161 :                 const char *sname = schema_name(sql->sa, c);
    3295      279153 :                 const char *_empty = "";
    3296      279153 :                 const char *tn = (tname) ? tname : _empty;
    3297      279153 :                 const char *sn = (sname) ? sname : _empty;
    3298      279153 :                 const char *cn = column_name(sql->sa, c);
    3299      279153 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3300      279144 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3301      279162 :                 size_t fqtnl;
    3302             : 
    3303      279162 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3304      279162 :                         char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3305      279159 :                         if (fqtn == NULL)
    3306             :                                 return NULL;
    3307      279159 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3308      279159 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3309      279155 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3310      279151 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3311      279157 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3312      279151 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3313      279153 :                         list = pushArgument(mb,list,c->nr);
    3314             :                 } else
    3315             :                         return NULL;
    3316             :         }
    3317       65666 :         sa_reset(sql->ta);
    3318       65654 :         pushInstruction(mb,list);
    3319       65654 :         return list;
    3320             : }
    3321             : 
    3322             : int
    3323      126040 : stmt_output(backend *be, stmt *lst)
    3324             : {
    3325      126040 :         MalBlkPtr mb = be->mb;
    3326      126040 :         InstrPtr q = NULL;
    3327      126040 :         list *l = lst->op4.lval;
    3328      126040 :         int cnt = list_length(l), ok = 0;
    3329      126101 :         node *n = l->h;
    3330      126101 :         stmt *first = n->data;
    3331             : 
    3332             :         /* single value result, has a fast exit */
    3333      126101 :         if (cnt == 1 && first->nrcols <= 0 ){
    3334       60447 :                 stmt *c = n->data;
    3335       60447 :                 sql_subtype *t = tail_type(c);
    3336       60392 :                 const char *tname = table_name(be->mvc->sa, c);
    3337       60337 :                 const char *sname = schema_name(be->mvc->sa, c);
    3338       60337 :                 const char *_empty = "";
    3339       60337 :                 const char *tn = (tname) ? tname : _empty;
    3340       60337 :                 const char *sn = (sname) ? sname : _empty;
    3341       60337 :                 const char *cn = column_name(be->mvc->sa, c);
    3342       60341 :                 const char *ntn = sql_escape_ident(be->mvc->ta, tn);
    3343       60481 :                 const char *nsn = sql_escape_ident(be->mvc->ta, sn);
    3344             : 
    3345       60494 :                 if (ntn && nsn) {
    3346       60494 :                         size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
    3347       60494 :                         char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
    3348       60493 :                         if (fqtn == NULL)
    3349             :                                 return -1;
    3350       60493 :                         ok = 1;
    3351       60493 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3352             : 
    3353       60493 :                         q = newStmt(mb, sqlRef, resultSetRef);
    3354       60498 :                         if (q == NULL)
    3355             :                                 return -1;
    3356       60498 :                         getArg(q,0) = newTmpVariable(mb,TYPE_int);
    3357       60498 :                         q = pushStr(mb, q, fqtn);
    3358       60495 :                         q = pushStr(mb, q, cn);
    3359       60495 :                         q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
    3360       60496 :                         q = pushInt(mb, q, t->digits);
    3361       60493 :                         q = pushInt(mb, q, t->scale);
    3362       60498 :                         q = pushInt(mb, q, t->type->eclass);
    3363       60488 :                         q = pushArgument(mb, q, c->nr);
    3364       60487 :                         pushInstruction(mb, q);
    3365             :                 }
    3366       60482 :                 sa_reset(be->mvc->ta);
    3367       60441 :                 if (!ok)
    3368             :                         return -1;
    3369             :         } else {
    3370       65654 :                 if ((q = dump_header(be->mvc, mb, l)) == NULL)
    3371             :                         return -1;
    3372             :         }
    3373             :         return 0;
    3374             : }
    3375             : 
    3376             : int
    3377      149287 : stmt_affected_rows(backend *be, int lastnr)
    3378             : {
    3379      149287 :         MalBlkPtr mb = be->mb;
    3380      149287 :         InstrPtr q = NULL;
    3381             : 
    3382      149287 :         q = newStmt(mb, sqlRef, affectedRowsRef);
    3383      149550 :         if (q == NULL)
    3384             :                 return -1;
    3385      149550 :         q = pushArgument(mb, q, be->mvc_var);
    3386      149550 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    3387      149551 :         q = pushArgument(mb, q, lastnr);
    3388      149550 :         pushInstruction(mb, q);
    3389      149548 :         be->mvc_var = getDestVar(q);
    3390      149548 :         return 0;
    3391             : }
    3392             : 
    3393             : stmt *
    3394      176551 : stmt_append(backend *be, stmt *c, stmt *a)
    3395             : {
    3396      176551 :         MalBlkPtr mb = be->mb;
    3397      176551 :         InstrPtr q = NULL;
    3398             : 
    3399      176551 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3400           0 :                 goto bailout;
    3401      176551 :         q = newStmt(mb, batRef, appendRef);
    3402      176551 :         if (q == NULL)
    3403           0 :                 goto bailout;
    3404      176551 :         q = pushArgument(mb, q, c->nr);
    3405      176551 :         q = pushArgument(mb, q, a->nr);
    3406      176551 :         q = pushBit(mb, q, TRUE);
    3407      176551 :         bool enabled = be->mvc->sa->eb.enabled;
    3408      176551 :         be->mvc->sa->eb.enabled = false;
    3409      176551 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3410      176551 :         be->mvc->sa->eb.enabled = enabled;
    3411      176551 :         if(!s) {
    3412           0 :                 freeInstruction(q);
    3413           0 :                 goto bailout;
    3414             :         }
    3415      176551 :         s->op1 = c;
    3416      176551 :         s->op2 = a;
    3417      176551 :         s->nrcols = c->nrcols;
    3418      176551 :         s->key = c->key;
    3419      176551 :         s->nr = getDestVar(q);
    3420      176551 :         s->q = q;
    3421      176551 :         pushInstruction(mb, q);
    3422      176551 :         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      137647 : stmt_append_bulk(backend *be, stmt *c, list *l)
    3432             : {
    3433      137647 :         MalBlkPtr mb = be->mb;
    3434      137647 :         InstrPtr q = NULL;
    3435      137647 :         bool needs_columns = false;
    3436             : 
    3437      137647 :         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      888393 :         for (node *n = l->h; n; n = n->next) {
    3443      750746 :                 stmt *t = n->data;
    3444      750746 :                 needs_columns |= t->nrcols > 0;
    3445             :         }
    3446      137647 :         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      137647 :         q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3);
    3455      138039 :         if (q == NULL)
    3456           0 :                 goto bailout;
    3457      138039 :         q = pushArgument(mb, q, c->nr);
    3458      138034 :         q = pushBit(mb, q, TRUE);
    3459      889096 :         for (node *n = l->h ; n ; n = n->next) {
    3460      751182 :                 stmt *a = n->data;
    3461      751182 :                 q = pushArgument(mb, q, a->nr);
    3462             :         }
    3463      137914 :         bool enabled = be->mvc->sa->eb.enabled;
    3464      137914 :         be->mvc->sa->eb.enabled = false;
    3465      137914 :         stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
    3466      137820 :         be->mvc->sa->eb.enabled = enabled;
    3467      137820 :         if(!s) {
    3468           0 :                 freeInstruction(q);
    3469           0 :                 goto bailout;
    3470             :         }
    3471      137820 :         s->op1 = c;
    3472      137820 :         s->op4.lval = l;
    3473      137820 :         s->nrcols = c->nrcols;
    3474      137820 :         s->key = c->key;
    3475      137820 :         s->nr = getDestVar(q);
    3476      137820 :         s->q = q;
    3477      137820 :         pushInstruction(mb, q);
    3478      137820 :         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       16049 : stmt_pack(backend *be, stmt *c, int n)
    3488             : {
    3489       16049 :         MalBlkPtr mb = be->mb;
    3490       16049 :         InstrPtr q = NULL;
    3491             : 
    3492       16049 :         if (c == NULL || c->nr < 0)
    3493           0 :                 goto bailout;
    3494       16049 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3495       16049 :         if (q == NULL)
    3496           0 :                 goto bailout;
    3497       16049 :         q = pushArgument(mb, q, c->nr);
    3498       16049 :         q = pushInt(mb, q, n);
    3499       16049 :         bool enabled = be->mvc->sa->eb.enabled;
    3500       16049 :         be->mvc->sa->eb.enabled = false;
    3501       16049 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3502       16049 :         be->mvc->sa->eb.enabled = enabled;
    3503       16049 :         if(!s) {
    3504           0 :                 freeInstruction(q);
    3505           0 :                 goto bailout;
    3506             :         }
    3507       16049 :         s->op1 = c;
    3508       16049 :         s->nrcols = c->nrcols;
    3509       16049 :         s->key = c->key;
    3510       16049 :         s->nr = getDestVar(q);
    3511       16049 :         s->q = q;
    3512       16049 :         pushInstruction(mb, q);
    3513       16049 :         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       29785 : stmt_pack_add(backend *be, stmt *c, stmt *a)
    3524             : {
    3525       29785 :         MalBlkPtr mb = be->mb;
    3526       29785 :         InstrPtr q = NULL;
    3527             : 
    3528       29785 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3529           0 :                 goto bailout;
    3530       29785 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3531       29785 :         if (q == NULL)
    3532           0 :                 goto bailout;
    3533       29785 :         q = pushArgument(mb, q, c->nr);
    3534       29785 :         q = pushArgument(mb, q, a->nr);
    3535       29785 :         bool enabled = be->mvc->sa->eb.enabled;
    3536       29785 :         be->mvc->sa->eb.enabled = false;
    3537       29785 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3538       29785 :         be->mvc->sa->eb.enabled = enabled;
    3539       29785 :         if(!s) {
    3540           0 :                 freeInstruction(q);
    3541           0 :                 goto bailout;
    3542             :         }
    3543       29785 :         s->op1 = c;
    3544       29785 :         s->op2 = a;
    3545       29785 :         s->nrcols = c->nrcols;
    3546       29785 :         s->key = c->key;
    3547       29785 :         s->nr = getDestVar(q);
    3548       29785 :         s->q = q;
    3549       29785 :         pushInstruction(mb, q);
    3550       29785 :         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      106159 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
    3560             : {
    3561      106159 :         MalBlkPtr mb = be->mb;
    3562      106159 :         InstrPtr q = NULL;
    3563             : 
    3564      106159 :         if (!t || cnt->nr < 0)
    3565           0 :                 goto bailout;
    3566      106159 :         assert(t->s);                                /* declared table */
    3567      106159 :         q = newStmtArgs(mb, sqlRef, claimRef, 6);
    3568      106241 :         if (q == NULL)
    3569           0 :                 goto bailout;
    3570             :         /* returns offset or offsets */
    3571      106241 :         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
    3572      106237 :         q = pushArgument(mb, q, be->mvc_var);
    3573      106229 :         q = pushSchema(mb, q, t);
    3574      106206 :         q = pushStr(mb, q, t->base.name);
    3575      106206 :         q = pushArgument(mb, q, cnt->nr);
    3576      106209 :         bool enabled = be->mvc->sa->eb.enabled;
    3577      106209 :         be->mvc->sa->eb.enabled = false;
    3578      106209 :         stmt *s = stmt_create(be->mvc->sa, st_claim);
    3579      106147 :         be->mvc->sa->eb.enabled = enabled;
    3580      106147 :         if(!s) {
    3581           0 :                 freeInstruction(q);
    3582           0 :                 goto bailout;
    3583             :         }
    3584      106147 :         s->op1 = cnt;
    3585      106147 :         s->op4.tval = t;
    3586      106147 :         s->nr = getDestVar(q);
    3587      106147 :         s->q = q;
    3588      106147 :         pushInstruction(mb, q);
    3589      106147 :         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      149240 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
    3599             : {
    3600      149240 :         MalBlkPtr mb = be->mb;
    3601      149240 :         InstrPtr q = NULL;
    3602             : 
    3603      149240 :         if (!t || cnt->nr < 0)
    3604           0 :                 goto bailout;
    3605      149240 :         q = newStmtArgs(mb, sqlRef, dependRef, 4);
    3606      149786 :         if (q == NULL)
    3607           0 :                 goto bailout;
    3608      149786 :         q = pushSchema(mb, q, t);
    3609      149763 :         q = pushStr(mb, q, t->base.name);
    3610      149771 :         q = pushArgument(mb, q, cnt->nr);
    3611      149765 :         pushInstruction(mb, q);
    3612      149765 :         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       14737 : stmt_add_column_predicate(backend *be, sql_column *c)
    3621             : {
    3622       14737 :         MalBlkPtr mb = be->mb;
    3623       14737 :         InstrPtr q = NULL;
    3624             : 
    3625       14737 :         if (!c)
    3626           0 :                 goto bailout;
    3627       14737 :         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       55617 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
    3643             : {
    3644       55617 :         MalBlkPtr mb = be->mb;
    3645       55617 :         InstrPtr q = NULL;
    3646             : 
    3647       55617 :         if (r->nr < 0)
    3648           0 :                 goto bailout;
    3649             : 
    3650       55617 :         q = newStmt(mb, batRef, replaceRef);
    3651       55617 :         if (q == NULL)
    3652           0 :                 goto bailout;
    3653       55617 :         q = pushArgument(mb, q, r->nr);
    3654       55617 :         q = pushArgument(mb, q, id->nr);
    3655       55617 :         q = pushArgument(mb, q, val->nr);
    3656       55617 :         q = pushBit(mb, q, TRUE); /* forced */
    3657       55617 :         bool enabled = be->mvc->sa->eb.enabled;
    3658       55617 :         be->mvc->sa->eb.enabled = false;
    3659       55617 :         stmt *s = stmt_create(be->mvc->sa, st_replace);
    3660       55617 :         be->mvc->sa->eb.enabled = enabled;
    3661       55617 :         if(!s) {
    3662           0 :                 freeInstruction(q);
    3663           0 :                 goto bailout;
    3664             :         }
    3665       55617 :         s->op1 = r;
    3666       55617 :         s->op2 = id;
    3667       55617 :         s->op3 = val;
    3668       55617 :         s->nrcols = r->nrcols;
    3669       55617 :         s->key = r->key;
    3670       55617 :         s->nr = getDestVar(q);
    3671       55617 :         s->q = q;
    3672       55617 :         s->cand = r->cand;
    3673       55617 :         pushInstruction(mb, q);
    3674       55617 :         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       41381 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
    3684             : {
    3685       41381 :         MalBlkPtr mb = be->mb;
    3686       41381 :         InstrPtr q = NULL;
    3687             : 
    3688       41381 :         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       41379 :                 q = newStmt(mb, sqlRef, clear_tableRef);
    3701       41829 :                 if (q == NULL)
    3702           0 :                         goto bailout;
    3703       41829 :                 q = pushSchema(mb, q, t);
    3704       41818 :                 q = pushStr(mb, q, t->base.name);
    3705       41787 :                 q = pushInt(mb, q, restart_sequences);
    3706       41791 :                 pushInstruction(mb, q);
    3707             :         }
    3708       41788 :         stmt *s = stmt_create(be->mvc->sa, st_table_clear);
    3709             : 
    3710       41663 :         if(!s) {
    3711           0 :                 goto bailout;
    3712             :         }
    3713       41663 :         s->op4.tval = t;
    3714       41663 :         s->nrcols = 0;
    3715       41663 :         s->nr = getDestVar(q);
    3716       41663 :         s->q = q;
    3717       41663 :         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       39304 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
    3727             : {
    3728       39304 :         MalBlkPtr mb = be->mb;
    3729       39304 :         InstrPtr q = NULL;
    3730             : 
    3731       39304 :         if (cond->nr < 0)
    3732             :                 return NULL;
    3733             : 
    3734             :         /* if(bit(l)) { error(r);}  ==raising an exception */
    3735       39304 :         q = newStmt(mb, sqlRef, assertRef);
    3736       39401 :         if (q == NULL)
    3737           0 :                 goto bailout;
    3738       39401 :         q = pushArgument(mb, q, cond->nr);
    3739       39401 :         q = pushStr(mb, q, errstr);
    3740       39401 :         bool enabled = be->mvc->sa->eb.enabled;
    3741       39401 :         be->mvc->sa->eb.enabled = false;
    3742       39401 :         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       15104 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
    3767             : {
    3768       40656 :         for (;;) {
    3769       40656 :                 switch (st->type) {
    3770        3689 :                 case st_const:
    3771        3689 :                         st = st->op2;
    3772        3689 :                         continue;
    3773       18251 :                 case st_alias:
    3774             :                 case st_gen_group:
    3775             :                 case st_order:
    3776       18251 :                         st = st->op1;
    3777       18251 :                         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        2779 :                 case st_aggr:
    3790             :                 case st_Nop: {
    3791        2779 :                         list *res = st->op4.funcval->res;
    3792             : 
    3793        2779 :                         if (res && list_length(res) == 1)
    3794        2779 :                                 res->h->data = t;
    3795             :                         return;
    3796             :                 }
    3797        6778 :                 case st_atom:
    3798        6778 :                         st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
    3799        6778 :                         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       51913 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    3939             : {
    3940       51913 :         MalBlkPtr mb = be->mb;
    3941       51913 :         InstrPtr q = NULL;
    3942       51913 :         const char *convert = t->type->impl, *mod = calcRef;
    3943       51913 :         int pushed = (v->cand && v->cand == sel), no_candidates = 0;
    3944       51913 :         bool add_tz = false;
    3945             :         /* convert types and make sure they are rounded up correctly */
    3946             : 
    3947       51913 :         if (v->nr < 0)
    3948           0 :                 goto bailout;
    3949             : 
    3950       51913 :         if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
    3951             :                 /* general cases */
    3952       51555 :                 ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
    3953       51555 :                 !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        1773 :                 (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       44583 :                 (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       15104 :                 tail_set_type(be->mvc, v, t);
    3960       15104 :                 return v;
    3961             :         }
    3962             : 
    3963             :         /* external types have sqlname convert functions,
    3964             :            these can generate errors (fromstr cannot) */
    3965       36809 :         if (t->type->eclass == EC_EXTERNAL)
    3966         331 :                 convert = t->type->base.name;
    3967       36478 :         else if (t->type->eclass == EC_MONTH)
    3968             :                 convert = "month_interval";
    3969       36455 :         else if (t->type->eclass == EC_SEC)
    3970         100 :                 convert = "second_interval";
    3971             : 
    3972       36809 :         no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
    3973             : 
    3974       36809 :         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       36685 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3986        8186 :                 q = newStmtArgs(mb, mod, convert, 13);
    3987        8186 :                 if (q == NULL)
    3988           0 :                         goto bailout;
    3989       28520 :         } 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       28478 :                 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       28478 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    4011       28479 :                 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       36852 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
    4017        1904 :                 q = pushInt(mb, q, f->type->eclass);
    4018        1904 :                 q = pushInt(mb, q, f->digits);
    4019        1904 :                 q = pushInt(mb, q, f->scale);
    4020        1904 :                 q = pushInt(mb, q, type_has_tz(f));
    4021       34782 :         } else if (f->type->eclass == EC_DEC) {
    4022             :                 /* scale of the current decimal */
    4023        1561 :                 q = pushInt(mb, q, f->scale);
    4024       33221 :         } 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       36686 :         q = pushArgument(mb, q, v->nr);
    4029       36685 :         if (add_tz)
    4030             :                         q = pushLng(mb, q, be->mvc->timezone);
    4031       36685 :         if (sel && !pushed && !v->cand) {
    4032        3572 :                 q = pushArgument(mb, q, sel->nr);
    4033        3572 :                 pushed = 1;
    4034       33113 :         } else if (v->nrcols > 0 && !no_candidates) {
    4035       24907 :                 q = pushNilBat(mb, q);
    4036             :         }
    4037       36685 :         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        3069 :                 q = pushInt(mb, q, t->digits);
    4040        3069 :                 if (!EC_TEMP_FRAC(t->type->eclass))
    4041        2730 :                         q = pushInt(mb, q, t->scale);
    4042             :         }
    4043             :         /* convert to string, give error on to large strings */
    4044       36851 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
    4045        1904 :                 q = pushInt(mb, q, t->digits);
    4046             :         /* convert a string to a time(stamp) with time zone */
    4047       36685 :         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       36685 :         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       36685 :         bool enabled = be->mvc->sa->eb.enabled;
    4073       36685 :         be->mvc->sa->eb.enabled = false;
    4074       36685 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4075       36686 :         be->mvc->sa->eb.enabled = enabled;
    4076       36686 :         if(!s) {
    4077           0 :                 freeInstruction(q);
    4078           0 :                 goto bailout;
    4079             :         }
    4080       36686 :         s->op1 = v;
    4081       36686 :         s->nrcols = 0;       /* function without arguments returns single value */
    4082       36686 :         s->key = v->key;
    4083       36686 :         s->nrcols = v->nrcols;
    4084       36686 :         s->aggr = v->aggr;
    4085       36686 :         s->op4.typeval = *t;
    4086       36686 :         s->nr = getDestVar(q);
    4087       36686 :         s->q = q;
    4088       36686 :         s->cand = pushed ? sel : NULL;
    4089       36686 :         pushInstruction(mb, q);
    4090       36685 :         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       27006 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
    4102             : {
    4103       27006 :         list *ops = sa_list(be->mvc->sa);
    4104       27077 :         list_append(ops, op1);
    4105       27089 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4106       27090 :         if (r && !r->cand)
    4107       27091 :                 r->cand = op1->cand;
    4108       27090 :         return r;
    4109             : }
    4110             : 
    4111             : stmt *
    4112       47190 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
    4113             : {
    4114       47190 :         list *ops = sa_list(be->mvc->sa);
    4115       47202 :         list_append(ops, op1);
    4116       47204 :         list_append(ops, op2);
    4117       47206 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4118       47207 :         if (r && !r->cand)
    4119       47207 :                 r->cand = op1->cand?op1->cand:op2->cand;
    4120       47207 :         return r;
    4121             : }
    4122             : 
    4123             : #define LANG_INT_OR_MAL(l)  ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
    4124             : 
    4125             : stmt *
    4126      220457 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
    4127             : {
    4128      220457 :         MalBlkPtr mb = be->mb;
    4129      220457 :         InstrPtr q = NULL;
    4130      220457 :         const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
    4131      220501 :         sql_subtype *tpe = NULL;
    4132      220501 :         int push_cands = 0, default_nargs;
    4133      220501 :         stmt *o = NULL, *card = NULL;
    4134             : 
    4135      220501 :         if (ops == NULL)
    4136           0 :                 goto bailout;
    4137             : 
    4138      220501 :         if (rows) {
    4139         103 :                 if (sel) /* if there's a candidate list, use it instead of 'rows' */
    4140           0 :                         rows = sel;
    4141             :                 o = rows;
    4142      220398 :         } else if (list_length(ops->op4.lval)) {
    4143      218597 :                 o = ops->op4.lval->h->data;
    4144      652792 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4145      434195 :                         stmt *c = n->data;
    4146             : 
    4147      434195 :                         if (c && o->nrcols < c->nrcols)
    4148      434195 :                                 o = c;
    4149             :                 }
    4150             :         }
    4151             : 
    4152             :         /* handle nullif */
    4153      220521 :         if (list_length(ops->op4.lval) == 2 &&
    4154      138546 :                 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      220389 :                 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
    4185           2 :                         goto bailout;
    4186      220419 :                 mod = sql_func_mod(f->func);
    4187      220434 :                 fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
    4188      220388 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4189      229578 :                 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      220442 :                 if (rows) {
    4191         103 :                         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         103 :                         default_nargs++;
    4193             :                 }
    4194             : 
    4195      220442 :                 if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
    4196      140686 :                         sql_subtype *res = f->res->h->data;
    4197             : 
    4198      281356 :                         q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
    4199      140687 :                         if (q == NULL)
    4200           0 :                                 goto bailout;
    4201      140687 :                         if (rows)
    4202         103 :                                 q = pushArgument(mb, q, card->nr);
    4203      140687 :                         q = pushStr(mb, q, mod);
    4204      140687 :                         q = pushStr(mb, q, fimp);
    4205      140687 :                         setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
    4206             :                 } else {
    4207       79756 :                         q = newStmtArgs(mb, mod, fimp, default_nargs);
    4208       79778 :                         if (q == NULL)
    4209           0 :                                 goto bailout;
    4210             : 
    4211       79778 :                         if (rows)
    4212           0 :                                 q = pushArgument(mb, q, card->nr);
    4213       79778 :                         if (f->res && list_length(f->res)) {
    4214       70622 :                                 sql_subtype *res = f->res->h->data;
    4215             : 
    4216       70622 :                                 setVarType(mb, getArg(q, 0), res->type->localtype);
    4217             :                         }
    4218             :                 }
    4219      220465 :                 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      220465 :                 if (f->func->lang == FUNC_LANG_C) {
    4229          35 :                         q = pushBit(mb, q, 0);
    4230      220430 :                 } else if (f->func->lang == FUNC_LANG_CPP) {
    4231           1 :                         q = pushBit(mb, q, 1);
    4232             :                 }
    4233      220465 :                 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      220465 :                 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      220465 :                 if (list_length(ops->op4.lval))
    4241      218655 :                         tpe = tail_type(ops->op4.lval->h->data);
    4242             : 
    4243      654800 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4244      434335 :                         stmt *op = n->data;
    4245      434335 :                         q = pushArgument(mb, q, op->nr);
    4246             :                 }
    4247             :                 /* push candidate lists if that's the case */
    4248      220465 :                 if (push_cands) {
    4249       77090 :                         for (node *n = ops->op4.lval->h; n; n = n->next) {
    4250       50855 :                                 stmt *op = n->data;
    4251             : 
    4252       50855 :                                 if (op->nrcols > 0) {
    4253       28523 :                                         if (op->cand && op->cand == sel) {
    4254        3788 :                                                 q = pushNilBat(mb, q);
    4255             :                                         } else {
    4256       24735 :                                                 q = pushArgument(mb, q, sel->nr);
    4257             :                                         }
    4258             :                                 }
    4259             :                         }
    4260             :                 }
    4261             :                 /* special case for round function on decimals */
    4262      220465 :                 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      220465 :                 pushInstruction(mb, q);
    4267             :         }
    4268             : 
    4269      220560 :         stmt *s = stmt_create(be->mvc->sa, st_Nop);
    4270      220559 :         if(!s) {
    4271           0 :                 goto bailout;
    4272             :         }
    4273      220559 :         s->op1 = ops;
    4274      220559 :         if (o) {
    4275      218767 :                 s->nrcols = o->nrcols;
    4276      218767 :                 s->key = o->key;
    4277      218767 :                 s->aggr = o->aggr;
    4278             :         } else {
    4279        1792 :                 s->nrcols = 0;
    4280        1792 :                 s->key = 1;
    4281             :         }
    4282      220559 :         s->op4.funcval = f;
    4283      220559 :         s->nr = getDestVar(q);
    4284      220559 :         s->q = q;
    4285      220559 :         if (sel && push_cands && s->nrcols)
    4286       24724 :                 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       85131 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
    4404             : {
    4405       85131 :         MalBlkPtr mb = be->mb;
    4406       85131 :         InstrPtr q = NULL;
    4407       85131 :         const char *mod, *aggrfunc;
    4408       85131 :         sql_subtype *res = op->res->h->data;
    4409       85131 :         int restype = res->type->localtype;
    4410       85131 :         bool complex_aggr = false;
    4411       85131 :         int *stmt_nr = NULL;
    4412       85131 :         int avg = 0;
    4413             : 
    4414       85131 :         if (op1->nr < 0)
    4415           0 :                 goto bailout;
    4416       85131 :         if (backend_create_subfunc(be, op, NULL) < 0)
    4417           0 :                 goto bailout;
    4418       85378 :         mod = sql_func_mod(op->func);
    4419       85446 :         aggrfunc = backend_function_imp(be, op->func);
    4420             : 
    4421       85473 :         if (LANG_INT_OR_MAL(op->func->lang)) {
    4422       85020 :                 if (strcmp(aggrfunc, "avg") == 0)
    4423             :                         avg = 1;
    4424       83650 :                 if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
    4425       76465 :                         || strcmp(aggrfunc, "str_group_concat") == 0)
    4426             :                         complex_aggr = true;
    4427       85020 :                 if (restype == TYPE_dbl)
    4428        1561 :                         avg = 0;
    4429             :         }
    4430             : 
    4431      170946 :         int argc = 1
    4432       85473 :                 + 2 * avg
    4433       85473 :                 + (LANG_EXT(op->func->lang) != 0)
    4434       85473 :                 + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
    4435       85473 :                 + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
    4436       85473 :                 + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
    4437       85473 :                 + (grp ? 4 : avg + 1);
    4438             : 
    4439       85473 :         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       78626 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4458       78711 :                 if (q == NULL)
    4459           0 :                         goto bailout;
    4460       78711 :                 if (complex_aggr) {
    4461        6745 :                         setVarType(mb, getArg(q, 0), restype);
    4462        6745 :                         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       85558 :         if (LANG_EXT(op->func->lang))
    4470          47 :                 q = pushPtr(mb, q, op->func);
    4471       85560 :         if (op->func->lang == FUNC_LANG_R ||
    4472       85525 :                 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       85560 :         if (op1->type != st_list) {
    4487       79653 :                 q = pushArgument(mb, q, op1->nr);
    4488             :         } else {
    4489        5907 :                 int i;
    4490        5907 :                 node *n;
    4491             : 
    4492       12236 :                 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
    4493        6329 :                         stmt *op = n->data;
    4494             : 
    4495        6329 :                         if (stmt_nr)
    4496             :                                 q = pushArgument(mb, q, stmt_nr[i]);
    4497             :                         else
    4498        6329 :                                 q = pushArgument(mb, q, op->nr);
    4499             :                 }
    4500             :         }
    4501       85557 :         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       78710 :         } 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       77067 :         } 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       77067 :         } 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       85557 :         bool enabled = be->mvc->sa->eb.enabled;
    4519       85557 :         be->mvc->sa->eb.enabled = false;
    4520       85557 :         stmt *s = stmt_create(be->mvc->sa, st_aggr);
    4521       85541 :         be->mvc->sa->eb.enabled = enabled;
    4522       85541 :         if(!s) {
    4523           0 :                 freeInstruction(q);
    4524           0 :                 goto bailout;
    4525             :         }
    4526       85541 :         s->op1 = op1;
    4527       85541 :         if (grp) {
    4528        6847 :                 s->op2 = grp;
    4529        6847 :                 s->op3 = ext;
    4530        6847 :                 s->nrcols = 1;
    4531             :         } else {
    4532       78694 :                 if (!reduce)
    4533           0 :                         s->nrcols = 1;
    4534             :         }
    4535       85541 :         s->key = reduce;
    4536       85541 :         s->aggr = reduce;
    4537       85541 :         s->flag = no_nil;
    4538       85541 :         s->op4.funcval = op;
    4539       85541 :         s->nr = getDestVar(q);
    4540       85541 :         s->q = q;
    4541       85541 :         pushInstruction(mb, q);
    4542       85541 :         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     5072987 : stmt_alias_(backend *be, stmt *op1, int label, const char *tname, const char *alias)
    4552             : {
    4553     5072987 :         assert(label);
    4554     5072987 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
    4555     5072580 :         if(!s) {
    4556             :                 return NULL;
    4557             :         }
    4558     5072580 :         s->label = label;
    4559     5072580 :         s->op1 = op1;
    4560     5072580 :         s->nrcols = op1->nrcols;
    4561     5072580 :         s->key = op1->key;
    4562     5072580 :         s->aggr = op1->aggr;
    4563             : 
    4564     5072580 :         s->tname = tname;
    4565     5072580 :         s->cname = alias;
    4566     5072580 :         s->nr = op1->nr;
    4567     5072580 :         s->q = op1->q;
    4568     5072580 :         return s;
    4569             : }
    4570             : 
    4571             : stmt *
    4572     4499613 : 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     4499613 :         return stmt_alias_(be, op1, label, tname, alias);
    4581             : }
    4582             : 
    4583             : stmt *
    4584      573424 : stmt_as(backend *be, stmt *s, stmt *org)
    4585             : {
    4586      573424 :         assert(org->type == st_alias);
    4587      573424 :         return stmt_alias_(be, s, org->label, org->tname, org->cname);
    4588             : }
    4589             : 
    4590             : sql_subtype *
    4591     1567427 : tail_type(stmt *st)
    4592             : {
    4593     8693593 :         for (;;) {
    4594     8693593 :                 switch (st->type) {
    4595       37114 :                 case st_const:
    4596       37114 :                         st = st->op2;
    4597       37114 :                         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     3462719 :                 case st_alias:
    4612     3462719 :                         if (!st->op1)
    4613         183 :                                 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     3922352 :                         st = st->op1;
    4621     3922352 :                         continue;
    4622           0 :                 case st_list:
    4623           0 :                         st = st->op4.lval->h->data;
    4624           0 :                         continue;
    4625      922400 :                 case st_bat:
    4626      922400 :                         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     3166726 :                         if (st->flag == cmp_project) {
    4638     3166700 :                                 st = st->op2;
    4639     3166700 :                                 continue;
    4640             :                         }
    4641             :                         /* fall through */
    4642             :                 case st_reorder:
    4643             :                 case st_group:
    4644             :                 case st_tid:
    4645             :                 case st_mirror:
    4646       15561 :                         return sql_bind_localtype("oid");
    4647       31195 :                 case st_result:
    4648       31195 :                         return &st->op4.typeval;
    4649           0 :                 case st_table_clear:
    4650           0 :                         return sql_bind_localtype("lng");
    4651      156483 :                 case st_aggr:
    4652             :                 case st_Nop: {
    4653      156483 :                         list *res = st->op4.funcval->res;
    4654             : 
    4655      156483 :                         if (res && list_length(res) == 1)
    4656      156483 :                                 return res->h->data;
    4657             : 
    4658             :                         return NULL;
    4659             :                 }
    4660      152392 :                 case st_atom:
    4661      152392 :                         return atom_type(st->op4.aval);
    4662      280951 :                 case st_convert:
    4663             :                 case st_temp:
    4664             :                 case st_single:
    4665             :                 case st_rs_column:
    4666      280951 :                         return &st->op4.typeval;
    4667        2308 :                 case st_var:
    4668        2308 :                         if (st->op4.typeval.type)
    4669        2308 :                                 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        6685 : stmt_has_null(stmt *s)
    4684             : {
    4685       21118 :         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        8278 :         case st_alias:
    4693        8278 :                 return stmt_has_null(s->op1);
    4694        6155 :         case st_join:
    4695        6155 :                 return stmt_has_null(s->op2);
    4696        4255 :         case st_bat:
    4697        4255 :                 return s->op4.cval->null;
    4698             : 
    4699        2430 :         default:
    4700        2430 :                 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     2664704 : column_name(allocator *sa, stmt *st)
    4734             : {
    4735     2664704 :         if (!st->cname)
    4736           0 :                 st->cname = _column_name(sa, st);
    4737     2664704 :         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     2649382 : table_name(allocator *sa, stmt *st)
    4808             : {
    4809     2649382 :         (void)sa;
    4810     2649382 :         return st->tname;
    4811             : }
    4812             : 
    4813             : const char *
    4814      339635 : schema_name(allocator *sa, stmt *st)
    4815             : {
    4816     3120826 :         switch (st->type) {
    4817     1200893 :         case st_const:
    4818             :         case st_semijoin:
    4819             :         case st_join:
    4820             :         case st_join2:
    4821             :         case st_joinN:
    4822     1200893 :                 return schema_name(sa, st->op2);
    4823      120710 :         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      120710 :                 if (st->op1)
    4843             :                         return schema_name(sa, st->op1);
    4844             :                 return NULL;
    4845     1428365 :         case st_alias:
    4846     1428365 :                 if (!st->op1)
    4847             :                         return NULL;
    4848             :                 return schema_name(sa, st->op1);
    4849      204049 :         case st_bat:
    4850      204049 :                 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       31378 :         case st_list:
    4858       31378 :                 if (list_length(st->op4.lval))
    4859       31258 :                         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         206 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
    4980             : {
    4981         206 :         int i;
    4982         206 :         node *n;
    4983             : 
    4984         206 :         if (q == NULL)
    4985             :                 return NULL;
    4986         206 :         q->retc = q->argc = 0;
    4987        1651 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4988        1445 :                 stmt *c = n->data;
    4989             : 
    4990        1445 :                 q = pushArgument(mb, q, c->nr);
    4991             :         }
    4992         206 :         if (q == NULL)
    4993             :                 return NULL;
    4994         206 :         q->retc = q->argc;
    4995             :         /* Let's make it a proper assignment */
    4996        1651 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4997        1445 :                 stmt *c = n->data;
    4998             : 
    4999        1445 :                 q = pushArgument(mb, q, c->nr);
    5000             :         }
    5001             :         return q;
    5002             : }
    5003             : 
    5004             : stmt *
    5005         662 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
    5006             : {
    5007         662 :         MalBlkPtr mb = be->mb;
    5008         662 :         InstrPtr q = NULL;
    5009             : 
    5010         662 :         if (val->nr < 0)
    5011           0 :                 goto bailout;
    5012         662 :         int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
    5013         206 :         if (args < MAXARG)
    5014             :                 args = MAXARG;
    5015         662 :         q = newInstructionArgs(mb, NULL, NULL, args);
    5016         662 :         if (q == NULL)
    5017           0 :                 goto bailout;
    5018         662 :         q->barrier= RETURNsymbol;
    5019         662 :         if (val->type == st_table) {
    5020         206 :                 list *l = val->op1->op4.lval;
    5021             : 
    5022         206 :                 q = dump_cols(mb, l, q);
    5023             :         } else {
    5024         456 :                 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
    5025         456 :                 q = pushArgument(mb, q, val->nr);
    5026             :         }
    5027             : 
    5028         662 :         bool enabled = be->mvc->sa->eb.enabled;
    5029         662 :         be->mvc->sa->eb.enabled = false;
    5030         662 :         stmt *s = stmt_create(be->mvc->sa, st_return);
    5031         662 :         be->mvc->sa->eb.enabled = enabled;
    5032         662 :         if(!s) {
    5033           0 :                 freeInstruction(q);
    5034           0 :                 goto bailout;
    5035             :         }
    5036         662 :         s->op1 = val;
    5037         662 :         s->flag = nr_declared_tables;
    5038         662 :         s->nr = getDestVar(q);
    5039         662 :         s->q = q;
    5040         662 :         pushInstruction(mb, q);
    5041         662 :         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        1416 : stmt_assign(backend *be, const char *sname, const char *varname, stmt *val, int level)
    5051             : {
    5052        1416 :         MalBlkPtr mb = be->mb;
    5053        1416 :         InstrPtr q = NULL;
    5054             : 
    5055        1416 :         if (val && val->nr < 0)
    5056           0 :                 goto bailout;
    5057        1416 :         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         379 :                 assert(sname); /* all global variables have a schema */
    5081         379 :                 q = newStmt(mb, sqlRef, setVariableRef);
    5082         379 :                 if (q == NULL)
    5083           0 :                         goto bailout;
    5084         379 :                 q = pushArgument(mb, q, be->mvc_var);
    5085         379 :                 q = pushStr(mb, q, sname);
    5086         379 :                 q = pushStr(mb, q, varname);
    5087         379 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    5088         379 :                 pushInstruction(mb, q);
    5089         379 :                 be->mvc_var = getDestVar(q);
    5090             :         }
    5091        1416 :         q = pushArgument(mb, q, val->nr);
    5092             : 
    5093        1416 :         bool enabled = be->mvc->sa->eb.enabled;
    5094        1416 :         be->mvc->sa->eb.enabled = false;
    5095        1416 :         stmt *s = stmt_create(be->mvc->sa, st_assign);
    5096        1416 :         be->mvc->sa->eb.enabled = enabled;
    5097        1416 :         if(!s) {
    5098           0 :                 goto bailout;
    5099             :         }
    5100        1416 :         s->op2 = val;
    5101        1416 :         s->flag = (level << 1);
    5102        1416 :         s->q = q;
    5103        1416 :         s->nr = 1;
    5104        1416 :         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       21622 : const_column(backend *be, stmt *val)
    5114             : {
    5115       21622 :         sql_subtype *ct = tail_type(val);
    5116       21622 :         MalBlkPtr mb = be->mb;
    5117       21622 :         InstrPtr q = NULL;
    5118       21622 :         int tt = ct->type->localtype;
    5119             : 
    5120       21622 :         if (val->nr < 0)
    5121           0 :                 goto bailout;
    5122       21622 :         q = newStmt(mb, batRef, singleRef);
    5123       21622 :         if (q == NULL)
    5124           0 :                 goto bailout;
    5125       21622 :         setVarType(mb, getArg(q, 0), newBatType(tt));
    5126       21622 :         q = pushArgument(mb, q, val->nr);
    5127             : 
    5128       21622 :         bool enabled = be->mvc->sa->eb.enabled;
    5129       21622 :         be->mvc->sa->eb.enabled = false;
    5130       21622 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5131       21622 :         be->mvc->sa->eb.enabled = enabled;
    5132       21622 :         if(!s) {
    5133           0 :                 freeInstruction(q);
    5134           0 :                 goto bailout;
    5135             :         }
    5136       21622 :         s->op1 = val;
    5137       21622 :         s->op4.typeval = *ct;
    5138       21622 :         s->nrcols = 1;
    5139             : 
    5140       21622 :         s->tname = val->tname;
    5141       21622 :         s->cname = val->cname;
    5142       21622 :         s->nr = getDestVar(q);
    5143       21622 :         s->q = q;
    5144       21622 :         pushInstruction(mb, q);
    5145       21622 :         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     1633008 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    5206             : {
    5207     1633008 :         int label = exp_get_label(exp);
    5208     1633015 :         const char *name = exp_name(exp);
    5209     1633335 :         const char *rname = exp_relname(exp);
    5210     1632905 :         stmt *o = s;
    5211             : 
    5212     1632905 :         if (!name && exp_is_atom(exp))
    5213           0 :                 name = sa_strdup(be->mvc->sa, "single_value");
    5214           0 :         assert(name);
    5215     1632905 :         s = stmt_alias(be, s, label, rname, name);
    5216     1633031 :         if (o->flag & OUTER_ZERO)
    5217         521 :                 s->flag |= OUTER_ZERO;
    5218     1633031 :         return s;
    5219             : }

Generated by: LCOV version 1.14