LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2873 3466 82.9 %
Date: 2024-11-15 19:37:45 Functions: 108 112 96.4 %

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

Generated by: LCOV version 1.14