LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2886 3480 82.9 %
Date: 2024-10-03 20:03:20 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       17717 : convertMultiplexMod(const char *mod, const char *op)
      32             : {
      33       17717 :         if (strcmp(op, "=") == 0)
      34           0 :                 return "calc";
      35             :         return mod;
      36             : }
      37             : 
      38             : static const char *
      39      254941 : convertMultiplexFcn(const char *op)
      40             : {
      41      254941 :         if (strcmp(op, "=") == 0)
      42       32543 :                 return "==";
      43             :         return op;
      44             : }
      45             : 
      46             : static InstrPtr
      47       17642 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
      48             : {
      49       17642 :         InstrPtr q = NULL;
      50             : 
      51       17642 :         q = newStmt(mb, malRef, multiplexRef);
      52       17642 :         if (q == NULL)
      53             :                 return NULL;
      54       17642 :         setVarType(mb, getArg(q, 0), newBatType(rtype));
      55       17642 :         q = pushStr(mb, q, convertMultiplexMod(mod, name));
      56       17642 :         q = pushStr(mb, q, convertMultiplexFcn(name));
      57       17642 :         q = pushArgument(mb, q, o1);
      58       17642 :         q = pushArgument(mb, q, o2);
      59       17642 :         pushInstruction(mb, q);
      60       17642 :         return q;
      61             : }
      62             : 
      63             : static InstrPtr
      64       50669 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
      65             : {
      66       50669 :         InstrPtr q = NULL;
      67             : 
      68       50669 :         if (o1 == NULL || o1->nr < 0)
      69             :                 return NULL;
      70       50669 :         q = newStmt(mb, mod, name);
      71       50669 :         q = pushArgument(mb, q, o1->nr);
      72       50669 :         pushInstruction(mb, q);
      73       50669 :         return q;
      74             : }
      75             : 
      76             : static InstrPtr
      77      179771 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
      78             : {
      79      179771 :         InstrPtr q = NULL;
      80             : 
      81      179771 :         if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
      82             :                 return NULL;
      83      179771 :         q = newStmt(mb, mod, name);
      84      179771 :         q = pushArgument(mb, q, o1->nr);
      85      179771 :         q = pushArgument(mb, q, o2->nr);
      86      179771 :         pushInstruction(mb, q);
      87      179771 :         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     2055436 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
     109             : {
     110     2055436 :         if (t->s)
     111     2055436 :                 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       19456 : stmt_atom_string_nil(backend *be)
     139             : {
     140       19456 :         sql_subtype t;
     141             : 
     142       19456 :         sql_find_subtype(&t, "varchar", 0, 0);
     143       19456 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
     144             : }
     145             : 
     146             : stmt *
     147        5752 : stmt_atom_int(backend *be, int i)
     148             : {
     149        5752 :         sql_subtype t;
     150             : 
     151        5752 :         sql_find_subtype(&t, "int", 32, 0);
     152        5752 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     153             : }
     154             : 
     155             : stmt *
     156      106650 : stmt_atom_lng(backend *be, lng i)
     157             : {
     158      106650 :         sql_subtype t;
     159             : 
     160      106650 :         sql_find_subtype(&t, "bigint", 64, 0);
     161      106650 :         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       40185 : stmt_bool(backend *be, int b)
     175             : {
     176       40185 :         sql_subtype t;
     177             : 
     178       40185 :         sql_find_subtype(&t, "boolean", 0, 0);
     179             : 
     180       40185 :         if (b == bit_nil) {
     181           0 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
     182       40185 :         } else if (b) {
     183       39056 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
     184             :         } else {
     185        1129 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
     186             :         }
     187             : }
     188             : 
     189             : static stmt *
     190    17378473 : stmt_create(allocator *sa, st_type type)
     191             : {
     192    17378473 :         stmt *s = SA_NEW(sa, stmt);
     193             : 
     194    17378286 :         if (!s)
     195             :                 return NULL;
     196    17378286 :         *s = (stmt) {
     197             :                 .type = type,
     198             :         };
     199    17378286 :         return s;
     200             : }
     201             : 
     202             : stmt *
     203       27771 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
     204             : {
     205       27771 :         MalBlkPtr mb = be->mb;
     206       27771 :         InstrPtr q = NULL;
     207             : 
     208       27771 :         if (s == NULL || s->nr < 0)
     209           0 :                 goto bailout;
     210       27771 :         if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
     211           0 :                 goto bailout;
     212             : 
     213       27771 :         q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
     214       27771 :         if (q == NULL)
     215           0 :                 goto bailout;
     216             : 
     217             :         /* output variables extent and hist */
     218       27771 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     219       27771 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     220       27771 :         q = pushArgument(mb, q, s->nr);
     221       27771 :         if (grp)
     222        6188 :                 q = pushArgument(mb, q, grp->nr);
     223             : 
     224       27771 :         bool enabled = be->mvc->sa->eb.enabled;
     225       27771 :         be->mvc->sa->eb.enabled = false;
     226       27771 :         stmt *ns = stmt_create(be->mvc->sa, st_group);
     227       27771 :         be->mvc->sa->eb.enabled = enabled;
     228       27771 :         if (ns == NULL) {
     229           0 :                 freeInstruction(q);
     230           0 :                 goto bailout;
     231             :         }
     232             : 
     233       27771 :         ns->op1 = s;
     234             : 
     235       27771 :         if (grp) {
     236        6188 :                 ns->op2 = grp;
     237        6188 :                 ns->op3 = ext;
     238        6188 :                 ns->op4.stval = cnt;
     239             :         }
     240       27771 :         ns->nrcols = s->nrcols;
     241       27771 :         ns->key = 0;
     242       27771 :         ns->q = q;
     243       27771 :         ns->nr = getDestVar(q);
     244       27771 :         pushInstruction(mb, q);
     245       27771 :         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        2776 : stmt_var(backend *be, const char *sname, const char *varname, sql_subtype *t, int declare, int level)
     336             : {
     337        2776 :         MalBlkPtr mb = be->mb;
     338        2776 :         InstrPtr q = NULL;
     339        2776 :         char *buf;
     340             : 
     341        2776 :         if (level == 0) { /* global */
     342         433 :                 int tt = t->type->localtype;
     343             : 
     344         433 :                 assert(sname);
     345         433 :                 q = newStmt(mb, sqlRef, getVariableRef);
     346         433 :                 if (q == NULL)
     347           0 :                         goto bailout;
     348         433 :                 q = pushArgument(mb, q, be->mvc_var);
     349         433 :                 q = pushStr(mb, q, sname); /* all global variables have a schema */
     350         433 :                 q = pushStr(mb, q, varname);
     351         433 :                 setVarType(mb, getArg(q, 0), tt);
     352        2343 :         } else if (!declare) {
     353        1954 :                 char levelstr[16];
     354             : 
     355        1954 :                 assert(!sname);
     356        1954 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     357        1954 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     358        1954 :                 if (!buf)
     359           1 :                         goto bailout;
     360        1954 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     361        1954 :                 q = newAssignment(mb);
     362        1954 :                 if (q == NULL)
     363           1 :                         goto bailout;
     364        1953 :                 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        2775 :         bool enabled = be->mvc->sa->eb.enabled;
     386        2775 :         be->mvc->sa->eb.enabled = false;
     387        2775 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     388        2775 :         be->mvc->sa->eb.enabled = enabled;
     389        2775 :         if (s == NULL) {
     390           0 :                 freeInstruction(q);
     391           0 :                 goto bailout;
     392             :         }
     393             : 
     394        2775 :         if (t)
     395        2775 :                 s->op4.typeval = *t;
     396             :         else
     397           0 :                 s->op4.typeval.type = NULL;
     398        2775 :         s->flag = declare + (level << 1);
     399        2775 :         s->key = 1;
     400        2775 :         s->q = q;
     401        2775 :         s->nr = getDestVar(q);
     402        2775 :         pushInstruction(mb, q);
     403        2775 :         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         678 : stmt_table(backend *be, stmt *cols, int temp)
     483             : {
     484         678 :         MalBlkPtr mb = be->mb;
     485             : 
     486         678 :         if (cols == NULL || cols->nr < 0)
     487           0 :                 goto bailout;
     488             : 
     489         678 :         stmt *s = stmt_create(be->mvc->sa, st_table);
     490             : 
     491         678 :         if (s == NULL)
     492           0 :                 goto bailout;
     493             : 
     494         678 :         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         678 :         s->op1 = cols;
     506         678 :         s->flag = temp;
     507         678 :         s->nr = cols->nr;
     508         678 :         s->nrcols = cols->nrcols;
     509         678 :         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      222888 : stmt_temp(backend *be, sql_subtype *t)
     519             : {
     520      222888 :         int tt = t->type->localtype;
     521      222888 :         MalBlkPtr mb = be->mb;
     522      222888 :         InstrPtr q = newStmt(mb, batRef, newRef);
     523             : 
     524      222941 :         if (q == NULL)
     525           0 :                 goto bailout;
     526      222941 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     527      222941 :         q = pushType(mb, q, tt);
     528      222920 :         bool enabled = be->mvc->sa->eb.enabled;
     529      222920 :         be->mvc->sa->eb.enabled = false;
     530      222920 :         stmt *s = stmt_create(be->mvc->sa, st_temp);
     531      222919 :         be->mvc->sa->eb.enabled = enabled;
     532             : 
     533      222919 :         if (s == NULL) {
     534           0 :                 freeInstruction(q);
     535           0 :                 goto bailout;
     536             :         }
     537      222919 :         s->op4.typeval = *t;
     538      222919 :         s->nrcols = 1;
     539      222919 :         s->q = q;
     540      222919 :         s->nr = getDestVar(q);
     541      222919 :         pushInstruction(mb, q);
     542      222919 :         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      202253 : stmt_tid(backend *be, sql_table *t, int partition)
     569             : {
     570      202253 :         int tt = TYPE_oid;
     571      202253 :         MalBlkPtr mb = be->mb;
     572      202253 :         InstrPtr q;
     573             : 
     574      202253 :         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      202237 :         q = newStmt(mb, sqlRef, tidRef);
     589      202237 :         if (q == NULL)
     590           0 :                 goto bailout;
     591      202237 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     592      202237 :         q = pushArgument(mb, q, be->mvc_var);
     593      202237 :         q = pushSchema(mb, q, t);
     594      202237 :         q = pushStr(mb, q, t->base.name);
     595      202237 :         if (t && isTable(t) && partition) {
     596       75408 :                 sql_trans *tr = be->mvc->session->tr;
     597       75408 :                 sqlstore *store = tr->store;
     598       75408 :                 BUN rows = (BUN) store->storage_api.count_col(tr, ol_first_node(t->columns)->data, RDONLY);
     599       75408 :                 setRowCnt(mb,getArg(q,0),rows);
     600             :         }
     601             : 
     602      202237 :         bool enabled = be->mvc->sa->eb.enabled;
     603      202237 :         be->mvc->sa->eb.enabled = false;
     604      202237 :         stmt *s = stmt_create(be->mvc->sa, st_tid);
     605      202236 :         be->mvc->sa->eb.enabled = enabled;
     606      202236 :         if (s == NULL) {
     607           0 :                 freeInstruction(q);
     608           0 :                 goto bailout;
     609             :         }
     610             : 
     611      202236 :         s->partition = partition;
     612      202236 :         s->op4.tval = t;
     613      202236 :         s->nrcols = 1;
     614      202236 :         s->nr = getDestVar(q);
     615      202236 :         s->q = q;
     616      202236 :         pushInstruction(mb, q);
     617      202236 :         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      981963 : find_real_column(backend *be, sql_column *c)
     627             : {
     628      981963 :         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      981963 : stmt_bat(backend *be, sql_column *c, int access, int partition)
     641             : {
     642      981963 :         int tt = c->type.type->localtype;
     643      981963 :         MalBlkPtr mb = be->mb;
     644      981963 :         InstrPtr q;
     645             : 
     646      981963 :         c = find_real_column(be, c);
     647             : 
     648      981963 :         if (access == RD_EXT)
     649         176 :                 partition = 0;
     650             : 
     651             :         /* for read access tid.project(col) */
     652      981963 :         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      981940 :         q = newStmtArgs(mb, sqlRef, bindRef, 9);
     670      981951 :         if (q == NULL)
     671           0 :                 goto bailout;
     672      981951 :         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      981775 :         if (access == RD_UPD_ID) {
     683      477052 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     684             :         } else {
     685      504899 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     686             :         }
     687      981949 :         q = pushArgument(mb, q, be->mvc_var);
     688      981948 :         q = pushSchema(mb, q, c->t);
     689      981952 :         q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
     690      981936 :         q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
     691      981944 :         q = pushArgument(mb, q, getIntConstant(mb,access));
     692             : 
     693      981941 :         if (access == RD_UPD_ID) {
     694      477049 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     695             :         }
     696      981941 :         if (partition) {
     697      544069 :                 sql_trans *tr = be->mvc->session->tr;
     698      544069 :                 sqlstore *store = tr->store;
     699             : 
     700      544069 :                 if (c && isTable(c->t)) {
     701      544068 :                         BUN rows = (BUN) store->storage_api.count_col(tr, c, QUICK);
     702      544065 :                         setRowCnt(mb,getArg(q,0),rows);
     703             :                 }
     704             :         }
     705             : 
     706      981938 :         bool enabled = be->mvc->sa->eb.enabled;
     707      981938 :         be->mvc->sa->eb.enabled = false;
     708      981938 :         stmt *s = stmt_create(be->mvc->sa, st_bat);
     709      981926 :         be->mvc->sa->eb.enabled = enabled;
     710      981926 :         if (s == NULL) {
     711           0 :                 freeInstruction(q);
     712           0 :                 goto bailout;
     713             :         }
     714             : 
     715      981926 :         s->partition = partition;
     716      981926 :         s->op4.cval = c;
     717      981926 :         s->nrcols = 1;
     718      981926 :         s->flag = access;
     719      981926 :         s->nr = getDestVar(q);
     720      981926 :         s->q = q;
     721      981926 :         s->tname = c->t->base.name;
     722      981926 :         s->cname = c->base.name;
     723      981926 :         pushInstruction(mb, q);
     724      981926 :         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      566990 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
     795             : {
     796      566990 :         MalBlkPtr mb = be->mb;
     797      566990 :         InstrPtr q = NULL;
     798             : 
     799      566990 :         if (b == NULL || b->nr < 0)
     800           0 :                 goto bailout;
     801             : 
     802      566990 :         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      566967 :         } else if (!fake) {     /* fake append */
     821      566967 :                 if (offset == NULL || offset->nr < 0)
     822           0 :                         goto bailout;
     823      566967 :                 q = newStmt(mb, sqlRef, appendRef);
     824      566988 :                 if (q == NULL)
     825           0 :                         goto bailout;
     826      566988 :                 q = pushArgument(mb, q, be->mvc_var);
     827      566989 :                 int tmpvar = newTmpVariable(mb, TYPE_int);
     828      566985 :                 getArg(q, 0) = tmpvar;
     829      566985 :                 if (mvc_var_update != NULL)
     830      566985 :                         *mvc_var_update = tmpvar;
     831      566985 :                 q = pushSchema(mb, q, c->t);
     832      566989 :                 q = pushStr(mb, q, c->t->base.name);
     833      566991 :                 q = pushStr(mb, q, c->base.name);
     834      566970 :                 q = pushArgument(mb, q, offset->nr);
     835             :                 /* also the offsets */
     836      566964 :                 assert(offset->q->retc == 2);
     837      566964 :                 q = pushArgument(mb, q, getArg(offset->q, 1));
     838      566965 :                 q = pushArgument(mb, q, b->nr);
     839      566963 :                 if (mvc_var_update != NULL)
     840      566963 :                         *mvc_var_update = getDestVar(q);
     841             :         } else {
     842             :                 return b;
     843             :         }
     844      566986 :         bool enabled = be->mvc->sa->eb.enabled;
     845      566986 :         be->mvc->sa->eb.enabled = false;
     846      566986 :         stmt *s = stmt_create(be->mvc->sa, st_append_col);
     847      566991 :         be->mvc->sa->eb.enabled = enabled;
     848             : 
     849      566991 :         if (s == NULL) {
     850           0 :                 freeInstruction(q);
     851           0 :                 goto bailout;
     852             :         }
     853      566991 :         s->op1 = b;
     854      566991 :         s->op2 = offset;
     855      566991 :         s->op4.cval = c;
     856      566991 :         s->q = q;
     857      566991 :         s->nr = getDestVar(q);
     858      566991 :         pushInstruction(mb, q);
     859      566991 :         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        2997 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
     916             : {
     917        2997 :         MalBlkPtr mb = be->mb;
     918        2997 :         InstrPtr q = NULL;
     919             : 
     920        2997 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     921           0 :                 goto bailout;
     922             : 
     923        2998 :         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        2996 :                 q = newStmt(mb, sqlRef, updateRef);
     934        2996 :                 if (q == NULL)
     935           0 :                         goto bailout;
     936        2996 :                 q = pushArgument(mb, q, be->mvc_var);
     937        2996 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     938        2996 :                 q = pushSchema(mb, q, c->t);
     939        2996 :                 q = pushStr(mb, q, c->t->base.name);
     940        2996 :                 q = pushStr(mb, q, c->base.name);
     941        2996 :                 q = pushArgument(mb, q, tids->nr);
     942        2996 :                 q = pushArgument(mb, q, upd->nr);
     943        2996 :                 be->mvc_var = getDestVar(q);
     944             :         }
     945        2997 :         bool enabled = be->mvc->sa->eb.enabled;
     946        2997 :         be->mvc->sa->eb.enabled = false;
     947        2997 :         stmt *s = stmt_create(be->mvc->sa, st_update_col);
     948        2997 :         be->mvc->sa->eb.enabled = enabled;
     949             : 
     950        2997 :         if (s == NULL) {
     951           0 :                 freeInstruction(q);
     952           0 :                 goto bailout;
     953             :         }
     954        2997 :         s->op1 = tids;
     955        2997 :         s->op2 = upd;
     956        2997 :         s->op4.cval = c;
     957        2997 :         s->q = q;
     958        2997 :         s->nr = getDestVar(q);
     959        2997 :         pushInstruction(mb, q);
     960        2997 :         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         349 : stmt_delete(backend *be, sql_table *t, stmt *tids)
    1014             : {
    1015         349 :         MalBlkPtr mb = be->mb;
    1016         349 :         InstrPtr q = NULL;
    1017             : 
    1018         349 :         if (tids == NULL || tids->nr < 0)
    1019           0 :                 goto bailout;
    1020             : 
    1021         350 :         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         348 :                 q = newStmt(mb, sqlRef, deleteRef);
    1031         348 :                 if (q == NULL)
    1032           0 :                         goto bailout;
    1033         348 :                 q = pushArgument(mb, q, be->mvc_var);
    1034         348 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    1035         348 :                 q = pushSchema(mb, q, t);
    1036         348 :                 q = pushStr(mb, q, t->base.name);
    1037         348 :                 q = pushArgument(mb, q, tids->nr);
    1038         348 :                 be->mvc_var = getDestVar(q);
    1039             :         }
    1040         349 :         bool enabled = be->mvc->sa->eb.enabled;
    1041         349 :         be->mvc->sa->eb.enabled = false;
    1042         349 :         stmt *s = stmt_create(be->mvc->sa, st_delete);
    1043         349 :         be->mvc->sa->eb.enabled = enabled;
    1044         349 :         if (s == NULL) {
    1045           0 :                 freeInstruction(q);
    1046           0 :                 goto bailout;
    1047             :         }
    1048             : 
    1049         349 :         s->op1 = tids;
    1050         349 :         s->op4.tval = t;
    1051         349 :         s->q = q;
    1052         349 :         s->nr = getDestVar(q);
    1053         349 :         pushInstruction(mb, q);
    1054         349 :         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      123330 : stmt_const(backend *be, stmt *s, stmt *val)
    1064             : {
    1065      123330 :         InstrPtr q = NULL;
    1066      123330 :         MalBlkPtr mb = be->mb;
    1067             : 
    1068      123330 :         if (s == NULL)
    1069           0 :                 goto bailout;
    1070      123330 :         if (val)
    1071      123330 :                 q = dump_2(mb, algebraRef, projectRef, s, val);
    1072             :         else
    1073           0 :                 q = dump_1(mb, algebraRef, projectRef, s);
    1074      123330 :         if (q) {
    1075      123330 :                 stmt *ns = stmt_create(be->mvc->sa, st_const);
    1076      123330 :                 if (ns == NULL) {
    1077           0 :                         goto bailout;
    1078             :                 }
    1079             : 
    1080      123330 :                 ns->op1 = s;
    1081      123330 :                 ns->op2 = val;
    1082      123330 :                 ns->nrcols = s->nrcols;
    1083      123330 :                 ns->key = s->key;
    1084      123330 :                 ns->aggr = s->aggr;
    1085      123330 :                 ns->q = q;
    1086      123330 :                 ns->nr = getDestVar(q);
    1087      123330 :                 ns->tname = val->tname;
    1088      123330 :                 ns->cname = val->cname;
    1089      123330 :                 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       50669 : stmt_mirror(backend *be, stmt *s)
    1131             : {
    1132       50669 :         MalBlkPtr mb = be->mb;
    1133             : 
    1134       50669 :         if (s == NULL)
    1135           0 :                 goto bailout;
    1136             : 
    1137       50669 :         InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
    1138             : 
    1139       50669 :         if (q) {
    1140       50669 :                 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
    1141       50669 :                 if (ns == NULL) {
    1142           0 :                         goto bailout;
    1143             :                 }
    1144             : 
    1145       50669 :                 ns->op1 = s;
    1146       50669 :                 ns->nrcols = 2;
    1147       50669 :                 ns->key = s->key;
    1148       50669 :                 ns->aggr = s->aggr;
    1149       50669 :                 ns->q = q;
    1150       50669 :                 ns->nr = getDestVar(q);
    1151       50669 :                 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      317781 : stmt_result(backend *be, stmt *s, int nr)
    1162             : {
    1163      317781 :         stmt *ns;
    1164             : 
    1165      317781 :         if (s == NULL)
    1166             :                 return NULL;
    1167             : 
    1168      317781 :         if (s->type == st_join && s->flag == cmp_joined) {
    1169        5469 :                 if (nr)
    1170        2313 :                         return s->op2;
    1171        3156 :                 return s->op1;
    1172             :         }
    1173             : 
    1174      312312 :         if (s->op1->nr < 0)
    1175             :                 return NULL;
    1176             : 
    1177      312312 :         ns = stmt_create(be->mvc->sa, st_result);
    1178      312312 :         if(!ns) {
    1179             :                 return NULL;
    1180             :         }
    1181      312312 :         if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
    1182           0 :                 assert(0);
    1183      312312 :         } else if (nr) {
    1184      178614 :                 int v = getArg(s->q, nr);
    1185             : 
    1186      178614 :                 assert(s->q->retc > nr);
    1187      178614 :                 ns->nr = v;
    1188             :         } else {
    1189      133698 :                 ns->nr = s->nr;
    1190             :         }
    1191      312312 :         ns->op1 = s;
    1192      312312 :         if (!nr && (s->type == st_order || s->type == st_reorder))
    1193       23505 :                 ns->op4.typeval = *tail_type(s->op1);
    1194      178614 :         else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
    1195        2933 :                 ns->op4.typeval = *sql_bind_localtype("bit");
    1196             :         else
    1197      285874 :                 ns->op4.typeval = *sql_bind_localtype("oid");
    1198      312312 :         ns->flag = nr;
    1199      312312 :         ns->nrcols = s->nrcols;
    1200      312312 :         ns->key = s->key;
    1201      312312 :         ns->aggr = s->aggr;
    1202      312312 :         return ns;
    1203             : }
    1204             : 
    1205             : 
    1206             : /* limit maybe atom nil */
    1207             : stmt *
    1208       17423 : 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       17423 :         MalBlkPtr mb = be->mb;
    1211       17423 :         InstrPtr q = NULL;
    1212       17423 :         int l, p, g, c;
    1213             : 
    1214       17423 :         if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
    1215           0 :                 goto bailout;
    1216       17423 :         if (piv && (piv->nr < 0 || gid->nr < 0))
    1217           0 :                 goto bailout;
    1218             : 
    1219       17423 :         c = (col) ? col->nr : 0;
    1220       17423 :         p = (piv) ? piv->nr : 0;
    1221       17423 :         g = (gid) ? gid->nr : 0;
    1222             : 
    1223             :         /* first insert single value into a bat */
    1224       17423 :         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       17423 :         if (order) {
    1244         583 :                 int topn = 0;
    1245             : 
    1246         583 :                 q = newStmt(mb, calcRef, plusRef);
    1247         583 :                 if (q == NULL)
    1248           0 :                         goto bailout;
    1249         583 :                 q = pushArgument(mb, q, offset->nr);
    1250         583 :                 q = pushArgument(mb, q, limit->nr);
    1251         583 :                 topn = getDestVar(q);
    1252         583 :                 pushInstruction(mb, q);
    1253             : 
    1254         583 :                 q = newStmtArgs(mb, algebraRef, firstnRef, 9);
    1255         583 :                 if (q == NULL)
    1256           0 :                         goto bailout;
    1257         583 :                 if (!last) /* we need the groups for the next firstn */
    1258         310 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1259         583 :                 q = pushArgument(mb, q, c);
    1260         583 :                 if (p)
    1261         310 :                         q = pushArgument(mb, q, p);
    1262             :                 else
    1263         273 :                         q = pushNilBat(mb, q);
    1264         583 :                 if (g)
    1265         310 :                         q = pushArgument(mb, q, g);
    1266             :                 else
    1267         273 :                         q = pushNilBat(mb, q);
    1268         583 :                 q = pushArgument(mb, q, topn);
    1269         583 :                 q = pushBit(mb, q, dir);
    1270         583 :                 q = pushBit(mb, q, nullslast);
    1271         583 :                 q = pushBit(mb, q, distinct != 0);
    1272             : 
    1273         583 :                 l = getArg(q, 0);
    1274         583 :                 l = getDestVar(q);
    1275         583 :                 pushInstruction(mb, q);
    1276             :         } else {
    1277       16840 :                 int len;
    1278             : 
    1279       16840 :                 q = newStmt(mb, calcRef, plusRef);
    1280       16840 :                 if (q == NULL)
    1281           0 :                         goto bailout;
    1282       16840 :                 q = pushArgument(mb, q, offset->nr);
    1283       16840 :                 q = pushArgument(mb, q, limit->nr);
    1284       16840 :                 len = getDestVar(q);
    1285       16840 :                 pushInstruction(mb, q);
    1286             : 
    1287             :                 /* since both arguments of algebra.subslice are
    1288             :                    inclusive correct the LIMIT value by
    1289             :                    subtracting 1 */
    1290       16840 :                 q = newStmt(mb, calcRef, minusRef);
    1291       16840 :                 if (q == NULL)
    1292           0 :                         goto bailout;
    1293       16840 :                 q = pushArgument(mb, q, len);
    1294       16840 :                 q = pushInt(mb, q, 1);
    1295       16837 :                 len = getDestVar(q);
    1296       16837 :                 pushInstruction(mb, q);
    1297             : 
    1298       16837 :                 q = newStmt(mb, algebraRef, subsliceRef);
    1299       16840 :                 if (q == NULL)
    1300           0 :                         goto bailout;
    1301       16840 :                 q = pushArgument(mb, q, c);
    1302       16840 :                 q = pushArgument(mb, q, offset->nr);
    1303       16840 :                 q = pushArgument(mb, q, len);
    1304       16840 :                 l = getDestVar(q);
    1305       16840 :                 pushInstruction(mb, q);
    1306             :         }
    1307             :         /* retrieve the single values again */
    1308       17423 :         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       34536 :         stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
    1319       17422 :         if (ns == NULL) {
    1320           0 :                 goto bailout;
    1321             :         }
    1322             : 
    1323       17422 :         ns->op1 = col;
    1324       17422 :         ns->op2 = offset;
    1325       17422 :         ns->op3 = limit;
    1326       17422 :         ns->nrcols = col->nrcols;
    1327       17422 :         ns->key = col->key;
    1328       17422 :         ns->aggr = col->aggr;
    1329       17422 :         ns->q = q;
    1330       17422 :         ns->nr = l;
    1331       17422 :         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       10384 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
    1394             : {
    1395       10384 :         MalBlkPtr mb = be->mb;
    1396       10384 :         InstrPtr q = NULL;
    1397             : 
    1398       10384 :         if (s == NULL || s->nr < 0)
    1399           0 :                 goto bailout;
    1400       10384 :         q = newStmt(mb, algebraRef, sortRef);
    1401       10384 :         if (q == NULL)
    1402           0 :                 goto bailout;
    1403             :         /* both ordered result and oid's order en subgroups */
    1404       10384 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1405       10384 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1406       10384 :         q = pushArgument(mb, q, s->nr);
    1407       10384 :         q = pushBit(mb, q, !direction);
    1408       10384 :         q = pushBit(mb, q, nullslast);
    1409       10384 :         q = pushBit(mb, q, FALSE);
    1410             : 
    1411       10384 :         bool enabled = be->mvc->sa->eb.enabled;
    1412       10384 :         be->mvc->sa->eb.enabled = false;
    1413       10384 :         stmt *ns = stmt_create(be->mvc->sa, st_order);
    1414       10384 :         be->mvc->sa->eb.enabled = enabled;
    1415       10384 :         if (ns == NULL) {
    1416           0 :                 freeInstruction(q);
    1417           0 :                 goto bailout;
    1418             :         }
    1419             : 
    1420       10384 :         ns->op1 = s;
    1421       10384 :         ns->flag = direction;
    1422       10384 :         ns->nrcols = s->nrcols;
    1423       10384 :         ns->key = s->key;
    1424       10384 :         ns->aggr = s->aggr;
    1425       10384 :         ns->q = q;
    1426       10384 :         ns->nr = getDestVar(q);
    1427       10384 :         pushInstruction(mb, q);
    1428       10384 :         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       13636 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
    1438             : {
    1439       13636 :         MalBlkPtr mb = be->mb;
    1440       13636 :         InstrPtr q = NULL;
    1441             : 
    1442       13636 :         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       13636 :         q = newStmtArgs(mb, algebraRef, sortRef, 9);
    1445       13636 :         if (q == NULL)
    1446           0 :                 goto bailout;
    1447             :         /* both ordered result and oid's order en subgroups */
    1448       13636 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1449       13636 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1450       13636 :         q = pushArgument(mb, q, s->nr);
    1451       13636 :         q = pushArgument(mb, q, orderby_ids->nr);
    1452       13636 :         q = pushArgument(mb, q, orderby_grp->nr);
    1453       13636 :         q = pushBit(mb, q, !direction);
    1454       13636 :         q = pushBit(mb, q, nullslast);
    1455       13636 :         q = pushBit(mb, q, FALSE);
    1456             : 
    1457       13636 :         bool enabled = be->mvc->sa->eb.enabled;
    1458       13636 :         be->mvc->sa->eb.enabled = false;
    1459       13636 :         stmt *ns = stmt_create(be->mvc->sa, st_reorder);
    1460       13636 :         be->mvc->sa->eb.enabled = enabled;
    1461       13636 :         if (ns == NULL) {
    1462           0 :                 freeInstruction(q);
    1463           0 :                 goto bailout;
    1464             :         }
    1465             : 
    1466       13636 :         ns->op1 = s;
    1467       13636 :         ns->op2 = orderby_ids;
    1468       13636 :         ns->op3 = orderby_grp;
    1469       13636 :         ns->flag = direction;
    1470       13636 :         ns->nrcols = s->nrcols;
    1471       13636 :         ns->key = s->key;
    1472       13636 :         ns->aggr = s->aggr;
    1473       13636 :         ns->nr = getDestVar(q);
    1474       13636 :         ns->q = q;
    1475       13636 :         pushInstruction(mb, q);
    1476       13636 :         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     3290016 : stmt_atom(backend *be, atom *a)
    1486             : {
    1487     3290016 :         MalBlkPtr mb = be->mb;
    1488             : 
    1489     3290016 :         if (a == NULL)
    1490           0 :                 goto bailout;
    1491             : 
    1492     3290016 :         InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->impl) : newAssignment(mb);
    1493             : 
    1494     3290077 :         if (q == NULL)
    1495           0 :                 goto bailout;
    1496     3290077 :         if (atom_null(a)) {
    1497      150201 :                 q = pushNil(mb, q, atom_type(a)->type->localtype);
    1498             :         } else {
    1499     3139876 :                 int k;
    1500     3139876 :                 if ((k = constantAtom(be, mb, a)) == -1) {
    1501           0 :                         freeInstruction(q);
    1502           0 :                         goto bailout;
    1503             :                 }
    1504     3139620 :                 q = pushArgument(mb, q, k);
    1505             :         }
    1506             :         /* digits of the result timestamp/daytime */
    1507     3289807 :         if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
    1508       47440 :                 q = pushInt(mb, q, atom_type(a)->digits);
    1509     3289777 :         bool enabled = be->mvc->sa->eb.enabled;
    1510     3289777 :         be->mvc->sa->eb.enabled = false;
    1511     3289777 :         stmt *s = stmt_create(be->mvc->sa, st_atom);
    1512     3289759 :         be->mvc->sa->eb.enabled = enabled;
    1513     3289759 :         if (s == NULL) {
    1514           0 :                 freeInstruction(q);
    1515           0 :                 goto bailout;
    1516             :         }
    1517             : 
    1518     3289759 :         s->op4.aval = a;
    1519     3289759 :         s->key = 1;          /* values are also unique */
    1520     3289759 :         s->q = q;
    1521     3289759 :         s->nr = getDestVar(q);
    1522     3289759 :         pushInstruction(mb, q);
    1523     3289759 :         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        3232 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
    1533             : {
    1534        3232 :         MalBlkPtr mb = be->mb;
    1535        3232 :         InstrPtr q = NULL;
    1536        3232 :         const char *mod, *op;
    1537        3232 :         node *n;
    1538        3232 :         int k;
    1539             : 
    1540        3232 :         if (lops == NULL || rops == NULL)
    1541           0 :                 goto bailout;
    1542             : 
    1543        3232 :         if (backend_create_subfunc(be, f, NULL) < 0)
    1544           0 :                 goto bailout;
    1545        3232 :         op = backend_function_imp(be, f->func);
    1546        3232 :         mod = sql_func_mod(f->func);
    1547             : 
    1548        3232 :         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        3178 :                 node *n;
    1588             : 
    1589        3178 :                 op = sa_strconcat(be->mvc->sa, op, selectRef);
    1590        3178 :                 q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
    1591        3178 :                 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        3178 :                 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        3178 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
    1599           0 :                         q = pushStr(mb, q, f->func->query);
    1600             : 
    1601        6356 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1602        3178 :                         stmt *op = n->data;
    1603             : 
    1604        3178 :                         q = pushArgument(mb, q, op->nr);
    1605             :                 }
    1606             :                 /* candidate lists */
    1607        3178 :                 if (sub)
    1608        3109 :                         q = pushArgument(mb, q, sub->nr);
    1609             :                 else
    1610          69 :                         q = pushNilBat(mb, q);
    1611             : 
    1612       12695 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1613        9517 :                         stmt *op = n->data;
    1614             : 
    1615        9517 :                         q = pushArgument(mb, q, op->nr);
    1616             :                 }
    1617             : 
    1618        3178 :                 q = pushBit(mb, q, anti);
    1619             :         }
    1620             : 
    1621        3232 :         bool enabled = be->mvc->sa->eb.enabled;
    1622        3232 :         be->mvc->sa->eb.enabled = false;
    1623        3232 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1624        3232 :         be->mvc->sa->eb.enabled = enabled;
    1625        3232 :         if (s == NULL) {
    1626           0 :                 freeInstruction(q);
    1627           0 :                 goto bailout;
    1628             :         }
    1629             : 
    1630        3232 :         s->op1 = lops;
    1631        3232 :         s->op2 = rops;
    1632        3232 :         s->op3 = sub;
    1633        3232 :         s->key = lops->nrcols == 0 && rops->nrcols == 0;
    1634        3232 :         s->flag = cmp_filter;
    1635        3232 :         s->nrcols = lops->nrcols;
    1636        3232 :         s->nr = getDestVar(q);
    1637        3232 :         s->q = q;
    1638        3232 :         s->cand = sub;
    1639        3232 :         pushInstruction(mb, q);
    1640        3232 :         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      213721 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
    1650             : {
    1651      213721 :         MalBlkPtr mb = be->mb;
    1652      213721 :         InstrPtr q = NULL;
    1653      213721 :         int l, r;
    1654      213721 :         stmt *sel = sub;
    1655             : 
    1656      213721 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
    1657           0 :                 goto bailout;
    1658      213721 :         l = op1->nr;
    1659      213721 :         r = op2->nr;
    1660             : 
    1661      213721 :         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      213721 :         if (op2->nrcols >= 1) {
    1671       17642 :                 bit need_not = FALSE;
    1672       17642 :                 const char *mod = calcRef;
    1673       17642 :                 const char *op = "=";
    1674       17642 :                 int k;
    1675             : 
    1676       17642 :                 switch (cmptype) {
    1677             :                 case cmp_equal:
    1678             :                         op = "=";
    1679             :                         break;
    1680             :                 case cmp_notequal:
    1681       17642 :                         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       27695 :                 if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
    1700           0 :                         goto bailout;
    1701       17642 :                 if (sub && (op1->cand || op2->cand)) {
    1702        1687 :                         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        1657 :                         } else if (!op1->cand && op2->cand) {
    1707        1622 :                                 q = pushArgument(mb, q, sub->nr);
    1708        1622 :                                 if (op2->nrcols > 0)
    1709        1622 :                                         q = pushNilBat(mb, q);
    1710             :                         }
    1711             :                         sub = NULL;
    1712             :                 }
    1713       17642 :                 if (is_semantics)
    1714        2972 :                         q = pushBit(mb, q, TRUE);
    1715       17642 :                 k = getDestVar(q);
    1716             : 
    1717       17642 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1718       17642 :                 if (q == NULL)
    1719           0 :                         goto bailout;
    1720       17642 :                 q = pushArgument(mb, q, k);
    1721       17642 :                 if (sub)
    1722        4364 :                         q = pushArgument(mb, q, sub->nr);
    1723       17642 :                 q = pushBit(mb, q, !need_not);
    1724       17642 :                 q = pushBit(mb, q, !need_not);
    1725       17642 :                 q = pushBit(mb, q, TRUE);
    1726       17642 :                 q = pushBit(mb, q, TRUE);
    1727       17642 :                 q = pushBit(mb, q, anti);
    1728       17642 :                 k = getDestVar(q);
    1729             :         } else {
    1730      196079 :                 assert (cmptype != cmp_filter);
    1731      196079 :                 if (is_semantics) {
    1732       19707 :                         assert(cmptype == cmp_equal || cmptype == cmp_notequal);
    1733       19707 :                         if (cmptype == cmp_notequal)
    1734          73 :                                 anti = !anti;
    1735       19707 :                         q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1736       19707 :                         if (q == NULL)
    1737           0 :                                 goto bailout;
    1738       19707 :                         q = pushArgument(mb, q, l);
    1739       19707 :                         if (sub && !op1->cand) {
    1740        1606 :                                 q = pushArgument(mb, q, sub->nr);
    1741             :                         } else {
    1742          14 :                                 assert(!sub || op1->cand == sub);
    1743             :                                 sub = NULL;
    1744             :                         }
    1745       19707 :                         q = pushArgument(mb, q, r);
    1746       19707 :                         q = pushArgument(mb, q, r);
    1747       19707 :                         q = pushBit(mb, q, TRUE);
    1748       19707 :                         q = pushBit(mb, q, TRUE);
    1749       19707 :                         q = pushBit(mb, q, anti);
    1750             :                 } else {
    1751      176372 :                         q = newStmt(mb, algebraRef, thetaselectRef);
    1752      176372 :                         if (q == NULL)
    1753           0 :                                 goto bailout;
    1754      176372 :                         q = pushArgument(mb, q, l);
    1755      176372 :                         if (sub && !op1->cand) {
    1756      126039 :                                 q = pushArgument(mb, q, sub->nr);
    1757             :                         } else {
    1758         610 :                                 assert(!sub || op1->cand == sub);
    1759       50333 :                                 q = pushNilBat(mb, q);
    1760       50333 :                                 sub = NULL;
    1761             :                         }
    1762      176372 :                         q = pushArgument(mb, q, r);
    1763      176372 :                         switch (cmptype) {
    1764      140588 :                         case cmp_equal:
    1765      140588 :                                 q = pushStr(mb, q, anti?"!=":"==");
    1766      140588 :                                 break;
    1767       32654 :                         case cmp_notequal:
    1768       32654 :                                 q = pushStr(mb, q, anti?"==":"!=");
    1769       32654 :                                 break;
    1770         355 :                         case cmp_lt:
    1771         355 :                                 q = pushStr(mb, q, anti?">=":"<");
    1772         355 :                                 break;
    1773          73 :                         case cmp_lte:
    1774          73 :                                 q = pushStr(mb, q, anti?">":"<=");
    1775          73 :                                 break;
    1776        2433 :                         case cmp_gt:
    1777        2433 :                                 q = pushStr(mb, q, anti?"<=":">");
    1778        2433 :                                 break;
    1779         269 :                         case cmp_gte:
    1780         269 :                                 q = pushStr(mb, q, anti?"<":">=");
    1781         269 :                                 break;
    1782           0 :                         default:
    1783           0 :                                 TRC_ERROR(SQL_EXECUTION, "Impossible select compare\n");
    1784           0 :                                 if (q)
    1785           0 :                                         freeInstruction(q);
    1786           0 :                                 q = NULL;
    1787           0 :                                 goto bailout;
    1788             :                         }
    1789             :                 }
    1790             :         }
    1791             : 
    1792      213721 :         bool enabled = be->mvc->sa->eb.enabled;
    1793      213721 :         be->mvc->sa->eb.enabled = false;
    1794      213721 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1795      213721 :         be->mvc->sa->eb.enabled = enabled;
    1796      213721 :         if (s == NULL) {
    1797           0 :                 freeInstruction(q);
    1798           0 :                 goto bailout;
    1799             :         }
    1800             : 
    1801      213721 :         s->op1 = op1;
    1802      213721 :         s->op2 = op2;
    1803      213721 :         s->op3 = sub;
    1804      213721 :         s->flag = cmptype;
    1805      213721 :         s->key = op1->nrcols == 0 && op2->nrcols == 0;
    1806      213721 :         s->nrcols = op1->nrcols;
    1807      213721 :         s->nr = getDestVar(q);
    1808      213721 :         s->q = q;
    1809      213721 :         s->cand = sub;
    1810      213721 :         pushInstruction(mb, q);
    1811      213721 :         if (!sub && sel) /* project back the old ids */
    1812        2311 :                 return stmt_project(be, s, sel);
    1813             :         return s;
    1814             : 
    1815           0 :   bailout:
    1816           0 :         if (be->mvc->sa->eb.enabled)
    1817           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1818             :         return NULL;
    1819             : }
    1820             : 
    1821             : /*
    1822             : static int
    1823             : range_join_convertable(stmt *s, stmt **base, stmt **L, stmt **H)
    1824             : {
    1825             :         int ls = 0, hs = 0;
    1826             :         stmt *l = NULL, *h = NULL;
    1827             :         stmt *bl = s->op2, *bh = s->op3;
    1828             :         int tt = tail_type(s->op2)->type->localtype;
    1829             : 
    1830             : #ifdef HAVE_HGE
    1831             :         if (tt > TYPE_hge)
    1832             : #else
    1833             :         if (tt > TYPE_lng)
    1834             : #endif
    1835             :                 return 0;
    1836             :         if (s->op2->type == st_Nop && list_length(s->op2->op1->op4.lval) == 2) {
    1837             :                 bl = s->op2->op1->op4.lval->h->data;
    1838             :                 l = s->op2->op1->op4.lval->t->data;
    1839             :         }
    1840             :         if (s->op3->type == st_Nop && list_length(s->op3->op1->op4.lval) == 2) {
    1841             :                 bh = s->op3->op1->op4.lval->h->data;
    1842             :                 h = s->op3->op1->op4.lval->t->data;
    1843             :         }
    1844             : 
    1845             :         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) {
    1846             :                 *base = bl;
    1847             :                 *L = l;
    1848             :                 *H = h;
    1849             :                 return 1;
    1850             :         }
    1851             :         return 0;
    1852             : }
    1853             : 
    1854             : static int
    1855             : argumentZero(MalBlkPtr mb, int tpe)
    1856             : {
    1857             :         ValRecord cst;
    1858             :         str msg;
    1859             : 
    1860             :         cst.vtype = TYPE_int;
    1861             :         cst.val.ival = 0;
    1862             :         msg = convertConstant(tpe, &cst);
    1863             :         if( msg)
    1864             :                 freeException(msg); // will not be called
    1865             :         return defConstant(mb, tpe, &cst);
    1866             : }
    1867             : */
    1868             : 
    1869             : static InstrPtr
    1870        5103 : select2_join2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt **Sub, int anti, int symmetric, int swapped, int type, int reduce)
    1871             : {
    1872        5103 :         MalBlkPtr mb = be->mb;
    1873        5103 :         InstrPtr p, q;
    1874        5103 :         int l;
    1875        5103 :         const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
    1876        5103 :         stmt *sub = (Sub)?*Sub:NULL;
    1877             : 
    1878        5103 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
    1879           0 :                 goto bailout;
    1880        5103 :         l = op1->nr;
    1881        8475 :         if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
    1882        3597 :                 int k;
    1883        3597 :                 int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
    1884             : 
    1885        3597 :                 if (op2->nr < 0 || op3->nr < 0)
    1886           0 :                         goto bailout;
    1887             : 
    1888        3597 :                 if (nrcols)
    1889        3556 :                         p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
    1890             :                 else
    1891          41 :                         p = newStmtArgs(mb, calcRef, betweenRef, 9);
    1892        3597 :                 if (p == NULL)
    1893           0 :                         goto bailout;
    1894        3597 :                 p = pushArgument(mb, p, l);
    1895        3597 :                 p = pushArgument(mb, p, op2->nr);
    1896        3597 :                 p = pushArgument(mb, p, op3->nr);
    1897             : 
    1898             :                 /* cands */
    1899        3597 :                 if ((sub && !reduce) || op1->cand || op2->cand || op3->cand) { /* some already handled the previous selection */
    1900        1568 :                         if (op1->cand && op1->nrcols)
    1901        1287 :                                 p = pushNilBat(mb, p);
    1902         281 :                         else if (op1->nrcols)
    1903         281 :                                 p = pushArgument(mb, p, sub->nr);
    1904        1568 :                         if (op2->nrcols) {
    1905        1466 :                                 if (op2->cand)
    1906        1220 :                                         p = pushNilBat(mb, p);
    1907         246 :                                 else if (op2->nrcols)
    1908         246 :                                         p = pushArgument(mb, p, sub->nr);
    1909             :                         }
    1910        1568 :                         if (op3->nrcols) {
    1911        1461 :                                 if (op3->cand)
    1912        1336 :                                         p = pushNilBat(mb, p);
    1913         125 :                                 else if (op3->nrcols)
    1914         125 :                                         p = pushArgument(mb, p, sub->nr);
    1915             :                         }
    1916             :                         sub = NULL;
    1917             :                 }
    1918             : 
    1919        3597 :                 p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
    1920        3597 :                 p = pushBit(mb, p, (cmp & 1) != 0);     /* lo inclusive */
    1921        3597 :                 p = pushBit(mb, p, (cmp & 2) != 0);     /* hi inclusive */
    1922        3597 :                 p = pushBit(mb, p, FALSE);                  /* nils_false */
    1923        3597 :                 p = pushBit(mb, p, (anti)?TRUE:FALSE);      /* anti */
    1924        3597 :                 pushInstruction(mb, p);
    1925        3597 :                 if (!reduce)
    1926             :                         return p;
    1927        3372 :                 k = getDestVar(p);
    1928             : 
    1929        3372 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1930        3372 :                 if (q == NULL)
    1931           0 :                         goto bailout;
    1932        3372 :                 q = pushArgument(mb, q, k);
    1933        3372 :                 if (sub)
    1934         896 :                         q = pushArgument(mb, q, sub->nr);
    1935        3372 :                 q = pushBit(mb, q, TRUE);
    1936        3372 :                 q = pushBit(mb, q, TRUE);
    1937        3372 :                 q = pushBit(mb, q, TRUE);
    1938        3372 :                 q = pushBit(mb, q, TRUE);
    1939        3372 :                 q = pushBit(mb, q, FALSE);
    1940        3372 :                 pushInstruction(mb, q);
    1941             :         } else {
    1942             :                 /* if st_join2 try to convert to bandjoin */
    1943             :                 /* ie check if we subtract/add a constant, to the
    1944             :                 same column */
    1945             :                 /* move this optimization into the relational phase! */
    1946             :         /*
    1947             :                 stmt *base, *low = NULL, *high = NULL;
    1948             :                 if (type == st_join2 && range_join_convertable(s, &base, &low, &high)) {
    1949             :                         int tt = tail_type(base)->type->localtype;
    1950             : 
    1951             :                         if ((rs = _dumpstmt(sql, mb, base)) < 0)
    1952             :                                 return -1;
    1953             :                         if (low) {
    1954             :                                 if ((r1 = _dumpstmt(sql, mb, low)) < 0)
    1955             :                                         return -1;
    1956             :                         } else
    1957             :                                 r1 = argumentZero(mb, tt);
    1958             :                         if (high) {
    1959             :                                 if ((r2 = _dumpstmt(sql, mb, high)) < 0)
    1960             :                                         return -1;
    1961             :                         } else
    1962             :                                 r2 = argumentZero(mb, tt);
    1963             :                         cmd = bandjoinRef;
    1964             :                 }
    1965             :         */
    1966             : 
    1967        1506 :                 int r1 = op2->nr;
    1968        1506 :                 int r2 = op3->nr;
    1969        1506 :                 int rs = 0;
    1970        1506 :                 q = newStmtArgs(mb, algebraRef, cmd, 12);
    1971        1506 :                 if (q == NULL)
    1972           0 :                         goto bailout;
    1973        1506 :                 if (type == st_join2)
    1974          54 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1975        1506 :                 q = pushArgument(mb, q, l);
    1976        1506 :                 if (sub) {
    1977        1187 :                         int cand = op1->cand || op2->cand || op3->cand;
    1978        1180 :                         if (cand) {
    1979           7 :                                 assert(!op1->nrcols || op1->cand);
    1980           7 :                                 assert(!op2->nrcols || op2->cand);
    1981           7 :                                 assert(!op3->nrcols || op3->cand);
    1982             :                                 sub = NULL;
    1983             :                         }
    1984             :                 }
    1985        1180 :                 if (sub) /* only for uselect2 */
    1986        1180 :                         q = pushArgument(mb, q, sub->nr);
    1987        1506 :                 if (rs) {
    1988             :                         q = pushArgument(mb, q, rs);
    1989             :                 } else {
    1990        1506 :                         q = pushArgument(mb, q, r1);
    1991        1506 :                         q = pushArgument(mb, q, r2);
    1992             :                 }
    1993        1506 :                 if (type == st_join2) {
    1994          54 :                         q = pushNilBat(mb, q);
    1995          54 :                         q = pushNilBat(mb, q);
    1996             :                 }
    1997             : 
    1998        1506 :                 switch (cmp & 3) {
    1999          59 :                 case 0:
    2000          59 :                         q = pushBit(mb, q, FALSE);
    2001          59 :                         q = pushBit(mb, q, FALSE);
    2002          59 :                         break;
    2003         228 :                 case 1:
    2004         228 :                         q = pushBit(mb, q, TRUE);
    2005         228 :                         q = pushBit(mb, q, FALSE);
    2006         228 :                         break;
    2007          11 :                 case 2:
    2008          11 :                         q = pushBit(mb, q, FALSE);
    2009          11 :                         q = pushBit(mb, q, TRUE);
    2010          11 :                         break;
    2011        1208 :                 case 3:
    2012        1208 :                         q = pushBit(mb, q, TRUE);
    2013        1208 :                         q = pushBit(mb, q, TRUE);
    2014        1208 :                         break;
    2015             :                 }
    2016        1506 :                 q = pushBit(mb, q, anti);
    2017        1506 :                 if (type == st_uselect2) {
    2018        1452 :                         q = pushBit(mb, q, TRUE); /* all nil's are != */
    2019             :                 } else {
    2020          54 :                         q = pushBit(mb, q, (symmetric)?TRUE:FALSE);
    2021             :                 }
    2022        1506 :                 if (type == st_join2)
    2023          54 :                         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2024        1506 :                 pushInstruction(mb, q);
    2025        1506 :                 if (swapped) {
    2026           2 :                         InstrPtr r = newInstruction(mb,  NULL, NULL);
    2027           2 :                         if (r == NULL)
    2028           0 :                                 goto bailout;
    2029           2 :                         getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2030           2 :                         r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2031           2 :                         r = pushArgument(mb, r, getArg(q,1));
    2032           2 :                         r = pushArgument(mb, r, getArg(q,0));
    2033           2 :                         pushInstruction(mb, r);
    2034           2 :                         q = r;
    2035             :                 }
    2036             :         }
    2037        4878 :         if (Sub)
    2038        4824 :                 *Sub = sub;
    2039             :         return q;
    2040             : 
    2041           0 :   bailout:
    2042           0 :         if (be->mvc->sa->eb.enabled)
    2043           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2044             :         return NULL;
    2045             : }
    2046             : 
    2047             : stmt *
    2048          38 : stmt_outerselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2049             : {
    2050          38 :         MalBlkPtr mb = be->mb;
    2051          38 :         InstrPtr q;
    2052             : 
    2053          38 :         q = newStmtArgs(mb, algebraRef, outerselectRef, 6);
    2054          38 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2055          38 :         q = pushArgument(mb, q, g->nr); /* group ids */
    2056          38 :         q = pushArgument(mb, q, m->nr); /* mark flag */
    2057          38 :         q = pushArgument(mb, q, p->nr); /* predicate */
    2058          38 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2059          38 :         pushInstruction(mb, q);
    2060             : 
    2061          38 :         if (!q)
    2062             :                 return NULL;
    2063          38 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2064          38 :         if (s == NULL) {
    2065           0 :                 freeInstruction(q);
    2066           0 :                 return NULL;
    2067             :         }
    2068             : 
    2069          38 :         s->op1 = g;
    2070          38 :         s->op2 = m;
    2071          38 :         s->flag = MARKJOIN;
    2072          38 :         s->key = 0;
    2073          38 :         s->nrcols = g->nrcols;
    2074          38 :         s->nr = getDestVar(q);
    2075          38 :         s->q = q;
    2076          38 :         return s;
    2077             : }
    2078             : 
    2079             : stmt *
    2080         402 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2081             : {
    2082         402 :         MalBlkPtr mb = be->mb;
    2083         402 :         InstrPtr q;
    2084             : 
    2085         402 :         q = newStmtArgs(mb, algebraRef, markselectRef, 6);
    2086         402 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2087         402 :         q = pushArgument(mb, q, g->nr); /* left ids */
    2088         402 :         q = pushArgument(mb, q, m->nr); /* mark info mask */
    2089         402 :         q = pushArgument(mb, q, p->nr);      /* predicate */
    2090         402 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2091         402 :         pushInstruction(mb, q);
    2092             : 
    2093         402 :         if (!q)
    2094             :                 return NULL;
    2095         402 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2096         402 :         if (s == NULL) {
    2097           0 :                 freeInstruction(q);
    2098           0 :                 return NULL;
    2099             :         }
    2100             : 
    2101         402 :         s->op1 = g;
    2102         402 :         s->op2 = m;
    2103         402 :         s->flag = MARKJOIN;
    2104         402 :         s->key = 0;
    2105         402 :         s->nrcols = g->nrcols;
    2106         402 :         s->nr = getDestVar(q);
    2107         402 :         s->q = q;
    2108         402 :         return s;
    2109             : }
    2110             : 
    2111             : stmt *
    2112        2488 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
    2113             : {
    2114        2488 :         MalBlkPtr mb = be->mb;
    2115        2488 :         InstrPtr q;
    2116             : 
    2117        2488 :         q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
    2118        2488 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2119        2488 :         if (!final)
    2120           5 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2121        2488 :         q = pushArgument(mb, q, l->nr); /* left ids */
    2122        2488 :         q = pushArgument(mb, q, r->nr); /* mark info mask */
    2123        2488 :         q = pushNilBat(mb, q);
    2124        2488 :         q = pushNilBat(mb, q);
    2125        2488 :         q = pushNil(mb, q, TYPE_lng);
    2126        2488 :         pushInstruction(mb, q);
    2127             : 
    2128        2488 :         if (!q)
    2129             :                 return NULL;
    2130        2488 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2131        2488 :         if (s == NULL) {
    2132           0 :                 freeInstruction(q);
    2133           0 :                 return NULL;
    2134             :         }
    2135             : 
    2136        2488 :         s->op1 = l;
    2137        2488 :         s->op2 = r;
    2138        2488 :         s->flag = MARKJOIN;
    2139        2488 :         s->key = 0;
    2140        2488 :         s->nrcols = l->nrcols;
    2141        2488 :         s->nr = getDestVar(q);
    2142        2488 :         s->q = q;
    2143        2488 :         return s;
    2144             : }
    2145             : 
    2146             : stmt *
    2147        5049 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
    2148             : {
    2149        5049 :         stmt *sel = sub;
    2150        5049 :         InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
    2151             : 
    2152        5049 :         if (q == NULL)
    2153             :                 return NULL;
    2154             : 
    2155        5049 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2156        5049 :         if (s == NULL) {
    2157             :                 return NULL;
    2158             :         }
    2159             : 
    2160        5049 :         s->op1 = op1;
    2161        5049 :         s->op2 = op2;
    2162        5049 :         s->op3 = op3;
    2163        5049 :         s->op4.stval = sub;
    2164        5049 :         s->flag = cmp;
    2165        5049 :         s->nrcols = op1->nrcols;
    2166        5049 :         s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
    2167        5049 :         s->nr = getDestVar(q);
    2168        5049 :         s->q = q;
    2169        5049 :         s->cand = sub;
    2170        5049 :         s->reduce = reduce;
    2171        5049 :         if (!sub && sel) /* project back the old ids */
    2172        1458 :                 return stmt_project(be, s, sel);
    2173             :         return s;
    2174             : }
    2175             : 
    2176             : stmt *
    2177       54044 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
    2178             : {
    2179       54044 :         InstrPtr q = NULL;
    2180       54044 :         MalBlkPtr mb = be->mb;
    2181             : 
    2182       54044 :         q = dump_2(mb, batRef, mergecandRef, op1, op2);
    2183       54044 :         if (q) {
    2184       54044 :                 stmt *s = stmt_create(be->mvc->sa, st_tunion);
    2185       54044 :                 if (s == NULL) {
    2186             :                         return NULL;
    2187             :                 }
    2188             : 
    2189       54044 :                 s->op1 = op1;
    2190       54044 :                 s->op2 = op2;
    2191       54044 :                 s->nrcols = op1->nrcols;
    2192       54044 :                 s->key = op1->key;
    2193       54044 :                 s->aggr = op1->aggr;
    2194       54044 :                 s->nr = getDestVar(q);
    2195       54044 :                 s->q = q;
    2196       54044 :                 return s;
    2197             :         }
    2198             : 
    2199           0 :         if (be->mvc->sa->eb.enabled)
    2200           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2201             :         return NULL;
    2202             : }
    2203             : 
    2204             : stmt *
    2205       44577 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2206             : {
    2207       44577 :         InstrPtr q = NULL;
    2208       44577 :         MalBlkPtr mb = be->mb;
    2209             : 
    2210       44577 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2211           0 :                 goto bailout;
    2212       44577 :         q = newStmt(mb, algebraRef, differenceRef);
    2213       44577 :         if (q == NULL)
    2214           0 :                 goto bailout;
    2215       44577 :         q = pushArgument(mb, q, op1->nr); /* left */
    2216       44577 :         q = pushArgument(mb, q, op2->nr); /* right */
    2217       44577 :         if (lcand)
    2218           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2219             :         else
    2220       44577 :                 q = pushNilBat(mb, q); /* left candidate */
    2221       44577 :         q = pushNilBat(mb, q); /* right candidate */
    2222       44577 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2223       44577 :         q = pushBit(mb, q, FALSE);    /* do not clear nils */
    2224       44577 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2225             : 
    2226       44577 :         bool enabled = be->mvc->sa->eb.enabled;
    2227       44577 :         be->mvc->sa->eb.enabled = false;
    2228       44577 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2229       44577 :         be->mvc->sa->eb.enabled = enabled;
    2230       44577 :         if (s == NULL) {
    2231           0 :                 freeInstruction(q);
    2232           0 :                 goto bailout;
    2233             :         }
    2234             : 
    2235       44577 :         s->op1 = op1;
    2236       44577 :         s->op2 = op2;
    2237       44577 :         s->nrcols = op1->nrcols;
    2238       44577 :         s->key = op1->key;
    2239       44577 :         s->aggr = op1->aggr;
    2240       44577 :         s->nr = getDestVar(q);
    2241       44577 :         s->q = q;
    2242       44577 :         pushInstruction(mb, q);
    2243       44577 :         return s;
    2244             : 
    2245           0 :   bailout:
    2246           0 :         if (be->mvc->sa->eb.enabled)
    2247           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2248             :         return NULL;
    2249             : }
    2250             : 
    2251             : stmt *
    2252        1332 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2253             : {
    2254        1332 :         InstrPtr q = NULL;
    2255        1332 :         MalBlkPtr mb = be->mb;
    2256             : 
    2257        1332 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2258           0 :                 goto bailout;
    2259        1332 :         q = newStmt(mb, algebraRef, differenceRef);
    2260        1332 :         if (q == NULL)
    2261           0 :                 goto bailout;
    2262        1332 :         q = pushArgument(mb, q, op1->nr); /* left */
    2263        1332 :         q = pushArgument(mb, q, op2->nr); /* right */
    2264        1332 :         if (lcand)
    2265           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2266             :         else
    2267        1332 :                 q = pushNilBat(mb, q); /* left candidate */
    2268        1332 :         q = pushNilBat(mb, q); /* right candidate */
    2269        1332 :         q = pushBit(mb, q, FALSE);     /* nil matches */
    2270        1332 :         q = pushBit(mb, q, TRUE);     /* not in */
    2271        1332 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2272             : 
    2273        1332 :         bool enabled = be->mvc->sa->eb.enabled;
    2274        1332 :         be->mvc->sa->eb.enabled = false;
    2275        1332 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2276        1332 :         be->mvc->sa->eb.enabled = enabled;
    2277        1332 :         if (s == NULL) {
    2278           0 :                 freeInstruction(q);
    2279           0 :                 goto bailout;
    2280             :         }
    2281             : 
    2282        1332 :         s->op1 = op1;
    2283        1332 :         s->op2 = op2;
    2284        1332 :         s->nrcols = op1->nrcols;
    2285        1332 :         s->key = op1->key;
    2286        1332 :         s->aggr = op1->aggr;
    2287        1332 :         s->nr = getDestVar(q);
    2288        1332 :         s->q = q;
    2289        1332 :         pushInstruction(mb, q);
    2290        1332 :         return s;
    2291             : 
    2292           0 :   bailout:
    2293           0 :         if (be->mvc->sa->eb.enabled)
    2294           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2295             :         return NULL;
    2296             : }
    2297             : 
    2298             : stmt *
    2299        2052 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
    2300             : {
    2301        2052 :         InstrPtr q = NULL;
    2302        2052 :         MalBlkPtr mb = be->mb;
    2303             : 
    2304        2052 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2305           0 :                 goto bailout;
    2306        2052 :         q = newStmt(mb, algebraRef, intersectRef);
    2307        2052 :         if (q == NULL)
    2308           0 :                 goto bailout;
    2309        2052 :         q = pushArgument(mb, q, op1->nr); /* left */
    2310        2052 :         q = pushArgument(mb, q, op2->nr); /* right */
    2311        2052 :         q = pushNilBat(mb, q); /* left candidate */
    2312        2052 :         q = pushNilBat(mb, q); /* right candidate */
    2313        2052 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2314        2052 :         q = pushBit(mb, q, single?TRUE:FALSE);    /* max_one */
    2315        2052 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2316             : 
    2317        2052 :         bool enabled = be->mvc->sa->eb.enabled;
    2318        2052 :         be->mvc->sa->eb.enabled = false;
    2319        2052 :         stmt *s = stmt_create(be->mvc->sa, st_tinter);
    2320        2052 :         be->mvc->sa->eb.enabled = enabled;
    2321        2052 :         if (s == NULL) {
    2322           0 :                 freeInstruction(q);
    2323           0 :                 goto bailout;
    2324             :         }
    2325             : 
    2326        2052 :         s->op1 = op1;
    2327        2052 :         s->op2 = op2;
    2328        2052 :         s->nrcols = op1->nrcols;
    2329        2052 :         s->key = op1->key;
    2330        2052 :         s->aggr = op1->aggr;
    2331        2052 :         s->nr = getDestVar(q);
    2332        2052 :         s->q = q;
    2333        2052 :         pushInstruction(mb, q);
    2334        2052 :         return s;
    2335             : 
    2336           0 :   bailout:
    2337           0 :         if (be->mvc->sa->eb.enabled)
    2338           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2339             :         return NULL;
    2340             : }
    2341             : 
    2342             : stmt *
    2343       93545 : 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)
    2344             : {
    2345       93545 :         MalBlkPtr mb = be->mb;
    2346       93545 :         InstrPtr q = NULL;
    2347       93545 :         const char *sjt = inner?joinRef:outerjoinRef;
    2348             : 
    2349       93545 :         (void)anti;
    2350       93545 :         (void)inner;
    2351             : 
    2352       93545 :         if (need_left) {
    2353         653 :                 cmptype = cmp_equal;
    2354         653 :                 sjt = leftjoinRef;
    2355             :         }
    2356       93545 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2357           0 :                 goto bailout;
    2358             : 
    2359       93545 :         assert (!single || cmptype == cmp_all);
    2360             : 
    2361       93545 :         switch (cmptype) {
    2362       75937 :         case cmp_equal:
    2363       75937 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2364       75937 :                 if (q == NULL)
    2365           0 :                         goto bailout;
    2366       75937 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2367       75937 :                 q = pushArgument(mb, q, op1->nr);
    2368       75937 :                 q = pushArgument(mb, q, op2->nr);
    2369       75937 :                 if (!lcand)
    2370       74875 :                         q = pushNilBat(mb, q);
    2371             :                 else
    2372        1062 :                         q = pushArgument(mb, q, lcand->nr);
    2373       75937 :                 if (!rcand)
    2374       75937 :                         q = pushNilBat(mb, q);
    2375             :                 else
    2376           0 :                         q = pushArgument(mb, q, rcand->nr);
    2377       75937 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2378       75937 :                 if (!inner)
    2379          75 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2380       75937 :                 q = pushNil(mb, q, TYPE_lng);
    2381       75937 :                 pushInstruction(mb, q);
    2382       75937 :                 break;
    2383          34 :         case cmp_notequal:
    2384          34 :                 if (inner)
    2385          34 :                         sjt = thetajoinRef;
    2386          34 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2387          34 :                 if (q == NULL)
    2388           0 :                         goto bailout;
    2389          34 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2390          34 :                 q = pushArgument(mb, q, op1->nr);
    2391          34 :                 q = pushArgument(mb, q, op2->nr);
    2392          34 :                 if (!lcand)
    2393          34 :                         q = pushNilBat(mb, q);
    2394             :                 else
    2395           0 :                         q = pushArgument(mb, q, lcand->nr);
    2396          34 :                 if (!rcand)
    2397          34 :                         q = pushNilBat(mb, q);
    2398             :                 else
    2399           0 :                         q = pushArgument(mb, q, rcand->nr);
    2400          34 :                 if (inner)
    2401          34 :                         q = pushInt(mb, q, JOIN_NE);
    2402          34 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2403          34 :                 if (!inner)
    2404           0 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2405          34 :                 q = pushNil(mb, q, TYPE_lng);
    2406          34 :                 pushInstruction(mb, q);
    2407          34 :                 break;
    2408        2583 :         case cmp_lt:
    2409             :         case cmp_lte:
    2410             :         case cmp_gt:
    2411             :         case cmp_gte:
    2412        2583 :                 q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
    2413        2583 :                 if (q == NULL)
    2414           0 :                         goto bailout;
    2415        2583 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2416        2583 :                 q = pushArgument(mb, q, op1->nr);
    2417        2583 :                 q = pushArgument(mb, q, op2->nr);
    2418        2583 :                 if (!lcand)
    2419        2583 :                         q = pushNilBat(mb, q);
    2420             :                 else
    2421           0 :                         q = pushArgument(mb, q, lcand->nr);
    2422        2583 :                 if (!rcand)
    2423        2583 :                         q = pushNilBat(mb, q);
    2424             :                 else
    2425           0 :                         q = pushArgument(mb, q, rcand->nr);
    2426        2583 :                 if (cmptype == cmp_lt)
    2427        2067 :                         q = pushInt(mb, q, JOIN_LT);
    2428         516 :                 else if (cmptype == cmp_lte)
    2429           8 :                         q = pushInt(mb, q, JOIN_LE);
    2430         508 :                 else if (cmptype == cmp_gt)
    2431         503 :                         q = pushInt(mb, q, JOIN_GT);
    2432           5 :                 else if (cmptype == cmp_gte)
    2433           5 :                         q = pushInt(mb, q, JOIN_GE);
    2434        2583 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2435        2583 :                 q = pushNil(mb, q, TYPE_lng);
    2436        2583 :                 pushInstruction(mb, q);
    2437        2583 :                 break;
    2438       11835 :         case cmp_all:   /* aka cross table */
    2439       11835 :                 q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
    2440       11835 :                 if (q == NULL)
    2441           0 :                         goto bailout;
    2442       11835 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2443       11835 :                 q = pushArgument(mb, q, op1->nr);
    2444       11835 :                 q = pushArgument(mb, q, op2->nr);
    2445       11835 :                 if (!inner) {
    2446         436 :                         q = pushNilBat(mb, q);
    2447         436 :                         q = pushNilBat(mb, q);
    2448             :                 }
    2449       11835 :                 q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2450       11835 :                 assert(!lcand && !rcand);
    2451       11835 :                 pushInstruction(mb, q);
    2452       11835 :                 break;
    2453        3156 :         case cmp_joined:
    2454        3156 :                 q = op1->q;
    2455        3156 :                 if (q == NULL)
    2456           0 :                         goto bailout;
    2457             :                 break;
    2458           0 :         default:
    2459           0 :                 TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
    2460             :         }
    2461             : 
    2462       93545 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2463       93545 :         if (s == NULL) {
    2464           0 :                 goto bailout;
    2465             :         }
    2466             : 
    2467       93545 :         s->op1 = op1;
    2468       93545 :         s->op2 = op2;
    2469       93545 :         s->flag = cmptype;
    2470       93545 :         s->key = 0;
    2471       93545 :         s->nrcols = 2;
    2472       93545 :         s->nr = getDestVar(q);
    2473       93545 :         s->q = q;
    2474       93545 :         return s;
    2475             : 
    2476           0 :   bailout:
    2477           0 :         if (be->mvc->sa->eb.enabled)
    2478           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2479             :         return NULL;
    2480             : }
    2481             : 
    2482             : stmt *
    2483       89481 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
    2484             : {
    2485       89481 :         return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
    2486             : }
    2487             : 
    2488             : stmt *
    2489        1432 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
    2490             : {
    2491        1432 :         MalBlkPtr mb = be->mb;
    2492        1432 :         InstrPtr q = NULL;
    2493             : 
    2494        1432 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2495           0 :                 goto bailout;
    2496             : 
    2497        1432 :         if (single) {
    2498         280 :                 q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
    2499         280 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2500             :         } else
    2501        1152 :                 q = newStmt(mb, algebraRef, intersectRef);
    2502        1432 :         if (q == NULL)
    2503           0 :                 goto bailout;
    2504        1432 :         q = pushArgument(mb, q, op1->nr);
    2505        1432 :         q = pushArgument(mb, q, op2->nr);
    2506        1432 :         if (lcand)
    2507        1149 :                 q = pushArgument(mb, q, lcand->nr);
    2508             :         else
    2509         283 :                 q = pushNilBat(mb, q);
    2510        1432 :         if (rcand)
    2511           0 :                 q = pushArgument(mb, q, rcand->nr);
    2512             :         else
    2513        1432 :                 q = pushNilBat(mb, q);
    2514        1432 :         q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2515        1432 :         q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2516        1432 :         q = pushNil(mb, q, TYPE_lng);
    2517             : 
    2518        1432 :         bool enabled = be->mvc->sa->eb.enabled;
    2519        1432 :         be->mvc->sa->eb.enabled = false;
    2520        1432 :         stmt *s = stmt_create(be->mvc->sa, st_semijoin);
    2521        1432 :         be->mvc->sa->eb.enabled = enabled;
    2522        1432 :         if (s == NULL) {
    2523           0 :                 freeInstruction(q);
    2524           0 :                 goto bailout;
    2525             :         }
    2526             : 
    2527        1432 :         s->op1 = op1;
    2528        1432 :         s->op2 = op2;
    2529        1432 :         s->flag = cmp_equal;
    2530        1432 :         s->key = 0;
    2531        1432 :         s->nrcols = 1;
    2532        1432 :         if (single)
    2533         280 :                 s->nrcols = 2;
    2534        1432 :         s->nr = getDestVar(q);
    2535        1432 :         s->q = q;
    2536        1432 :         pushInstruction(mb, q);
    2537        1432 :         return s;
    2538             : 
    2539           0 :   bailout:
    2540           0 :         if (be->mvc->sa->eb.enabled)
    2541           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2542             :         return NULL;
    2543             : }
    2544             : 
    2545             : static InstrPtr
    2546     3500497 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
    2547             : {
    2548     3500497 :         MalBlkPtr mb = be->mb;
    2549     3500497 :         InstrPtr q = NULL;
    2550             : 
    2551     3500497 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2552             :                 return NULL;
    2553             :         /* delta bat */
    2554     3500497 :         if (delta) {
    2555      479926 :                 int uval = getArg(op2->q, 1);
    2556             : 
    2557      479926 :                 q = newStmt(mb, sqlRef, deltaRef);
    2558      479928 :                 q = pushArgument(mb, q, op1->nr);
    2559      479928 :                 q = pushArgument(mb, q, op2->nr);
    2560      479927 :                 q = pushArgument(mb, q, uval);
    2561             :         } else {
    2562             :                 /* projections, ie left is void headed */
    2563     3020571 :                 q = newStmt(mb, algebraRef, projectionRef);
    2564     3020589 :                 q = pushArgument(mb, q, op1->nr);
    2565     3020588 :                 q = pushArgument(mb, q, op2->nr);
    2566             :         }
    2567     3500514 :         pushInstruction(mb, q);
    2568     3500514 :         return q;
    2569             : }
    2570             : 
    2571             : stmt *
    2572     3029877 : stmt_project(backend *be, stmt *op1, stmt *op2)
    2573             : {
    2574     3029877 :         if (op1 == NULL || op2 == NULL)
    2575             :                 return NULL;
    2576     3029877 :         if (!op2->nrcols)
    2577        9305 :                 return stmt_const(be, op1, op2);
    2578     3020572 :         InstrPtr q = stmt_project_join(be, op1, op2, false);
    2579     3020587 :         if (q) {
    2580     3020587 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2581     3020573 :                 if (s == NULL) {
    2582             :                         return NULL;
    2583             :                 }
    2584             : 
    2585     3020573 :                 s->op1 = op1;
    2586     3020573 :                 s->op2 = op2;
    2587     3020573 :                 s->flag = cmp_project;
    2588     3020573 :                 s->key = 0;
    2589     3020573 :                 s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2590     3020573 :                 s->nr = getDestVar(q);
    2591     3020573 :                 s->q = q;
    2592     3020573 :                 s->tname = op2->tname;
    2593     3020573 :                 s->cname = op2->cname;
    2594     3020573 :                 s->label = op2->label;
    2595     3020573 :                 return s;
    2596             :         }
    2597           0 :         if (be->mvc->sa->eb.enabled)
    2598           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);
    2599             :         return NULL;
    2600             : }
    2601             : 
    2602             : stmt *
    2603      479927 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
    2604             : {
    2605      479927 :         InstrPtr q = stmt_project_join(be, col, upd, true);
    2606      479928 :         if (q) {
    2607      479928 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2608      479928 :                 if (s == NULL) {
    2609             :                         return NULL;
    2610             :                 }
    2611             : 
    2612      479928 :                 s->op1 = col;
    2613      479928 :                 s->op2 = upd;
    2614      479928 :                 s->flag = cmp_project;
    2615      479928 :                 s->key = 0;
    2616      479928 :                 s->nrcols = 2;
    2617      479928 :                 s->nr = getDestVar(q);
    2618      479928 :                 s->q = q;
    2619      479928 :                 s->tname = col->tname;
    2620      479928 :                 s->cname = col->cname;
    2621      479928 :                 return s;
    2622             :         }
    2623             : 
    2624           0 :         if (be->mvc->sa->eb.enabled)
    2625           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);
    2626             :         return NULL;
    2627             : }
    2628             : 
    2629             : stmt *
    2630          43 : stmt_left_project(backend *be, stmt *op1, stmt *op2, stmt *op3)
    2631             : {
    2632          43 :         MalBlkPtr mb = be->mb;
    2633          43 :         InstrPtr q = NULL;
    2634          43 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || op2->nr < 0 || op3->nr < 0)
    2635           0 :                 goto bailout;
    2636             : 
    2637          43 :         q = newStmt(mb, sqlRef, projectRef);
    2638          43 :         if (q == NULL)
    2639           0 :                 goto bailout;
    2640          43 :         q = pushArgument(mb, q, op1->nr);
    2641          43 :         q = pushArgument(mb, q, op2->nr);
    2642          43 :         q = pushArgument(mb, q, op3->nr);
    2643             : 
    2644          43 :         bool enabled = be->mvc->sa->eb.enabled;
    2645          43 :         be->mvc->sa->eb.enabled = false;
    2646          43 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2647          43 :         be->mvc->sa->eb.enabled = enabled;
    2648          43 :         if (s == NULL) {
    2649           0 :                 freeInstruction(q);
    2650           0 :                 goto bailout;
    2651             :         }
    2652             : 
    2653          43 :         s->op1 = op1;
    2654          43 :         s->op2 = op2;
    2655          43 :         s->op3 = op3;
    2656          43 :         s->flag = cmp_left_project;
    2657          43 :         s->key = 0;
    2658          43 :         s->nrcols = 2;
    2659          43 :         s->nr = getDestVar(q);
    2660          43 :         s->q = q;
    2661          43 :         pushInstruction(mb, q);
    2662          43 :         return s;
    2663             : 
    2664           0 :   bailout:
    2665           0 :         if (be->mvc->sa->eb.enabled)
    2666           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2667             :         return NULL;
    2668             : }
    2669             : 
    2670             : stmt *
    2671         176 : stmt_dict(backend *be, stmt *op1, stmt *op2)
    2672             : {
    2673         176 :         MalBlkPtr mb = be->mb;
    2674         176 :         InstrPtr q = NULL;
    2675             : 
    2676         176 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2677             :                 return NULL;
    2678             : 
    2679         176 :         q = newStmt(mb, dictRef, decompressRef);
    2680         176 :         if (q == NULL)
    2681           0 :                 goto bailout;
    2682         176 :         q = pushArgument(mb, q, op1->nr);
    2683         176 :         q = pushArgument(mb, q, op2->nr);
    2684             : 
    2685         176 :         bool enabled = be->mvc->sa->eb.enabled;
    2686         176 :         be->mvc->sa->eb.enabled = false;
    2687         176 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2688         176 :         be->mvc->sa->eb.enabled = enabled;
    2689         176 :         if (s == NULL) {
    2690           0 :                 freeInstruction(q);
    2691           0 :                 return NULL;
    2692             :         }
    2693             : 
    2694         176 :         s->op1 = op1;
    2695         176 :         s->op2 = op2;
    2696         176 :         s->flag = cmp_project;
    2697         176 :         s->key = 0;
    2698         176 :         s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2699         176 :         s->nr = getDestVar(q);
    2700         176 :         s->q = q;
    2701         176 :         s->tname = op1->tname;
    2702         176 :         s->cname = op1->cname;
    2703         176 :         pushInstruction(mb, q);
    2704         176 :         return s;
    2705             : 
    2706           0 :   bailout:
    2707           0 :         if (be->mvc->sa->eb.enabled)
    2708           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2709             :         return NULL;
    2710             : }
    2711             : 
    2712             : stmt *
    2713           8 : stmt_for(backend *be, stmt *op1, stmt *min_val)
    2714             : {
    2715           8 :         MalBlkPtr mb = be->mb;
    2716           8 :         InstrPtr q = NULL;
    2717             : 
    2718           8 :         if (op1 == NULL || min_val == NULL || op1->nr < 0)
    2719             :                 return NULL;
    2720             : 
    2721           8 :         q = newStmt(mb, forRef, decompressRef);
    2722           8 :         if (q == NULL)
    2723           0 :                 goto bailout;
    2724           8 :         q = pushArgument(mb, q, op1->nr);
    2725           8 :         q = pushArgument(mb, q, min_val->nr);
    2726             : 
    2727           8 :         bool enabled = be->mvc->sa->eb.enabled;
    2728           8 :         be->mvc->sa->eb.enabled = false;
    2729           8 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2730           8 :         be->mvc->sa->eb.enabled = enabled;
    2731           8 :         if (s == NULL) {
    2732           0 :                 freeInstruction(q);
    2733           0 :                 return NULL;
    2734             :         }
    2735             : 
    2736           8 :         s->op1 = op1;
    2737           8 :         s->op2 = min_val;
    2738           8 :         s->flag = cmp_project;
    2739           8 :         s->key = 0;
    2740           8 :         s->nrcols = op1->nrcols;
    2741           8 :         s->nr = getDestVar(q);
    2742           8 :         s->q = q;
    2743           8 :         s->tname = op1->tname;
    2744           8 :         s->cname = op1->cname;
    2745           8 :         pushInstruction(mb, q);
    2746           8 :         return s;
    2747             : 
    2748           0 :   bailout:
    2749           0 :         if (be->mvc->sa->eb.enabled)
    2750           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2751             :         return NULL;
    2752             : }
    2753             : 
    2754             : stmt *
    2755          54 : stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int symmetric, int swapped)
    2756             : {
    2757          54 :         InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, swapped, st_join2, 1/*reduce semantics*/);
    2758          54 :         if (q == NULL)
    2759             :                 return NULL;
    2760             : 
    2761          54 :         stmt *s = stmt_create(be->mvc->sa, st_join2);
    2762          54 :         if (s == NULL) {
    2763             :                 return NULL;
    2764             :         }
    2765             : 
    2766          54 :         s->op1 = l;
    2767          54 :         s->op2 = ra;
    2768          54 :         s->op3 = rb;
    2769          54 :         s->flag = cmp;
    2770          54 :         s->nrcols = 2;
    2771          54 :         s->nr = getDestVar(q);
    2772          54 :         s->q = q;
    2773          54 :         s->reduce = 1;
    2774          54 :         return s;
    2775             : }
    2776             : 
    2777             : stmt *
    2778          49 : stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
    2779             : {
    2780          49 :         MalBlkPtr mb = be->mb;
    2781          49 :         InstrPtr q = NULL;
    2782          49 :         const char *mod, *fimp;
    2783          49 :         node *n;
    2784             : 
    2785          49 :         if (l == NULL || r == NULL)
    2786           0 :                 goto bailout;
    2787          49 :         if (backend_create_subfunc(be, op, NULL) < 0)
    2788           0 :                 goto bailout;
    2789          49 :         mod = sql_func_mod(op->func);
    2790          49 :         fimp = backend_function_imp(be, op->func);
    2791          49 :         fimp = sa_strconcat(be->mvc->sa, fimp, "join");
    2792             : 
    2793             :         /* filter qualifying tuples, return oids of h and tail */
    2794          49 :         q = newStmtArgs(mb, mod, fimp, list_length(l->op4.lval) + list_length(r->op4.lval) + 7);
    2795          49 :         if (q == NULL)
    2796           0 :                 goto bailout;
    2797          49 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2798          98 :         for (n = l->op4.lval->h; n; n = n->next) {
    2799          49 :                 stmt *op = n->data;
    2800             : 
    2801          49 :                 q = pushArgument(mb, q, op->nr);
    2802             :         }
    2803             : 
    2804         162 :         for (n = r->op4.lval->h; n; n = n->next) {
    2805         113 :                 stmt *op = n->data;
    2806             : 
    2807         113 :                 q = pushArgument(mb, q, op->nr);
    2808             :         }
    2809          49 :         q = pushNilBat(mb, q); /* candidate lists */
    2810          49 :         q = pushNilBat(mb, q); /* candidate lists */
    2811          49 :         q = pushBit(mb, q, TRUE);     /* nil_matches */
    2812          49 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2813          49 :         q = pushBit(mb, q, anti?TRUE:FALSE); /* 'not' matching */
    2814          49 :         pushInstruction(mb, q);
    2815             : 
    2816          49 :         if (swapped) {
    2817           7 :                 InstrPtr r = newInstruction(mb,  NULL, NULL);
    2818           7 :                 if (r == NULL)
    2819           0 :                         goto bailout;
    2820           7 :                 getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2821           7 :                 r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2822           7 :                 r = pushArgument(mb, r, getArg(q,1));
    2823           7 :                 r = pushArgument(mb, r, getArg(q,0));
    2824           7 :                 pushInstruction(mb, r);
    2825           7 :                 q = r;
    2826             :         }
    2827             : 
    2828          49 :         stmt *s = stmt_create(be->mvc->sa, st_joinN);
    2829          49 :         if (s == NULL) {
    2830           0 :                 goto bailout;
    2831             :         }
    2832             : 
    2833          49 :         s->op1 = l;
    2834          49 :         s->op2 = r;
    2835          49 :         s->op4.funcval = op;
    2836          49 :         s->nrcols = 2;
    2837          49 :         if (swapped)
    2838           7 :                 s->flag |= SWAPPED;
    2839          49 :         s->nr = getDestVar(q);
    2840          49 :         s->q = q;
    2841          49 :         return s;
    2842             : 
    2843           0 :   bailout:
    2844           0 :         if (be->mvc->sa->eb.enabled)
    2845           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2846             :         return NULL;
    2847             : }
    2848             : 
    2849             : stmt *
    2850       26837 : stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
    2851             : {
    2852       26837 :         InstrPtr q = NULL;
    2853             : 
    2854       26837 :         if (rs == NULL || rs->nr < 0)
    2855             :                 return NULL;
    2856       26837 :         q = rs->q;
    2857       26837 :         if (q) {
    2858       26621 :                 stmt *s = stmt_create(be->mvc->sa, st_rs_column);
    2859       26621 :                 if (s == NULL) {
    2860             :                         return NULL;
    2861             :                 }
    2862             : 
    2863       26621 :                 s->op1 = rs;
    2864       26621 :                 s->op4.typeval = *tpe;
    2865       26621 :                 s->flag = i;
    2866       26621 :                 s->nrcols = 1;
    2867       26621 :                 s->key = 0;
    2868       26621 :                 s->q = q;
    2869       26621 :                 s->nr = getArg(q, s->flag);
    2870       26621 :                 return s;
    2871         216 :         } else if (rs->type == st_list) {
    2872         216 :                 list *cols = rs->op4.lval;
    2873         216 :                 if (i < list_length(cols))
    2874         216 :                         return list_fetch(cols, i);
    2875             :         }
    2876             :         return NULL;
    2877             : }
    2878             : 
    2879             : /*
    2880             :  * The dump_header produces a sequence of instructions for
    2881             :  * the front-end to prepare presentation of a result table.
    2882             :  *
    2883             :  * A secondary scheme is added to assemble all information
    2884             :  * in columns first. Then it can be returned to the environment.
    2885             :  */
    2886             : #define NEWRESULTSET
    2887             : 
    2888             : #define meta(P, Id, Tpe, Args)                                          \
    2889             :         do {                                                                                    \
    2890             :                 P = newStmtArgs(mb, batRef, packRef, Args);     \
    2891             :                 if (P) {                                                                        \
    2892             :                         Id = getArg(P,0);                                               \
    2893             :                         setVarType(mb, Id, newBatType(Tpe));    \
    2894             :                         setVarFixed(mb, Id);                                    \
    2895             :                         list = pushArgument(mb, list, Id);              \
    2896             :                         pushInstruction(mb, P);                                 \
    2897             :                 }                                                                                       \
    2898             :         } while (0)
    2899             : 
    2900             : static int
    2901          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)
    2902             : {
    2903          32 :         node *n;
    2904          32 :         int ret = -1;
    2905          32 :         int args;
    2906             : 
    2907             :         // gather the meta information
    2908          32 :         int tblId, nmeId, tpeId, lenId, scaleId;
    2909          32 :         InstrPtr list;
    2910          32 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    2911             : 
    2912          32 :         args = list_length(l) + 1;
    2913             : 
    2914          32 :         list = newInstructionArgs(mb, sqlRef, export_tableRef, args + 13);
    2915          32 :         if (list == NULL)
    2916             :                 return -1;
    2917          32 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    2918          32 :         if( file >= 0){
    2919          32 :                 list = pushArgument(mb, list, file);
    2920          32 :                 list = pushStr(mb, list, format);
    2921          32 :                 list = pushStr(mb, list, sep);
    2922          32 :                 list = pushStr(mb, list, rsep);
    2923          32 :                 list = pushStr(mb, list, ssep);
    2924          32 :                 list = pushStr(mb, list, ns);
    2925          32 :                 list = pushInt(mb, list, onclient);
    2926             :         }
    2927          32 :         meta(tblPtr, tblId, TYPE_str, args);
    2928          32 :         meta(nmePtr, nmeId, TYPE_str, args);
    2929          32 :         meta(tpePtr, tpeId, TYPE_str, args);
    2930          32 :         meta(lenPtr, lenId, TYPE_int, args);
    2931          32 :         meta(scalePtr, scaleId, TYPE_int, args);
    2932          32 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    2933             :                 return -1;
    2934             : 
    2935         172 :         for (n = l->h; n; n = n->next) {
    2936         140 :                 stmt *c = n->data;
    2937         140 :                 sql_subtype *t = tail_type(c);
    2938         140 :                 const char *tname = table_name(sql->sa, c);
    2939         140 :                 const char *sname = schema_name(sql->sa, c);
    2940         140 :                 const char *_empty = "";
    2941         140 :                 const char *tn = (tname) ? tname : _empty;
    2942         140 :                 const char *sn = (sname) ? sname : _empty;
    2943         140 :                 const char *cn = column_name(sql->sa, c);
    2944         140 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    2945         140 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    2946         140 :                 size_t fqtnl;
    2947         140 :                 char *fqtn = NULL;
    2948             : 
    2949         140 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    2950         140 :                         fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    2951         140 :                         if (fqtn == NULL)
    2952             :                                 return -1;
    2953         140 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    2954         140 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    2955         140 :                         nmePtr = pushStr(mb, nmePtr, cn);
    2956         140 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    2957         140 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    2958         140 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    2959         140 :                         list = pushArgument(mb, list, c->nr);
    2960             :                 } else
    2961             :                         return -1;
    2962             :         }
    2963          32 :         sa_reset(sql->ta);
    2964          32 :         ret = getArg(list,0);
    2965          32 :         pushInstruction(mb,list);
    2966          32 :         return ret;
    2967             : }
    2968             : 
    2969             : 
    2970             : stmt *
    2971          32 : stmt_export(backend *be, stmt *t, const char *sep, const char *rsep, const char *ssep, const char *null_string, int onclient, stmt *file)
    2972             : {
    2973          32 :         MalBlkPtr mb = be->mb;
    2974          32 :         InstrPtr q = NULL;
    2975          32 :         int fnr;
    2976          32 :         list *l;
    2977             : 
    2978          32 :         if (t == NULL || t->nr < 0)
    2979           0 :                 goto bailout;
    2980          32 :         l = t->op4.lval;
    2981          32 :         if (file) {
    2982          23 :                 if (file->nr < 0)
    2983           0 :                         goto bailout;
    2984             :                 fnr = file->nr;
    2985             :         } else {
    2986           9 :                 q = newAssignment(mb);
    2987           9 :                 if (q == NULL)
    2988           0 :                         goto bailout;
    2989           9 :                 q = pushStr(mb,q,"stdout");
    2990           9 :                 fnr = getArg(q,0);
    2991           9 :                 pushInstruction(mb, q);
    2992             :         }
    2993          32 :         if (t->type == st_list) {
    2994          32 :                 if (dump_export_header(be->mvc, mb, l, fnr, "csv", sep, rsep, ssep, null_string, onclient) < 0)
    2995           0 :                         goto bailout;
    2996             :         } else {
    2997           0 :                 q = newStmt(mb, sqlRef, raiseRef);
    2998           0 :                 if (q == NULL)
    2999           0 :                         goto bailout;
    3000           0 :                 q = pushStr(mb, q, "not a valid output list\n");
    3001           0 :                 pushInstruction(mb, q);
    3002             :         }
    3003          32 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3004          32 :         if(!s) {
    3005           0 :                 goto bailout;
    3006             :         }
    3007          32 :         s->op1 = t;
    3008          32 :         s->op2 = file;
    3009          32 :         s->q = q;
    3010          32 :         s->nr = 1;
    3011          32 :         return s;
    3012             : 
    3013           0 :   bailout:
    3014           0 :         if (be->mvc->sa->eb.enabled)
    3015           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3016             :         return NULL;
    3017             : }
    3018             : 
    3019             : stmt *
    3020         150 : stmt_export_bin(backend *be, stmt *colstmt, bool byteswap, const char *filename, int on_client)
    3021             : {
    3022         150 :         MalBlkPtr mb = be->mb;
    3023         150 :         InstrPtr q;
    3024             : 
    3025         150 :         if (colstmt == NULL)
    3026           0 :                 goto bailout;
    3027         150 :         q = newStmt(mb, sqlRef, export_bin_columnRef);
    3028         150 :         if (q == NULL)
    3029           0 :                 goto bailout;
    3030         150 :         pushArgument(mb, q, colstmt->nr);
    3031         150 :         pushBit(mb, q, byteswap);
    3032         150 :         pushStr(mb, q, filename);
    3033         150 :         pushInt(mb, q, on_client);
    3034         150 :         pushInstruction(mb, q);
    3035             : 
    3036         150 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3037         150 :         if (!s)
    3038           0 :                 goto bailout;
    3039             : 
    3040         150 :         s->q = q;
    3041         150 :         return s;
    3042             : 
    3043           0 :   bailout:
    3044           0 :         if (be->mvc->sa->eb.enabled)
    3045           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3046             :         return NULL;
    3047             : }
    3048             : 
    3049             : stmt *
    3050        3157 : stmt_trans(backend *be, int type, stmt *chain, stmt *name)
    3051             : {
    3052        3157 :         MalBlkPtr mb = be->mb;
    3053        3157 :         InstrPtr q = NULL;
    3054             : 
    3055        3157 :         if (chain == NULL || chain->nr < 0)
    3056           0 :                 goto bailout;
    3057             : 
    3058        3157 :         switch(type){
    3059          13 :         case ddl_release:
    3060          13 :                 q = newStmt(mb, sqlRef, transaction_releaseRef);
    3061          13 :                 break;
    3062         556 :         case ddl_commit:
    3063         556 :                 q = newStmt(mb, sqlRef, transaction_commitRef);
    3064         556 :                 break;
    3065        1082 :         case ddl_rollback:
    3066        1082 :                 q = newStmt(mb, sqlRef, transaction_rollbackRef);
    3067        1082 :                 break;
    3068        1506 :         case ddl_trans:
    3069        1506 :                 q = newStmt(mb, sqlRef, transaction_beginRef);
    3070        1506 :                 break;
    3071           0 :         default:
    3072           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown transaction type\n");
    3073           0 :                 goto bailout;
    3074             :         }
    3075        3157 :         if (q == NULL)
    3076           0 :                 goto bailout;
    3077        3157 :         q = pushArgument(mb, q, chain->nr);
    3078        3157 :         if (name)
    3079          79 :                 q = pushArgument(mb, q, name->nr);
    3080             :         else
    3081        3078 :                 q = pushNil(mb, q, TYPE_str);
    3082             : 
    3083        3157 :         bool enabled = be->mvc->sa->eb.enabled;
    3084        3157 :         be->mvc->sa->eb.enabled = false;
    3085        3157 :         stmt *s = stmt_create(be->mvc->sa, st_trans);
    3086        3157 :         be->mvc->sa->eb.enabled = enabled;
    3087        3157 :         if(!s) {
    3088           0 :                 freeInstruction(q);
    3089           0 :                 goto bailout;
    3090             :         }
    3091        3157 :         s->op1 = chain;
    3092        3157 :         s->op2 = name;
    3093        3157 :         s->flag = type;
    3094        3157 :         s->q = q;
    3095        3157 :         s->nr = getDestVar(q);
    3096        3157 :         pushInstruction(mb, q);
    3097        3157 :         return s;
    3098             : 
    3099           0 :   bailout:
    3100           0 :         if (be->mvc->sa->eb.enabled)
    3101           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3102             :         return NULL;
    3103             : }
    3104             : 
    3105             : stmt *
    3106      283712 : stmt_catalog(backend *be, int type, stmt *args)
    3107             : {
    3108      283712 :         MalBlkPtr mb = be->mb;
    3109      283712 :         InstrPtr q = NULL;
    3110      283712 :         node *n;
    3111             : 
    3112      283712 :         if (args == NULL || args->nr < 0)
    3113           0 :                 goto bailout;
    3114             : 
    3115             :         /* cast them into properly named operations */
    3116      283712 :         const char *ref;
    3117      283712 :         switch(type){
    3118         313 :         case ddl_create_seq:                    ref = create_seqRef;            break;
    3119          47 :         case ddl_alter_seq:                             ref = alter_seqRef;                     break;
    3120          32 :         case ddl_drop_seq:                              ref = drop_seqRef;                      break;
    3121        1082 :         case ddl_create_schema:                 ref = create_schemaRef;         break;
    3122         191 :         case ddl_drop_schema:                   ref = drop_schemaRef;           break;
    3123       10087 :         case ddl_create_table:                  ref = create_tableRef;          break;
    3124       22358 :         case ddl_create_view:                   ref = create_viewRef;           break;
    3125        3673 :         case ddl_drop_table:                    ref = drop_tableRef;            break;
    3126         314 :         case ddl_drop_view:                             ref = drop_viewRef;                     break;
    3127         150 :         case ddl_drop_constraint:               ref = drop_constraintRef;       break;
    3128        1369 :         case ddl_alter_table:                   ref = alter_tableRef;           break;
    3129         906 :         case ddl_create_type:                   ref = create_typeRef;           break;
    3130           4 :         case ddl_drop_type:                             ref = drop_typeRef;                     break;
    3131          40 :         case ddl_grant_roles:                   ref = grant_rolesRef;           break;
    3132          10 :         case ddl_revoke_roles:                  ref = revoke_rolesRef;          break;
    3133       18455 :         case ddl_grant:                                 ref = grantRef;                         break;
    3134          15 :         case ddl_revoke:                                ref = revokeRef;                        break;
    3135       99018 :         case ddl_grant_func:                    ref = grant_functionRef;        break;
    3136           1 :         case ddl_revoke_func:                   ref = revoke_functionRef;       break;
    3137         358 :         case ddl_create_user:                   ref = create_userRef;           break;
    3138         107 :         case ddl_drop_user:                             ref = drop_userRef;                     break;
    3139          83 :         case ddl_alter_user:                    ref = alter_userRef;            break;
    3140           5 :         case ddl_rename_user:                   ref = rename_userRef;           break;
    3141          26 :         case ddl_create_role:                   ref = create_roleRef;           break;
    3142          19 :         case ddl_drop_role:                             ref = drop_roleRef;                     break;
    3143         160 :         case ddl_drop_index:                    ref = drop_indexRef;            break;
    3144         668 :         case ddl_drop_function:                 ref = drop_functionRef;         break;
    3145      120295 :         case ddl_create_function:               ref = create_functionRef;       break;
    3146         345 :         case ddl_create_trigger:                ref = create_triggerRef;        break;
    3147          84 :         case ddl_drop_trigger:                  ref = drop_triggerRef;          break;
    3148         312 :         case ddl_alter_table_add_table: ref = alter_add_tableRef;       break;
    3149         180 :         case ddl_alter_table_del_table: ref = alter_del_tableRef;       break;
    3150        2310 :         case ddl_alter_table_set_access:ref = alter_set_tableRef;       break;
    3151         215 :         case ddl_alter_table_add_range_partition: ref = alter_add_range_partitionRef; break;
    3152          60 :         case ddl_alter_table_add_list_partition: ref = alter_add_value_partitionRef; break;
    3153         354 :         case ddl_comment_on:                    ref = comment_onRef;            break;
    3154           8 :         case ddl_rename_schema:                 ref = rename_schemaRef;         break;
    3155          45 :         case ddl_rename_table:                  ref = rename_tableRef;          break;
    3156          13 :         case ddl_rename_column:                 ref = rename_columnRef;         break;
    3157           0 :         default:
    3158           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown catalog operation\n");
    3159           0 :                 goto bailout;
    3160             :         }
    3161      283712 :         q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
    3162      283712 :         if (q == NULL)
    3163           0 :                 goto bailout;
    3164             :         // pass all arguments as before
    3165     1696640 :         for (n = args->op4.lval->h; n; n = n->next) {
    3166     1412928 :                 stmt *c = n->data;
    3167             : 
    3168     1412928 :                 q = pushArgument(mb, q, c->nr);
    3169             :         }
    3170             : 
    3171      283712 :         bool enabled = be->mvc->sa->eb.enabled;
    3172      283712 :         be->mvc->sa->eb.enabled = false;
    3173      283712 :         stmt *s = stmt_create(be->mvc->sa, st_catalog);
    3174      283712 :         be->mvc->sa->eb.enabled = enabled;
    3175      283712 :         if(!s) {
    3176           0 :                 freeInstruction(q);
    3177           0 :                 goto bailout;
    3178             :         }
    3179      283712 :         s->op1 = args;
    3180      283712 :         s->flag = type;
    3181      283712 :         s->q = q;
    3182      283712 :         s->nr = getDestVar(q);
    3183      283712 :         pushInstruction(mb, q);
    3184      283712 :         return s;
    3185             : 
    3186           0 :   bailout:
    3187           0 :         if (be->mvc->sa->eb.enabled)
    3188           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3189             :         return NULL;
    3190             : }
    3191             : 
    3192             : void
    3193     1823624 : stmt_set_nrcols(stmt *s)
    3194             : {
    3195     1823624 :         unsigned nrcols = 0;
    3196     1823624 :         int key = 1;
    3197     1823624 :         node *n;
    3198     1823624 :         list *l = s->op4.lval;
    3199             : 
    3200     1823624 :         assert(s->type == st_list);
    3201     8876689 :         for (n = l->h; n; n = n->next) {
    3202     7053065 :                 stmt *f = n->data;
    3203             : 
    3204     7053065 :                 if (!f)
    3205           0 :                         continue;
    3206     7053065 :                 if (f->nrcols > nrcols)
    3207             :                         nrcols = f->nrcols;
    3208     7053065 :                 key &= f->key;
    3209     7053065 :                 s->nr = f->nr;
    3210             :         }
    3211     1823624 :         s->nrcols = nrcols;
    3212     1823624 :         s->key = key;
    3213     1823624 : }
    3214             : 
    3215             : stmt *
    3216     1427596 : stmt_list(backend *be, list *l)
    3217             : {
    3218     1427596 :         if (l == NULL)
    3219             :                 return NULL;
    3220     1427596 :         stmt *s = stmt_create(be->mvc->sa, st_list);
    3221     1427581 :         if(!s) {
    3222             :                 return NULL;
    3223             :         }
    3224     1427581 :         s->op4.lval = l;
    3225     1427581 :         stmt_set_nrcols(s);
    3226     1427581 :         return s;
    3227             : }
    3228             : 
    3229             : static InstrPtr
    3230       64237 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
    3231             : {
    3232       64237 :         node *n;
    3233             :         // gather the meta information
    3234       64237 :         int tblId, nmeId, tpeId, lenId, scaleId;
    3235       64237 :         int args;
    3236       64237 :         InstrPtr list;
    3237       64237 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    3238             : 
    3239       64237 :         args = list_length(l) + 1;
    3240             : 
    3241       64236 :         list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 5);
    3242       64237 :         if(!list) {
    3243             :                 return NULL;
    3244             :         }
    3245       64237 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3246       64237 :         meta(tblPtr, tblId, TYPE_str, args);
    3247       64237 :         meta(nmePtr, nmeId, TYPE_str, args);
    3248       64237 :         meta(tpePtr, tpeId, TYPE_str, args);
    3249       64237 :         meta(lenPtr, lenId, TYPE_int, args);
    3250       64237 :         meta(scalePtr, scaleId, TYPE_int, args);
    3251       64237 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    3252             :                 return NULL;
    3253             : 
    3254      337990 :         for (n = l->h; n; n = n->next) {
    3255      273753 :                 stmt *c = n->data;
    3256      273753 :                 sql_subtype *t = tail_type(c);
    3257      273756 :                 const char *tname = table_name(sql->sa, c);
    3258      273756 :                 const char *sname = schema_name(sql->sa, c);
    3259      273756 :                 const char *_empty = "";
    3260      273756 :                 const char *tn = (tname) ? tname : _empty;
    3261      273756 :                 const char *sn = (sname) ? sname : _empty;
    3262      273756 :                 const char *cn = column_name(sql->sa, c);
    3263      273755 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3264      273754 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3265      273765 :                 size_t fqtnl;
    3266             : 
    3267      273765 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3268      273765 :                         char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3269      273764 :                         if (fqtn == NULL)
    3270             :                                 return NULL;
    3271      273764 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3272      273764 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3273      273764 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3274      273759 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3275      273762 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3276      273761 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3277      273755 :                         list = pushArgument(mb,list,c->nr);
    3278             :                 } else
    3279             :                         return NULL;
    3280             :         }
    3281       64237 :         sa_reset(sql->ta);
    3282       64237 :         pushInstruction(mb,list);
    3283       64237 :         return list;
    3284             : }
    3285             : 
    3286             : int
    3287      124691 : stmt_output(backend *be, stmt *lst)
    3288             : {
    3289      124691 :         MalBlkPtr mb = be->mb;
    3290      124691 :         InstrPtr q = NULL;
    3291      124691 :         list *l = lst->op4.lval;
    3292      124691 :         int cnt = list_length(l), ok = 0;
    3293      124688 :         node *n = l->h;
    3294      124688 :         stmt *first = n->data;
    3295             : 
    3296             :         /* single value result, has a fast exit */
    3297      124688 :         if (cnt == 1 && first->nrcols <= 0 ){
    3298       60452 :                 stmt *c = n->data;
    3299       60452 :                 sql_subtype *t = tail_type(c);
    3300       60451 :                 const char *tname = table_name(be->mvc->sa, c);
    3301       60450 :                 const char *sname = schema_name(be->mvc->sa, c);
    3302       60443 :                 const char *_empty = "";
    3303       60443 :                 const char *tn = (tname) ? tname : _empty;
    3304       60443 :                 const char *sn = (sname) ? sname : _empty;
    3305       60443 :                 const char *cn = column_name(be->mvc->sa, c);
    3306       60449 :                 const char *ntn = sql_escape_ident(be->mvc->ta, tn);
    3307       60432 :                 const char *nsn = sql_escape_ident(be->mvc->ta, sn);
    3308             : 
    3309       60450 :                 if (ntn && nsn) {
    3310       60450 :                         size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
    3311       60450 :                         char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
    3312       60449 :                         if (fqtn == NULL)
    3313             :                                 return -1;
    3314       60449 :                         ok = 1;
    3315       60449 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3316             : 
    3317       60449 :                         q = newStmt(mb, sqlRef, resultSetRef);
    3318       60454 :                         if (q == NULL)
    3319             :                                 return -1;
    3320       60454 :                         getArg(q,0) = newTmpVariable(mb,TYPE_int);
    3321       60454 :                         q = pushStr(mb, q, fqtn);
    3322       60453 :                         q = pushStr(mb, q, cn);
    3323       60455 :                         q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
    3324       60455 :                         q = pushInt(mb, q, t->digits);
    3325       60452 :                         q = pushInt(mb, q, t->scale);
    3326       60452 :                         q = pushInt(mb, q, t->type->eclass);
    3327       60455 :                         q = pushArgument(mb, q, c->nr);
    3328       60455 :                         pushInstruction(mb, q);
    3329             :                 }
    3330       60455 :                 sa_reset(be->mvc->ta);
    3331       60455 :                 if (!ok)
    3332             :                         return -1;
    3333             :         } else {
    3334       64236 :                 if ((q = dump_header(be->mvc, mb, l)) == NULL)
    3335             :                         return -1;
    3336             :         }
    3337             :         return 0;
    3338             : }
    3339             : 
    3340             : int
    3341      138756 : stmt_affected_rows(backend *be, int lastnr)
    3342             : {
    3343      138756 :         MalBlkPtr mb = be->mb;
    3344      138756 :         InstrPtr q = NULL;
    3345             : 
    3346      138756 :         q = newStmt(mb, sqlRef, affectedRowsRef);
    3347      138753 :         if (q == NULL)
    3348             :                 return -1;
    3349      138753 :         q = pushArgument(mb, q, be->mvc_var);
    3350      138756 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    3351      138756 :         q = pushArgument(mb, q, lastnr);
    3352      138756 :         pushInstruction(mb, q);
    3353      138756 :         be->mvc_var = getDestVar(q);
    3354      138756 :         return 0;
    3355             : }
    3356             : 
    3357             : stmt *
    3358      176779 : stmt_append(backend *be, stmt *c, stmt *a)
    3359             : {
    3360      176779 :         MalBlkPtr mb = be->mb;
    3361      176779 :         InstrPtr q = NULL;
    3362             : 
    3363      176779 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3364           0 :                 goto bailout;
    3365      176779 :         q = newStmt(mb, batRef, appendRef);
    3366      176779 :         if (q == NULL)
    3367           0 :                 goto bailout;
    3368      176779 :         q = pushArgument(mb, q, c->nr);
    3369      176779 :         q = pushArgument(mb, q, a->nr);
    3370      176779 :         q = pushBit(mb, q, TRUE);
    3371      176779 :         bool enabled = be->mvc->sa->eb.enabled;
    3372      176779 :         be->mvc->sa->eb.enabled = false;
    3373      176779 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3374      176779 :         be->mvc->sa->eb.enabled = enabled;
    3375      176779 :         if(!s) {
    3376           0 :                 freeInstruction(q);
    3377           0 :                 goto bailout;
    3378             :         }
    3379      176779 :         s->op1 = c;
    3380      176779 :         s->op2 = a;
    3381      176779 :         s->nrcols = c->nrcols;
    3382      176779 :         s->key = c->key;
    3383      176779 :         s->nr = getDestVar(q);
    3384      176779 :         s->q = q;
    3385      176779 :         pushInstruction(mb, q);
    3386      176779 :         return s;
    3387             : 
    3388           0 :   bailout:
    3389           0 :         if (be->mvc->sa->eb.enabled)
    3390           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3391             :         return NULL;
    3392             : }
    3393             : 
    3394             : stmt *
    3395      137691 : stmt_append_bulk(backend *be, stmt *c, list *l)
    3396             : {
    3397      137691 :         MalBlkPtr mb = be->mb;
    3398      137691 :         InstrPtr q = NULL;
    3399      137691 :         bool needs_columns = false;
    3400             : 
    3401      137691 :         if (c->nr < 0)
    3402           0 :                 goto bailout;
    3403             : 
    3404             :         /* currently appendBulk accepts its inputs all either scalar or vectors
    3405             :            if there is one vector and any scala, then the scalars mut be upgraded to vectors */
    3406      888088 :         for (node *n = l->h; n; n = n->next) {
    3407      750397 :                 stmt *t = n->data;
    3408      750397 :                 needs_columns |= t->nrcols > 0;
    3409             :         }
    3410      137691 :         if (needs_columns) {
    3411           0 :                 for (node *n = l->h; n; n = n->next) {
    3412           0 :                         stmt *t = n->data;
    3413           0 :                         if (t->nrcols == 0)
    3414           0 :                                 n->data = const_column(be, t);
    3415             :                 }
    3416             :         }
    3417             : 
    3418      137691 :         q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3);
    3419      137686 :         if (q == NULL)
    3420           0 :                 goto bailout;
    3421      137686 :         q = pushArgument(mb, q, c->nr);
    3422      137689 :         q = pushBit(mb, q, TRUE);
    3423      887977 :         for (node *n = l->h ; n ; n = n->next) {
    3424      750308 :                 stmt *a = n->data;
    3425      750308 :                 q = pushArgument(mb, q, a->nr);
    3426             :         }
    3427      137669 :         bool enabled = be->mvc->sa->eb.enabled;
    3428      137669 :         be->mvc->sa->eb.enabled = false;
    3429      137669 :         stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
    3430      137669 :         be->mvc->sa->eb.enabled = enabled;
    3431      137669 :         if(!s) {
    3432           0 :                 freeInstruction(q);
    3433           0 :                 goto bailout;
    3434             :         }
    3435      137669 :         s->op1 = c;
    3436      137669 :         s->op4.lval = l;
    3437      137669 :         s->nrcols = c->nrcols;
    3438      137669 :         s->key = c->key;
    3439      137669 :         s->nr = getDestVar(q);
    3440      137669 :         s->q = q;
    3441      137669 :         pushInstruction(mb, q);
    3442      137669 :         return s;
    3443             : 
    3444           0 :   bailout:
    3445           0 :         if (be->mvc->sa->eb.enabled)
    3446           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3447             :         return NULL;
    3448             : }
    3449             : 
    3450             : stmt *
    3451       16046 : stmt_pack(backend *be, stmt *c, int n)
    3452             : {
    3453       16046 :         MalBlkPtr mb = be->mb;
    3454       16046 :         InstrPtr q = NULL;
    3455             : 
    3456       16046 :         if (c == NULL || c->nr < 0)
    3457           0 :                 goto bailout;
    3458       16046 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3459       16046 :         if (q == NULL)
    3460           0 :                 goto bailout;
    3461       16046 :         q = pushArgument(mb, q, c->nr);
    3462       16046 :         q = pushInt(mb, q, n);
    3463       16046 :         bool enabled = be->mvc->sa->eb.enabled;
    3464       16046 :         be->mvc->sa->eb.enabled = false;
    3465       16046 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3466       16046 :         be->mvc->sa->eb.enabled = enabled;
    3467       16046 :         if(!s) {
    3468           0 :                 freeInstruction(q);
    3469           0 :                 goto bailout;
    3470             :         }
    3471       16046 :         s->op1 = c;
    3472       16046 :         s->nrcols = c->nrcols;
    3473       16046 :         s->key = c->key;
    3474       16046 :         s->nr = getDestVar(q);
    3475       16046 :         s->q = q;
    3476       16046 :         pushInstruction(mb, q);
    3477       16046 :         return s;
    3478             : 
    3479           0 :   bailout:
    3480           0 :         if (be->mvc->sa->eb.enabled)
    3481           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3482             :         return NULL;
    3483             : 
    3484             : }
    3485             : 
    3486             : stmt *
    3487       29766 : stmt_pack_add(backend *be, stmt *c, stmt *a)
    3488             : {
    3489       29766 :         MalBlkPtr mb = be->mb;
    3490       29766 :         InstrPtr q = NULL;
    3491             : 
    3492       29766 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3493           0 :                 goto bailout;
    3494       29766 :         q = newStmtArgs(mb, matRef, packIncrementRef, 3);
    3495       29766 :         if (q == NULL)
    3496           0 :                 goto bailout;
    3497       29766 :         q = pushArgument(mb, q, c->nr);
    3498       29766 :         q = pushArgument(mb, q, a->nr);
    3499       29766 :         bool enabled = be->mvc->sa->eb.enabled;
    3500       29766 :         be->mvc->sa->eb.enabled = false;
    3501       29766 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3502       29766 :         be->mvc->sa->eb.enabled = enabled;
    3503       29766 :         if(!s) {
    3504           0 :                 freeInstruction(q);
    3505           0 :                 goto bailout;
    3506             :         }
    3507       29766 :         s->op1 = c;
    3508       29766 :         s->op2 = a;
    3509       29766 :         s->nrcols = c->nrcols;
    3510       29766 :         s->key = c->key;
    3511       29766 :         s->nr = getDestVar(q);
    3512       29766 :         s->q = q;
    3513       29766 :         pushInstruction(mb, q);
    3514       29766 :         return s;
    3515             : 
    3516           0 :   bailout:
    3517           0 :         if (be->mvc->sa->eb.enabled)
    3518           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3519             :         return NULL;
    3520             : }
    3521             : 
    3522             : stmt *
    3523       95749 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
    3524             : {
    3525       95749 :         MalBlkPtr mb = be->mb;
    3526       95749 :         InstrPtr q = NULL;
    3527             : 
    3528       95749 :         if (!t || cnt->nr < 0)
    3529           0 :                 goto bailout;
    3530       95749 :         assert(t->s);                                /* declared table */
    3531       95749 :         q = newStmtArgs(mb, sqlRef, claimRef, 6);
    3532       95749 :         if (q == NULL)
    3533           0 :                 goto bailout;
    3534             :         /* returns offset or offsets */
    3535       95749 :         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
    3536       95749 :         q = pushArgument(mb, q, be->mvc_var);
    3537       95748 :         q = pushSchema(mb, q, t);
    3538       95749 :         q = pushStr(mb, q, t->base.name);
    3539       95749 :         q = pushArgument(mb, q, cnt->nr);
    3540       95749 :         bool enabled = be->mvc->sa->eb.enabled;
    3541       95749 :         be->mvc->sa->eb.enabled = false;
    3542       95749 :         stmt *s = stmt_create(be->mvc->sa, st_claim);
    3543       95747 :         be->mvc->sa->eb.enabled = enabled;
    3544       95747 :         if(!s) {
    3545           0 :                 freeInstruction(q);
    3546           0 :                 goto bailout;
    3547             :         }
    3548       95747 :         s->op1 = cnt;
    3549       95747 :         s->op4.tval = t;
    3550       95747 :         s->nr = getDestVar(q);
    3551       95747 :         s->q = q;
    3552       95747 :         pushInstruction(mb, q);
    3553       95747 :         return s;
    3554             : 
    3555           0 :   bailout:
    3556           0 :         if (be->mvc->sa->eb.enabled)
    3557           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3558             :         return NULL;
    3559             : }
    3560             : 
    3561             : void
    3562      138988 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
    3563             : {
    3564      138988 :         MalBlkPtr mb = be->mb;
    3565      138988 :         InstrPtr q = NULL;
    3566             : 
    3567      138988 :         if (!t || cnt->nr < 0)
    3568           0 :                 goto bailout;
    3569      138988 :         q = newStmtArgs(mb, sqlRef, dependRef, 4);
    3570      138989 :         if (q == NULL)
    3571           0 :                 goto bailout;
    3572      138989 :         q = pushSchema(mb, q, t);
    3573      138987 :         q = pushStr(mb, q, t->base.name);
    3574      138987 :         q = pushArgument(mb, q, cnt->nr);
    3575      138987 :         pushInstruction(mb, q);
    3576      138987 :         return;
    3577             : 
    3578           0 :   bailout:
    3579           0 :         if (be->mvc->sa->eb.enabled)
    3580           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);
    3581             : }
    3582             : 
    3583             : void
    3584       14878 : stmt_add_column_predicate(backend *be, sql_column *c)
    3585             : {
    3586       14878 :         MalBlkPtr mb = be->mb;
    3587       14878 :         InstrPtr q = NULL;
    3588             : 
    3589       14878 :         if (!c)
    3590           0 :                 goto bailout;
    3591       14878 :         q = newStmtArgs(mb, sqlRef, predicateRef, 4);
    3592       14878 :         if (q == NULL)
    3593           0 :                 goto bailout;
    3594       14878 :         q = pushSchema(mb, q, c->t);
    3595       14878 :         q = pushStr(mb, q, c->t->base.name);
    3596       14878 :         q = pushStr(mb, q, c->base.name);
    3597       14878 :         pushInstruction(mb, q);
    3598       14878 :         return;
    3599             : 
    3600           0 :   bailout:
    3601           0 :         if (be->mvc->sa->eb.enabled)
    3602           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);
    3603             : }
    3604             : 
    3605             : stmt *
    3606       55248 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
    3607             : {
    3608       55248 :         MalBlkPtr mb = be->mb;
    3609       55248 :         InstrPtr q = NULL;
    3610             : 
    3611       55248 :         if (r->nr < 0)
    3612           0 :                 goto bailout;
    3613             : 
    3614       55248 :         q = newStmt(mb, batRef, replaceRef);
    3615       55248 :         if (q == NULL)
    3616           0 :                 goto bailout;
    3617       55248 :         q = pushArgument(mb, q, r->nr);
    3618       55248 :         q = pushArgument(mb, q, id->nr);
    3619       55248 :         q = pushArgument(mb, q, val->nr);
    3620       55248 :         q = pushBit(mb, q, TRUE); /* forced */
    3621       55248 :         bool enabled = be->mvc->sa->eb.enabled;
    3622       55248 :         be->mvc->sa->eb.enabled = false;
    3623       55248 :         stmt *s = stmt_create(be->mvc->sa, st_replace);
    3624       55248 :         be->mvc->sa->eb.enabled = enabled;
    3625       55248 :         if(!s) {
    3626           0 :                 freeInstruction(q);
    3627           0 :                 goto bailout;
    3628             :         }
    3629       55248 :         s->op1 = r;
    3630       55248 :         s->op2 = id;
    3631       55248 :         s->op3 = val;
    3632       55248 :         s->nrcols = r->nrcols;
    3633       55248 :         s->key = r->key;
    3634       55248 :         s->nr = getDestVar(q);
    3635       55248 :         s->q = q;
    3636       55248 :         s->cand = r->cand;
    3637       55248 :         pushInstruction(mb, q);
    3638       55248 :         return s;
    3639             : 
    3640           0 :   bailout:
    3641           0 :         if (be->mvc->sa->eb.enabled)
    3642           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3643             :         return NULL;
    3644             : }
    3645             : 
    3646             : stmt *
    3647       41827 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
    3648             : {
    3649       41827 :         MalBlkPtr mb = be->mb;
    3650       41827 :         InstrPtr q = NULL;
    3651             : 
    3652       41827 :         if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
    3653           2 :                 int *l = ATOMIC_PTR_GET(&t->data), cnt = ol_length(t->columns)+1;
    3654             : 
    3655           6 :                 for (int i = 0; i < cnt; i++) {
    3656           4 :                         q = newStmt(mb, batRef, deleteRef);
    3657           4 :                         if (q == NULL)
    3658           0 :                                 goto bailout;
    3659           4 :                         q = pushArgument(mb, q, l[i]);
    3660           4 :                         pushInstruction(mb, q);
    3661             :                 }
    3662             :                 /* declared tables don't have sequences */
    3663             :         } else {
    3664       41825 :                 q = newStmt(mb, sqlRef, clear_tableRef);
    3665       41825 :                 if (q == NULL)
    3666           0 :                         goto bailout;
    3667       41825 :                 q = pushSchema(mb, q, t);
    3668       41825 :                 q = pushStr(mb, q, t->base.name);
    3669       41824 :                 q = pushInt(mb, q, restart_sequences);
    3670       41823 :                 pushInstruction(mb, q);
    3671             :         }
    3672       41825 :         stmt *s = stmt_create(be->mvc->sa, st_table_clear);
    3673             : 
    3674       41824 :         if(!s) {
    3675           0 :                 goto bailout;
    3676             :         }
    3677       41824 :         s->op4.tval = t;
    3678       41824 :         s->nrcols = 0;
    3679       41824 :         s->nr = getDestVar(q);
    3680       41824 :         s->q = q;
    3681       41824 :         return s;
    3682             : 
    3683           0 :   bailout:
    3684           0 :         if (be->mvc->sa->eb.enabled)
    3685           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3686             :         return NULL;
    3687             : }
    3688             : 
    3689             : stmt *
    3690       39493 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
    3691             : {
    3692       39493 :         MalBlkPtr mb = be->mb;
    3693       39493 :         InstrPtr q = NULL;
    3694             : 
    3695       39493 :         if (cond->nr < 0)
    3696             :                 return NULL;
    3697             : 
    3698             :         /* if(bit(l)) { error(r);}  ==raising an exception */
    3699       39493 :         q = newStmt(mb, sqlRef, assertRef);
    3700       39493 :         if (q == NULL)
    3701           0 :                 goto bailout;
    3702       39493 :         q = pushArgument(mb, q, cond->nr);
    3703       39493 :         q = pushStr(mb, q, errstr);
    3704       39493 :         bool enabled = be->mvc->sa->eb.enabled;
    3705       39493 :         be->mvc->sa->eb.enabled = false;
    3706       39493 :         stmt *s = stmt_create(be->mvc->sa, st_exception);
    3707       39493 :         be->mvc->sa->eb.enabled = enabled;
    3708       39493 :         if(!s) {
    3709           0 :                 freeInstruction(q);
    3710           0 :                 return NULL;
    3711             :         }
    3712       39493 :         assert(cond);
    3713       39493 :         s->op1 = cond;
    3714       39493 :         (void)errcode;
    3715       39493 :         s->nrcols = 0;
    3716       39493 :         s->q = q;
    3717       39493 :         s->nr = getDestVar(q);
    3718       39493 :         pushInstruction(mb, q);
    3719       39493 :         return s;
    3720             : 
    3721           0 :   bailout:
    3722           0 :         if (be->mvc->sa->eb.enabled)
    3723           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3724             :         return NULL;
    3725             : }
    3726             : 
    3727             : /* The type setting is not propagated to statements such as st_bat and st_append,
    3728             :         because they are not considered projections */
    3729             : static void
    3730       14761 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
    3731             : {
    3732       39815 :         for (;;) {
    3733       39815 :                 switch (st->type) {
    3734        3688 :                 case st_const:
    3735        3688 :                         st = st->op2;
    3736        3688 :                         continue;
    3737       17996 :                 case st_alias:
    3738             :                 case st_gen_group:
    3739             :                 case st_order:
    3740       17996 :                         st = st->op1;
    3741       17996 :                         continue;
    3742           0 :                 case st_list:
    3743           0 :                         st = st->op4.lval->h->data;
    3744           0 :                         continue;
    3745        3370 :                 case st_join:
    3746             :                 case st_join2:
    3747             :                 case st_joinN:
    3748        3370 :                         if (st->flag == cmp_project) {
    3749        3370 :                                 st = st->op2;
    3750        3370 :                                 continue;
    3751             :                         }
    3752             :                         return;
    3753        2783 :                 case st_aggr:
    3754             :                 case st_Nop: {
    3755        2783 :                         list *res = st->op4.funcval->res;
    3756             : 
    3757        2783 :                         if (res && list_length(res) == 1)
    3758        2783 :                                 res->h->data = t;
    3759             :                         return;
    3760             :                 }
    3761        6690 :                 case st_atom:
    3762        6690 :                         st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
    3763        6690 :                         return;
    3764          60 :                 case st_convert:
    3765             :                 case st_temp:
    3766             :                 case st_single:
    3767          60 :                         st->op4.typeval = *t;
    3768          60 :                         return;
    3769          86 :                 case st_var:
    3770          86 :                         if (st->op4.typeval.type)
    3771          86 :                                 st->op4.typeval = *t;
    3772             :                         return;
    3773             :                 default:
    3774             :                         return;
    3775             :                 }
    3776             :         }
    3777             : }
    3778             : 
    3779             : #define trivial_string_conversion(x) ((x) == EC_BIT || (x) == EC_CHAR || (x) == EC_STRING || (x) == EC_NUM || (x) == EC_POS || (x) == EC_FLT \
    3780             :                                                                           || (x) == EC_DATE || (x) == EC_BLOB || (x) == EC_MONTH)
    3781             : 
    3782             : static stmt *
    3783         351 : temporal_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t, bool before)
    3784             : {
    3785         351 :         MalBlkPtr mb = be->mb;
    3786         351 :         InstrPtr q = NULL;
    3787         351 :         const char *convert = t->type->impl, *mod = mtimeRef;
    3788         351 :         bool add_tz = false, pushed = (v->cand && v->cand == sel), cand = 0;
    3789             : 
    3790         351 :         if (before) {
    3791         290 :                 if (f->type->eclass == EC_TIMESTAMP_TZ && (t->type->eclass == EC_TIMESTAMP || t->type->eclass == EC_TIME)) {
    3792             :                         /* call timestamp+local_timezone */
    3793             :                         convert = "timestamp_add_msec_interval";
    3794             :                         add_tz = true;
    3795         211 :                 } else if (f->type->eclass == EC_TIMESTAMP_TZ && t->type->eclass == EC_DATE) {
    3796             :                         /* call convert timestamp with tz to date */
    3797          13 :                         convert = "datetz";
    3798          13 :                         mod = calcRef;
    3799          13 :                         add_tz = true;
    3800         198 :                 } else if (f->type->eclass == EC_TIMESTAMP && t->type->eclass == EC_TIMESTAMP_TZ) {
    3801             :                         /* call timestamp+local_timezone */
    3802             :                         convert = "timestamp_sub_msec_interval";
    3803             :                         add_tz = true;
    3804         159 :                 } else if (f->type->eclass == EC_TIME_TZ && (t->type->eclass == EC_TIME || t->type->eclass == EC_TIMESTAMP)) {
    3805             :                         /* call times+local_timezone */
    3806             :                         convert = "time_add_msec_interval";
    3807             :                         add_tz = true;
    3808         146 :                 } else if (f->type->eclass == EC_TIME && t->type->eclass == EC_TIME_TZ) {
    3809             :                         /* call times+local_timezone */
    3810             :                         convert = "time_sub_msec_interval";
    3811             :                         add_tz = true;
    3812         131 :                 } else if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass)) {
    3813         124 :                         if (t->type->eclass == EC_TIME_TZ)
    3814             :                                 convert = "daytimetz";
    3815             :                         else
    3816         100 :                                 convert = "timestamptz";
    3817         124 :                         mod = calcRef;
    3818         124 :                         add_tz = true;
    3819         124 :                         cand = 1;
    3820             :                 } else {
    3821             :                         return v;
    3822             :                 }
    3823             :         } else {
    3824          61 :                 if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIMESTAMP_TZ) {
    3825             :                         convert = "timestamp_sub_msec_interval";
    3826             :                         add_tz = true;
    3827          56 :                 } else if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIME_TZ) {
    3828             :                         convert = "time_sub_msec_interval";
    3829             :                         add_tz = true;
    3830             :                 } else {
    3831             :                         return v;
    3832             :                 }
    3833             :         }
    3834             : 
    3835         288 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3836         171 :                 q = newStmtArgs(mb, mod, convert, 13);
    3837         171 :                 if (q == NULL)
    3838           0 :                         goto bailout;
    3839             :         } else {
    3840         117 :                 if (sel && !pushed && v->nrcols == 0) {
    3841           1 :                         pushed = 1;
    3842           1 :                         v = stmt_project(be, sel, v);
    3843           1 :                         v->cand = sel;
    3844             :                 }
    3845         117 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3846         117 :                 if (q == NULL)
    3847           0 :                         goto bailout;
    3848             :         }
    3849         288 :         q = pushArgument(mb, q, v->nr);
    3850             : 
    3851         288 :         if (cand) {
    3852         124 :                 if (sel && !pushed && !v->cand) {
    3853          14 :                         q = pushArgument(mb, q, sel->nr);
    3854          14 :                         pushed = 1;
    3855         110 :                 } else if (v->nrcols > 0) {
    3856          18 :                         q = pushNilBat(mb, q);
    3857             :                 }
    3858             :         }
    3859             : 
    3860         288 :         if (EC_VARCHAR(f->type->eclass))
    3861         124 :                 q = pushInt(mb, q, t->digits);
    3862             : 
    3863         288 :         if (add_tz)
    3864         288 :                         q = pushLng(mb, q, be->mvc->timezone);
    3865             : 
    3866         288 :         if (!cand) {
    3867         164 :                 if (sel && !pushed && !v->cand) {
    3868           2 :                         q = pushArgument(mb, q, sel->nr);
    3869           2 :                         pushed = 1;
    3870         162 :                 } else if (v->nrcols > 0) {
    3871          83 :                         q = pushNilBat(mb, q);
    3872             :                 }
    3873             :         }
    3874             : 
    3875         288 :         bool enabled = be->mvc->sa->eb.enabled;
    3876         288 :         be->mvc->sa->eb.enabled = false;
    3877         288 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    3878         288 :         be->mvc->sa->eb.enabled = enabled;
    3879         288 :         if(!s) {
    3880           0 :                 freeInstruction(q);
    3881           0 :                 goto bailout;
    3882             :         }
    3883         288 :         s->op1 = v;
    3884         288 :         s->nrcols = 0;       /* function without arguments returns single value */
    3885         288 :         s->key = v->key;
    3886         288 :         s->nrcols = v->nrcols;
    3887         288 :         s->aggr = v->aggr;
    3888         288 :         s->op4.typeval = *t;
    3889         288 :         s->nr = getDestVar(q);
    3890         288 :         s->q = q;
    3891         288 :         s->cand = pushed ? sel : NULL;
    3892         288 :         pushInstruction(mb, q);
    3893         288 :         return s;
    3894             : 
    3895           0 :   bailout:
    3896           0 :         if (be->mvc->sa->eb.enabled)
    3897           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3898             :         return NULL;
    3899             : }
    3900             : 
    3901             : stmt *
    3902       51285 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    3903             : {
    3904       51285 :         MalBlkPtr mb = be->mb;
    3905       51285 :         InstrPtr q = NULL;
    3906       51285 :         const char *convert = t->type->impl, *mod = calcRef;
    3907       51285 :         int pushed = (v->cand && v->cand == sel), no_candidates = 0;
    3908       51285 :         bool add_tz = false;
    3909             :         /* convert types and make sure they are rounded up correctly */
    3910             : 
    3911       51285 :         if (v->nr < 0)
    3912           0 :                 goto bailout;
    3913             : 
    3914       51285 :         if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
    3915             :                 /* general cases */
    3916       50927 :                 ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
    3917       50927 :                 !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)) ||
    3918             :                 /* trivial decimal cases */
    3919        2063 :                 (f->type->eclass == EC_DEC && t->type->eclass == EC_DEC && f->scale == t->scale && f->type->localtype == t->type->localtype) ||
    3920             :                 /* trivial string cases */
    3921       44237 :                 (EC_VARCHAR(f->type->eclass) && EC_VARCHAR(t->type->eclass) && (t->digits == 0 || (f->digits > 0 && t->digits >= f->digits))))) {
    3922             :                 /* set output type. Despite the MAL code already being generated, the output type may still be checked */
    3923       14761 :                 tail_set_type(be->mvc, v, t);
    3924       14761 :                 return v;
    3925             :         }
    3926             : 
    3927             :         /* external types have sqlname convert functions,
    3928             :            these can generate errors (fromstr cannot) */
    3929       36524 :         if (t->type->eclass == EC_EXTERNAL)
    3930         331 :                 convert = t->type->base.name;
    3931       36193 :         else if (t->type->eclass == EC_MONTH)
    3932             :                 convert = "month_interval";
    3933       36170 :         else if (t->type->eclass == EC_SEC)
    3934         100 :                 convert = "second_interval";
    3935             : 
    3936       36524 :         no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
    3937             : 
    3938       36524 :         if ((type_has_tz(f) && !type_has_tz(t) && !EC_VARCHAR(t->type->eclass)) || (!type_has_tz(f) && type_has_tz(t))) {
    3939         290 :                 v = temporal_convert(be, v, sel, f, t, true);
    3940         290 :                 sel = NULL;
    3941         290 :                 pushed = 0;
    3942         290 :                 if (EC_VARCHAR(f->type->eclass))
    3943             :                         return v;
    3944             :         }
    3945             : 
    3946             :         /* Lookup the sql convert function, there is no need
    3947             :          * for single value vs bat, this is handled by the
    3948             :          * mal function resolution */
    3949       36400 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3950        8220 :                 q = newStmtArgs(mb, mod, convert, 13);
    3951        8220 :                 if (q == NULL)
    3952           0 :                         goto bailout;
    3953       28201 :         } else if ((v->nrcols > 0 || (sel && sel->nrcols > 0)) && no_candidates) {
    3954          21 :                 int type = t->type->localtype;
    3955             : 
    3956             :                 /* with our current implementation, all internal SQL types have candidate list support on their conversions */
    3957          21 :                 if (sel && !pushed) {
    3958           0 :                         pushed = 1;
    3959           0 :                         v = stmt_project(be, sel, v);
    3960           0 :                         v->cand = sel;
    3961             :                 }
    3962          21 :                 q = newStmtArgs(mb, malRef, multiplexRef, 15);
    3963          21 :                 if (q == NULL)
    3964           0 :                         goto bailout;
    3965          21 :                 setVarType(mb, getArg(q, 0), newBatType(type));
    3966          21 :                 q = pushStr(mb, q, convertMultiplexMod(mod, convert));
    3967          21 :                 q = pushStr(mb, q, convertMultiplexFcn(convert));
    3968             :         } else {
    3969       28159 :                 if (v->nrcols == 0 && sel && !pushed) {
    3970         905 :                         pushed = 1;
    3971         905 :                         v = stmt_project(be, sel, v);
    3972         905 :                         v->cand = sel;
    3973             :                 }
    3974       28159 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3975       28159 :                 if (q == NULL)
    3976           0 :                         goto bailout;
    3977             :         }
    3978             : 
    3979             :         /* convert to string is complex, we need full type info and mvc for the timezone */
    3980       36560 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
    3981        1839 :                 q = pushInt(mb, q, f->type->eclass);
    3982        1839 :                 q = pushInt(mb, q, f->digits);
    3983        1839 :                 q = pushInt(mb, q, f->scale);
    3984        1839 :                 q = pushInt(mb, q, type_has_tz(f));
    3985       34561 :         } else if (f->type->eclass == EC_DEC) {
    3986             :                 /* scale of the current decimal */
    3987        1688 :                 q = pushInt(mb, q, f->scale);
    3988       32873 :         } else if (f->type->eclass == EC_SEC && (EC_COMPUTE(t->type->eclass) || t->type->eclass == EC_DEC)) {
    3989             :                 /* scale of the current decimal */
    3990           0 :                 q = pushInt(mb, q, 3);
    3991             :         }
    3992       36400 :         q = pushArgument(mb, q, v->nr);
    3993       36400 :         if (add_tz)
    3994             :                         q = pushLng(mb, q, be->mvc->timezone);
    3995       36400 :         if (sel && !pushed && !v->cand) {
    3996        3478 :                 q = pushArgument(mb, q, sel->nr);
    3997        3478 :                 pushed = 1;
    3998       32922 :         } else if (v->nrcols > 0 && !no_candidates) {
    3999       24681 :                 q = pushNilBat(mb, q);
    4000             :         }
    4001       36400 :         if (!add_tz && (t->type->eclass == EC_DEC || EC_TEMP_FRAC(t->type->eclass) || EC_INTERVAL(t->type->eclass))) {
    4002             :                 /* digits, scale of the result decimal */
    4003        3155 :                 q = pushInt(mb, q, t->digits);
    4004        3155 :                 if (!EC_TEMP_FRAC(t->type->eclass))
    4005        2816 :                         q = pushInt(mb, q, t->scale);
    4006             :         }
    4007             :         /* convert to string, give error on to large strings */
    4008       36560 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
    4009        1839 :                 q = pushInt(mb, q, t->digits);
    4010             :         /* convert a string to a time(stamp) with time zone */
    4011       36400 :         if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass))
    4012             :                 //q = pushInt(mb, q, type_has_tz(t));
    4013           0 :                 q = pushLng(mb, q, be->mvc->timezone);
    4014       36400 :         if (t->type->eclass == EC_GEOM) {
    4015             :                 /* push the type and coordinates of the column */
    4016         687 :                 q = pushInt(mb, q, t->digits);
    4017             :                 /* push the SRID of the whole columns */
    4018         687 :                 q = pushInt(mb, q, t->scale);
    4019             :                 /* push the type and coordinates of the inserted value */
    4020             :                 //q = pushInt(mb, q, f->digits);
    4021             :                 /* push the SRID of the inserted value */
    4022             :                 //q = pushInt(mb, q, f->scale);
    4023             :                 /* we decided to create the EWKB type also used by PostGIS and has the SRID provided by the user inside already */
    4024             :                 /* push the SRID provided for this value */
    4025             :                 /* GEOS library is able to store in the returned wkb the type an
    4026             :                  * number if coordinates but not the SRID so SRID should be provided
    4027             :                  * from this level */
    4028             : /*              if(be->argc > 1)
    4029             :                         f->scale = ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival;
    4030             : 
    4031             :                         q = pushInt(mb, q, f->digits);
    4032             :                         q = pushInt(mb, q, f->scale);
    4033             : */                      //q = pushInt(mb, q, ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival);
    4034             :         }
    4035             : 
    4036       36400 :         bool enabled = be->mvc->sa->eb.enabled;
    4037       36400 :         be->mvc->sa->eb.enabled = false;
    4038       36400 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    4039       36400 :         be->mvc->sa->eb.enabled = enabled;
    4040       36400 :         if(!s) {
    4041           0 :                 freeInstruction(q);
    4042           0 :                 goto bailout;
    4043             :         }
    4044       36400 :         s->op1 = v;
    4045       36400 :         s->nrcols = 0;       /* function without arguments returns single value */
    4046       36400 :         s->key = v->key;
    4047       36400 :         s->nrcols = v->nrcols;
    4048       36400 :         s->aggr = v->aggr;
    4049       36400 :         s->op4.typeval = *t;
    4050       36400 :         s->nr = getDestVar(q);
    4051       36400 :         s->q = q;
    4052       36400 :         s->cand = pushed ? sel : NULL;
    4053       36400 :         pushInstruction(mb, q);
    4054       36400 :         if ((!type_has_tz(f) && type_has_tz(t)))
    4055          61 :                 return temporal_convert(be, s, NULL, f, t, false);
    4056             :         return s;
    4057             : 
    4058           0 :   bailout:
    4059           0 :         if (be->mvc->sa->eb.enabled)
    4060           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4061             :         return NULL;
    4062             : }
    4063             : 
    4064             : stmt *
    4065       26999 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
    4066             : {
    4067       26999 :         list *ops = sa_list(be->mvc->sa);
    4068       26999 :         list_append(ops, op1);
    4069       26999 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4070       26999 :         if (r && !r->cand)
    4071       26999 :                 r->cand = op1->cand;
    4072       26999 :         return r;
    4073             : }
    4074             : 
    4075             : stmt *
    4076       44189 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
    4077             : {
    4078       44189 :         list *ops = sa_list(be->mvc->sa);
    4079       44189 :         list_append(ops, op1);
    4080       44189 :         list_append(ops, op2);
    4081       44189 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    4082       44189 :         if (r && !r->cand)
    4083       44189 :                 r->cand = op1->cand?op1->cand:op2->cand;
    4084       44189 :         return r;
    4085             : }
    4086             : 
    4087             : #define LANG_INT_OR_MAL(l)  ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
    4088             : 
    4089             : stmt *
    4090      216501 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
    4091             : {
    4092      216501 :         MalBlkPtr mb = be->mb;
    4093      216501 :         InstrPtr q = NULL;
    4094      216501 :         const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
    4095      216501 :         sql_subtype *tpe = NULL;
    4096      216501 :         int push_cands = 0, default_nargs;
    4097      216501 :         stmt *o = NULL, *card = NULL;
    4098             : 
    4099      216501 :         if (ops == NULL)
    4100           0 :                 goto bailout;
    4101             : 
    4102      216501 :         if (rows) {
    4103         101 :                 if (sel) /* if there's a candidate list, use it instead of 'rows' */
    4104           0 :                         rows = sel;
    4105             :                 o = rows;
    4106      216400 :         } else if (list_length(ops->op4.lval)) {
    4107      214486 :                 o = ops->op4.lval->h->data;
    4108      640546 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4109      426060 :                         stmt *c = n->data;
    4110             : 
    4111      426060 :                         if (c && o->nrcols < c->nrcols)
    4112      426060 :                                 o = c;
    4113             :                 }
    4114             :         }
    4115             : 
    4116             :         /* handle nullif */
    4117      216501 :         if (list_length(ops->op4.lval) == 2 &&
    4118      135062 :                 strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
    4119          95 :                 stmt *e1 = ops->op4.lval->h->data;
    4120          95 :                 stmt *e2 = ops->op4.lval->h->next->data;
    4121          95 :                 int nrcols = 0;
    4122             : 
    4123          95 :                 nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols;
    4124             :                 /* nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) */
    4125          95 :                 if (strcmp(f->func->base.name, "nullif") == 0) {
    4126          95 :                         const char *mod = (!nrcols)?calcRef:batcalcRef;
    4127          95 :                         sql_subtype *t = tail_type(e1);
    4128          95 :                         int tt = t->type->localtype;
    4129          95 :                         q = newStmt(mb, mod, "==");
    4130          95 :                         if (q == NULL)
    4131           0 :                                 goto bailout;
    4132          95 :                         q = pushArgument(mb, q, e1->nr);
    4133          95 :                         q = pushArgument(mb, q, e2->nr);
    4134          95 :                         int nr = getDestVar(q);
    4135          95 :                         pushInstruction(mb, q);
    4136             : 
    4137          95 :                         q = newStmt(mb, mod, ifthenelseRef);
    4138          95 :                         if (q == NULL)
    4139           0 :                                 goto bailout;
    4140          95 :                         q = pushArgument(mb, q, nr);
    4141          95 :                         q = pushNil(mb, q, tt);
    4142          95 :                         q = pushArgument(mb, q, e1->nr);
    4143          95 :                         pushInstruction(mb, q);
    4144             :                 }
    4145          95 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4146             :         }
    4147          95 :         if (q == NULL) {
    4148      216406 :                 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
    4149           2 :                         goto bailout;
    4150      216404 :                 mod = sql_func_mod(f->func);
    4151      216404 :                 fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
    4152      216404 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4153      225378 :                 default_nargs = (f->res && list_length(f->res) ? list_length(f->res) : 1) + list_length(ops->op4.lval) + (o && o->nrcols > 0 ? 6 : 4);
    4154      216403 :                 if (rows) {
    4155         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);
    4156         101 :                         default_nargs++;
    4157             :                 }
    4158             : 
    4159      216403 :                 if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
    4160      136742 :                         sql_subtype *res = f->res->h->data;
    4161             : 
    4162      136742 :                         q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
    4163      136742 :                         if (q == NULL)
    4164           0 :                                 goto bailout;
    4165      136742 :                         if (rows)
    4166         101 :                                 q = pushArgument(mb, q, card->nr);
    4167      136742 :                         q = pushStr(mb, q, mod);
    4168      136742 :                         q = pushStr(mb, q, fimp);
    4169      136742 :                         setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
    4170             :                 } else {
    4171       79661 :                         q = newStmtArgs(mb, mod, fimp, default_nargs);
    4172       79662 :                         if (q == NULL)
    4173           0 :                                 goto bailout;
    4174             : 
    4175       79662 :                         if (rows)
    4176           0 :                                 q = pushArgument(mb, q, card->nr);
    4177       79662 :                         if (f->res && list_length(f->res)) {
    4178       70688 :                                 sql_subtype *res = f->res->h->data;
    4179             : 
    4180       70688 :                                 setVarType(mb, getArg(q, 0), res->type->localtype);
    4181             :                         }
    4182             :                 }
    4183      216404 :                 if (LANG_EXT(f->func->lang)) {
    4184             :                         /* TODO LOADER functions still use information in sql_subfunc struct
    4185             :                            that won't be visible to other sessions if another function uses them.
    4186             :                            It has to be cleaned up */
    4187         221 :                         if (f->func->type == F_LOADER)
    4188          25 :                                 q = pushPtr(mb, q, f);
    4189             :                         else
    4190         196 :                                 q = pushPtr(mb, q, f->func);
    4191             :                 }
    4192      216404 :                 if (f->func->lang == FUNC_LANG_C) {
    4193          35 :                         q = pushBit(mb, q, 0);
    4194      216369 :                 } else if (f->func->lang == FUNC_LANG_CPP) {
    4195           1 :                         q = pushBit(mb, q, 1);
    4196             :                 }
    4197      216404 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY ||
    4198             :                         f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) {
    4199         221 :                         q = pushStr(mb, q, f->func->query);
    4200             :                 }
    4201             :                 /* first dynamic output of copy* functions */
    4202      216404 :                 if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
    4203        2787 :                         q = table_func_create_result(mb, q, f->func, f->res);
    4204      216404 :                 if (list_length(ops->op4.lval))
    4205      214475 :                         tpe = tail_type(ops->op4.lval->h->data);
    4206             : 
    4207      642443 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4208      426039 :                         stmt *op = n->data;
    4209      426039 :                         q = pushArgument(mb, q, op->nr);
    4210             :                 }
    4211             :                 /* push candidate lists if that's the case */
    4212      216404 :                 if (push_cands) {
    4213       76791 :                         for (node *n = ops->op4.lval->h; n; n = n->next) {
    4214       50651 :                                 stmt *op = n->data;
    4215             : 
    4216       50651 :                                 if (op->nrcols > 0) {
    4217       28454 :                                         if (op->cand && op->cand == sel) {
    4218        3838 :                                                 q = pushNilBat(mb, q);
    4219             :                                         } else {
    4220       24616 :                                                 q = pushArgument(mb, q, sel->nr);
    4221             :                                         }
    4222             :                                 }
    4223             :                         }
    4224             :                 }
    4225             :                 /* special case for round function on decimals */
    4226      216404 :                 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) {
    4227          48 :                         q = pushInt(mb, q, tpe->digits);
    4228          48 :                         q = pushInt(mb, q, tpe->scale);
    4229             :                 }
    4230      216404 :                 pushInstruction(mb, q);
    4231             :         }
    4232             : 
    4233      216499 :         stmt *s = stmt_create(be->mvc->sa, st_Nop);
    4234      216499 :         if(!s) {
    4235           0 :                 goto bailout;
    4236             :         }
    4237      216499 :         s->op1 = ops;
    4238      216499 :         if (o) {
    4239      214586 :                 s->nrcols = o->nrcols;
    4240      214586 :                 s->key = o->key;
    4241      214586 :                 s->aggr = o->aggr;
    4242             :         } else {
    4243        1913 :                 s->nrcols = 0;
    4244        1913 :                 s->key = 1;
    4245             :         }
    4246      216499 :         s->op4.funcval = f;
    4247      216499 :         s->nr = getDestVar(q);
    4248      216499 :         s->q = q;
    4249      216499 :         if (sel && push_cands && s->nrcols)
    4250       24627 :                 s->cand = sel;
    4251             :         return s;
    4252             : 
    4253           2 :   bailout:
    4254           2 :         if (be->mvc->sa->eb.enabled)
    4255           2 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4256             :         return NULL;
    4257             : }
    4258             : 
    4259             : stmt *
    4260          23 : stmt_direct_func(backend *be, InstrPtr q)
    4261             : {
    4262          23 :         if (q) {
    4263          23 :                 stmt *s = stmt_create(be->mvc->sa, st_func);
    4264          23 :                 if(!s) {
    4265             :                         return NULL;
    4266             :                 }
    4267          23 :                 s->flag = op_union;
    4268          23 :                 s->nrcols = 3;
    4269          23 :                 s->nr = getDestVar(q);
    4270          23 :                 s->q = q;
    4271          23 :                 return s;
    4272             :         }
    4273             :         return NULL;
    4274             : }
    4275             : 
    4276             : stmt *
    4277         186 : stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
    4278             : {
    4279         186 :         MalBlkPtr mb = be->mb;
    4280         186 :         InstrPtr q = NULL;
    4281         186 :         prop *p = NULL;
    4282             : 
    4283             :         /* dump args */
    4284         186 :         if (ops && ops->nr < 0)
    4285           0 :                 goto bailout;
    4286             : 
    4287         186 :         if ((p = find_prop(rel->p, PROP_REMOTE)))
    4288         186 :                 rel->p = prop_remove(rel->p, p);
    4289             :         /* sql_processrelation may split projections, so make sure the topmost relation only contains references */
    4290         186 :         rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 1, 1));
    4291         186 :         if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
    4292           0 :                 goto bailout;
    4293         186 :         if (p) {
    4294         186 :                 p->p = rel->p;
    4295         186 :                 rel->p = p;
    4296             :         }
    4297             : 
    4298         186 :         if (monet5_create_relational_function(be->mvc, sql_private_module_name, name, rel, ops, NULL, 1) < 0)
    4299           0 :                 goto bailout;
    4300             : 
    4301         186 :         int nargs;
    4302         186 :         sql_rel *r = relational_func_create_result_part1(be->mvc, rel, &nargs);
    4303         186 :         if (ops)
    4304         186 :                 nargs += list_length(ops->op4.lval);
    4305         186 :         if (f_union)
    4306           0 :                 q = newStmt(mb, batmalRef, multiplexRef);
    4307             :         else
    4308         186 :                 q = newStmt(mb, sql_private_module_name, name);
    4309         186 :         if (q == NULL)
    4310           0 :                 goto bailout;
    4311         186 :         q = relational_func_create_result_part2(mb, q, r);
    4312         186 :         if (f_union) {
    4313           0 :                 q = pushStr(mb, q, sql_private_module_name);
    4314           0 :                 q = pushStr(mb, q, name);
    4315             :         }
    4316         186 :         if (ops) {
    4317         208 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4318          22 :                         stmt *op = n->data;
    4319             : 
    4320          22 :                         q = pushArgument(mb, q, op->nr);
    4321             :                 }
    4322             :         }
    4323             : 
    4324         186 :         allocator *sa = be->mvc->sa;
    4325         186 :         bool enabled = be->mvc->sa->eb.enabled;
    4326         186 :         be->mvc->sa->eb.enabled = false;
    4327         186 :         stmt *o = NULL, *s = stmt_create(sa, st_func);
    4328         186 :         be->mvc->sa->eb.enabled = enabled;
    4329         186 :         if(!s) {
    4330           0 :                 freeInstruction(q);
    4331           0 :                 goto bailout;
    4332             :         }
    4333         186 :         s->op1 = ops;
    4334         186 :         s->op2 = stmt_atom_string(be, name);
    4335         186 :         s->op4.rel = rel;
    4336         186 :         s->flag = f_union;
    4337         186 :         if (ops && list_length(ops->op4.lval)) {
    4338          10 :                 node *n;
    4339          32 :                 for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
    4340          22 :                         stmt *c = n->data;
    4341             : 
    4342          22 :                         if (o->nrcols < c->nrcols)
    4343           0 :                                 o = c;
    4344             :                 }
    4345             :         }
    4346             : 
    4347          10 :         if (o) {
    4348          10 :                 s->nrcols = o->nrcols;
    4349          10 :                 s->key = o->key;
    4350          10 :                 s->aggr = o->aggr;
    4351             :         } else {
    4352         176 :                 s->nrcols = 0;
    4353         176 :                 s->key = 1;
    4354             :         }
    4355         186 :         s->nr = getDestVar(q);
    4356         186 :         s->q = q;
    4357         186 :         pushInstruction(mb, q);
    4358         186 :         return s;
    4359             : 
    4360           0 :   bailout:
    4361           0 :         if (be->mvc->sa->eb.enabled)
    4362           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4363             :         return NULL;
    4364             : }
    4365             : 
    4366             : stmt *
    4367       85255 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
    4368             : {
    4369       85255 :         MalBlkPtr mb = be->mb;
    4370       85255 :         InstrPtr q = NULL;
    4371       85255 :         const char *mod, *aggrfunc;
    4372       85255 :         sql_subtype *res = op->res->h->data;
    4373       85255 :         int restype = res->type->localtype;
    4374       85255 :         bool complex_aggr = false;
    4375       85255 :         int *stmt_nr = NULL;
    4376       85255 :         int avg = 0;
    4377             : 
    4378       85255 :         if (op1->nr < 0)
    4379           0 :                 goto bailout;
    4380       85255 :         if (backend_create_subfunc(be, op, NULL) < 0)
    4381           0 :                 goto bailout;
    4382       85256 :         mod = sql_func_mod(op->func);
    4383       85256 :         aggrfunc = backend_function_imp(be, op->func);
    4384             : 
    4385       85257 :         if (LANG_INT_OR_MAL(op->func->lang)) {
    4386       85207 :                 if (strcmp(aggrfunc, "avg") == 0)
    4387             :                         avg = 1;
    4388       83837 :                 if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
    4389       76575 :                         || strcmp(aggrfunc, "str_group_concat") == 0)
    4390             :                         complex_aggr = true;
    4391       85207 :                 if (restype == TYPE_dbl)
    4392        1561 :                         avg = 0;
    4393             :         }
    4394             : 
    4395      170514 :         int argc = 1
    4396       85257 :                 + 2 * avg
    4397       85257 :                 + (LANG_EXT(op->func->lang) != 0)
    4398       85257 :                 + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
    4399       85257 :                 + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
    4400       85257 :                 + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
    4401       85257 :                 + (grp ? 4 : avg + 1);
    4402             : 
    4403       85257 :         if (grp) {
    4404        6829 :                 char *aggrF = SA_NEW_ARRAY(be->mvc->sa, char, strlen(aggrfunc) + 4);
    4405        6829 :                 if (!aggrF)
    4406           0 :                         goto bailout;
    4407        6829 :                 stpcpy(stpcpy(aggrF, "sub"), aggrfunc);
    4408        6829 :                 aggrfunc = aggrF;
    4409        6829 :                 if ((grp && grp->nr < 0) || (ext && ext->nr < 0))
    4410           0 :                         goto bailout;
    4411             : 
    4412        6829 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4413        6829 :                 if (q == NULL)
    4414           0 :                         goto bailout;
    4415        6829 :                 setVarType(mb, getArg(q, 0), newBatType(restype));
    4416        6829 :                 if (avg) { /* for avg also return rest and count */
    4417          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4418          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4419             :                 }
    4420             :         } else {
    4421       78428 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4422       78428 :                 if (q == NULL)
    4423           0 :                         goto bailout;
    4424       78428 :                 if (complex_aggr) {
    4425        6714 :                         setVarType(mb, getArg(q, 0), restype);
    4426        6714 :                         if (avg) { /* for avg also return rest and count */
    4427          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4428          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4429             :                         }
    4430             :                 }
    4431             :         }
    4432             : 
    4433       85257 :         if (LANG_EXT(op->func->lang))
    4434          47 :                 q = pushPtr(mb, q, op->func);
    4435       85257 :         if (op->func->lang == FUNC_LANG_R ||
    4436       85222 :                 op->func->lang >= FUNC_LANG_PY ||
    4437             :                 op->func->lang == FUNC_LANG_C ||
    4438             :                 op->func->lang == FUNC_LANG_CPP) {
    4439          47 :                 if (!grp) {
    4440          20 :                         setVarType(mb, getArg(q, 0), restype);
    4441             :                 }
    4442          47 :                 if (op->func->lang == FUNC_LANG_C) {
    4443          12 :                         q = pushBit(mb, q, 0);
    4444          35 :                 } else if (op->func->lang == FUNC_LANG_CPP) {
    4445           0 :                         q = pushBit(mb, q, 1);
    4446             :                 }
    4447          47 :                 q = pushStr(mb, q, op->func->query);
    4448             :         }
    4449             : 
    4450       85257 :         if (op1->type != st_list) {
    4451       79278 :                 q = pushArgument(mb, q, op1->nr);
    4452             :         } else {
    4453        5979 :                 int i;
    4454        5979 :                 node *n;
    4455             : 
    4456       12358 :                 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
    4457        6379 :                         stmt *op = n->data;
    4458             : 
    4459        6379 :                         if (stmt_nr)
    4460             :                                 q = pushArgument(mb, q, stmt_nr[i]);
    4461             :                         else
    4462        6379 :                                 q = pushArgument(mb, q, op->nr);
    4463             :                 }
    4464             :         }
    4465       85257 :         if (grp) {
    4466        6829 :                 q = pushArgument(mb, q, grp->nr);
    4467        6829 :                 q = pushArgument(mb, q, ext->nr);
    4468        6829 :                 if (LANG_INT_OR_MAL(op->func->lang)) {
    4469        6802 :                         if (avg) /* push nil candidates */
    4470          96 :                                 q = pushNilBat(mb, q);
    4471        6802 :                         q = pushBit(mb, q, no_nil);
    4472             :                 }
    4473       78428 :         } else if (LANG_INT_OR_MAL(op->func->lang) && no_nil && strncmp(aggrfunc, "count", 5) == 0) {
    4474        1643 :                 q = pushBit(mb, q, no_nil);
    4475       76785 :         } else if (LANG_INT_OR_MAL(op->func->lang) && !nil_if_empty && strncmp(aggrfunc, "sum", 3) == 0) {
    4476           0 :                 q = pushBit(mb, q, FALSE);
    4477       76785 :         } else if (LANG_INT_OR_MAL(op->func->lang) && avg) { /* push candidates */
    4478          57 :                 q = pushNilBat(mb, q);
    4479          57 :                 q = pushBit(mb, q, no_nil);
    4480             :         }
    4481             : 
    4482       85257 :         bool enabled = be->mvc->sa->eb.enabled;
    4483       85257 :         be->mvc->sa->eb.enabled = false;
    4484       85257 :         stmt *s = stmt_create(be->mvc->sa, st_aggr);
    4485       85257 :         be->mvc->sa->eb.enabled = enabled;
    4486       85257 :         if(!s) {
    4487           0 :                 freeInstruction(q);
    4488           0 :                 goto bailout;
    4489             :         }
    4490       85257 :         s->op1 = op1;
    4491       85257 :         if (grp) {
    4492        6829 :                 s->op2 = grp;
    4493        6829 :                 s->op3 = ext;
    4494        6829 :                 s->nrcols = 1;
    4495             :         } else {
    4496       78428 :                 if (!reduce)
    4497           0 :                         s->nrcols = 1;
    4498             :         }
    4499       85257 :         s->key = reduce;
    4500       85257 :         s->aggr = reduce;
    4501       85257 :         s->flag = no_nil;
    4502       85257 :         s->op4.funcval = op;
    4503       85257 :         s->nr = getDestVar(q);
    4504       85257 :         s->q = q;
    4505       85257 :         pushInstruction(mb, q);
    4506       85257 :         return s;
    4507             : 
    4508           0 :   bailout:
    4509           0 :         if (be->mvc->sa->eb.enabled)
    4510           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4511             :         return NULL;
    4512             : }
    4513             : 
    4514             : static stmt *
    4515     4919474 : stmt_alias_(backend *be, stmt *op1, int label, const char *tname, const char *alias)
    4516             : {
    4517     4919474 :         assert(label);
    4518     4919474 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
    4519     4919278 :         if(!s) {
    4520             :                 return NULL;
    4521             :         }
    4522     4919278 :         s->label = label;
    4523     4919278 :         s->op1 = op1;
    4524     4919278 :         s->nrcols = op1->nrcols;
    4525     4919278 :         s->key = op1->key;
    4526     4919278 :         s->aggr = op1->aggr;
    4527             : 
    4528     4919278 :         s->tname = tname;
    4529     4919278 :         s->cname = alias;
    4530     4919278 :         s->nr = op1->nr;
    4531     4919278 :         s->q = op1->q;
    4532     4919278 :         return s;
    4533             : }
    4534             : 
    4535             : stmt *
    4536     4361013 : stmt_alias(backend *be, stmt *op1, int label, const char *tname, const char *alias)
    4537             : {
    4538             :         /*
    4539             :         if (((!op1->tname && !tname) ||
    4540             :             (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
    4541             :             op1->cname && strcmp(op1->cname, alias)==0)
    4542             :                 return op1;
    4543             :                 */
    4544     4361013 :         return stmt_alias_(be, op1, label, tname, alias);
    4545             : }
    4546             : 
    4547             : stmt *
    4548      558484 : stmt_as(backend *be, stmt *s, stmt *org)
    4549             : {
    4550      558484 :         assert(org->type == st_alias);
    4551      558484 :         return stmt_alias_(be, s, org->label, org->tname, org->cname);
    4552             : }
    4553             : 
    4554             : sql_subtype *
    4555     1538876 : tail_type(stmt *st)
    4556             : {
    4557     8554205 :         for (;;) {
    4558     8554205 :                 switch (st->type) {
    4559       36432 :                 case st_const:
    4560       36432 :                         st = st->op2;
    4561       36432 :                         continue;
    4562        3378 :                 case st_uselect:
    4563             :                 case st_semijoin:
    4564             :                 case st_limit:
    4565             :                 case st_limit2:
    4566             :                 case st_sample:
    4567             :                 case st_tunion:
    4568             :                 case st_tdiff:
    4569             :                 case st_tinter:
    4570        3378 :                         return sql_bind_localtype("oid");
    4571         587 :                 case st_uselect2:
    4572         587 :                         if (!st->reduce)
    4573          61 :                                 return sql_bind_localtype("bit");
    4574         526 :                         return sql_bind_localtype("oid");
    4575     3866879 :                 case st_append:
    4576             :                 case st_append_bulk:
    4577             :                 case st_replace:
    4578             :                 case st_alias:
    4579             :                 case st_gen_group:
    4580             :                 case st_order:
    4581     3866879 :                         st = st->op1;
    4582     3866879 :                         continue;
    4583           0 :                 case st_list:
    4584           0 :                         st = st->op4.lval->h->data;
    4585           0 :                         continue;
    4586      902459 :                 case st_bat:
    4587      902459 :                         return &st->op4.cval->type;
    4588        2016 :                 case st_idxbat:
    4589        2016 :                         if (hash_index(st->op4.idxval->type)) {
    4590         269 :                                 return sql_bind_localtype("lng");
    4591        1747 :                         } else if (oid_index(st->op4.idxval->type)) {
    4592        1747 :                                 return sql_bind_localtype("oid");
    4593             :                         }
    4594             :                         /* fall through */
    4595             :                 case st_join:
    4596             :                 case st_join2:
    4597             :                 case st_joinN:
    4598     3112061 :                         if (st->flag == cmp_project) {
    4599     3112018 :                                 st = st->op2;
    4600     3112018 :                                 continue;
    4601             :                         }
    4602             :                         /* fall through */
    4603             :                 case st_reorder:
    4604             :                 case st_group:
    4605             :                 case st_tid:
    4606             :                 case st_mirror:
    4607       15182 :                         return sql_bind_localtype("oid");
    4608       31083 :                 case st_result:
    4609       31083 :                         return &st->op4.typeval;
    4610           0 :                 case st_table_clear:
    4611           0 :                         return sql_bind_localtype("lng");
    4612      154784 :                 case st_aggr:
    4613             :                 case st_Nop: {
    4614      154784 :                         list *res = st->op4.funcval->res;
    4615             : 
    4616      154784 :                         if (res && list_length(res) == 1)
    4617      154784 :                                 return res->h->data;
    4618             : 
    4619             :                         return NULL;
    4620             :                 }
    4621      149381 :                 case st_atom:
    4622      149381 :                         return atom_type(st->op4.aval);
    4623      277701 :                 case st_convert:
    4624             :                 case st_temp:
    4625             :                 case st_single:
    4626             :                 case st_rs_column:
    4627      277701 :                         return &st->op4.typeval;
    4628        2297 :                 case st_var:
    4629        2297 :                         if (st->op4.typeval.type)
    4630        2297 :                                 return &st->op4.typeval;
    4631             :                         /* fall through */
    4632             :                 case st_exception:
    4633             :                         return NULL;
    4634           8 :                 case st_table:
    4635           8 :                         return sql_bind_localtype("bat");
    4636             :                 default:
    4637           0 :                         assert(0);
    4638             :                         return NULL;
    4639             :                 }
    4640             :         }
    4641             : }
    4642             : 
    4643             : int
    4644        6625 : stmt_has_null(stmt *s)
    4645             : {
    4646       20822 :         switch (s->type) {
    4647             :         case st_aggr:
    4648             :         case st_semijoin:
    4649             :         case st_uselect:
    4650             :         case st_uselect2:
    4651             :         case st_atom:
    4652             :                 return 0;
    4653        8174 :         case st_alias:
    4654        8174 :                 return stmt_has_null(s->op1);
    4655        6023 :         case st_join:
    4656        6023 :                 return stmt_has_null(s->op2);
    4657        4203 :         case st_bat:
    4658        4203 :                 return s->op4.cval->null;
    4659             : 
    4660        2422 :         default:
    4661        2422 :                 return 1;
    4662             :         }
    4663             : }
    4664             : 
    4665             : static const char *
    4666           0 : func_name(allocator *sa, const char *n1, const char *n2)
    4667             : {
    4668           0 :         size_t l1 = _strlen(n1), l2;
    4669             : 
    4670           0 :         if (!sa)
    4671             :                 return n1;
    4672           0 :         if (!n2)
    4673           0 :                 return sa_strdup(sa, n1);
    4674           0 :         l2 = _strlen(n2);
    4675             : 
    4676           0 :         if (l2 > 16) {               /* only support short names */
    4677           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l2 + 1);
    4678           0 :                 if(!ns)
    4679             :                         return NULL;
    4680           0 :                 snprintf(ns, l2 + 1, "%s", n2);
    4681           0 :                 return ns;
    4682             :         } else {
    4683           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l1 + l2 + 2), *s = ns;
    4684           0 :                 if(!ns)
    4685             :                         return NULL;
    4686           0 :                 snprintf(ns, l1 + l2 + 2, "%s_%s", n1, n2);
    4687           0 :                 return s;
    4688             :         }
    4689             : }
    4690             : 
    4691             : static const char *_column_name(allocator *sa, stmt *st);
    4692             : 
    4693             : const char *
    4694     2645292 : column_name(allocator *sa, stmt *st)
    4695             : {
    4696     2645292 :         if (!st->cname)
    4697           0 :                 st->cname = _column_name(sa, st);
    4698     2645292 :         return st->cname;
    4699             : }
    4700             : 
    4701             : static const char *
    4702           0 : _column_name(allocator *sa, stmt *st)
    4703             : {
    4704           0 :         switch (st->type) {
    4705           0 :         case st_order:
    4706             :         case st_reorder:
    4707           0 :                 return column_name(sa, st->op1);
    4708           0 :         case st_const:
    4709             :         case st_join:
    4710             :         case st_join2:
    4711             :         case st_joinN:
    4712           0 :                 return column_name(sa, st->op2);
    4713             : 
    4714           0 :         case st_mirror:
    4715             :         case st_group:
    4716             :         case st_result:
    4717             :         case st_append:
    4718             :         case st_append_bulk:
    4719             :         case st_replace:
    4720             :         case st_gen_group:
    4721             :         case st_semijoin:
    4722             :         case st_uselect:
    4723             :         case st_uselect2:
    4724             :         case st_limit:
    4725             :         case st_limit2:
    4726             :         case st_sample:
    4727             :         case st_tunion:
    4728             :         case st_tdiff:
    4729             :         case st_tinter:
    4730             :         case st_convert:
    4731           0 :                 return column_name(sa, st->op1);
    4732           0 :         case st_Nop:
    4733             :         case st_aggr:
    4734             :         {
    4735           0 :                 const char *cn = column_name(sa, st->op1);
    4736           0 :                 return func_name(sa, st->op4.funcval->func->base.name, cn);
    4737             :         }
    4738           0 :         case st_alias:
    4739           0 :                 if (st->op3)
    4740           0 :                         return column_name(sa, st->op3);
    4741             :                 break;
    4742           0 :         case st_bat:
    4743           0 :                 return st->op4.cval->base.name;
    4744           0 :         case st_atom:
    4745           0 :                 if (st->op4.aval->data.vtype == TYPE_str)
    4746           0 :                         return atom2string(sa, st->op4.aval);
    4747             :                 /* fall through */
    4748             :         case st_var:
    4749             :         case st_temp:
    4750             :         case st_single:
    4751           0 :                 if (sa)
    4752           0 :                         return sa_strdup(sa, "single_value");
    4753             :                 return "single_value";
    4754             : 
    4755           0 :         case st_list:
    4756           0 :                 if (list_length(st->op4.lval))
    4757           0 :                         return column_name(sa, st->op4.lval->h->data);
    4758             :                 /* fall through */
    4759             :         case st_rs_column:
    4760             :                 return NULL;
    4761             :         default:
    4762             :                 return NULL;
    4763             :         }
    4764             :         return NULL;
    4765             : }
    4766             : 
    4767             : const char *
    4768     2629951 : table_name(allocator *sa, stmt *st)
    4769             : {
    4770     2629951 :         (void)sa;
    4771     2629951 :         return st->tname;
    4772             : }
    4773             : 
    4774             : const char *
    4775      334343 : schema_name(allocator *sa, stmt *st)
    4776             : {
    4777     3092694 :         switch (st->type) {
    4778     1190256 :         case st_const:
    4779             :         case st_semijoin:
    4780             :         case st_join:
    4781             :         case st_join2:
    4782             :         case st_joinN:
    4783     1190256 :                 return schema_name(sa, st->op2);
    4784      120423 :         case st_mirror:
    4785             :         case st_group:
    4786             :         case st_result:
    4787             :         case st_append:
    4788             :         case st_append_bulk:
    4789             :         case st_replace:
    4790             :         case st_gen_group:
    4791             :         case st_uselect:
    4792             :         case st_uselect2:
    4793             :         case st_limit:
    4794             :         case st_limit2:
    4795             :         case st_sample:
    4796             :         case st_tunion:
    4797             :         case st_tdiff:
    4798             :         case st_tinter:
    4799             :         case st_convert:
    4800             :         case st_Nop:
    4801             :         case st_aggr:
    4802             :                 /* there are no schema aliases, ie look into the base column */
    4803      120423 :                 if (st->op1)
    4804             :                         return schema_name(sa, st->op1);
    4805             :                 return NULL;
    4806     1416282 :         case st_alias:
    4807     1416282 :                 return schema_name(sa, st->op1);
    4808      201314 :         case st_bat:
    4809      201314 :                 return st->op4.cval->t->s->base.name;
    4810             :         case st_atom:
    4811             :                 return NULL;
    4812             :         case st_var:
    4813             :         case st_temp:
    4814             :         case st_single:
    4815             :                 return NULL;
    4816       31510 :         case st_list:
    4817       31510 :                 if (list_length(st->op4.lval))
    4818       31390 :                         return schema_name(sa, st->op4.lval->h->data);
    4819             :                 return NULL;
    4820             :         default:
    4821             :                 return NULL;
    4822             :         }
    4823             : }
    4824             : 
    4825             : stmt *
    4826        1118 : stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
    4827             : {
    4828        1118 :         MalBlkPtr mb = be->mb;
    4829        1118 :         InstrPtr q = NULL;
    4830             : 
    4831        1118 :         if (cond->nr < 0)
    4832           0 :                 goto bailout;
    4833        1118 :         if (anti) {
    4834          25 :                 sql_subtype *bt = sql_bind_localtype("bit");
    4835          25 :                 sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    4836          25 :                 sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    4837          25 :                 sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    4838          25 :                 cond = stmt_binop(be,
    4839             :                         stmt_unop(be, cond, NULL, not),
    4840             :                         stmt_unop(be, cond, NULL, isnull), NULL, or);
    4841             :         }
    4842        1118 :         if (!loop) {    /* if */
    4843        1101 :                 q = newAssignment(mb);
    4844        1101 :                 if (q == NULL)
    4845           0 :                         goto bailout;
    4846        1101 :                 q->barrier = BARRIERsymbol;
    4847        1101 :                 q = pushArgument(mb, q, cond->nr);
    4848             :         } else {        /* while */
    4849          17 :                 int c;
    4850             : 
    4851          17 :                 if (outer->nr < 0)
    4852           0 :                         goto bailout;
    4853             :                 /* leave barrier */
    4854          17 :                 q = newStmt(mb, calcRef, notRef);
    4855          17 :                 if (q == NULL)
    4856           0 :                         goto bailout;
    4857          17 :                 q = pushArgument(mb, q, cond->nr);
    4858          17 :                 c = getArg(q, 0);
    4859          17 :                 pushInstruction(mb, q);
    4860             : 
    4861          17 :                 q = newAssignment(mb);
    4862          17 :                 if (q == NULL)
    4863           0 :                         goto bailout;
    4864          17 :                 getArg(q, 0) = outer->nr;
    4865          17 :                 q->barrier = LEAVEsymbol;
    4866          17 :                 q = pushArgument(mb, q, c);
    4867             :         }
    4868             : 
    4869        1118 :         bool enabled = be->mvc->sa->eb.enabled;
    4870        1118 :         be->mvc->sa->eb.enabled = false;
    4871        1118 :         stmt *s = stmt_create(be->mvc->sa, st_cond);
    4872        1118 :         be->mvc->sa->eb.enabled = enabled;
    4873        1118 :         if(!s) {
    4874           0 :                 freeInstruction(q);
    4875           0 :                 goto bailout;
    4876             :         }
    4877        1118 :         s->flag = be->mvc_var; /* keep the mvc_var of the outer context */
    4878        1118 :         s->loop = loop;
    4879        1118 :         s->op1 = cond;
    4880        1118 :         s->nr = getArg(q, 0);
    4881        1118 :         pushInstruction(mb, q);
    4882        1118 :         return s;
    4883             : 
    4884           0 :   bailout:
    4885           0 :         if (be->mvc->sa->eb.enabled)
    4886           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4887             :         return NULL;
    4888             : }
    4889             : 
    4890             : stmt *
    4891        1118 : stmt_control_end(backend *be, stmt *cond)
    4892             : {
    4893        1118 :         MalBlkPtr mb = be->mb;
    4894        1118 :         InstrPtr q = NULL;
    4895             : 
    4896        1118 :         if (cond->nr < 0)
    4897           0 :                 goto bailout;
    4898             : 
    4899        1118 :         if (cond->loop) {    /* while */
    4900             :                 /* redo barrier */
    4901          17 :                 q = newAssignment(mb);
    4902          17 :                 if (q == NULL)
    4903           0 :                         goto bailout;
    4904          17 :                 getArg(q, 0) = cond->nr;
    4905          17 :                 q->argc = q->retc = 1;
    4906          17 :                 q->barrier = REDOsymbol;
    4907          17 :                 q = pushBit(mb, q, TRUE);
    4908             :         } else {
    4909        1101 :                 q = newAssignment(mb);
    4910        1101 :                 if (q == NULL)
    4911           0 :                         goto bailout;
    4912        1101 :                 getArg(q, 0) = cond->nr;
    4913        1101 :                 q->argc = q->retc = 1;
    4914        1101 :                 q->barrier = EXITsymbol;
    4915             :         }
    4916        1118 :         be->mvc_var = cond->flag; /* restore old mvc_var from before the barrier */
    4917        1118 :         bool enabled = be->mvc->sa->eb.enabled;
    4918        1118 :         be->mvc->sa->eb.enabled = false;
    4919        1118 :         stmt *s = stmt_create(be->mvc->sa, st_control_end);
    4920        1118 :         be->mvc->sa->eb.enabled = enabled;
    4921        1118 :         if(!s) {
    4922           0 :                 freeInstruction(q);
    4923           0 :                 goto bailout;
    4924             :         }
    4925        1118 :         s->op1 = cond;
    4926        1118 :         s->nr = getArg(q, 0);
    4927        1118 :         pushInstruction(mb, q);
    4928        1118 :         return s;
    4929             : 
    4930           0 :   bailout:
    4931           0 :         if (be->mvc->sa->eb.enabled)
    4932           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4933             :         return NULL;
    4934             : }
    4935             : 
    4936             : 
    4937             : static InstrPtr
    4938         206 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
    4939             : {
    4940         206 :         int i;
    4941         206 :         node *n;
    4942             : 
    4943         206 :         if (q == NULL)
    4944             :                 return NULL;
    4945         206 :         q->retc = q->argc = 0;
    4946        1651 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4947        1445 :                 stmt *c = n->data;
    4948             : 
    4949        1445 :                 q = pushArgument(mb, q, c->nr);
    4950             :         }
    4951         206 :         if (q == NULL)
    4952             :                 return NULL;
    4953         206 :         q->retc = q->argc;
    4954             :         /* Let's make it a proper assignment */
    4955        1651 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4956        1445 :                 stmt *c = n->data;
    4957             : 
    4958        1445 :                 q = pushArgument(mb, q, c->nr);
    4959             :         }
    4960             :         return q;
    4961             : }
    4962             : 
    4963             : stmt *
    4964         658 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
    4965             : {
    4966         658 :         MalBlkPtr mb = be->mb;
    4967         658 :         InstrPtr q = NULL;
    4968             : 
    4969         658 :         if (val->nr < 0)
    4970           0 :                 goto bailout;
    4971         658 :         int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
    4972         206 :         if (args < MAXARG)
    4973             :                 args = MAXARG;
    4974         658 :         q = newInstructionArgs(mb, NULL, NULL, args);
    4975         658 :         if (q == NULL)
    4976           0 :                 goto bailout;
    4977         658 :         q->barrier= RETURNsymbol;
    4978         658 :         if (val->type == st_table) {
    4979         206 :                 list *l = val->op1->op4.lval;
    4980             : 
    4981         206 :                 q = dump_cols(mb, l, q);
    4982             :         } else {
    4983         452 :                 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
    4984         452 :                 q = pushArgument(mb, q, val->nr);
    4985             :         }
    4986             : 
    4987         658 :         bool enabled = be->mvc->sa->eb.enabled;
    4988         658 :         be->mvc->sa->eb.enabled = false;
    4989         658 :         stmt *s = stmt_create(be->mvc->sa, st_return);
    4990         658 :         be->mvc->sa->eb.enabled = enabled;
    4991         658 :         if(!s) {
    4992           0 :                 freeInstruction(q);
    4993           0 :                 goto bailout;
    4994             :         }
    4995         658 :         s->op1 = val;
    4996         658 :         s->flag = nr_declared_tables;
    4997         658 :         s->nr = getDestVar(q);
    4998         658 :         s->q = q;
    4999         658 :         pushInstruction(mb, q);
    5000         658 :         return s;
    5001             : 
    5002           0 :   bailout:
    5003           0 :         if (be->mvc->sa->eb.enabled)
    5004           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5005             :         return NULL;
    5006             : }
    5007             : 
    5008             : stmt *
    5009        1418 : stmt_assign(backend *be, const char *sname, const char *varname, stmt *val, int level)
    5010             : {
    5011        1418 :         MalBlkPtr mb = be->mb;
    5012        1418 :         InstrPtr q = NULL;
    5013             : 
    5014        1418 :         if (val && val->nr < 0)
    5015           0 :                 goto bailout;
    5016        1418 :         if (level != 0) {
    5017        1037 :                 char *buf,  levelstr[16];
    5018             : 
    5019        1037 :                 if (!val) {
    5020             :                         /* drop declared table */
    5021           0 :                         assert(0);
    5022             :                 }
    5023             : 
    5024        1037 :                 assert(!sname);
    5025        1037 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
    5026        1037 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
    5027        1037 :                 if (!buf)
    5028           0 :                         goto bailout;
    5029        1037 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
    5030        1037 :                 q = newInstruction(mb, NULL, NULL);
    5031        1037 :                 if (q == NULL) {
    5032           0 :                         goto bailout;
    5033             :                 }
    5034        1037 :                 q->argc = q->retc = 0;
    5035        1037 :                 q = pushArgumentId(mb, q, buf);
    5036        1037 :                 pushInstruction(mb, q);
    5037        1037 :                 q->retc++;
    5038             :         } else {
    5039         381 :                 assert(sname); /* all global variables have a schema */
    5040         381 :                 q = newStmt(mb, sqlRef, setVariableRef);
    5041         381 :                 if (q == NULL)
    5042           0 :                         goto bailout;
    5043         381 :                 q = pushArgument(mb, q, be->mvc_var);
    5044         381 :                 q = pushStr(mb, q, sname);
    5045         381 :                 q = pushStr(mb, q, varname);
    5046         381 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    5047         381 :                 pushInstruction(mb, q);
    5048         381 :                 be->mvc_var = getDestVar(q);
    5049             :         }
    5050        1418 :         q = pushArgument(mb, q, val->nr);
    5051             : 
    5052        1418 :         bool enabled = be->mvc->sa->eb.enabled;
    5053        1418 :         be->mvc->sa->eb.enabled = false;
    5054        1418 :         stmt *s = stmt_create(be->mvc->sa, st_assign);
    5055        1418 :         be->mvc->sa->eb.enabled = enabled;
    5056        1418 :         if(!s) {
    5057           0 :                 goto bailout;
    5058             :         }
    5059        1418 :         s->op2 = val;
    5060        1418 :         s->flag = (level << 1);
    5061        1418 :         s->q = q;
    5062        1418 :         s->nr = 1;
    5063        1418 :         return s;
    5064             : 
    5065           0 :   bailout:
    5066           0 :         if (be->mvc->sa->eb.enabled)
    5067           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5068             :         return NULL;
    5069             : }
    5070             : 
    5071             : stmt *
    5072       19970 : const_column(backend *be, stmt *val)
    5073             : {
    5074       19970 :         sql_subtype *ct = tail_type(val);
    5075       19970 :         MalBlkPtr mb = be->mb;
    5076       19970 :         InstrPtr q = NULL;
    5077       19970 :         int tt = ct->type->localtype;
    5078             : 
    5079       19970 :         if (val->nr < 0)
    5080           0 :                 goto bailout;
    5081       19970 :         q = newStmt(mb, batRef, singleRef);
    5082       19970 :         if (q == NULL)
    5083           0 :                 goto bailout;
    5084       19970 :         setVarType(mb, getArg(q, 0), newBatType(tt));
    5085       19970 :         q = pushArgument(mb, q, val->nr);
    5086             : 
    5087       19970 :         bool enabled = be->mvc->sa->eb.enabled;
    5088       19970 :         be->mvc->sa->eb.enabled = false;
    5089       19970 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5090       19970 :         be->mvc->sa->eb.enabled = enabled;
    5091       19970 :         if(!s) {
    5092           0 :                 freeInstruction(q);
    5093           0 :                 goto bailout;
    5094             :         }
    5095       19970 :         s->op1 = val;
    5096       19970 :         s->op4.typeval = *ct;
    5097       19970 :         s->nrcols = 1;
    5098             : 
    5099       19970 :         s->tname = val->tname;
    5100       19970 :         s->cname = val->cname;
    5101       19970 :         s->nr = getDestVar(q);
    5102       19970 :         s->q = q;
    5103       19970 :         pushInstruction(mb, q);
    5104       19970 :         return s;
    5105             : 
    5106           0 :   bailout:
    5107           0 :         if (be->mvc->sa->eb.enabled)
    5108           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5109             :         return NULL;
    5110             : }
    5111             : 
    5112             : stmt *
    5113          10 : stmt_fetch(backend *be, stmt *val)
    5114             : {
    5115          10 :         sql_subtype *ct;
    5116          10 :         MalBlkPtr mb = be->mb;
    5117          10 :         InstrPtr q = NULL;
    5118          10 :         int tt;
    5119             : 
    5120          10 :         if (val->nr < 0)
    5121           0 :                 goto bailout;
    5122             :         /* pick from first column on a table case */
    5123          10 :         if (val->type == st_table) {
    5124           0 :                 if (list_length(val->op1->op4.lval) > 1)
    5125           0 :                         goto bailout;
    5126           0 :                 val = val->op1->op4.lval->h->data;
    5127             :         }
    5128          10 :         ct = tail_type(val);
    5129          10 :         tt = ct->type->localtype;
    5130             : 
    5131          10 :         q = newStmt(mb, algebraRef, fetchRef);
    5132          10 :         if (q == NULL)
    5133           0 :                 goto bailout;
    5134          10 :         setVarType(mb, getArg(q, 0), tt);
    5135          10 :         q = pushArgument(mb, q, val->nr);
    5136          10 :         q = pushOid(mb, q, 0);
    5137             : 
    5138          10 :         bool enabled = be->mvc->sa->eb.enabled;
    5139          10 :         be->mvc->sa->eb.enabled = false;
    5140          10 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5141          10 :         be->mvc->sa->eb.enabled = enabled;
    5142          10 :         if(!s) {
    5143           0 :                 freeInstruction(q);
    5144           0 :                 goto bailout;
    5145             :         }
    5146          10 :         s->op1 = val;
    5147          10 :         s->op4.typeval = *ct;
    5148          10 :         s->nrcols = 0;
    5149             : 
    5150          10 :         s->tname = val->tname;
    5151          10 :         s->cname = val->cname;
    5152          10 :         s->nr = getDestVar(q);
    5153          10 :         s->q = q;
    5154          10 :         pushInstruction(mb, q);
    5155          10 :         return s;
    5156             : 
    5157           0 :   bailout:
    5158           0 :         if (be->mvc->sa->eb.enabled)
    5159           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5160             :         return NULL;
    5161             : }
    5162             : 
    5163             : stmt *
    5164     1518373 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    5165             : {
    5166     1518373 :         int label = exp_get_label(exp);
    5167     1518400 :         const char *name = exp_name(exp);
    5168     1518392 :         const char *rname = exp_relname(exp);
    5169     1518377 :         stmt *o = s;
    5170             : 
    5171     1518377 :         if (!name && exp_is_atom(exp))
    5172           0 :                 name = sa_strdup(be->mvc->sa, "single_value");
    5173           0 :         assert(name);
    5174     1518377 :         s = stmt_alias(be, s, label, rname, name);
    5175     1518358 :         if (o->flag & OUTER_ZERO)
    5176         521 :                 s->flag |= OUTER_ZERO;
    5177     1518358 :         return s;
    5178             : }

Generated by: LCOV version 1.14