LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2836 3411 83.1 %
Date: 2024-04-26 00:35:57 Functions: 107 109 98.2 %

          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       16406 : convertMultiplexMod(const char *mod, const char *op)
      32             : {
      33       16406 :         if (strcmp(op, "=") == 0)
      34           0 :                 return "calc";
      35             :         return mod;
      36             : }
      37             : 
      38             : static const char *
      39      236573 : convertMultiplexFcn(const char *op)
      40             : {
      41      236573 :         if (strcmp(op, "=") == 0)
      42       25761 :                 return "==";
      43             :         return op;
      44             : }
      45             : 
      46             : static InstrPtr
      47       16332 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
      48             : {
      49       16332 :         InstrPtr q = NULL;
      50             : 
      51       16332 :         q = newStmt(mb, malRef, multiplexRef);
      52       16332 :         if (q == NULL)
      53             :                 return NULL;
      54       16332 :         setVarType(mb, getArg(q, 0), newBatType(rtype));
      55       16332 :         q = pushStr(mb, q, convertMultiplexMod(mod, name));
      56       16332 :         q = pushStr(mb, q, convertMultiplexFcn(name));
      57       16332 :         q = pushArgument(mb, q, o1);
      58       16332 :         q = pushArgument(mb, q, o2);
      59       16332 :         pushInstruction(mb, q);
      60       16332 :         return q;
      61             : }
      62             : 
      63             : static InstrPtr
      64       42129 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
      65             : {
      66       42129 :         InstrPtr q = NULL;
      67             : 
      68       42129 :         if (o1 == NULL || o1->nr < 0)
      69             :                 return NULL;
      70       42129 :         q = newStmt(mb, mod, name);
      71       42129 :         q = pushArgument(mb, q, o1->nr);
      72       42129 :         pushInstruction(mb, q);
      73       42129 :         return q;
      74             : }
      75             : 
      76             : static InstrPtr
      77      150623 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
      78             : {
      79      150623 :         InstrPtr q = NULL;
      80             : 
      81      150623 :         if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
      82             :                 return NULL;
      83      150623 :         q = newStmt(mb, mod, name);
      84      150623 :         q = pushArgument(mb, q, o1->nr);
      85      150623 :         q = pushArgument(mb, q, o2->nr);
      86      150623 :         pushInstruction(mb, q);
      87      150623 :         return q;
      88             : }
      89             : 
      90             : static InstrPtr
      91         263 : pushPtr(MalBlkPtr mb, InstrPtr q, ptr val)
      92             : {
      93         263 :         int _t;
      94         263 :         ValRecord cst;
      95             : 
      96         263 :         if (q == NULL || mb->errors)
      97             :                 return q;
      98         263 :         cst.vtype= TYPE_ptr;
      99         263 :         cst.val.pval = val;
     100         263 :         cst.len = 0;
     101         263 :         _t = defConstant(mb, TYPE_ptr, &cst);
     102         263 :         if( _t >= 0)
     103         263 :                 return pushArgument(mb, q, _t);
     104             :         return q;
     105             : }
     106             : 
     107             : static InstrPtr
     108     2084567 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
     109             : {
     110     2084567 :         if (t->s)
     111     2084567 :                 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       13843 : stmt_key(stmt *s)
     118             : {
     119       13843 :         const char *nme = column_name(NULL, s);
     120             : 
     121       13843 :         return hash_key(nme);
     122             : }
     123             : 
     124             : /* #TODO make proper traversal operations */
     125             : stmt *
     126         204 : stmt_atom_string(backend *be, const char *S)
     127             : {
     128         204 :         const char *s = sa_strdup(be->mvc->sa, S);
     129         204 :         sql_subtype t;
     130             : 
     131         204 :         if (s == NULL)
     132             :                 return NULL;
     133         204 :         sql_find_subtype(&t, "varchar", _strlen(s), 0);
     134         204 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, s));
     135             : }
     136             : 
     137             : stmt *
     138       18754 : stmt_atom_string_nil(backend *be)
     139             : {
     140       18754 :         sql_subtype t;
     141             : 
     142       18754 :         sql_find_subtype(&t, "varchar", 0, 0);
     143       18754 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
     144             : }
     145             : 
     146             : stmt *
     147        4931 : stmt_atom_int(backend *be, int i)
     148             : {
     149        4931 :         sql_subtype t;
     150             : 
     151        4931 :         sql_find_subtype(&t, "int", 32, 0);
     152        4931 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     153             : }
     154             : 
     155             : stmt *
     156      115240 : stmt_atom_lng(backend *be, lng i)
     157             : {
     158      115240 :         sql_subtype t;
     159             : 
     160      115240 :         sql_find_subtype(&t, "bigint", 64, 0);
     161      115271 :         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       32972 : stmt_bool(backend *be, int b)
     175             : {
     176       32972 :         sql_subtype t;
     177             : 
     178       32972 :         sql_find_subtype(&t, "boolean", 0, 0);
     179             : 
     180       32972 :         if (b == bit_nil) {
     181           0 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
     182       32972 :         } else if (b) {
     183       32017 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
     184             :         } else {
     185         955 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
     186             :         }
     187             : }
     188             : 
     189             : static stmt *
     190    13044039 : stmt_create(allocator *sa, st_type type)
     191             : {
     192    13044039 :         stmt *s = SA_NEW(sa, stmt);
     193             : 
     194    13043485 :         if (!s)
     195             :                 return NULL;
     196    13043485 :         *s = (stmt) {
     197             :                 .type = type,
     198             :         };
     199    13043485 :         return s;
     200             : }
     201             : 
     202             : stmt *
     203       26418 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
     204             : {
     205       26418 :         MalBlkPtr mb = be->mb;
     206       26418 :         InstrPtr q = NULL;
     207             : 
     208       26418 :         if (s == NULL || s->nr < 0)
     209           0 :                 goto bailout;
     210       26418 :         if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
     211           0 :                 goto bailout;
     212             : 
     213       26418 :         q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
     214       26418 :         if (q == NULL)
     215           0 :                 goto bailout;
     216             : 
     217             :         /* output variables extent and hist */
     218       26418 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     219       26418 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     220       26418 :         q = pushArgument(mb, q, s->nr);
     221       26418 :         if (grp)
     222        5570 :                 q = pushArgument(mb, q, grp->nr);
     223             : 
     224       26418 :         bool enabled = be->mvc->sa->eb.enabled;
     225       26418 :         be->mvc->sa->eb.enabled = false;
     226       26418 :         stmt *ns = stmt_create(be->mvc->sa, st_group);
     227       26418 :         be->mvc->sa->eb.enabled = enabled;
     228       26418 :         if (ns == NULL) {
     229           0 :                 freeInstruction(q);
     230           0 :                 goto bailout;
     231             :         }
     232             : 
     233       26418 :         ns->op1 = s;
     234             : 
     235       26418 :         if (grp) {
     236        5570 :                 ns->op2 = grp;
     237        5570 :                 ns->op3 = ext;
     238        5570 :                 ns->op4.stval = cnt;
     239             :         }
     240       26418 :         ns->nrcols = s->nrcols;
     241       26418 :         ns->key = 0;
     242       26418 :         ns->q = q;
     243       26418 :         ns->nr = getDestVar(q);
     244       26418 :         pushInstruction(mb, q);
     245       26418 :         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          67 : stmt_unique(backend *be, stmt *s)
     255             : {
     256          67 :         MalBlkPtr mb = be->mb;
     257          67 :         InstrPtr q = NULL;
     258             : 
     259          67 :         if (s == NULL || s->nr < 0)
     260           0 :                 goto bailout;
     261             : 
     262          67 :         q = newStmt(mb, algebraRef, uniqueRef);
     263          67 :         if (q == NULL)
     264           0 :                 goto bailout;
     265             : 
     266          67 :         q = pushArgument(mb, q, s->nr);
     267          67 :         q = pushNilBat(mb, q); /* candidate list */
     268             : 
     269          67 :         bool enabled = be->mvc->sa->eb.enabled;
     270          67 :         be->mvc->sa->eb.enabled = false;
     271          67 :         stmt *ns = stmt_create(be->mvc->sa, st_unique);
     272          67 :         be->mvc->sa->eb.enabled = enabled;
     273          67 :         if (ns == NULL) {
     274           0 :                 freeInstruction(q);
     275           0 :                 goto bailout;
     276             :         }
     277             : 
     278          67 :         ns->op1 = s;
     279          67 :         ns->nrcols = s->nrcols;
     280          67 :         ns->key = 1;
     281          67 :         ns->q = q;
     282          67 :         ns->nr = getDestVar(q);
     283          67 :         pushInstruction(mb, q);
     284          67 :         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        2415 : stmt_var(backend *be, const char *sname, const char *varname, sql_subtype *t, int declare, int level)
     336             : {
     337        2415 :         MalBlkPtr mb = be->mb;
     338        2415 :         InstrPtr q = NULL;
     339        2415 :         char *buf;
     340             : 
     341        2415 :         if (level == 0) { /* global */
     342         313 :                 int tt = t->type->localtype;
     343             : 
     344         313 :                 assert(sname);
     345         313 :                 q = newStmt(mb, sqlRef, getVariableRef);
     346         313 :                 if (q == NULL)
     347           0 :                         goto bailout;
     348         313 :                 q = pushArgument(mb, q, be->mvc_var);
     349         313 :                 q = pushStr(mb, q, sname); /* all global variables have a schema */
     350         313 :                 q = pushStr(mb, q, varname);
     351         313 :                 setVarType(mb, getArg(q, 0), tt);
     352        2102 :         } else if (!declare) {
     353        1741 :                 char levelstr[16];
     354             : 
     355        1741 :                 assert(!sname);
     356        1741 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     357        1741 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     358        1741 :                 if (!buf)
     359           1 :                         goto bailout;
     360        1741 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     361        1741 :                 q = newAssignment(mb);
     362        1743 :                 if (q == NULL)
     363           1 :                         goto bailout;
     364        1742 :                 q = pushArgumentId(mb, q, buf);
     365             :         } else {
     366         361 :                 int tt = t->type->localtype;
     367         361 :                 char levelstr[16];
     368             : 
     369         361 :                 assert(!sname);
     370         361 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     371         361 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     372         361 :                 if (!buf)
     373           0 :                         goto bailout;
     374         361 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     375             : 
     376         361 :                 q = newInstruction(mb, NULL, NULL);
     377         362 :                 if (q == NULL) {
     378           0 :                         goto bailout;
     379             :                 }
     380         362 :                 q->argc = q->retc = 0;
     381         362 :                 q = pushArgumentId(mb, q, buf);
     382         362 :                 q = pushNil(mb, q, tt);
     383         360 :                 q->retc++;
     384             :         }
     385        2415 :         bool enabled = be->mvc->sa->eb.enabled;
     386        2415 :         be->mvc->sa->eb.enabled = false;
     387        2415 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     388        2414 :         be->mvc->sa->eb.enabled = enabled;
     389        2414 :         if (s == NULL) {
     390           0 :                 freeInstruction(q);
     391           0 :                 goto bailout;
     392             :         }
     393             : 
     394        2414 :         if (t)
     395        2414 :                 s->op4.typeval = *t;
     396             :         else
     397           0 :                 s->op4.typeval.type = NULL;
     398        2414 :         s->flag = declare + (level << 1);
     399        2414 :         s->key = 1;
     400        2414 :         s->q = q;
     401        2414 :         s->nr = getDestVar(q);
     402        2414 :         pushInstruction(mb, q);
     403        2414 :         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        1560 : stmt_varnr(backend *be, int nr, sql_subtype *t)
     443             : {
     444        1560 :         MalBlkPtr mb = be->mb;
     445        1560 :         InstrPtr q = newAssignment(mb);
     446        1560 :         char buf[IDLENGTH];
     447             : 
     448        1560 :         if (q == NULL)
     449           0 :                 goto bailout;
     450             : 
     451        1560 :         (void) snprintf(buf, sizeof(buf), "A%d", nr);
     452        1560 :         q = pushArgumentId(mb, q, buf);
     453             : 
     454        1560 :         bool enabled = be->mvc->sa->eb.enabled;
     455        1560 :         be->mvc->sa->eb.enabled = false;
     456        1560 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     457        1560 :         be->mvc->sa->eb.enabled = enabled;
     458        1560 :         if (s == NULL) {
     459           0 :                 freeInstruction(q);
     460           0 :                 goto bailout;
     461             :         }
     462             : 
     463        1560 :         s->op1 = NULL;
     464        1560 :         if (t)
     465        1560 :                 s->op4.typeval = *t;
     466             :         else
     467           0 :                 s->op4.typeval.type = NULL;
     468        1560 :         s->flag = nr;
     469        1560 :         s->key = 1;
     470        1560 :         s->q = q;
     471        1560 :         s->nr = getDestVar(q);
     472        1560 :         pushInstruction(mb, q);
     473        1560 :         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         662 : stmt_table(backend *be, stmt *cols, int temp)
     483             : {
     484         662 :         MalBlkPtr mb = be->mb;
     485             : 
     486         662 :         if (cols == NULL || cols->nr < 0)
     487           0 :                 goto bailout;
     488             : 
     489         662 :         stmt *s = stmt_create(be->mvc->sa, st_table);
     490             : 
     491         663 :         if (s == NULL)
     492           0 :                 goto bailout;
     493             : 
     494         663 :         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         663 :         s->op1 = cols;
     506         663 :         s->flag = temp;
     507         663 :         s->nr = cols->nr;
     508         663 :         s->nrcols = cols->nrcols;
     509         663 :         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      229860 : stmt_temp(backend *be, sql_subtype *t)
     519             : {
     520      229860 :         int tt = t->type->localtype;
     521      229860 :         MalBlkPtr mb = be->mb;
     522      229860 :         InstrPtr q = newStmt(mb, batRef, newRef);
     523             : 
     524      230784 :         if (q == NULL)
     525           0 :                 goto bailout;
     526      230784 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     527      230784 :         q = pushType(mb, q, tt);
     528      230631 :         bool enabled = be->mvc->sa->eb.enabled;
     529      230631 :         be->mvc->sa->eb.enabled = false;
     530      230631 :         stmt *s = stmt_create(be->mvc->sa, st_temp);
     531      230527 :         be->mvc->sa->eb.enabled = enabled;
     532             : 
     533      230527 :         if (s == NULL) {
     534           0 :                 freeInstruction(q);
     535           0 :                 goto bailout;
     536             :         }
     537      230527 :         s->op4.typeval = *t;
     538      230527 :         s->nrcols = 1;
     539      230527 :         s->q = q;
     540      230527 :         s->nr = getDestVar(q);
     541      230527 :         pushInstruction(mb, q);
     542      230527 :         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      194713 : stmt_tid(backend *be, sql_table *t, int partition)
     569             : {
     570      194713 :         int tt = TYPE_oid;
     571      194713 :         MalBlkPtr mb = be->mb;
     572      194713 :         InstrPtr q;
     573             : 
     574      194713 :         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      194697 :         q = newStmt(mb, sqlRef, tidRef);
     589      194830 :         if (q == NULL)
     590           0 :                 goto bailout;
     591      194830 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     592      194830 :         q = pushArgument(mb, q, be->mvc_var);
     593      194830 :         q = pushSchema(mb, q, t);
     594      194816 :         q = pushStr(mb, q, t->base.name);
     595      194807 :         if (t && isTable(t) && partition) {
     596       71619 :                 sql_trans *tr = be->mvc->session->tr;
     597       71619 :                 sqlstore *store = tr->store;
     598       71619 :                 BUN rows = (BUN) store->storage_api.count_col(tr, ol_first_node(t->columns)->data, RDONLY);
     599       71622 :                 setRowCnt(mb,getArg(q,0),rows);
     600             :         }
     601             : 
     602      194810 :         bool enabled = be->mvc->sa->eb.enabled;
     603      194810 :         be->mvc->sa->eb.enabled = false;
     604      194810 :         stmt *s = stmt_create(be->mvc->sa, st_tid);
     605      194700 :         be->mvc->sa->eb.enabled = enabled;
     606      194700 :         if (s == NULL) {
     607           0 :                 freeInstruction(q);
     608           0 :                 goto bailout;
     609             :         }
     610             : 
     611      194700 :         s->partition = partition;
     612      194700 :         s->op4.tval = t;
     613      194700 :         s->nrcols = 1;
     614      194700 :         s->nr = getDestVar(q);
     615      194700 :         s->q = q;
     616      194700 :         pushInstruction(mb, q);
     617      194700 :         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      909121 : find_real_column(backend *be, sql_column *c)
     627             : {
     628      909121 :         if (c && c->t && c->t->s && c->t->persistence == SQL_DECLARED_TABLE) {
     629       36546 :                 sql_table *nt = find_sql_table_id(be->mvc->session->tr, c->t->s, c->t->base.id);
     630       36546 :                 if (nt) {
     631       36546 :                         node *n = ol_find_id(nt->columns, c->base.id);
     632       36546 :                         if (n)
     633       36546 :                                 return n->data;
     634             :                 }
     635             :         }
     636             :         return c;
     637             : }
     638             : 
     639             : stmt *
     640      909112 : stmt_bat(backend *be, sql_column *c, int access, int partition)
     641             : {
     642      909112 :         int tt = c->type.type->localtype;
     643      909112 :         MalBlkPtr mb = be->mb;
     644      909112 :         InstrPtr q;
     645             : 
     646      909112 :         c = find_real_column(be, c);
     647             : 
     648      909143 :         if (access == RD_EXT)
     649         172 :                 partition = 0;
     650             : 
     651             :         /* for read access tid.project(col) */
     652      909143 :         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      909120 :         q = newStmtArgs(mb, sqlRef, bindRef, 9);
     670      909195 :         if (q == NULL)
     671           0 :                 goto bailout;
     672      909195 :         if (c->storage_type && access != RD_EXT) {
     673         360 :                 sql_trans *tr = be->mvc->session->tr;
     674         360 :                 sqlstore *store = tr->store;
     675         360 :                 BAT *b = store->storage_api.bind_col(tr, c, QUICK);
     676         360 :                 if (!b) {
     677           0 :                         freeInstruction(q);
     678           0 :                         goto bailout;
     679             :                 }
     680         360 :                 tt = b->ttype;
     681             :         }
     682      909023 :         if (access == RD_UPD_ID) {
     683      442348 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     684             :         } else {
     685      466847 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     686             :         }
     687      909196 :         q = pushArgument(mb, q, be->mvc_var);
     688      909165 :         q = pushSchema(mb, q, c->t);
     689      909185 :         q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
     690      909187 :         q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
     691      909154 :         q = pushArgument(mb, q, getIntConstant(mb,access));
     692             : 
     693      909139 :         if (access == RD_UPD_ID) {
     694      442334 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     695             :         }
     696      909139 :         if (partition) {
     697      521046 :                 sql_trans *tr = be->mvc->session->tr;
     698      521046 :                 sqlstore *store = tr->store;
     699             : 
     700      521046 :                 if (c && isTable(c->t)) {
     701      521052 :                         BUN rows = (BUN) store->storage_api.count_col(tr, c, QUICK);
     702      521081 :                         setRowCnt(mb,getArg(q,0),rows);
     703             :                 }
     704             :         }
     705             : 
     706      909168 :         bool enabled = be->mvc->sa->eb.enabled;
     707      909168 :         be->mvc->sa->eb.enabled = false;
     708      909168 :         stmt *s = stmt_create(be->mvc->sa, st_bat);
     709      909050 :         be->mvc->sa->eb.enabled = enabled;
     710      909050 :         if (s == NULL) {
     711           0 :                 freeInstruction(q);
     712           0 :                 goto bailout;
     713             :         }
     714             : 
     715      909050 :         s->partition = partition;
     716      909050 :         s->op4.cval = c;
     717      909050 :         s->nrcols = 1;
     718      909050 :         s->flag = access;
     719      909050 :         s->nr = getDestVar(q);
     720      909050 :         s->q = q;
     721      909050 :         s->tname = c->t->base.name;
     722      909050 :         s->cname = c->base.name;
     723      909050 :         pushInstruction(mb, q);
     724      909050 :         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        6405 : stmt_idxbat(backend *be, sql_idx *i, int access, int partition)
     734             : {
     735        6405 :         int tt = hash_index(i->type)?TYPE_lng:TYPE_oid;
     736        6405 :         MalBlkPtr mb = be->mb;
     737        6405 :         InstrPtr q = newStmtArgs(mb, sqlRef, bindidxRef, 9);
     738             : 
     739        6405 :         if (q == NULL)
     740           0 :                 goto bailout;
     741             : 
     742        6405 :         if (access == RD_UPD_ID) {
     743        2848 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     744             :         } else {
     745        3557 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     746             :         }
     747             : 
     748        6405 :         q = pushArgument(mb, q, be->mvc_var);
     749        6405 :         q = pushSchema(mb, q, i->t);
     750        6405 :         q = pushArgument(mb, q, getStrConstant(mb, i->t->base.name));
     751        6405 :         q = pushArgument(mb, q, getStrConstant(mb, i->base.name));
     752        6405 :         q = pushArgument(mb, q, getIntConstant(mb, access));
     753             : 
     754        6405 :         if (access == RD_UPD_ID) {
     755        2848 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     756             :         }
     757        6405 :         if (partition) {
     758        3301 :                 sql_trans *tr = be->mvc->session->tr;
     759        3301 :                 sqlstore *store = tr->store;
     760             : 
     761        3301 :                 if (i && isTable(i->t)) {
     762        3301 :                         BUN rows = (BUN) store->storage_api.count_idx(tr, i, QUICK);
     763        3301 :                         setRowCnt(mb,getArg(q,0),rows);
     764             :                 }
     765             :         }
     766             : 
     767        6405 :         bool enabled = be->mvc->sa->eb.enabled;
     768        6405 :         be->mvc->sa->eb.enabled = false;
     769        6405 :         stmt *s = stmt_create(be->mvc->sa, st_idxbat);
     770        6405 :         be->mvc->sa->eb.enabled = enabled;
     771        6405 :         if (s == NULL) {
     772           0 :                 freeInstruction(q);
     773           0 :                 goto bailout;
     774             :         }
     775             : 
     776        6405 :         s->partition = partition;
     777        6405 :         s->op4.idxval = i;
     778        6405 :         s->nrcols = 1;
     779        6405 :         s->flag = access;
     780        6405 :         s->nr = getDestVar(q);
     781        6405 :         s->q = q;
     782        6405 :         s->tname = i->t->base.name;
     783        6405 :         s->cname = i->base.name;
     784        6405 :         pushInstruction(mb, q);
     785        6405 :         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      657889 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
     795             : {
     796      657889 :         MalBlkPtr mb = be->mb;
     797      657889 :         InstrPtr q = NULL;
     798             : 
     799      657889 :         if (b == NULL || b->nr < 0)
     800           0 :                 goto bailout;
     801             : 
     802      657889 :         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      657866 :         } else if (!fake) {     /* fake append */
     821      657866 :                 if (offset == NULL || offset->nr < 0)
     822           0 :                         goto bailout;
     823      657866 :                 q = newStmt(mb, sqlRef, appendRef);
     824      658510 :                 if (q == NULL)
     825           0 :                         goto bailout;
     826      658510 :                 q = pushArgument(mb, q, be->mvc_var);
     827      658507 :                 int tmpvar = newTmpVariable(mb, TYPE_int);
     828      658511 :                 getArg(q, 0) = tmpvar;
     829      658511 :                 if (mvc_var_update != NULL)
     830      658511 :                         *mvc_var_update = tmpvar;
     831      658511 :                 q = pushSchema(mb, q, c->t);
     832      658468 :                 q = pushStr(mb, q, c->t->base.name);
     833      658496 :                 q = pushStr(mb, q, c->base.name);
     834      658379 :                 q = pushArgument(mb, q, offset->nr);
     835             :                 /* also the offsets */
     836      658419 :                 assert(offset->q->retc == 2);
     837      658419 :                 q = pushArgument(mb, q, getArg(offset->q, 1));
     838      658398 :                 q = pushArgument(mb, q, b->nr);
     839      658388 :                 if (mvc_var_update != NULL)
     840      658388 :                         *mvc_var_update = getDestVar(q);
     841             :         } else {
     842             :                 return b;
     843             :         }
     844      658411 :         bool enabled = be->mvc->sa->eb.enabled;
     845      658411 :         be->mvc->sa->eb.enabled = false;
     846      658411 :         stmt *s = stmt_create(be->mvc->sa, st_append_col);
     847      658204 :         be->mvc->sa->eb.enabled = enabled;
     848             : 
     849      658204 :         if (s == NULL) {
     850           0 :                 freeInstruction(q);
     851           0 :                 goto bailout;
     852             :         }
     853      658204 :         s->op1 = b;
     854      658204 :         s->op2 = offset;
     855      658204 :         s->op4.cval = c;
     856      658204 :         s->q = q;
     857      658204 :         s->nr = getDestVar(q);
     858      658204 :         pushInstruction(mb, q);
     859      658204 :         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        2211 : stmt_append_idx(backend *be, sql_idx *i, stmt *offset, stmt *b)
     869             : {
     870        2211 :         MalBlkPtr mb = be->mb;
     871        2211 :         InstrPtr q = NULL;
     872             : 
     873        2211 :         if (offset == NULL || b == NULL || offset->nr < 0 || b->nr < 0)
     874           0 :                 goto bailout;
     875             : 
     876        2211 :         q = newStmt(mb, sqlRef, appendRef);
     877        2211 :         if (q == NULL)
     878           0 :                 goto bailout;
     879        2211 :         q = pushArgument(mb, q, be->mvc_var);
     880        2211 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     881        2211 :         q = pushSchema(mb, q, i->t);
     882        2211 :         q = pushStr(mb, q, i->t->base.name);
     883        2211 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
     884        2211 :         q = pushArgument(mb, q, offset->nr);
     885             :         /* also the offsets */
     886        2211 :         assert(offset->q->retc == 2);
     887        2211 :         q = pushArgument(mb, q, getArg(offset->q, 1));
     888        2211 :         q = pushArgument(mb, q, b->nr);
     889        2211 :         be->mvc_var = getDestVar(q);
     890             : 
     891        2211 :         bool enabled = be->mvc->sa->eb.enabled;
     892        2211 :         be->mvc->sa->eb.enabled = false;
     893        2211 :         stmt *s = stmt_create(be->mvc->sa, st_append_idx);
     894        2211 :         be->mvc->sa->eb.enabled = enabled;
     895        2211 :         if (s == NULL) {
     896           0 :                 freeInstruction(q);
     897           0 :                 goto bailout;
     898             :         }
     899             : 
     900        2211 :         s->op1 = b;
     901        2211 :         s->op2 = offset;
     902        2211 :         s->op4.idxval = i;
     903        2211 :         s->q = q;
     904        2211 :         s->nr = getDestVar(q);
     905        2211 :         pushInstruction(mb, q);
     906        2211 :         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        3305 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
     916             : {
     917        3305 :         MalBlkPtr mb = be->mb;
     918        3305 :         InstrPtr q = NULL;
     919             : 
     920        3305 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     921           0 :                 goto bailout;
     922             : 
     923        3306 :         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        3304 :                 q = newStmt(mb, sqlRef, updateRef);
     934        3304 :                 if (q == NULL)
     935           0 :                         goto bailout;
     936        3304 :                 q = pushArgument(mb, q, be->mvc_var);
     937        3304 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     938        3304 :                 q = pushSchema(mb, q, c->t);
     939        3304 :                 q = pushStr(mb, q, c->t->base.name);
     940        3304 :                 q = pushStr(mb, q, c->base.name);
     941        3304 :                 q = pushArgument(mb, q, tids->nr);
     942        3304 :                 q = pushArgument(mb, q, upd->nr);
     943        3304 :                 be->mvc_var = getDestVar(q);
     944             :         }
     945        3305 :         bool enabled = be->mvc->sa->eb.enabled;
     946        3305 :         be->mvc->sa->eb.enabled = false;
     947        3305 :         stmt *s = stmt_create(be->mvc->sa, st_update_col);
     948        3305 :         be->mvc->sa->eb.enabled = enabled;
     949             : 
     950        3305 :         if (s == NULL) {
     951           0 :                 freeInstruction(q);
     952           0 :                 goto bailout;
     953             :         }
     954        3305 :         s->op1 = tids;
     955        3305 :         s->op2 = upd;
     956        3305 :         s->op4.cval = c;
     957        3305 :         s->q = q;
     958        3305 :         s->nr = getDestVar(q);
     959        3305 :         pushInstruction(mb, q);
     960        3305 :         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         816 : stmt_update_idx(backend *be, sql_idx *i, stmt *tids, stmt *upd)
     971             : {
     972         816 :         MalBlkPtr mb = be->mb;
     973         816 :         InstrPtr q = NULL;
     974             : 
     975         816 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     976           0 :                 goto bailout;
     977             : 
     978         816 :         q = newStmt(mb, sqlRef, updateRef);
     979         816 :         if (q == NULL)
     980           0 :                 goto bailout;
     981         816 :         q = pushArgument(mb, q, be->mvc_var);
     982         816 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     983         816 :         q = pushSchema(mb, q, i->t);
     984         816 :         q = pushStr(mb, q, i->t->base.name);
     985         816 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
     986         816 :         q = pushArgument(mb, q, tids->nr);
     987         816 :         q = pushArgument(mb, q, upd->nr);
     988         816 :         be->mvc_var = getDestVar(q);
     989         816 :         bool enabled = be->mvc->sa->eb.enabled;
     990         816 :         be->mvc->sa->eb.enabled = false;
     991         816 :         stmt *s = stmt_create(be->mvc->sa, st_update_idx);
     992         816 :         be->mvc->sa->eb.enabled = enabled;
     993         816 :         if (s == NULL) {
     994           0 :                 freeInstruction(q);
     995           0 :                 goto bailout;
     996             :         }
     997             : 
     998         816 :         s->op1 = tids;
     999         816 :         s->op2 = upd;
    1000         816 :         s->op4.idxval = i;
    1001         816 :         s->q = q;
    1002         816 :         s->nr = getDestVar(q);
    1003         816 :         pushInstruction(mb, q);
    1004         816 :         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         352 : stmt_delete(backend *be, sql_table *t, stmt *tids)
    1014             : {
    1015         352 :         MalBlkPtr mb = be->mb;
    1016         352 :         InstrPtr q = NULL;
    1017             : 
    1018         352 :         if (tids == NULL || tids->nr < 0)
    1019           0 :                 goto bailout;
    1020             : 
    1021         353 :         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         351 :                 q = newStmt(mb, sqlRef, deleteRef);
    1031         351 :                 if (q == NULL)
    1032           0 :                         goto bailout;
    1033         351 :                 q = pushArgument(mb, q, be->mvc_var);
    1034         351 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    1035         351 :                 q = pushSchema(mb, q, t);
    1036         351 :                 q = pushStr(mb, q, t->base.name);
    1037         351 :                 q = pushArgument(mb, q, tids->nr);
    1038         351 :                 be->mvc_var = getDestVar(q);
    1039             :         }
    1040         352 :         bool enabled = be->mvc->sa->eb.enabled;
    1041         352 :         be->mvc->sa->eb.enabled = false;
    1042         352 :         stmt *s = stmt_create(be->mvc->sa, st_delete);
    1043         352 :         be->mvc->sa->eb.enabled = enabled;
    1044         352 :         if (s == NULL) {
    1045           0 :                 freeInstruction(q);
    1046           0 :                 goto bailout;
    1047             :         }
    1048             : 
    1049         352 :         s->op1 = tids;
    1050         352 :         s->op4.tval = t;
    1051         352 :         s->q = q;
    1052         352 :         s->nr = getDestVar(q);
    1053         352 :         pushInstruction(mb, q);
    1054         352 :         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       96238 : stmt_const(backend *be, stmt *s, stmt *val)
    1064             : {
    1065       96238 :         InstrPtr q = NULL;
    1066       96238 :         MalBlkPtr mb = be->mb;
    1067             : 
    1068       96238 :         if (s == NULL)
    1069           0 :                 goto bailout;
    1070       96238 :         if (val)
    1071       96238 :                 q = dump_2(mb, algebraRef, projectRef, s, val);
    1072             :         else
    1073           0 :                 q = dump_1(mb, algebraRef, projectRef, s);
    1074       96238 :         if (q) {
    1075       96238 :                 stmt *ns = stmt_create(be->mvc->sa, st_const);
    1076       96238 :                 if (ns == NULL) {
    1077           0 :                         goto bailout;
    1078             :                 }
    1079             : 
    1080       96238 :                 ns->op1 = s;
    1081       96238 :                 ns->op2 = val;
    1082       96238 :                 ns->nrcols = s->nrcols;
    1083       96238 :                 ns->key = s->key;
    1084       96238 :                 ns->aggr = s->aggr;
    1085       96238 :                 ns->q = q;
    1086       96238 :                 ns->nr = getDestVar(q);
    1087       96238 :                 ns->tname = val->tname;
    1088       96238 :                 ns->cname = val->cname;
    1089       96238 :                 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        2367 : stmt_gen_group(backend *be, stmt *gids, stmt *cnts)
    1099             : {
    1100        2367 :         MalBlkPtr mb = be->mb;
    1101             : 
    1102        2367 :         if (gids == NULL || cnts == NULL)
    1103           0 :                 goto bailout;
    1104             : 
    1105        2367 :         InstrPtr q = dump_2(mb, algebraRef, groupbyRef, gids, cnts);
    1106             : 
    1107        2367 :         if (q) {
    1108        2367 :                 stmt *ns = stmt_create(be->mvc->sa, st_gen_group);
    1109        2367 :                 if (ns == NULL) {
    1110           0 :                         goto bailout;
    1111             :                 }
    1112             : 
    1113        2367 :                 ns->op1 = gids;
    1114        2367 :                 ns->op2 = cnts;
    1115             : 
    1116        2367 :                 ns->nrcols = gids->nrcols;
    1117        2367 :                 ns->key = 0;
    1118        2367 :                 ns->aggr = 0;
    1119        2367 :                 ns->q = q;
    1120        2367 :                 ns->nr = getDestVar(q);
    1121        2367 :                 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       42129 : stmt_mirror(backend *be, stmt *s)
    1131             : {
    1132       42129 :         MalBlkPtr mb = be->mb;
    1133             : 
    1134       42129 :         if (s == NULL)
    1135           0 :                 goto bailout;
    1136             : 
    1137       42129 :         InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
    1138             : 
    1139       42129 :         if (q) {
    1140       42129 :                 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
    1141       42129 :                 if (ns == NULL) {
    1142           0 :                         goto bailout;
    1143             :                 }
    1144             : 
    1145       42129 :                 ns->op1 = s;
    1146       42129 :                 ns->nrcols = 2;
    1147       42129 :                 ns->key = s->key;
    1148       42129 :                 ns->aggr = s->aggr;
    1149       42129 :                 ns->q = q;
    1150       42129 :                 ns->nr = getDestVar(q);
    1151       42129 :                 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      299349 : stmt_result(backend *be, stmt *s, int nr)
    1162             : {
    1163      299349 :         stmt *ns;
    1164             : 
    1165      299349 :         if (s == NULL)
    1166             :                 return NULL;
    1167             : 
    1168      299349 :         if (s->type == st_join && s->flag == cmp_joined) {
    1169        4925 :                 if (nr)
    1170        2186 :                         return s->op2;
    1171        2739 :                 return s->op1;
    1172             :         }
    1173             : 
    1174      294424 :         if (s->op1->nr < 0)
    1175             :                 return NULL;
    1176             : 
    1177      294424 :         ns = stmt_create(be->mvc->sa, st_result);
    1178      294424 :         if(!ns) {
    1179             :                 return NULL;
    1180             :         }
    1181      294424 :         if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
    1182           0 :                 assert(0);
    1183      294424 :         } else if (nr) {
    1184      168524 :                 int v = getArg(s->q, nr);
    1185             : 
    1186      168524 :                 assert(s->q->retc > nr);
    1187      168524 :                 ns->nr = v;
    1188             :         } else {
    1189      125900 :                 ns->nr = s->nr;
    1190             :         }
    1191      294424 :         ns->op1 = s;
    1192      294424 :         if (!nr && (s->type == st_order || s->type == st_reorder))
    1193       22191 :                 ns->op4.typeval = *tail_type(s->op1);
    1194      168524 :         else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
    1195        2657 :                 ns->op4.typeval = *sql_bind_localtype("bit");
    1196             :         else
    1197      269576 :                 ns->op4.typeval = *sql_bind_localtype("oid");
    1198      294424 :         ns->flag = nr;
    1199      294424 :         ns->nrcols = s->nrcols;
    1200      294424 :         ns->key = s->key;
    1201      294424 :         ns->aggr = s->aggr;
    1202      294424 :         return ns;
    1203             : }
    1204             : 
    1205             : 
    1206             : /* limit maybe atom nil */
    1207             : stmt *
    1208       17601 : 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       17601 :         MalBlkPtr mb = be->mb;
    1211       17601 :         InstrPtr q = NULL;
    1212       17601 :         int l, p, g, c;
    1213             : 
    1214       17601 :         if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
    1215           0 :                 goto bailout;
    1216       17601 :         if (piv && (piv->nr < 0 || gid->nr < 0))
    1217           0 :                 goto bailout;
    1218             : 
    1219       17601 :         c = (col) ? col->nr : 0;
    1220       17601 :         p = (piv) ? piv->nr : 0;
    1221       17601 :         g = (gid) ? gid->nr : 0;
    1222             : 
    1223             :         /* first insert single value into a bat */
    1224       17601 :         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       17601 :         if (order) {
    1244         734 :                 int topn = 0;
    1245             : 
    1246         734 :                 q = newStmt(mb, calcRef, plusRef);
    1247         734 :                 if (q == NULL)
    1248           0 :                         goto bailout;
    1249         734 :                 q = pushArgument(mb, q, offset->nr);
    1250         734 :                 q = pushArgument(mb, q, limit->nr);
    1251         734 :                 topn = getDestVar(q);
    1252         734 :                 pushInstruction(mb, q);
    1253             : 
    1254         734 :                 q = newStmtArgs(mb, algebraRef, firstnRef, 9);
    1255         734 :                 if (q == NULL)
    1256           0 :                         goto bailout;
    1257         734 :                 if (!last) /* we need the groups for the next firstn */
    1258         387 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1259         734 :                 q = pushArgument(mb, q, c);
    1260         734 :                 if (p)
    1261         387 :                         q = pushArgument(mb, q, p);
    1262             :                 else
    1263         347 :                         q = pushNilBat(mb, q);
    1264         734 :                 if (g)
    1265         387 :                         q = pushArgument(mb, q, g);
    1266             :                 else
    1267         347 :                         q = pushNilBat(mb, q);
    1268         734 :                 q = pushArgument(mb, q, topn);
    1269         734 :                 q = pushBit(mb, q, dir);
    1270         734 :                 q = pushBit(mb, q, nullslast);
    1271         734 :                 q = pushBit(mb, q, distinct != 0);
    1272             : 
    1273         734 :                 l = getArg(q, 0);
    1274         734 :                 l = getDestVar(q);
    1275         734 :                 pushInstruction(mb, q);
    1276             :         } else {
    1277       16867 :                 int len;
    1278             : 
    1279       16867 :                 q = newStmt(mb, calcRef, plusRef);
    1280       16908 :                 if (q == NULL)
    1281           0 :                         goto bailout;
    1282       16908 :                 q = pushArgument(mb, q, offset->nr);
    1283       16907 :                 q = pushArgument(mb, q, limit->nr);
    1284       16907 :                 len = getDestVar(q);
    1285       16907 :                 pushInstruction(mb, q);
    1286             : 
    1287             :                 /* since both arguments of algebra.subslice are
    1288             :                    inclusive correct the LIMIT value by
    1289             :                    subtracting 1 */
    1290       16908 :                 q = newStmt(mb, calcRef, minusRef);
    1291       16908 :                 if (q == NULL)
    1292           0 :                         goto bailout;
    1293       16908 :                 q = pushArgument(mb, q, len);
    1294       16907 :                 q = pushInt(mb, q, 1);
    1295       16908 :                 len = getDestVar(q);
    1296       16908 :                 pushInstruction(mb, q);
    1297             : 
    1298       16908 :                 q = newStmt(mb, algebraRef, subsliceRef);
    1299       16908 :                 if (q == NULL)
    1300           0 :                         goto bailout;
    1301       16908 :                 q = pushArgument(mb, q, c);
    1302       16908 :                 q = pushArgument(mb, q, offset->nr);
    1303       16907 :                 q = pushArgument(mb, q, len);
    1304       16907 :                 l = getDestVar(q);
    1305       16907 :                 pushInstruction(mb, q);
    1306             :         }
    1307             :         /* retrieve the single values again */
    1308       17640 :         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       34893 :         stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
    1319       17641 :         if (ns == NULL) {
    1320           0 :                 goto bailout;
    1321             :         }
    1322             : 
    1323       17641 :         ns->op1 = col;
    1324       17641 :         ns->op2 = offset;
    1325       17641 :         ns->op3 = limit;
    1326       17641 :         ns->nrcols = col->nrcols;
    1327       17641 :         ns->key = col->key;
    1328       17641 :         ns->aggr = col->aggr;
    1329       17641 :         ns->q = q;
    1330       17641 :         ns->nr = l;
    1331       17641 :         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       10030 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
    1394             : {
    1395       10030 :         MalBlkPtr mb = be->mb;
    1396       10030 :         InstrPtr q = NULL;
    1397             : 
    1398       10030 :         if (s == NULL || s->nr < 0)
    1399           0 :                 goto bailout;
    1400       10030 :         q = newStmt(mb, algebraRef, sortRef);
    1401       10030 :         if (q == NULL)
    1402           0 :                 goto bailout;
    1403             :         /* both ordered result and oid's order en subgroups */
    1404       10030 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1405       10030 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1406       10030 :         q = pushArgument(mb, q, s->nr);
    1407       10030 :         q = pushBit(mb, q, !direction);
    1408       10030 :         q = pushBit(mb, q, nullslast);
    1409       10030 :         q = pushBit(mb, q, FALSE);
    1410             : 
    1411       10030 :         bool enabled = be->mvc->sa->eb.enabled;
    1412       10030 :         be->mvc->sa->eb.enabled = false;
    1413       10030 :         stmt *ns = stmt_create(be->mvc->sa, st_order);
    1414       10030 :         be->mvc->sa->eb.enabled = enabled;
    1415       10030 :         if (ns == NULL) {
    1416           0 :                 freeInstruction(q);
    1417           0 :                 goto bailout;
    1418             :         }
    1419             : 
    1420       10030 :         ns->op1 = s;
    1421       10030 :         ns->flag = direction;
    1422       10030 :         ns->nrcols = s->nrcols;
    1423       10030 :         ns->key = s->key;
    1424       10030 :         ns->aggr = s->aggr;
    1425       10030 :         ns->q = q;
    1426       10030 :         ns->nr = getDestVar(q);
    1427       10030 :         pushInstruction(mb, q);
    1428       10030 :         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       12658 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
    1438             : {
    1439       12658 :         MalBlkPtr mb = be->mb;
    1440       12658 :         InstrPtr q = NULL;
    1441             : 
    1442       12658 :         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       12658 :         q = newStmtArgs(mb, algebraRef, sortRef, 9);
    1445       12658 :         if (q == NULL)
    1446           0 :                 goto bailout;
    1447             :         /* both ordered result and oid's order en subgroups */
    1448       12658 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1449       12658 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1450       12658 :         q = pushArgument(mb, q, s->nr);
    1451       12658 :         q = pushArgument(mb, q, orderby_ids->nr);
    1452       12658 :         q = pushArgument(mb, q, orderby_grp->nr);
    1453       12658 :         q = pushBit(mb, q, !direction);
    1454       12658 :         q = pushBit(mb, q, nullslast);
    1455       12658 :         q = pushBit(mb, q, FALSE);
    1456             : 
    1457       12658 :         bool enabled = be->mvc->sa->eb.enabled;
    1458       12658 :         be->mvc->sa->eb.enabled = false;
    1459       12658 :         stmt *ns = stmt_create(be->mvc->sa, st_reorder);
    1460       12658 :         be->mvc->sa->eb.enabled = enabled;
    1461       12658 :         if (ns == NULL) {
    1462           0 :                 freeInstruction(q);
    1463           0 :                 goto bailout;
    1464             :         }
    1465             : 
    1466       12658 :         ns->op1 = s;
    1467       12658 :         ns->op2 = orderby_ids;
    1468       12658 :         ns->op3 = orderby_grp;
    1469       12658 :         ns->flag = direction;
    1470       12658 :         ns->nrcols = s->nrcols;
    1471       12658 :         ns->key = s->key;
    1472       12658 :         ns->aggr = s->aggr;
    1473       12658 :         ns->nr = getDestVar(q);
    1474       12658 :         ns->q = q;
    1475       12658 :         pushInstruction(mb, q);
    1476       12658 :         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     3058353 : stmt_atom(backend *be, atom *a)
    1486             : {
    1487     3058353 :         MalBlkPtr mb = be->mb;
    1488             : 
    1489     3058353 :         if (a == NULL)
    1490           0 :                 goto bailout;
    1491             : 
    1492     3058353 :         InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->impl) : newAssignment(mb);
    1493             : 
    1494     3059390 :         if (q == NULL)
    1495           0 :                 goto bailout;
    1496     3059390 :         if (atom_null(a)) {
    1497       95981 :                 q = pushNil(mb, q, atom_type(a)->type->localtype);
    1498             :         } else {
    1499     2963409 :                 int k;
    1500     2963409 :                 if ((k = constantAtom(be, mb, a)) == -1) {
    1501           0 :                         freeInstruction(q);
    1502           0 :                         goto bailout;
    1503             :                 }
    1504     2962493 :                 q = pushArgument(mb, q, k);
    1505             :         }
    1506             :         /* digits of the result timestamp/daytime */
    1507     3058551 :         if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
    1508        3720 :                 q = pushInt(mb, q, atom_type(a)->digits);
    1509     3059057 :         bool enabled = be->mvc->sa->eb.enabled;
    1510     3059057 :         be->mvc->sa->eb.enabled = false;
    1511     3059057 :         stmt *s = stmt_create(be->mvc->sa, st_atom);
    1512     3058448 :         be->mvc->sa->eb.enabled = enabled;
    1513     3058448 :         if (s == NULL) {
    1514           0 :                 freeInstruction(q);
    1515           0 :                 goto bailout;
    1516             :         }
    1517             : 
    1518     3058448 :         s->op4.aval = a;
    1519     3058448 :         s->key = 1;          /* values are also unique */
    1520     3058448 :         s->q = q;
    1521     3058448 :         s->nr = getDestVar(q);
    1522     3058448 :         pushInstruction(mb, q);
    1523     3058448 :         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        3432 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
    1533             : {
    1534        3432 :         MalBlkPtr mb = be->mb;
    1535        3432 :         InstrPtr q = NULL;
    1536        3432 :         const char *mod, *op;
    1537        3432 :         node *n;
    1538        3432 :         int k;
    1539             : 
    1540        3432 :         if (lops == NULL || rops == NULL)
    1541           0 :                 goto bailout;
    1542             : 
    1543        3432 :         if (backend_create_subfunc(be, f, NULL) < 0)
    1544           0 :                 goto bailout;
    1545        3432 :         op = backend_function_imp(be, f->func);
    1546        3432 :         mod = sql_func_mod(f->func);
    1547             : 
    1548        3432 :         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         174 :                 for (n = rops->op4.lval->h; n; n = n->next)
    1555         120 :                         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         174 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1568         120 :                         stmt *op = n->data;
    1569             : 
    1570         120 :                         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          35 :                         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        3378 :                 node *n;
    1588             : 
    1589        3378 :                 op = sa_strconcat(be->mvc->sa, op, selectRef);
    1590        3378 :                 q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
    1591        3378 :                 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        3378 :                 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        3378 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
    1599           0 :                         q = pushStr(mb, q, f->func->query);
    1600             : 
    1601        6756 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1602        3378 :                         stmt *op = n->data;
    1603             : 
    1604        3378 :                         q = pushArgument(mb, q, op->nr);
    1605             :                 }
    1606             :                 /* candidate lists */
    1607        3378 :                 if (sub)
    1608        3316 :                         q = pushArgument(mb, q, sub->nr);
    1609             :                 else
    1610          62 :                         q = pushNilBat(mb, q);
    1611             : 
    1612       13499 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1613       10121 :                         stmt *op = n->data;
    1614             : 
    1615       10121 :                         q = pushArgument(mb, q, op->nr);
    1616             :                 }
    1617             : 
    1618        3378 :                 q = pushBit(mb, q, anti);
    1619             :         }
    1620             : 
    1621        3432 :         bool enabled = be->mvc->sa->eb.enabled;
    1622        3432 :         be->mvc->sa->eb.enabled = false;
    1623        3432 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1624        3432 :         be->mvc->sa->eb.enabled = enabled;
    1625        3432 :         if (s == NULL) {
    1626           0 :                 freeInstruction(q);
    1627           0 :                 goto bailout;
    1628             :         }
    1629             : 
    1630        3432 :         s->op1 = lops;
    1631        3432 :         s->op2 = rops;
    1632        3432 :         s->op3 = sub;
    1633        3432 :         s->key = lops->nrcols == 0 && rops->nrcols == 0;
    1634        3432 :         s->flag = cmp_filter;
    1635        3432 :         s->nrcols = lops->nrcols;
    1636        3432 :         s->nr = getDestVar(q);
    1637        3432 :         s->q = q;
    1638        3432 :         s->cand = sub;
    1639        3432 :         pushInstruction(mb, q);
    1640        3432 :         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      202231 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
    1650             : {
    1651      202231 :         MalBlkPtr mb = be->mb;
    1652      202231 :         InstrPtr q = NULL;
    1653      202231 :         int l, r;
    1654      202231 :         stmt *sel = sub;
    1655             : 
    1656      202231 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
    1657           0 :                 goto bailout;
    1658      202231 :         l = op1->nr;
    1659      202231 :         r = op2->nr;
    1660             : 
    1661      202231 :         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      202231 :         if (op2->nrcols >= 1) {
    1671       16332 :                 bit need_not = FALSE;
    1672       16332 :                 const char *mod = calcRef;
    1673       16332 :                 const char *op = "=";
    1674       16332 :                 int k;
    1675             : 
    1676       16332 :                 switch (cmptype) {
    1677             :                 case cmp_equal:
    1678             :                         op = "=";
    1679             :                         break;
    1680             :                 case cmp_notequal:
    1681       16332 :                         op = "!=";
    1682             :                         break;
    1683         855 :                 case cmp_lt:
    1684         855 :                         op = "<";
    1685         855 :                         break;
    1686         756 :                 case cmp_lte:
    1687         756 :                         op = "<=";
    1688         756 :                         break;
    1689        4781 :                 case cmp_gt:
    1690        4781 :                         op = ">";
    1691        4781 :                         break;
    1692         750 :                 case cmp_gte:
    1693         750 :                         op = ">=";
    1694         750 :                         break;
    1695           0 :                 default:
    1696           0 :                         TRC_ERROR(SQL_EXECUTION, "Unknown operator\n");
    1697             :                 }
    1698             : 
    1699       25400 :                 if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
    1700           0 :                         goto bailout;
    1701       16332 :                 if (sub && (op1->cand || op2->cand)) {
    1702        1294 :                         if (op1->cand && !op2->cand) {
    1703          28 :                                 if (op1->nrcols > 0)
    1704          28 :                                         q = pushNilBat(mb, q);
    1705          28 :                                 q = pushArgument(mb, q, sub->nr);
    1706        1266 :                         } else if (!op1->cand && op2->cand) {
    1707        1255 :                                 q = pushArgument(mb, q, sub->nr);
    1708        1255 :                                 if (op2->nrcols > 0)
    1709        1255 :                                         q = pushNilBat(mb, q);
    1710             :                         }
    1711             :                         sub = NULL;
    1712             :                 }
    1713       16332 :                 if (is_semantics)
    1714        2797 :                         q = pushBit(mb, q, TRUE);
    1715       16332 :                 k = getDestVar(q);
    1716             : 
    1717       16332 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1718       16332 :                 if (q == NULL)
    1719           0 :                         goto bailout;
    1720       16332 :                 q = pushArgument(mb, q, k);
    1721       16332 :                 if (sub)
    1722        4362 :                         q = pushArgument(mb, q, sub->nr);
    1723       16332 :                 q = pushBit(mb, q, !need_not);
    1724       16332 :                 q = pushBit(mb, q, !need_not);
    1725       16332 :                 q = pushBit(mb, q, TRUE);
    1726       16332 :                 q = pushBit(mb, q, TRUE);
    1727       16332 :                 q = pushBit(mb, q, anti);
    1728       16332 :                 k = getDestVar(q);
    1729             :         } else {
    1730      185899 :                 assert (cmptype != cmp_filter);
    1731      185899 :                 if (is_semantics) {
    1732       19229 :                         assert(cmptype == cmp_equal || cmptype == cmp_notequal);
    1733       19229 :                         if (cmptype == cmp_notequal)
    1734          71 :                                 anti = !anti;
    1735       19229 :                         q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1736       19229 :                         if (q == NULL)
    1737           0 :                                 goto bailout;
    1738       19229 :                         q = pushArgument(mb, q, l);
    1739       19229 :                         if (sub && !op1->cand) {
    1740        2133 :                                 q = pushArgument(mb, q, sub->nr);
    1741             :                         } else {
    1742          12 :                                 assert(!sub || op1->cand == sub);
    1743             :                                 sub = NULL;
    1744             :                         }
    1745       19229 :                         q = pushArgument(mb, q, r);
    1746       19229 :                         q = pushArgument(mb, q, r);
    1747       19229 :                         q = pushBit(mb, q, TRUE);
    1748       19229 :                         q = pushBit(mb, q, TRUE);
    1749       19229 :                         q = pushBit(mb, q, anti);
    1750             :                 } else {
    1751      166670 :                         q = newStmt(mb, algebraRef, thetaselectRef);
    1752      166670 :                         if (q == NULL)
    1753           0 :                                 goto bailout;
    1754      166670 :                         q = pushArgument(mb, q, l);
    1755      166670 :                         if (sub && !op1->cand) {
    1756      124987 :                                 q = pushArgument(mb, q, sub->nr);
    1757             :                         } else {
    1758         310 :                                 assert(!sub || op1->cand == sub);
    1759       41683 :                                 q = pushNilBat(mb, q);
    1760       41683 :                                 sub = NULL;
    1761             :                         }
    1762      166669 :                         q = pushArgument(mb, q, r);
    1763      166668 :                         switch (cmptype) {
    1764      130200 :                         case cmp_equal:
    1765      130200 :                                 q = pushStr(mb, q, anti?"!=":"==");
    1766      130200 :                                 break;
    1767       33665 :                         case cmp_notequal:
    1768       33665 :                                 q = pushStr(mb, q, anti?"==":"!=");
    1769       33665 :                                 break;
    1770         429 :                         case cmp_lt:
    1771         429 :                                 q = pushStr(mb, q, anti?">=":"<");
    1772         429 :                                 break;
    1773          85 :                         case cmp_lte:
    1774          85 :                                 q = pushStr(mb, q, anti?">":"<=");
    1775          85 :                                 break;
    1776        1992 :                         case cmp_gt:
    1777        1992 :                                 q = pushStr(mb, q, anti?"<=":">");
    1778        1992 :                                 break;
    1779         297 :                         case cmp_gte:
    1780         297 :                                 q = pushStr(mb, q, anti?"<":">=");
    1781         297 :                                 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      202231 :         bool enabled = be->mvc->sa->eb.enabled;
    1793      202231 :         be->mvc->sa->eb.enabled = false;
    1794      202231 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1795      202231 :         be->mvc->sa->eb.enabled = enabled;
    1796      202231 :         if (s == NULL) {
    1797           0 :                 freeInstruction(q);
    1798           0 :                 goto bailout;
    1799             :         }
    1800             : 
    1801      202231 :         s->op1 = op1;
    1802      202231 :         s->op2 = op2;
    1803      202231 :         s->op3 = sub;
    1804      202231 :         s->flag = cmptype;
    1805      202231 :         s->key = op1->nrcols == 0 && op2->nrcols == 0;
    1806      202231 :         s->nrcols = op1->nrcols;
    1807      202231 :         s->nr = getDestVar(q);
    1808      202231 :         s->q = q;
    1809      202231 :         s->cand = sub;
    1810      202231 :         pushInstruction(mb, q);
    1811      202230 :         if (!sub && sel) /* project back the old ids */
    1812        1616 :                 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        5062 : 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        5062 :         MalBlkPtr mb = be->mb;
    1873        5062 :         InstrPtr p, q;
    1874        5062 :         int l;
    1875        5062 :         const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
    1876        5062 :         stmt *sub = (Sub)?*Sub:NULL;
    1877             : 
    1878        5062 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
    1879           0 :                 goto bailout;
    1880        5062 :         l = op1->nr;
    1881        8421 :         if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
    1882        3580 :                 int k;
    1883        3580 :                 int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
    1884             : 
    1885        3580 :                 if (op2->nr < 0 || op3->nr < 0)
    1886           0 :                         goto bailout;
    1887             : 
    1888        3580 :                 if (nrcols)
    1889        3542 :                         p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
    1890             :                 else
    1891          38 :                         p = newStmtArgs(mb, calcRef, betweenRef, 9);
    1892        3580 :                 if (p == NULL)
    1893           0 :                         goto bailout;
    1894        3580 :                 p = pushArgument(mb, p, l);
    1895        3580 :                 p = pushArgument(mb, p, op2->nr);
    1896        3580 :                 p = pushArgument(mb, p, op3->nr);
    1897             : 
    1898             :                 /* cands */
    1899        3580 :                 if ((sub && !reduce) || op1->cand || op2->cand || op3->cand) { /* some already handled the previous selection */
    1900        1492 :                         if (op1->cand && op1->nrcols)
    1901        1214 :                                 p = pushNilBat(mb, p);
    1902         278 :                         else if (op1->nrcols)
    1903         278 :                                 p = pushArgument(mb, p, sub->nr);
    1904        1492 :                         if (op2->nrcols) {
    1905        1388 :                                 if (op2->cand)
    1906        1211 :                                         p = pushNilBat(mb, p);
    1907         177 :                                 else if (op2->nrcols)
    1908         177 :                                         p = pushArgument(mb, p, sub->nr);
    1909             :                         }
    1910        1492 :                         if (op3->nrcols) {
    1911        1383 :                                 if (op3->cand)
    1912        1295 :                                         p = pushNilBat(mb, p);
    1913          88 :                                 else if (op3->nrcols)
    1914          88 :                                         p = pushArgument(mb, p, sub->nr);
    1915             :                         }
    1916             :                         sub = NULL;
    1917             :                 }
    1918             : 
    1919        3580 :                 p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
    1920        3580 :                 p = pushBit(mb, p, (cmp & 1) != 0);     /* lo inclusive */
    1921        3580 :                 p = pushBit(mb, p, (cmp & 2) != 0);     /* hi inclusive */
    1922        3580 :                 p = pushBit(mb, p, FALSE);                  /* nils_false */
    1923        3580 :                 p = pushBit(mb, p, (anti)?TRUE:FALSE);      /* anti */
    1924        3580 :                 pushInstruction(mb, p);
    1925        3580 :                 if (!reduce)
    1926             :                         return p;
    1927        3359 :                 k = getDestVar(p);
    1928             : 
    1929        3359 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1930        3359 :                 if (q == NULL)
    1931           0 :                         goto bailout;
    1932        3359 :                 q = pushArgument(mb, q, k);
    1933        3359 :                 if (sub)
    1934         896 :                         q = pushArgument(mb, q, sub->nr);
    1935        3359 :                 q = pushBit(mb, q, TRUE);
    1936        3359 :                 q = pushBit(mb, q, TRUE);
    1937        3359 :                 q = pushBit(mb, q, TRUE);
    1938        3359 :                 q = pushBit(mb, q, TRUE);
    1939        3359 :                 q = pushBit(mb, q, FALSE);
    1940        3359 :                 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        1482 :                 int r1 = op2->nr;
    1968        1482 :                 int r2 = op3->nr;
    1969        1482 :                 int rs = 0;
    1970        1482 :                 q = newStmtArgs(mb, algebraRef, cmd, 12);
    1971        1482 :                 if (q == NULL)
    1972           0 :                         goto bailout;
    1973        1482 :                 if (type == st_join2)
    1974          43 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1975        1482 :                 q = pushArgument(mb, q, l);
    1976        1482 :                 if (sub) {
    1977        1179 :                         int cand = op1->cand || op2->cand || op3->cand;
    1978        1168 :                         if (cand) {
    1979          11 :                                 assert(!op1->nrcols || op1->cand);
    1980          11 :                                 assert(!op2->nrcols || op2->cand);
    1981          11 :                                 assert(!op3->nrcols || op3->cand);
    1982             :                                 sub = NULL;
    1983             :                         }
    1984             :                 }
    1985        1168 :                 if (sub) /* only for uselect2 */
    1986        1168 :                         q = pushArgument(mb, q, sub->nr);
    1987        1482 :                 if (rs) {
    1988             :                         q = pushArgument(mb, q, rs);
    1989             :                 } else {
    1990        1482 :                         q = pushArgument(mb, q, r1);
    1991        1482 :                         q = pushArgument(mb, q, r2);
    1992             :                 }
    1993        1482 :                 if (type == st_join2) {
    1994          43 :                         q = pushNilBat(mb, q);
    1995          43 :                         q = pushNilBat(mb, q);
    1996             :                 }
    1997             : 
    1998        1482 :                 switch (cmp & 3) {
    1999          53 :                 case 0:
    2000          53 :                         q = pushBit(mb, q, FALSE);
    2001          53 :                         q = pushBit(mb, q, FALSE);
    2002          53 :                         break;
    2003         228 :                 case 1:
    2004         228 :                         q = pushBit(mb, q, TRUE);
    2005         228 :                         q = pushBit(mb, q, FALSE);
    2006         228 :                         break;
    2007           8 :                 case 2:
    2008           8 :                         q = pushBit(mb, q, FALSE);
    2009           8 :                         q = pushBit(mb, q, TRUE);
    2010           8 :                         break;
    2011        1193 :                 case 3:
    2012        1193 :                         q = pushBit(mb, q, TRUE);
    2013        1193 :                         q = pushBit(mb, q, TRUE);
    2014        1193 :                         break;
    2015             :                 }
    2016        1482 :                 q = pushBit(mb, q, anti);
    2017        1482 :                 if (type == st_uselect2) {
    2018        1439 :                         q = pushBit(mb, q, TRUE); /* all nil's are != */
    2019             :                 } else {
    2020          43 :                         q = pushBit(mb, q, (symmetric)?TRUE:FALSE);
    2021             :                 }
    2022        1482 :                 if (type == st_join2)
    2023          43 :                         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2024        1482 :                 pushInstruction(mb, q);
    2025        1482 :                 if (swapped) {
    2026           1 :                         InstrPtr r = newInstruction(mb,  NULL, NULL);
    2027           1 :                         if (r == NULL)
    2028           0 :                                 goto bailout;
    2029           1 :                         getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2030           1 :                         r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2031           1 :                         r = pushArgument(mb, r, getArg(q,1));
    2032           1 :                         r = pushArgument(mb, r, getArg(q,0));
    2033           1 :                         pushInstruction(mb, r);
    2034           1 :                         q = r;
    2035             :                 }
    2036             :         }
    2037        4841 :         if (Sub)
    2038        4798 :                 *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          36 : stmt_outerselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2049             : {
    2050          36 :         MalBlkPtr mb = be->mb;
    2051          36 :         InstrPtr q;
    2052             : 
    2053          36 :         q = newStmtArgs(mb, algebraRef, outerselectRef, 6);
    2054          36 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2055          36 :         q = pushArgument(mb, q, g->nr); /* group ids */
    2056          36 :         q = pushArgument(mb, q, m->nr); /* mark flag */
    2057          36 :         q = pushArgument(mb, q, p->nr); /* predicate */
    2058          36 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2059          36 :         pushInstruction(mb, q);
    2060             : 
    2061          36 :         if (!q)
    2062             :                 return NULL;
    2063          36 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2064          36 :         if (s == NULL) {
    2065           0 :                 freeInstruction(q);
    2066           0 :                 return NULL;
    2067             :         }
    2068             : 
    2069          36 :         s->op1 = g;
    2070          36 :         s->op2 = m;
    2071          36 :         s->flag = MARKJOIN;
    2072          36 :         s->key = 0;
    2073          36 :         s->nrcols = g->nrcols;
    2074          36 :         s->nr = getDestVar(q);
    2075          36 :         s->q = q;
    2076          36 :         return s;
    2077             : }
    2078             : 
    2079             : stmt *
    2080         388 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2081             : {
    2082         388 :         MalBlkPtr mb = be->mb;
    2083         388 :         InstrPtr q;
    2084             : 
    2085         388 :         q = newStmtArgs(mb, algebraRef, markselectRef, 6);
    2086         388 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2087         388 :         q = pushArgument(mb, q, g->nr); /* left ids */
    2088         388 :         q = pushArgument(mb, q, m->nr); /* mark info mask */
    2089         388 :         q = pushArgument(mb, q, p->nr);      /* predicate */
    2090         388 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2091         388 :         pushInstruction(mb, q);
    2092             : 
    2093         388 :         if (!q)
    2094             :                 return NULL;
    2095         388 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2096         388 :         if (s == NULL) {
    2097           0 :                 freeInstruction(q);
    2098           0 :                 return NULL;
    2099             :         }
    2100             : 
    2101         388 :         s->op1 = g;
    2102         388 :         s->op2 = m;
    2103         388 :         s->flag = MARKJOIN;
    2104         388 :         s->key = 0;
    2105         388 :         s->nrcols = g->nrcols;
    2106         388 :         s->nr = getDestVar(q);
    2107         388 :         s->q = q;
    2108         388 :         return s;
    2109             : }
    2110             : 
    2111             : stmt *
    2112        2228 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
    2113             : {
    2114        2228 :         MalBlkPtr mb = be->mb;
    2115        2228 :         InstrPtr q;
    2116             : 
    2117        2228 :         q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
    2118        2228 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2119        2228 :         if (!final)
    2120           5 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2121        2228 :         q = pushArgument(mb, q, l->nr); /* left ids */
    2122        2228 :         q = pushArgument(mb, q, r->nr); /* mark info mask */
    2123        2228 :         q = pushNilBat(mb, q);
    2124        2228 :         q = pushNilBat(mb, q);
    2125        2228 :         q = pushNil(mb, q, TYPE_lng);
    2126        2228 :         pushInstruction(mb, q);
    2127             : 
    2128        2228 :         if (!q)
    2129             :                 return NULL;
    2130        2228 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2131        2228 :         if (s == NULL) {
    2132           0 :                 freeInstruction(q);
    2133           0 :                 return NULL;
    2134             :         }
    2135             : 
    2136        2228 :         s->op1 = l;
    2137        2228 :         s->op2 = r;
    2138        2228 :         s->flag = MARKJOIN;
    2139        2228 :         s->key = 0;
    2140        2228 :         s->nrcols = l->nrcols;
    2141        2228 :         s->nr = getDestVar(q);
    2142        2228 :         s->q = q;
    2143        2228 :         return s;
    2144             : }
    2145             : 
    2146             : stmt *
    2147        5019 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
    2148             : {
    2149        5019 :         stmt *sel = sub;
    2150        5019 :         InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
    2151             : 
    2152        5019 :         if (q == NULL)
    2153             :                 return NULL;
    2154             : 
    2155        5019 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2156        5019 :         if (s == NULL) {
    2157             :                 return NULL;
    2158             :         }
    2159             : 
    2160        5019 :         s->op1 = op1;
    2161        5019 :         s->op2 = op2;
    2162        5019 :         s->op3 = op3;
    2163        5019 :         s->op4.stval = sub;
    2164        5019 :         s->flag = cmp;
    2165        5019 :         s->nrcols = op1->nrcols;
    2166        5019 :         s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
    2167        5019 :         s->nr = getDestVar(q);
    2168        5019 :         s->q = q;
    2169        5019 :         s->cand = sub;
    2170        5019 :         s->reduce = reduce;
    2171        5019 :         if (!sub && sel) /* project back the old ids */
    2172        1380 :                 return stmt_project(be, s, sel);
    2173             :         return s;
    2174             : }
    2175             : 
    2176             : stmt *
    2177       52018 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
    2178             : {
    2179       52018 :         InstrPtr q = NULL;
    2180       52018 :         MalBlkPtr mb = be->mb;
    2181             : 
    2182       52018 :         q = dump_2(mb, batRef, mergecandRef, op1, op2);
    2183       52018 :         if (q) {
    2184       52018 :                 stmt *s = stmt_create(be->mvc->sa, st_tunion);
    2185       52018 :                 if (s == NULL) {
    2186             :                         return NULL;
    2187             :                 }
    2188             : 
    2189       52018 :                 s->op1 = op1;
    2190       52018 :                 s->op2 = op2;
    2191       52018 :                 s->nrcols = op1->nrcols;
    2192       52018 :                 s->key = op1->key;
    2193       52018 :                 s->aggr = op1->aggr;
    2194       52018 :                 s->nr = getDestVar(q);
    2195       52018 :                 s->q = q;
    2196       52018 :                 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       37707 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2206             : {
    2207       37707 :         InstrPtr q = NULL;
    2208       37707 :         MalBlkPtr mb = be->mb;
    2209             : 
    2210       37707 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2211           0 :                 goto bailout;
    2212       37707 :         q = newStmt(mb, algebraRef, differenceRef);
    2213       37707 :         if (q == NULL)
    2214           0 :                 goto bailout;
    2215       37707 :         q = pushArgument(mb, q, op1->nr); /* left */
    2216       37707 :         q = pushArgument(mb, q, op2->nr); /* right */
    2217       37707 :         if (lcand)
    2218           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2219             :         else
    2220       37707 :                 q = pushNilBat(mb, q); /* left candidate */
    2221       37707 :         q = pushNilBat(mb, q); /* right candidate */
    2222       37707 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2223       37707 :         q = pushBit(mb, q, FALSE);    /* do not clear nils */
    2224       37707 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2225             : 
    2226       37707 :         bool enabled = be->mvc->sa->eb.enabled;
    2227       37707 :         be->mvc->sa->eb.enabled = false;
    2228       37707 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2229       37707 :         be->mvc->sa->eb.enabled = enabled;
    2230       37707 :         if (s == NULL) {
    2231           0 :                 freeInstruction(q);
    2232           0 :                 goto bailout;
    2233             :         }
    2234             : 
    2235       37707 :         s->op1 = op1;
    2236       37707 :         s->op2 = op2;
    2237       37707 :         s->nrcols = op1->nrcols;
    2238       37707 :         s->key = op1->key;
    2239       37707 :         s->aggr = op1->aggr;
    2240       37707 :         s->nr = getDestVar(q);
    2241       37707 :         s->q = q;
    2242       37707 :         pushInstruction(mb, q);
    2243       37707 :         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        1393 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2253             : {
    2254        1393 :         InstrPtr q = NULL;
    2255        1393 :         MalBlkPtr mb = be->mb;
    2256             : 
    2257        1393 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2258           0 :                 goto bailout;
    2259        1393 :         q = newStmt(mb, algebraRef, differenceRef);
    2260        1393 :         if (q == NULL)
    2261           0 :                 goto bailout;
    2262        1393 :         q = pushArgument(mb, q, op1->nr); /* left */
    2263        1393 :         q = pushArgument(mb, q, op2->nr); /* right */
    2264        1393 :         if (lcand)
    2265           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2266             :         else
    2267        1393 :                 q = pushNilBat(mb, q); /* left candidate */
    2268        1393 :         q = pushNilBat(mb, q); /* right candidate */
    2269        1393 :         q = pushBit(mb, q, FALSE);     /* nil matches */
    2270        1393 :         q = pushBit(mb, q, TRUE);     /* not in */
    2271        1393 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2272             : 
    2273        1393 :         bool enabled = be->mvc->sa->eb.enabled;
    2274        1393 :         be->mvc->sa->eb.enabled = false;
    2275        1393 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2276        1393 :         be->mvc->sa->eb.enabled = enabled;
    2277        1393 :         if (s == NULL) {
    2278           0 :                 freeInstruction(q);
    2279           0 :                 goto bailout;
    2280             :         }
    2281             : 
    2282        1393 :         s->op1 = op1;
    2283        1393 :         s->op2 = op2;
    2284        1393 :         s->nrcols = op1->nrcols;
    2285        1393 :         s->key = op1->key;
    2286        1393 :         s->aggr = op1->aggr;
    2287        1393 :         s->nr = getDestVar(q);
    2288        1393 :         s->q = q;
    2289        1393 :         pushInstruction(mb, q);
    2290        1393 :         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        1779 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
    2300             : {
    2301        1779 :         InstrPtr q = NULL;
    2302        1779 :         MalBlkPtr mb = be->mb;
    2303             : 
    2304        1779 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2305           0 :                 goto bailout;
    2306        1779 :         q = newStmt(mb, algebraRef, intersectRef);
    2307        1779 :         if (q == NULL)
    2308           0 :                 goto bailout;
    2309        1779 :         q = pushArgument(mb, q, op1->nr); /* left */
    2310        1779 :         q = pushArgument(mb, q, op2->nr); /* right */
    2311        1779 :         q = pushNilBat(mb, q); /* left candidate */
    2312        1779 :         q = pushNilBat(mb, q); /* right candidate */
    2313        1779 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2314        1779 :         q = pushBit(mb, q, single?TRUE:FALSE);    /* max_one */
    2315        1779 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2316             : 
    2317        1779 :         bool enabled = be->mvc->sa->eb.enabled;
    2318        1779 :         be->mvc->sa->eb.enabled = false;
    2319        1779 :         stmt *s = stmt_create(be->mvc->sa, st_tinter);
    2320        1779 :         be->mvc->sa->eb.enabled = enabled;
    2321        1779 :         if (s == NULL) {
    2322           0 :                 freeInstruction(q);
    2323           0 :                 goto bailout;
    2324             :         }
    2325             : 
    2326        1779 :         s->op1 = op1;
    2327        1779 :         s->op2 = op2;
    2328        1779 :         s->nrcols = op1->nrcols;
    2329        1779 :         s->key = op1->key;
    2330        1779 :         s->aggr = op1->aggr;
    2331        1779 :         s->nr = getDestVar(q);
    2332        1779 :         s->q = q;
    2333        1779 :         pushInstruction(mb, q);
    2334        1779 :         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       87226 : 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       87226 :         MalBlkPtr mb = be->mb;
    2346       87226 :         InstrPtr q = NULL;
    2347       87226 :         const char *sjt = inner?joinRef:outerjoinRef;
    2348             : 
    2349       87226 :         (void)anti;
    2350       87226 :         (void)inner;
    2351             : 
    2352       87226 :         if (need_left) {
    2353         653 :                 cmptype = cmp_equal;
    2354         653 :                 sjt = leftjoinRef;
    2355             :         }
    2356       87226 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2357           0 :                 goto bailout;
    2358             : 
    2359       87226 :         assert (!single || cmptype == cmp_all);
    2360             : 
    2361       87226 :         switch (cmptype) {
    2362       70114 :         case cmp_equal:
    2363       70114 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2364       70114 :                 if (q == NULL)
    2365           0 :                         goto bailout;
    2366       70114 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2367       70114 :                 q = pushArgument(mb, q, op1->nr);
    2368       70114 :                 q = pushArgument(mb, q, op2->nr);
    2369       70114 :                 if (!lcand)
    2370       69359 :                         q = pushNilBat(mb, q);
    2371             :                 else
    2372         755 :                         q = pushArgument(mb, q, lcand->nr);
    2373       70114 :                 if (!rcand)
    2374       70114 :                         q = pushNilBat(mb, q);
    2375             :                 else
    2376           0 :                         q = pushArgument(mb, q, rcand->nr);
    2377       70114 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2378       70114 :                 if (!inner)
    2379          58 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2380       70114 :                 q = pushNil(mb, q, TYPE_lng);
    2381       70114 :                 pushInstruction(mb, q);
    2382       70114 :                 break;
    2383          33 :         case cmp_notequal:
    2384          33 :                 if (inner)
    2385          33 :                         sjt = thetajoinRef;
    2386          33 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2387          33 :                 if (q == NULL)
    2388           0 :                         goto bailout;
    2389          33 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2390          33 :                 q = pushArgument(mb, q, op1->nr);
    2391          33 :                 q = pushArgument(mb, q, op2->nr);
    2392          33 :                 if (!lcand)
    2393          33 :                         q = pushNilBat(mb, q);
    2394             :                 else
    2395           0 :                         q = pushArgument(mb, q, lcand->nr);
    2396          33 :                 if (!rcand)
    2397          33 :                         q = pushNilBat(mb, q);
    2398             :                 else
    2399           0 :                         q = pushArgument(mb, q, rcand->nr);
    2400          33 :                 if (inner)
    2401          33 :                         q = pushInt(mb, q, JOIN_NE);
    2402          33 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2403          33 :                 if (!inner)
    2404           0 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2405          33 :                 q = pushNil(mb, q, TYPE_lng);
    2406          33 :                 pushInstruction(mb, q);
    2407          33 :                 break;
    2408        2571 :         case cmp_lt:
    2409             :         case cmp_lte:
    2410             :         case cmp_gt:
    2411             :         case cmp_gte:
    2412        2571 :                 q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
    2413        2571 :                 if (q == NULL)
    2414           0 :                         goto bailout;
    2415        2571 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2416        2571 :                 q = pushArgument(mb, q, op1->nr);
    2417        2571 :                 q = pushArgument(mb, q, op2->nr);
    2418        2571 :                 if (!lcand)
    2419        2571 :                         q = pushNilBat(mb, q);
    2420             :                 else
    2421           0 :                         q = pushArgument(mb, q, lcand->nr);
    2422        2571 :                 if (!rcand)
    2423        2571 :                         q = pushNilBat(mb, q);
    2424             :                 else
    2425           0 :                         q = pushArgument(mb, q, rcand->nr);
    2426        2571 :                 if (cmptype == cmp_lt)
    2427        2058 :                         q = pushInt(mb, q, JOIN_LT);
    2428         513 :                 else if (cmptype == cmp_lte)
    2429           8 :                         q = pushInt(mb, q, JOIN_LE);
    2430         505 :                 else if (cmptype == cmp_gt)
    2431         501 :                         q = pushInt(mb, q, JOIN_GT);
    2432           4 :                 else if (cmptype == cmp_gte)
    2433           4 :                         q = pushInt(mb, q, JOIN_GE);
    2434        2571 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2435        2571 :                 q = pushNil(mb, q, TYPE_lng);
    2436        2571 :                 pushInstruction(mb, q);
    2437        2571 :                 break;
    2438       11769 :         case cmp_all:   /* aka cross table */
    2439       11769 :                 q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
    2440       11769 :                 if (q == NULL)
    2441           0 :                         goto bailout;
    2442       11769 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2443       11769 :                 q = pushArgument(mb, q, op1->nr);
    2444       11769 :                 q = pushArgument(mb, q, op2->nr);
    2445       11769 :                 if (!inner) {
    2446         416 :                         q = pushNilBat(mb, q);
    2447         416 :                         q = pushNilBat(mb, q);
    2448             :                 }
    2449       11769 :                 q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2450       11769 :                 assert(!lcand && !rcand);
    2451       11769 :                 pushInstruction(mb, q);
    2452       11769 :                 break;
    2453        2739 :         case cmp_joined:
    2454        2739 :                 q = op1->q;
    2455        2739 :                 if (q == NULL)
    2456           0 :                         goto bailout;
    2457             :                 break;
    2458           0 :         default:
    2459           0 :                 TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
    2460             :         }
    2461             : 
    2462       87226 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2463       87226 :         if (s == NULL) {
    2464           0 :                 goto bailout;
    2465             :         }
    2466             : 
    2467       87226 :         s->op1 = op1;
    2468       87226 :         s->op2 = op2;
    2469       87226 :         s->flag = cmptype;
    2470       87226 :         s->key = 0;
    2471       87226 :         s->nrcols = 2;
    2472       87226 :         s->nr = getDestVar(q);
    2473       87226 :         s->q = q;
    2474       87226 :         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       84217 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
    2484             : {
    2485       84217 :         return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
    2486             : }
    2487             : 
    2488             : stmt *
    2489        1104 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
    2490             : {
    2491        1104 :         MalBlkPtr mb = be->mb;
    2492        1104 :         InstrPtr q = NULL;
    2493             : 
    2494        1104 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2495           0 :                 goto bailout;
    2496             : 
    2497        1104 :         if (single) {
    2498         256 :                 q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
    2499         256 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2500             :         } else
    2501         848 :                 q = newStmt(mb, algebraRef, intersectRef);
    2502        1104 :         if (q == NULL)
    2503           0 :                 goto bailout;
    2504        1104 :         q = pushArgument(mb, q, op1->nr);
    2505        1104 :         q = pushArgument(mb, q, op2->nr);
    2506        1104 :         if (lcand)
    2507         845 :                 q = pushArgument(mb, q, lcand->nr);
    2508             :         else
    2509         259 :                 q = pushNilBat(mb, q);
    2510        1104 :         if (rcand)
    2511           0 :                 q = pushArgument(mb, q, rcand->nr);
    2512             :         else
    2513        1104 :                 q = pushNilBat(mb, q);
    2514        1104 :         q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2515        1104 :         q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2516        1104 :         q = pushNil(mb, q, TYPE_lng);
    2517             : 
    2518        1104 :         bool enabled = be->mvc->sa->eb.enabled;
    2519        1104 :         be->mvc->sa->eb.enabled = false;
    2520        1104 :         stmt *s = stmt_create(be->mvc->sa, st_semijoin);
    2521        1104 :         be->mvc->sa->eb.enabled = enabled;
    2522        1104 :         if (s == NULL) {
    2523           0 :                 freeInstruction(q);
    2524           0 :                 goto bailout;
    2525             :         }
    2526             : 
    2527        1104 :         s->op1 = op1;
    2528        1104 :         s->op2 = op2;
    2529        1104 :         s->flag = cmp_equal;
    2530        1104 :         s->key = 0;
    2531        1104 :         s->nrcols = 1;
    2532        1104 :         if (single)
    2533         256 :                 s->nrcols = 2;
    2534        1104 :         s->nr = getDestVar(q);
    2535        1104 :         s->q = q;
    2536        1104 :         pushInstruction(mb, q);
    2537        1104 :         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     3305584 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
    2547             : {
    2548     3305584 :         MalBlkPtr mb = be->mb;
    2549     3305584 :         InstrPtr q = NULL;
    2550             : 
    2551     3305584 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2552             :                 return NULL;
    2553             :         /* delta bat */
    2554     3305584 :         if (delta) {
    2555      445150 :                 int uval = getArg(op2->q, 1);
    2556             : 
    2557      445150 :                 q = newStmt(mb, sqlRef, deltaRef);
    2558      445199 :                 q = pushArgument(mb, q, op1->nr);
    2559      445198 :                 q = pushArgument(mb, q, op2->nr);
    2560      445198 :                 q = pushArgument(mb, q, uval);
    2561             :         } else {
    2562             :                 /* projections, ie left is void headed */
    2563     2860434 :                 q = newStmt(mb, algebraRef, projectionRef);
    2564     2860477 :                 q = pushArgument(mb, q, op1->nr);
    2565     2860475 :                 q = pushArgument(mb, q, op2->nr);
    2566             :         }
    2567     3305661 :         pushInstruction(mb, q);
    2568     3305661 :         return q;
    2569             : }
    2570             : 
    2571             : stmt *
    2572     2865091 : stmt_project(backend *be, stmt *op1, stmt *op2)
    2573             : {
    2574     2865091 :         if (op1 == NULL || op2 == NULL)
    2575             :                 return NULL;
    2576     2865091 :         if (!op2->nrcols)
    2577        4658 :                 return stmt_const(be, op1, op2);
    2578     2860433 :         InstrPtr q = stmt_project_join(be, op1, op2, false);
    2579     2860469 :         if (q) {
    2580     2860469 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2581     2860450 :                 if (s == NULL) {
    2582             :                         return NULL;
    2583             :                 }
    2584             : 
    2585     2860450 :                 s->op1 = op1;
    2586     2860450 :                 s->op2 = op2;
    2587     2860450 :                 s->flag = cmp_project;
    2588     2860450 :                 s->key = 0;
    2589     2860450 :                 s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2590     2860450 :                 s->nr = getDestVar(q);
    2591     2860450 :                 s->q = q;
    2592     2860450 :                 s->tname = op2->tname;
    2593     2860450 :                 s->cname = op2->cname;
    2594     2860450 :                 return s;
    2595             :         }
    2596           0 :         if (be->mvc->sa->eb.enabled)
    2597           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);
    2598             :         return NULL;
    2599             : }
    2600             : 
    2601             : stmt *
    2602      445153 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
    2603             : {
    2604      445153 :         InstrPtr q = stmt_project_join(be, col, upd, true);
    2605      445199 :         if (q) {
    2606      445199 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2607      445193 :                 if (s == NULL) {
    2608             :                         return NULL;
    2609             :                 }
    2610             : 
    2611      445193 :                 s->op1 = col;
    2612      445193 :                 s->op2 = upd;
    2613      445193 :                 s->flag = cmp_project;
    2614      445193 :                 s->key = 0;
    2615      445193 :                 s->nrcols = 2;
    2616      445193 :                 s->nr = getDestVar(q);
    2617      445193 :                 s->q = q;
    2618      445193 :                 s->tname = col->tname;
    2619      445193 :                 s->cname = col->cname;
    2620      445193 :                 return s;
    2621             :         }
    2622             : 
    2623           0 :         if (be->mvc->sa->eb.enabled)
    2624           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);
    2625             :         return NULL;
    2626             : }
    2627             : 
    2628             : stmt *
    2629          43 : stmt_left_project(backend *be, stmt *op1, stmt *op2, stmt *op3)
    2630             : {
    2631          43 :         MalBlkPtr mb = be->mb;
    2632          43 :         InstrPtr q = NULL;
    2633          43 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || op2->nr < 0 || op3->nr < 0)
    2634           0 :                 goto bailout;
    2635             : 
    2636          43 :         q = newStmt(mb, sqlRef, projectRef);
    2637          43 :         if (q == NULL)
    2638           0 :                 goto bailout;
    2639          43 :         q = pushArgument(mb, q, op1->nr);
    2640          43 :         q = pushArgument(mb, q, op2->nr);
    2641          43 :         q = pushArgument(mb, q, op3->nr);
    2642             : 
    2643          43 :         bool enabled = be->mvc->sa->eb.enabled;
    2644          43 :         be->mvc->sa->eb.enabled = false;
    2645          43 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2646          43 :         be->mvc->sa->eb.enabled = enabled;
    2647          43 :         if (s == NULL) {
    2648           0 :                 freeInstruction(q);
    2649           0 :                 goto bailout;
    2650             :         }
    2651             : 
    2652          43 :         s->op1 = op1;
    2653          43 :         s->op2 = op2;
    2654          43 :         s->op3 = op3;
    2655          43 :         s->flag = cmp_left_project;
    2656          43 :         s->key = 0;
    2657          43 :         s->nrcols = 2;
    2658          43 :         s->nr = getDestVar(q);
    2659          43 :         s->q = q;
    2660          43 :         pushInstruction(mb, q);
    2661          43 :         return s;
    2662             : 
    2663           0 :   bailout:
    2664           0 :         if (be->mvc->sa->eb.enabled)
    2665           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2666             :         return NULL;
    2667             : }
    2668             : 
    2669             : stmt *
    2670         172 : stmt_dict(backend *be, stmt *op1, stmt *op2)
    2671             : {
    2672         172 :         MalBlkPtr mb = be->mb;
    2673         172 :         InstrPtr q = NULL;
    2674             : 
    2675         172 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2676             :                 return NULL;
    2677             : 
    2678         172 :         q = newStmt(mb, dictRef, decompressRef);
    2679         172 :         if (q == NULL)
    2680           0 :                 goto bailout;
    2681         172 :         q = pushArgument(mb, q, op1->nr);
    2682         172 :         q = pushArgument(mb, q, op2->nr);
    2683             : 
    2684         172 :         bool enabled = be->mvc->sa->eb.enabled;
    2685         172 :         be->mvc->sa->eb.enabled = false;
    2686         172 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2687         172 :         be->mvc->sa->eb.enabled = enabled;
    2688         172 :         if (s == NULL) {
    2689           0 :                 freeInstruction(q);
    2690           0 :                 return NULL;
    2691             :         }
    2692             : 
    2693         172 :         s->op1 = op1;
    2694         172 :         s->op2 = op2;
    2695         172 :         s->flag = cmp_project;
    2696         172 :         s->key = 0;
    2697         172 :         s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2698         172 :         s->nr = getDestVar(q);
    2699         172 :         s->q = q;
    2700         172 :         s->tname = op1->tname;
    2701         172 :         s->cname = op1->cname;
    2702         172 :         pushInstruction(mb, q);
    2703         172 :         return s;
    2704             : 
    2705           0 :   bailout:
    2706           0 :         if (be->mvc->sa->eb.enabled)
    2707           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2708             :         return NULL;
    2709             : }
    2710             : 
    2711             : stmt *
    2712           8 : stmt_for(backend *be, stmt *op1, stmt *min_val)
    2713             : {
    2714           8 :         MalBlkPtr mb = be->mb;
    2715           8 :         InstrPtr q = NULL;
    2716             : 
    2717           8 :         if (op1 == NULL || min_val == NULL || op1->nr < 0)
    2718             :                 return NULL;
    2719             : 
    2720           8 :         q = newStmt(mb, forRef, decompressRef);
    2721           8 :         if (q == NULL)
    2722           0 :                 goto bailout;
    2723           8 :         q = pushArgument(mb, q, op1->nr);
    2724           8 :         q = pushArgument(mb, q, min_val->nr);
    2725             : 
    2726           8 :         bool enabled = be->mvc->sa->eb.enabled;
    2727           8 :         be->mvc->sa->eb.enabled = false;
    2728           8 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2729           8 :         be->mvc->sa->eb.enabled = enabled;
    2730           8 :         if (s == NULL) {
    2731           0 :                 freeInstruction(q);
    2732           0 :                 return NULL;
    2733             :         }
    2734             : 
    2735           8 :         s->op1 = op1;
    2736           8 :         s->op2 = min_val;
    2737           8 :         s->flag = cmp_project;
    2738           8 :         s->key = 0;
    2739           8 :         s->nrcols = op1->nrcols;
    2740           8 :         s->nr = getDestVar(q);
    2741           8 :         s->q = q;
    2742           8 :         s->tname = op1->tname;
    2743           8 :         s->cname = op1->cname;
    2744           8 :         pushInstruction(mb, q);
    2745           8 :         return s;
    2746             : 
    2747           0 :   bailout:
    2748           0 :         if (be->mvc->sa->eb.enabled)
    2749           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2750             :         return NULL;
    2751             : }
    2752             : 
    2753             : stmt *
    2754          43 : stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int symmetric, int swapped)
    2755             : {
    2756          43 :         InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, swapped, st_join2, 1/*reduce semantics*/);
    2757          43 :         if (q == NULL)
    2758             :                 return NULL;
    2759             : 
    2760          43 :         stmt *s = stmt_create(be->mvc->sa, st_join2);
    2761          43 :         if (s == NULL) {
    2762             :                 return NULL;
    2763             :         }
    2764             : 
    2765          43 :         s->op1 = l;
    2766          43 :         s->op2 = ra;
    2767          43 :         s->op3 = rb;
    2768          43 :         s->flag = cmp;
    2769          43 :         s->nrcols = 2;
    2770          43 :         s->nr = getDestVar(q);
    2771          43 :         s->q = q;
    2772          43 :         s->reduce = 1;
    2773          43 :         return s;
    2774             : }
    2775             : 
    2776             : stmt *
    2777          45 : stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
    2778             : {
    2779          45 :         MalBlkPtr mb = be->mb;
    2780          45 :         InstrPtr q = NULL;
    2781          45 :         const char *mod, *fimp;
    2782          45 :         node *n;
    2783             : 
    2784          45 :         if (l == NULL || r == NULL)
    2785           0 :                 goto bailout;
    2786          45 :         if (backend_create_subfunc(be, op, NULL) < 0)
    2787           0 :                 goto bailout;
    2788          45 :         mod = sql_func_mod(op->func);
    2789          45 :         fimp = backend_function_imp(be, op->func);
    2790          45 :         fimp = sa_strconcat(be->mvc->sa, fimp, "join");
    2791             : 
    2792             :         /* filter qualifying tuples, return oids of h and tail */
    2793          45 :         q = newStmtArgs(mb, mod, fimp, list_length(l->op4.lval) + list_length(r->op4.lval) + 7);
    2794          45 :         if (q == NULL)
    2795           0 :                 goto bailout;
    2796          45 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2797          90 :         for (n = l->op4.lval->h; n; n = n->next) {
    2798          45 :                 stmt *op = n->data;
    2799             : 
    2800          45 :                 q = pushArgument(mb, q, op->nr);
    2801             :         }
    2802             : 
    2803         150 :         for (n = r->op4.lval->h; n; n = n->next) {
    2804         105 :                 stmt *op = n->data;
    2805             : 
    2806         105 :                 q = pushArgument(mb, q, op->nr);
    2807             :         }
    2808          45 :         q = pushNilBat(mb, q); /* candidate lists */
    2809          45 :         q = pushNilBat(mb, q); /* candidate lists */
    2810          45 :         q = pushBit(mb, q, TRUE);     /* nil_matches */
    2811          45 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2812          45 :         q = pushBit(mb, q, anti?TRUE:FALSE); /* 'not' matching */
    2813          45 :         pushInstruction(mb, q);
    2814             : 
    2815          45 :         if (swapped) {
    2816           6 :                 InstrPtr r = newInstruction(mb,  NULL, NULL);
    2817           6 :                 if (r == NULL)
    2818           0 :                         goto bailout;
    2819           6 :                 getArg(r, 0) = newTmpVariable(mb, TYPE_any);
    2820           6 :                 r = pushReturn(mb, r, newTmpVariable(mb, TYPE_any));
    2821           6 :                 r = pushArgument(mb, r, getArg(q,1));
    2822           6 :                 r = pushArgument(mb, r, getArg(q,0));
    2823           6 :                 pushInstruction(mb, r);
    2824           6 :                 q = r;
    2825             :         }
    2826             : 
    2827          45 :         stmt *s = stmt_create(be->mvc->sa, st_joinN);
    2828          45 :         if (s == NULL) {
    2829           0 :                 goto bailout;
    2830             :         }
    2831             : 
    2832          45 :         s->op1 = l;
    2833          45 :         s->op2 = r;
    2834          45 :         s->op4.funcval = op;
    2835          45 :         s->nrcols = 2;
    2836          45 :         if (swapped)
    2837           6 :                 s->flag |= SWAPPED;
    2838          45 :         s->nr = getDestVar(q);
    2839          45 :         s->q = q;
    2840          45 :         return s;
    2841             : 
    2842           0 :   bailout:
    2843           0 :         if (be->mvc->sa->eb.enabled)
    2844           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    2845             :         return NULL;
    2846             : }
    2847             : 
    2848             : stmt *
    2849       22160 : stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
    2850             : {
    2851       22160 :         InstrPtr q = NULL;
    2852             : 
    2853       22160 :         if (rs == NULL || rs->nr < 0)
    2854             :                 return NULL;
    2855       22160 :         q = rs->q;
    2856       22160 :         if (q) {
    2857       21944 :                 stmt *s = stmt_create(be->mvc->sa, st_rs_column);
    2858       21944 :                 if (s == NULL) {
    2859             :                         return NULL;
    2860             :                 }
    2861             : 
    2862       21944 :                 s->op1 = rs;
    2863       21944 :                 s->op4.typeval = *tpe;
    2864       21944 :                 s->flag = i;
    2865       21944 :                 s->nrcols = 1;
    2866       21944 :                 s->key = 0;
    2867       21944 :                 s->q = q;
    2868       21944 :                 s->nr = getArg(q, s->flag);
    2869       21944 :                 return s;
    2870         216 :         } else if (rs->type == st_list) {
    2871         216 :                 list *cols = rs->op4.lval;
    2872         216 :                 if (i < list_length(cols))
    2873         216 :                         return list_fetch(cols, i);
    2874             :         }
    2875             :         return NULL;
    2876             : }
    2877             : 
    2878             : /*
    2879             :  * The dump_header produces a sequence of instructions for
    2880             :  * the front-end to prepare presentation of a result table.
    2881             :  *
    2882             :  * A secondary scheme is added to assemble all information
    2883             :  * in columns first. Then it can be returned to the environment.
    2884             :  */
    2885             : #define NEWRESULTSET
    2886             : 
    2887             : #define meta(P, Id, Tpe, Args)                                          \
    2888             :         do {                                                                                    \
    2889             :                 P = newStmtArgs(mb, batRef, packRef, Args);     \
    2890             :                 if (P) {                                                                        \
    2891             :                         Id = getArg(P,0);                                               \
    2892             :                         setVarType(mb, Id, newBatType(Tpe));    \
    2893             :                         setVarFixed(mb, Id);                                    \
    2894             :                         list = pushArgument(mb, list, Id);              \
    2895             :                         pushInstruction(mb, P);                                 \
    2896             :                 }                                                                                       \
    2897             :         } while (0)
    2898             : 
    2899             : static int
    2900          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)
    2901             : {
    2902          32 :         node *n;
    2903          32 :         int ret = -1;
    2904          32 :         int args;
    2905             : 
    2906             :         // gather the meta information
    2907          32 :         int tblId, nmeId, tpeId, lenId, scaleId;
    2908          32 :         InstrPtr list;
    2909          32 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    2910             : 
    2911          32 :         args = list_length(l) + 1;
    2912             : 
    2913          32 :         list = newInstructionArgs(mb, sqlRef, export_tableRef, args + 13);
    2914          32 :         if (list == NULL)
    2915             :                 return -1;
    2916          32 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    2917          32 :         if( file >= 0){
    2918          32 :                 list = pushArgument(mb, list, file);
    2919          32 :                 list = pushStr(mb, list, format);
    2920          32 :                 list = pushStr(mb, list, sep);
    2921          32 :                 list = pushStr(mb, list, rsep);
    2922          32 :                 list = pushStr(mb, list, ssep);
    2923          32 :                 list = pushStr(mb, list, ns);
    2924          32 :                 list = pushInt(mb, list, onclient);
    2925             :         }
    2926          32 :         meta(tblPtr, tblId, TYPE_str, args);
    2927          32 :         meta(nmePtr, nmeId, TYPE_str, args);
    2928          32 :         meta(tpePtr, tpeId, TYPE_str, args);
    2929          32 :         meta(lenPtr, lenId, TYPE_int, args);
    2930          32 :         meta(scalePtr, scaleId, TYPE_int, args);
    2931          32 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    2932             :                 return -1;
    2933             : 
    2934         172 :         for (n = l->h; n; n = n->next) {
    2935         140 :                 stmt *c = n->data;
    2936         140 :                 sql_subtype *t = tail_type(c);
    2937         140 :                 const char *tname = table_name(sql->sa, c);
    2938         140 :                 const char *sname = schema_name(sql->sa, c);
    2939         140 :                 const char *_empty = "";
    2940         140 :                 const char *tn = (tname) ? tname : _empty;
    2941         140 :                 const char *sn = (sname) ? sname : _empty;
    2942         140 :                 const char *cn = column_name(sql->sa, c);
    2943         140 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    2944         140 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    2945         140 :                 size_t fqtnl;
    2946         140 :                 char *fqtn = NULL;
    2947             : 
    2948         140 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    2949         140 :                         fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    2950         140 :                         if (fqtn == NULL)
    2951             :                                 return -1;
    2952         140 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    2953         140 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    2954         140 :                         nmePtr = pushStr(mb, nmePtr, cn);
    2955         140 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    2956         140 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    2957         140 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    2958         140 :                         list = pushArgument(mb, list, c->nr);
    2959             :                 } else
    2960             :                         return -1;
    2961             :         }
    2962          32 :         sa_reset(sql->ta);
    2963          32 :         ret = getArg(list,0);
    2964          32 :         pushInstruction(mb,list);
    2965          32 :         return ret;
    2966             : }
    2967             : 
    2968             : 
    2969             : stmt *
    2970          32 : stmt_export(backend *be, stmt *t, const char *sep, const char *rsep, const char *ssep, const char *null_string, int onclient, stmt *file)
    2971             : {
    2972          32 :         MalBlkPtr mb = be->mb;
    2973          32 :         InstrPtr q = NULL;
    2974          32 :         int fnr;
    2975          32 :         list *l;
    2976             : 
    2977          32 :         if (t == NULL || t->nr < 0)
    2978           0 :                 goto bailout;
    2979          32 :         l = t->op4.lval;
    2980          32 :         if (file) {
    2981          23 :                 if (file->nr < 0)
    2982           0 :                         goto bailout;
    2983             :                 fnr = file->nr;
    2984             :         } else {
    2985           9 :                 q = newAssignment(mb);
    2986           9 :                 if (q == NULL)
    2987           0 :                         goto bailout;
    2988           9 :                 q = pushStr(mb,q,"stdout");
    2989           9 :                 fnr = getArg(q,0);
    2990           9 :                 pushInstruction(mb, q);
    2991             :         }
    2992          32 :         if (t->type == st_list) {
    2993          32 :                 if (dump_export_header(be->mvc, mb, l, fnr, "csv", sep, rsep, ssep, null_string, onclient) < 0)
    2994           0 :                         goto bailout;
    2995             :         } else {
    2996           0 :                 q = newStmt(mb, sqlRef, raiseRef);
    2997           0 :                 if (q == NULL)
    2998           0 :                         goto bailout;
    2999           0 :                 q = pushStr(mb, q, "not a valid output list\n");
    3000           0 :                 pushInstruction(mb, q);
    3001             :         }
    3002          32 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3003          32 :         if(!s) {
    3004           0 :                 goto bailout;
    3005             :         }
    3006          32 :         s->op1 = t;
    3007          32 :         s->op2 = file;
    3008          32 :         s->q = q;
    3009          32 :         s->nr = 1;
    3010          32 :         return s;
    3011             : 
    3012           0 :   bailout:
    3013           0 :         if (be->mvc->sa->eb.enabled)
    3014           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3015             :         return NULL;
    3016             : }
    3017             : 
    3018             : stmt *
    3019         150 : stmt_export_bin(backend *be, stmt *colstmt, bool byteswap, const char *filename, int on_client)
    3020             : {
    3021         150 :         MalBlkPtr mb = be->mb;
    3022         150 :         InstrPtr q;
    3023             : 
    3024         150 :         if (colstmt == NULL)
    3025           0 :                 goto bailout;
    3026         150 :         q = newStmt(mb, sqlRef, export_bin_columnRef);
    3027         150 :         if (q == NULL)
    3028           0 :                 goto bailout;
    3029         150 :         pushArgument(mb, q, colstmt->nr);
    3030         150 :         pushBit(mb, q, byteswap);
    3031         150 :         pushStr(mb, q, filename);
    3032         150 :         pushInt(mb, q, on_client);
    3033         150 :         pushInstruction(mb, q);
    3034             : 
    3035         150 :         stmt *s = stmt_create(be->mvc->sa, st_export);
    3036         150 :         if (!s)
    3037           0 :                 goto bailout;
    3038             : 
    3039         150 :         s->q = q;
    3040         150 :         return s;
    3041             : 
    3042           0 :   bailout:
    3043           0 :         if (be->mvc->sa->eb.enabled)
    3044           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3045             :         return NULL;
    3046             : }
    3047             : 
    3048             : stmt *
    3049        3040 : stmt_trans(backend *be, int type, stmt *chain, stmt *name)
    3050             : {
    3051        3040 :         MalBlkPtr mb = be->mb;
    3052        3040 :         InstrPtr q = NULL;
    3053             : 
    3054        3040 :         if (chain == NULL || chain->nr < 0)
    3055           0 :                 goto bailout;
    3056             : 
    3057        3040 :         switch(type){
    3058          12 :         case ddl_release:
    3059          12 :                 q = newStmt(mb, sqlRef, transaction_releaseRef);
    3060          12 :                 break;
    3061         558 :         case ddl_commit:
    3062         558 :                 q = newStmt(mb, sqlRef, transaction_commitRef);
    3063         558 :                 break;
    3064        1026 :         case ddl_rollback:
    3065        1026 :                 q = newStmt(mb, sqlRef, transaction_rollbackRef);
    3066        1026 :                 break;
    3067        1444 :         case ddl_trans:
    3068        1444 :                 q = newStmt(mb, sqlRef, transaction_beginRef);
    3069        1444 :                 break;
    3070           0 :         default:
    3071           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown transaction type\n");
    3072           0 :                 goto bailout;
    3073             :         }
    3074        3040 :         if (q == NULL)
    3075           0 :                 goto bailout;
    3076        3040 :         q = pushArgument(mb, q, chain->nr);
    3077        3040 :         if (name)
    3078          77 :                 q = pushArgument(mb, q, name->nr);
    3079             :         else
    3080        2963 :                 q = pushNil(mb, q, TYPE_str);
    3081             : 
    3082        3040 :         bool enabled = be->mvc->sa->eb.enabled;
    3083        3040 :         be->mvc->sa->eb.enabled = false;
    3084        3040 :         stmt *s = stmt_create(be->mvc->sa, st_trans);
    3085        3040 :         be->mvc->sa->eb.enabled = enabled;
    3086        3040 :         if(!s) {
    3087           0 :                 freeInstruction(q);
    3088           0 :                 goto bailout;
    3089             :         }
    3090        3040 :         s->op1 = chain;
    3091        3040 :         s->op2 = name;
    3092        3040 :         s->flag = type;
    3093        3040 :         s->q = q;
    3094        3040 :         s->nr = getDestVar(q);
    3095        3040 :         pushInstruction(mb, q);
    3096        3040 :         return s;
    3097             : 
    3098           0 :   bailout:
    3099           0 :         if (be->mvc->sa->eb.enabled)
    3100           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3101             :         return NULL;
    3102             : }
    3103             : 
    3104             : stmt *
    3105      272780 : stmt_catalog(backend *be, int type, stmt *args)
    3106             : {
    3107      272780 :         MalBlkPtr mb = be->mb;
    3108      272780 :         InstrPtr q = NULL;
    3109      272780 :         node *n;
    3110             : 
    3111      272780 :         if (args == NULL || args->nr < 0)
    3112           0 :                 goto bailout;
    3113             : 
    3114             :         /* cast them into properly named operations */
    3115      272780 :         const char *ref;
    3116      272780 :         switch(type){
    3117         307 :         case ddl_create_seq:                    ref = create_seqRef;            break;
    3118          47 :         case ddl_alter_seq:                             ref = alter_seqRef;                     break;
    3119          32 :         case ddl_drop_seq:                              ref = drop_seqRef;                      break;
    3120        1055 :         case ddl_create_schema:                 ref = create_schemaRef;         break;
    3121         173 :         case ddl_drop_schema:                   ref = drop_schemaRef;           break;
    3122        9334 :         case ddl_create_table:                  ref = create_tableRef;          break;
    3123       22074 :         case ddl_create_view:                   ref = create_viewRef;           break;
    3124        3391 :         case ddl_drop_table:                    ref = drop_tableRef;            break;
    3125         374 :         case ddl_drop_view:                             ref = drop_viewRef;                     break;
    3126         145 :         case ddl_drop_constraint:               ref = drop_constraintRef;       break;
    3127        1317 :         case ddl_alter_table:                   ref = alter_tableRef;           break;
    3128         890 :         case ddl_create_type:                   ref = create_typeRef;           break;
    3129           4 :         case ddl_drop_type:                             ref = drop_typeRef;                     break;
    3130          27 :         case ddl_grant_roles:                   ref = grant_rolesRef;           break;
    3131           8 :         case ddl_revoke_roles:                  ref = revoke_rolesRef;          break;
    3132       17783 :         case ddl_grant:                                 ref = grantRef;                         break;
    3133          10 :         case ddl_revoke:                                ref = revokeRef;                        break;
    3134       93217 :         case ddl_grant_func:                    ref = grant_functionRef;        break;
    3135           1 :         case ddl_revoke_func:                   ref = revoke_functionRef;       break;
    3136         318 :         case ddl_create_user:                   ref = create_userRef;           break;
    3137          89 :         case ddl_drop_user:                             ref = drop_userRef;                     break;
    3138          68 :         case ddl_alter_user:                    ref = alter_userRef;            break;
    3139           5 :         case ddl_rename_user:                   ref = rename_userRef;           break;
    3140          23 :         case ddl_create_role:                   ref = create_roleRef;           break;
    3141          19 :         case ddl_drop_role:                             ref = drop_roleRef;                     break;
    3142         157 :         case ddl_drop_index:                    ref = drop_indexRef;            break;
    3143         794 :         case ddl_drop_function:                 ref = drop_functionRef;         break;
    3144      117555 :         case ddl_create_function:               ref = create_functionRef;       break;
    3145         334 :         case ddl_create_trigger:                ref = create_triggerRef;        break;
    3146          80 :         case ddl_drop_trigger:                  ref = drop_triggerRef;          break;
    3147         247 :         case ddl_alter_table_add_table: ref = alter_add_tableRef;       break;
    3148         169 :         case ddl_alter_table_del_table: ref = alter_del_tableRef;       break;
    3149        2036 :         case ddl_alter_table_set_access:ref = alter_set_tableRef;       break;
    3150         214 :         case ddl_alter_table_add_range_partition: ref = alter_add_range_partitionRef; break;
    3151          59 :         case ddl_alter_table_add_list_partition: ref = alter_add_value_partitionRef; break;
    3152         358 :         case ddl_comment_on:                    ref = comment_onRef;            break;
    3153           8 :         case ddl_rename_schema:                 ref = rename_schemaRef;         break;
    3154          45 :         case ddl_rename_table:                  ref = rename_tableRef;          break;
    3155          13 :         case ddl_rename_column:                 ref = rename_columnRef;         break;
    3156           0 :         default:
    3157           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown catalog operation\n");
    3158           0 :                 goto bailout;
    3159             :         }
    3160      272780 :         q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
    3161      272781 :         if (q == NULL)
    3162           0 :                 goto bailout;
    3163             :         // pass all arguments as before
    3164     1628049 :         for (n = args->op4.lval->h; n; n = n->next) {
    3165     1355268 :                 stmt *c = n->data;
    3166             : 
    3167     1355268 :                 q = pushArgument(mb, q, c->nr);
    3168             :         }
    3169             : 
    3170      272781 :         bool enabled = be->mvc->sa->eb.enabled;
    3171      272781 :         be->mvc->sa->eb.enabled = false;
    3172      272781 :         stmt *s = stmt_create(be->mvc->sa, st_catalog);
    3173      272781 :         be->mvc->sa->eb.enabled = enabled;
    3174      272781 :         if(!s) {
    3175           0 :                 freeInstruction(q);
    3176           0 :                 goto bailout;
    3177             :         }
    3178      272781 :         s->op1 = args;
    3179      272781 :         s->flag = type;
    3180      272781 :         s->q = q;
    3181      272781 :         s->nr = getDestVar(q);
    3182      272781 :         pushInstruction(mb, q);
    3183      272781 :         return s;
    3184             : 
    3185           0 :   bailout:
    3186           0 :         if (be->mvc->sa->eb.enabled)
    3187           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3188             :         return NULL;
    3189             : }
    3190             : 
    3191             : void
    3192     1764015 : stmt_set_nrcols(stmt *s)
    3193             : {
    3194     1764015 :         unsigned nrcols = 0;
    3195     1764015 :         int key = 1;
    3196     1764015 :         node *n;
    3197     1764015 :         list *l = s->op4.lval;
    3198             : 
    3199     1764015 :         assert(s->type == st_list);
    3200     8545392 :         for (n = l->h; n; n = n->next) {
    3201     6781377 :                 stmt *f = n->data;
    3202             : 
    3203     6781377 :                 if (!f)
    3204           0 :                         continue;
    3205     6781377 :                 if (f->nrcols > nrcols)
    3206             :                         nrcols = f->nrcols;
    3207     6781377 :                 key &= f->key;
    3208     6781377 :                 s->nr = f->nr;
    3209             :         }
    3210     1764015 :         s->nrcols = nrcols;
    3211     1764015 :         s->key = key;
    3212     1764015 : }
    3213             : 
    3214             : stmt *
    3215     1374068 : stmt_list(backend *be, list *l)
    3216             : {
    3217     1374068 :         if (l == NULL)
    3218             :                 return NULL;
    3219     1374068 :         stmt *s = stmt_create(be->mvc->sa, st_list);
    3220     1374049 :         if(!s) {
    3221             :                 return NULL;
    3222             :         }
    3223     1374049 :         s->op4.lval = l;
    3224     1374049 :         stmt_set_nrcols(s);
    3225     1374049 :         return s;
    3226             : }
    3227             : 
    3228             : static InstrPtr
    3229       60555 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
    3230             : {
    3231       60555 :         node *n;
    3232             :         // gather the meta information
    3233       60555 :         int tblId, nmeId, tpeId, lenId, scaleId;
    3234       60555 :         int args;
    3235       60555 :         InstrPtr list;
    3236       60555 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    3237             : 
    3238       60555 :         args = list_length(l) + 1;
    3239             : 
    3240       60572 :         list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 5);
    3241       60575 :         if(!list) {
    3242             :                 return NULL;
    3243             :         }
    3244       60575 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3245       60572 :         meta(tblPtr, tblId, TYPE_str, args);
    3246       60577 :         meta(nmePtr, nmeId, TYPE_str, args);
    3247       60577 :         meta(tpePtr, tpeId, TYPE_str, args);
    3248       60577 :         meta(lenPtr, lenId, TYPE_int, args);
    3249       60577 :         meta(scalePtr, scaleId, TYPE_int, args);
    3250       60577 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    3251             :                 return NULL;
    3252             : 
    3253      312932 :         for (n = l->h; n; n = n->next) {
    3254      252356 :                 stmt *c = n->data;
    3255      252356 :                 sql_subtype *t = tail_type(c);
    3256      252356 :                 const char *tname = table_name(sql->sa, c);
    3257      252359 :                 const char *sname = schema_name(sql->sa, c);
    3258      252343 :                 const char *_empty = "";
    3259      252343 :                 const char *tn = (tname) ? tname : _empty;
    3260      252343 :                 const char *sn = (sname) ? sname : _empty;
    3261      252343 :                 const char *cn = column_name(sql->sa, c);
    3262      252350 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3263      252343 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3264      252355 :                 size_t fqtnl;
    3265             : 
    3266      252355 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3267      252355 :                         char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3268      252352 :                         if (fqtn == NULL)
    3269             :                                 return NULL;
    3270      252352 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3271      252352 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3272      252350 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3273      252348 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3274      252355 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3275      252348 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3276      252356 :                         list = pushArgument(mb,list,c->nr);
    3277             :                 } else
    3278             :                         return NULL;
    3279             :         }
    3280       60576 :         sa_reset(sql->ta);
    3281       60561 :         pushInstruction(mb,list);
    3282       60561 :         return list;
    3283             : }
    3284             : 
    3285             : int
    3286      120823 : stmt_output(backend *be, stmt *lst)
    3287             : {
    3288      120823 :         MalBlkPtr mb = be->mb;
    3289      120823 :         InstrPtr q = NULL;
    3290      120823 :         list *l = lst->op4.lval;
    3291      120823 :         int cnt = list_length(l), ok = 0;
    3292      120898 :         node *n = l->h;
    3293      120898 :         stmt *first = n->data;
    3294             : 
    3295             :         /* single value result, has a fast exit */
    3296      120898 :         if (cnt == 1 && first->nrcols <= 0 ){
    3297       60306 :                 stmt *c = n->data;
    3298       60306 :                 sql_subtype *t = tail_type(c);
    3299       60266 :                 const char *tname = table_name(be->mvc->sa, c);
    3300       60210 :                 const char *sname = schema_name(be->mvc->sa, c);
    3301       60242 :                 const char *_empty = "";
    3302       60242 :                 const char *tn = (tname) ? tname : _empty;
    3303       60242 :                 const char *sn = (sname) ? sname : _empty;
    3304       60242 :                 const char *cn = column_name(be->mvc->sa, c);
    3305       60294 :                 const char *ntn = sql_escape_ident(be->mvc->ta, tn);
    3306       60356 :                 const char *nsn = sql_escape_ident(be->mvc->ta, sn);
    3307             : 
    3308       60368 :                 if (ntn && nsn) {
    3309       60368 :                         size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
    3310       60368 :                         char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
    3311       60368 :                         if (fqtn == NULL)
    3312             :                                 return -1;
    3313       60368 :                         ok = 1;
    3314       60368 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3315             : 
    3316       60368 :                         q = newStmt(mb, sqlRef, resultSetRef);
    3317       60366 :                         if (q == NULL)
    3318             :                                 return -1;
    3319       60366 :                         getArg(q,0) = newTmpVariable(mb,TYPE_int);
    3320       60368 :                         q = pushStr(mb, q, fqtn);
    3321       60362 :                         q = pushStr(mb, q, cn);
    3322       60367 :                         q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
    3323       60366 :                         q = pushInt(mb, q, t->digits);
    3324       60364 :                         q = pushInt(mb, q, t->scale);
    3325       60362 :                         q = pushInt(mb, q, t->type->eclass);
    3326       60362 :                         q = pushArgument(mb, q, c->nr);
    3327       60353 :                         pushInstruction(mb, q);
    3328             :                 }
    3329       60356 :                 sa_reset(be->mvc->ta);
    3330       60332 :                 if (!ok)
    3331             :                         return -1;
    3332             :         } else {
    3333       60592 :                 if ((q = dump_header(be->mvc, mb, l)) == NULL)
    3334             :                         return -1;
    3335             :         }
    3336             :         return 0;
    3337             : }
    3338             : 
    3339             : int
    3340      148027 : stmt_affected_rows(backend *be, int lastnr)
    3341             : {
    3342      148027 :         MalBlkPtr mb = be->mb;
    3343      148027 :         InstrPtr q = NULL;
    3344             : 
    3345      148027 :         q = newStmt(mb, sqlRef, affectedRowsRef);
    3346      148317 :         if (q == NULL)
    3347             :                 return -1;
    3348      148317 :         q = pushArgument(mb, q, be->mvc_var);
    3349      148316 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    3350      148316 :         q = pushArgument(mb, q, lastnr);
    3351      148318 :         pushInstruction(mb, q);
    3352      148310 :         be->mvc_var = getDestVar(q);
    3353      148310 :         return 0;
    3354             : }
    3355             : 
    3356             : stmt *
    3357      192935 : stmt_append(backend *be, stmt *c, stmt *a)
    3358             : {
    3359      192935 :         MalBlkPtr mb = be->mb;
    3360      192935 :         InstrPtr q = NULL;
    3361             : 
    3362      192935 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3363           0 :                 goto bailout;
    3364      192935 :         q = newStmt(mb, batRef, appendRef);
    3365      192935 :         if (q == NULL)
    3366           0 :                 goto bailout;
    3367      192935 :         q = pushArgument(mb, q, c->nr);
    3368      192935 :         q = pushArgument(mb, q, a->nr);
    3369      192935 :         q = pushBit(mb, q, TRUE);
    3370      192935 :         bool enabled = be->mvc->sa->eb.enabled;
    3371      192935 :         be->mvc->sa->eb.enabled = false;
    3372      192935 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3373      192935 :         be->mvc->sa->eb.enabled = enabled;
    3374      192935 :         if(!s) {
    3375           0 :                 freeInstruction(q);
    3376           0 :                 goto bailout;
    3377             :         }
    3378      192935 :         s->op1 = c;
    3379      192935 :         s->op2 = a;
    3380      192935 :         s->nrcols = c->nrcols;
    3381      192935 :         s->key = c->key;
    3382      192935 :         s->nr = getDestVar(q);
    3383      192935 :         s->q = q;
    3384      192935 :         pushInstruction(mb, q);
    3385      192935 :         return s;
    3386             : 
    3387           0 :   bailout:
    3388           0 :         if (be->mvc->sa->eb.enabled)
    3389           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3390             :         return NULL;
    3391             : }
    3392             : 
    3393             : stmt *
    3394      137031 : stmt_append_bulk(backend *be, stmt *c, list *l)
    3395             : {
    3396      137031 :         MalBlkPtr mb = be->mb;
    3397      137031 :         InstrPtr q = NULL;
    3398      137031 :         bool needs_columns = false;
    3399             : 
    3400      137031 :         if (c->nr < 0)
    3401           0 :                 goto bailout;
    3402             : 
    3403             :         /* currently appendBulk accepts its inputs all either scalar or vectors
    3404             :            if there is one vector and any scala, then the scalars mut be upgraded to vectors */
    3405      663230 :         for (node *n = l->h; n; n = n->next) {
    3406      526199 :                 stmt *t = n->data;
    3407      526199 :                 needs_columns |= t->nrcols > 0;
    3408             :         }
    3409      137031 :         if (needs_columns) {
    3410           0 :                 for (node *n = l->h; n; n = n->next) {
    3411           0 :                         stmt *t = n->data;
    3412           0 :                         if (t->nrcols == 0)
    3413           0 :                                 n->data = const_column(be, t);
    3414             :                 }
    3415             :         }
    3416             : 
    3417      137031 :         q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3);
    3418      137383 :         if (q == NULL)
    3419           0 :                 goto bailout;
    3420      137383 :         q = pushArgument(mb, q, c->nr);
    3421      137375 :         q = pushBit(mb, q, TRUE);
    3422      663615 :         for (node *n = l->h ; n ; n = n->next) {
    3423      526333 :                 stmt *a = n->data;
    3424      526333 :                 q = pushArgument(mb, q, a->nr);
    3425             :         }
    3426      137282 :         bool enabled = be->mvc->sa->eb.enabled;
    3427      137282 :         be->mvc->sa->eb.enabled = false;
    3428      137282 :         stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
    3429      137194 :         be->mvc->sa->eb.enabled = enabled;
    3430      137194 :         if(!s) {
    3431           0 :                 freeInstruction(q);
    3432           0 :                 goto bailout;
    3433             :         }
    3434      137194 :         s->op1 = c;
    3435      137194 :         s->op4.lval = l;
    3436      137194 :         s->nrcols = c->nrcols;
    3437      137194 :         s->key = c->key;
    3438      137194 :         s->nr = getDestVar(q);
    3439      137194 :         s->q = q;
    3440      137194 :         pushInstruction(mb, q);
    3441      137194 :         return s;
    3442             : 
    3443           0 :   bailout:
    3444           0 :         if (be->mvc->sa->eb.enabled)
    3445           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3446             :         return NULL;
    3447             : }
    3448             : 
    3449             : stmt *
    3450      104807 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
    3451             : {
    3452      104807 :         MalBlkPtr mb = be->mb;
    3453      104807 :         InstrPtr q = NULL;
    3454             : 
    3455      104807 :         if (!t || cnt->nr < 0)
    3456           0 :                 goto bailout;
    3457      104807 :         assert(t->s);                                /* declared table */
    3458      104807 :         q = newStmtArgs(mb, sqlRef, claimRef, 6);
    3459      104898 :         if (q == NULL)
    3460           0 :                 goto bailout;
    3461             :         /* returns offset or offsets */
    3462      104898 :         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
    3463      104892 :         q = pushArgument(mb, q, be->mvc_var);
    3464      104894 :         q = pushSchema(mb, q, t);
    3465      104875 :         q = pushStr(mb, q, t->base.name);
    3466      104871 :         q = pushArgument(mb, q, cnt->nr);
    3467      104875 :         bool enabled = be->mvc->sa->eb.enabled;
    3468      104875 :         be->mvc->sa->eb.enabled = false;
    3469      104875 :         stmt *s = stmt_create(be->mvc->sa, st_claim);
    3470      104804 :         be->mvc->sa->eb.enabled = enabled;
    3471      104804 :         if(!s) {
    3472           0 :                 freeInstruction(q);
    3473           0 :                 goto bailout;
    3474             :         }
    3475      104804 :         s->op1 = cnt;
    3476      104804 :         s->op4.tval = t;
    3477      104804 :         s->nr = getDestVar(q);
    3478      104804 :         s->q = q;
    3479      104804 :         pushInstruction(mb, q);
    3480      104804 :         return s;
    3481             : 
    3482           0 :   bailout:
    3483           0 :         if (be->mvc->sa->eb.enabled)
    3484           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3485             :         return NULL;
    3486             : }
    3487             : 
    3488             : void
    3489      148099 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
    3490             : {
    3491      148099 :         MalBlkPtr mb = be->mb;
    3492      148099 :         InstrPtr q = NULL;
    3493             : 
    3494      148099 :         if (!t || cnt->nr < 0)
    3495           0 :                 goto bailout;
    3496      148099 :         q = newStmtArgs(mb, sqlRef, dependRef, 4);
    3497      148550 :         if (q == NULL)
    3498           0 :                 goto bailout;
    3499      148550 :         q = pushSchema(mb, q, t);
    3500      148513 :         q = pushStr(mb, q, t->base.name);
    3501      148537 :         q = pushArgument(mb, q, cnt->nr);
    3502      148540 :         pushInstruction(mb, q);
    3503      148540 :         return;
    3504             : 
    3505           0 :   bailout:
    3506           0 :         if (be->mvc->sa->eb.enabled)
    3507           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);
    3508             : }
    3509             : 
    3510             : void
    3511       13993 : stmt_add_column_predicate(backend *be, sql_column *c)
    3512             : {
    3513       13993 :         MalBlkPtr mb = be->mb;
    3514       13993 :         InstrPtr q = NULL;
    3515             : 
    3516       13993 :         if (!c)
    3517           0 :                 goto bailout;
    3518       13993 :         q = newStmtArgs(mb, sqlRef, predicateRef, 4);
    3519       14009 :         if (q == NULL)
    3520           0 :                 goto bailout;
    3521       14009 :         q = pushSchema(mb, q, c->t);
    3522       14009 :         q = pushStr(mb, q, c->t->base.name);
    3523       14009 :         q = pushStr(mb, q, c->base.name);
    3524       14009 :         pushInstruction(mb, q);
    3525       14009 :         return;
    3526             : 
    3527           0 :   bailout:
    3528           0 :         if (be->mvc->sa->eb.enabled)
    3529           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);
    3530             : }
    3531             : 
    3532             : stmt *
    3533       47290 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
    3534             : {
    3535       47290 :         MalBlkPtr mb = be->mb;
    3536       47290 :         InstrPtr q = NULL;
    3537             : 
    3538       47290 :         if (r->nr < 0)
    3539           0 :                 goto bailout;
    3540             : 
    3541       47290 :         q = newStmt(mb, batRef, replaceRef);
    3542       47290 :         if (q == NULL)
    3543           0 :                 goto bailout;
    3544       47290 :         q = pushArgument(mb, q, r->nr);
    3545       47290 :         q = pushArgument(mb, q, id->nr);
    3546       47290 :         q = pushArgument(mb, q, val->nr);
    3547       47290 :         q = pushBit(mb, q, TRUE); /* forced */
    3548       47290 :         bool enabled = be->mvc->sa->eb.enabled;
    3549       47290 :         be->mvc->sa->eb.enabled = false;
    3550       47290 :         stmt *s = stmt_create(be->mvc->sa, st_replace);
    3551       47290 :         be->mvc->sa->eb.enabled = enabled;
    3552       47290 :         if(!s) {
    3553           0 :                 freeInstruction(q);
    3554           0 :                 goto bailout;
    3555             :         }
    3556       47290 :         s->op1 = r;
    3557       47290 :         s->op2 = id;
    3558       47290 :         s->op3 = val;
    3559       47290 :         s->nrcols = r->nrcols;
    3560       47290 :         s->key = r->key;
    3561       47290 :         s->nr = getDestVar(q);
    3562       47290 :         s->q = q;
    3563       47290 :         s->cand = r->cand;
    3564       47290 :         pushInstruction(mb, q);
    3565       47290 :         return s;
    3566             : 
    3567           0 :   bailout:
    3568           0 :         if (be->mvc->sa->eb.enabled)
    3569           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3570             :         return NULL;
    3571             : }
    3572             : 
    3573             : stmt *
    3574       41363 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
    3575             : {
    3576       41363 :         MalBlkPtr mb = be->mb;
    3577       41363 :         InstrPtr q = NULL;
    3578             : 
    3579       41363 :         if (!t->s && ATOMIC_PTR_GET(&t->data)) { /* declared table */
    3580           2 :                 int *l = ATOMIC_PTR_GET(&t->data), cnt = ol_length(t->columns)+1;
    3581             : 
    3582           6 :                 for (int i = 0; i < cnt; i++) {
    3583           4 :                         q = newStmt(mb, batRef, deleteRef);
    3584           4 :                         if (q == NULL)
    3585           0 :                                 goto bailout;
    3586           4 :                         q = pushArgument(mb, q, l[i]);
    3587           4 :                         pushInstruction(mb, q);
    3588             :                 }
    3589             :                 /* declared tables don't have sequences */
    3590             :         } else {
    3591       41361 :                 q = newStmt(mb, sqlRef, clear_tableRef);
    3592       41816 :                 if (q == NULL)
    3593           0 :                         goto bailout;
    3594       41816 :                 q = pushSchema(mb, q, t);
    3595       41811 :                 q = pushStr(mb, q, t->base.name);
    3596       41796 :                 q = pushInt(mb, q, restart_sequences);
    3597       41779 :                 pushInstruction(mb, q);
    3598             :         }
    3599       41776 :         stmt *s = stmt_create(be->mvc->sa, st_table_clear);
    3600             : 
    3601       41633 :         if(!s) {
    3602           0 :                 goto bailout;
    3603             :         }
    3604       41633 :         s->op4.tval = t;
    3605       41633 :         s->nrcols = 0;
    3606       41633 :         s->nr = getDestVar(q);
    3607       41633 :         s->q = q;
    3608       41633 :         return s;
    3609             : 
    3610           0 :   bailout:
    3611           0 :         if (be->mvc->sa->eb.enabled)
    3612           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3613             :         return NULL;
    3614             : }
    3615             : 
    3616             : stmt *
    3617       37079 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
    3618             : {
    3619       37079 :         MalBlkPtr mb = be->mb;
    3620       37079 :         InstrPtr q = NULL;
    3621             : 
    3622       37079 :         if (cond->nr < 0)
    3623             :                 return NULL;
    3624             : 
    3625             :         /* if(bit(l)) { error(r);}  ==raising an exception */
    3626       37079 :         q = newStmt(mb, sqlRef, assertRef);
    3627       37096 :         if (q == NULL)
    3628           0 :                 goto bailout;
    3629       37096 :         q = pushArgument(mb, q, cond->nr);
    3630       37096 :         q = pushStr(mb, q, errstr);
    3631       37095 :         bool enabled = be->mvc->sa->eb.enabled;
    3632       37095 :         be->mvc->sa->eb.enabled = false;
    3633       37095 :         stmt *s = stmt_create(be->mvc->sa, st_exception);
    3634       37094 :         be->mvc->sa->eb.enabled = enabled;
    3635       37094 :         if(!s) {
    3636           0 :                 freeInstruction(q);
    3637           0 :                 return NULL;
    3638             :         }
    3639       37094 :         assert(cond);
    3640       37094 :         s->op1 = cond;
    3641       37094 :         (void)errcode;
    3642       37094 :         s->nrcols = 0;
    3643       37094 :         s->q = q;
    3644       37094 :         s->nr = getDestVar(q);
    3645       37094 :         pushInstruction(mb, q);
    3646       37094 :         return s;
    3647             : 
    3648           0 :   bailout:
    3649           0 :         if (be->mvc->sa->eb.enabled)
    3650           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3651             :         return NULL;
    3652             : }
    3653             : 
    3654             : /* The type setting is not propagated to statements such as st_bat and st_append,
    3655             :         because they are not considered projections */
    3656             : static void
    3657       10025 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
    3658             : {
    3659       18917 :         for (;;) {
    3660       18917 :                 switch (st->type) {
    3661        1228 :                 case st_const:
    3662        1228 :                         st = st->op2;
    3663        1228 :                         continue;
    3664        4195 :                 case st_alias:
    3665             :                 case st_gen_group:
    3666             :                 case st_order:
    3667        4195 :                         st = st->op1;
    3668        4195 :                         continue;
    3669           0 :                 case st_list:
    3670           0 :                         st = st->op4.lval->h->data;
    3671           0 :                         continue;
    3672        3469 :                 case st_join:
    3673             :                 case st_join2:
    3674             :                 case st_joinN:
    3675        3469 :                         if (st->flag == cmp_project) {
    3676        3469 :                                 st = st->op2;
    3677        3469 :                                 continue;
    3678             :                         }
    3679             :                         return;
    3680        1312 :                 case st_aggr:
    3681             :                 case st_Nop: {
    3682        1312 :                         list *res = st->op4.funcval->res;
    3683             : 
    3684        1312 :                         if (res && list_length(res) == 1)
    3685        1312 :                                 res->h->data = t;
    3686             :                         return;
    3687             :                 }
    3688        2812 :                 case st_atom:
    3689        2812 :                         st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
    3690        2812 :                         return;
    3691          60 :                 case st_convert:
    3692             :                 case st_temp:
    3693             :                 case st_single:
    3694          60 :                         st->op4.typeval = *t;
    3695          60 :                         return;
    3696          65 :                 case st_var:
    3697          65 :                         if (st->op4.typeval.type)
    3698          65 :                                 st->op4.typeval = *t;
    3699             :                         return;
    3700             :                 default:
    3701             :                         return;
    3702             :                 }
    3703             :         }
    3704             : }
    3705             : 
    3706             : #define trivial_string_conversion(x) ((x) == EC_BIT || (x) == EC_CHAR || (x) == EC_STRING || (x) == EC_NUM || (x) == EC_POS || (x) == EC_FLT \
    3707             :                                                                           || (x) == EC_DATE || (x) == EC_BLOB || (x) == EC_MONTH)
    3708             : 
    3709             : static stmt *
    3710         321 : temporal_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t, bool before)
    3711             : {
    3712         321 :         MalBlkPtr mb = be->mb;
    3713         321 :         InstrPtr q = NULL;
    3714         321 :         const char *convert = t->type->impl, *mod = mtimeRef;
    3715         321 :         bool add_tz = false, pushed = (v->cand && v->cand == sel);
    3716             : 
    3717         321 :         if (before) {
    3718         263 :                 if (f->type->eclass == EC_TIMESTAMP_TZ && (t->type->eclass == EC_TIMESTAMP || t->type->eclass == EC_TIME)) {
    3719             :                         /* call timestamp+local_timezone */
    3720             :                         convert = "timestamp_add_msec_interval";
    3721             :                         add_tz = true;
    3722         208 :                 } else if (f->type->eclass == EC_TIMESTAMP_TZ && t->type->eclass == EC_DATE) {
    3723             :                         /* call convert timestamp with tz to date */
    3724          13 :                         convert = "datetz";
    3725          13 :                         mod = calcRef;
    3726          13 :                         add_tz = true;
    3727         195 :                 } else if (f->type->eclass == EC_TIMESTAMP && t->type->eclass == EC_TIMESTAMP_TZ) {
    3728             :                         /* call timestamp+local_timezone */
    3729             :                         convert = "timestamp_sub_msec_interval";
    3730             :                         add_tz = true;
    3731         159 :                 } else if (f->type->eclass == EC_TIME_TZ && (t->type->eclass == EC_TIME || t->type->eclass == EC_TIMESTAMP)) {
    3732             :                         /* call times+local_timezone */
    3733             :                         convert = "time_add_msec_interval";
    3734             :                         add_tz = true;
    3735         146 :                 } else if (f->type->eclass == EC_TIME && t->type->eclass == EC_TIME_TZ) {
    3736             :                         /* call times+local_timezone */
    3737             :                         convert = "time_sub_msec_interval";
    3738             :                         add_tz = true;
    3739         131 :                 } else if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass)) {
    3740         124 :                         if (t->type->eclass == EC_TIME_TZ)
    3741             :                                 convert = "daytimetz";
    3742             :                         else
    3743         100 :                                 convert = "timestamptz";
    3744         124 :                         mod = calcRef;
    3745         124 :                         add_tz = true;
    3746             :                 } else {
    3747             :                         return v;
    3748             :                 }
    3749             :         } else {
    3750          58 :                 if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIMESTAMP_TZ) {
    3751             :                         convert = "timestamp_sub_msec_interval";
    3752             :                         add_tz = true;
    3753          53 :                 } else if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIME_TZ) {
    3754             :                         convert = "time_sub_msec_interval";
    3755             :                         add_tz = true;
    3756             :                 } else {
    3757             :                         return v;
    3758             :                 }
    3759             :         }
    3760             : 
    3761         261 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3762         180 :                 q = newStmtArgs(mb, mod, convert, 13);
    3763         180 :                 if (q == NULL)
    3764           0 :                         goto bailout;
    3765             :         } else {
    3766          81 :                 if (sel && !pushed && v->nrcols == 0) {
    3767           0 :                         pushed = 1;
    3768           0 :                         v = stmt_project(be, sel, v);
    3769           0 :                         v->cand = sel;
    3770             :                 }
    3771          81 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3772          81 :                 if (q == NULL)
    3773           0 :                         goto bailout;
    3774             :         }
    3775         261 :         q = pushArgument(mb, q, v->nr);
    3776             : 
    3777         261 :         if (EC_VARCHAR(f->type->eclass))
    3778         124 :                 q = pushInt(mb, q, t->digits);
    3779             : 
    3780         261 :         if (add_tz)
    3781         261 :                         q = pushLng(mb, q, be->mvc->timezone);
    3782             : 
    3783         261 :         if (sel && !pushed && !v->cand) {
    3784           2 :                 q = pushArgument(mb, q, sel->nr);
    3785           2 :                 pushed = 1;
    3786         259 :         } else if (v->nrcols > 0) {
    3787          79 :                 q = pushNilBat(mb, q);
    3788             :         }
    3789             : 
    3790         261 :         bool enabled = be->mvc->sa->eb.enabled;
    3791         261 :         be->mvc->sa->eb.enabled = false;
    3792         261 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    3793         261 :         be->mvc->sa->eb.enabled = enabled;
    3794         261 :         if(!s) {
    3795           0 :                 freeInstruction(q);
    3796           0 :                 goto bailout;
    3797             :         }
    3798         261 :         s->op1 = v;
    3799         261 :         s->nrcols = 0;       /* function without arguments returns single value */
    3800         261 :         s->key = v->key;
    3801         261 :         s->nrcols = v->nrcols;
    3802         261 :         s->aggr = v->aggr;
    3803         261 :         s->op4.typeval = *t;
    3804         261 :         s->nr = getDestVar(q);
    3805         261 :         s->q = q;
    3806         261 :         s->cand = pushed ? sel : NULL;
    3807         261 :         pushInstruction(mb, q);
    3808         261 :         return s;
    3809             : 
    3810           0 :   bailout:
    3811           0 :         if (be->mvc->sa->eb.enabled)
    3812           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3813             :         return NULL;
    3814             : }
    3815             : 
    3816             : stmt *
    3817       43341 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    3818             : {
    3819       43341 :         MalBlkPtr mb = be->mb;
    3820       43341 :         InstrPtr q = NULL;
    3821       43341 :         const char *convert = t->type->impl, *mod = calcRef;
    3822       43341 :         int pushed = (v->cand && v->cand == sel), no_candidates = 0;
    3823       43341 :         bool add_tz = false;
    3824             :         /* convert types and make sure they are rounded up correctly */
    3825             : 
    3826       43341 :         if (v->nr < 0)
    3827           0 :                 goto bailout;
    3828             : 
    3829       43341 :         if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
    3830             :                 /* general cases */
    3831       43006 :                 ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
    3832       43006 :                 !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)) ||
    3833             :                 /* trivial decimal cases */
    3834        1651 :                 (f->type->eclass == EC_DEC && t->type->eclass == EC_DEC && f->scale == t->scale && f->type->localtype == t->type->localtype) ||
    3835             :                 /* trivial string cases */
    3836       37241 :                 (EC_VARCHAR(f->type->eclass) && EC_VARCHAR(t->type->eclass) && (t->digits == 0 || (f->digits > 0 && t->digits >= f->digits))))) {
    3837             :                 /* set output type. Despite the MAL code already being generated, the output type may still be checked */
    3838       10025 :                 tail_set_type(be->mvc, v, t);
    3839       10025 :                 return v;
    3840             :         }
    3841             : 
    3842             :         /* external types have sqlname convert functions,
    3843             :            these can generate errors (fromstr cannot) */
    3844       33316 :         if (t->type->eclass == EC_EXTERNAL)
    3845         308 :                 convert = t->type->base.name;
    3846       33008 :         else if (t->type->eclass == EC_MONTH)
    3847             :                 convert = "month_interval";
    3848       32997 :         else if (t->type->eclass == EC_SEC)
    3849          93 :                 convert = "second_interval";
    3850             : 
    3851       33316 :         no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
    3852             : 
    3853       33316 :         if ((type_has_tz(f) && !type_has_tz(t) && !EC_VARCHAR(t->type->eclass)) || (!type_has_tz(f) && type_has_tz(t))) {
    3854         263 :                 v = temporal_convert(be, v, sel, f, t, true);
    3855         263 :                 sel = NULL;
    3856         263 :                 pushed = 0;
    3857         263 :                 if (EC_VARCHAR(f->type->eclass))
    3858             :                         return v;
    3859             :         }
    3860             : 
    3861             :         /* Lookup the sql convert function, there is no need
    3862             :          * for single value vs bat, this is handled by the
    3863             :          * mal function resolution */
    3864       33192 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3865        8272 :                 q = newStmtArgs(mb, mod, convert, 13);
    3866        8272 :                 if (q == NULL)
    3867           0 :                         goto bailout;
    3868       24940 :         } else if ((v->nrcols > 0 || (sel && sel->nrcols > 0)) && no_candidates) {
    3869          20 :                 int type = t->type->localtype;
    3870             : 
    3871             :                 /* with our current implementation, all internal SQL types have candidate list support on their conversions */
    3872          20 :                 if (sel && !pushed) {
    3873           0 :                         pushed = 1;
    3874           0 :                         v = stmt_project(be, sel, v);
    3875           0 :                         v->cand = sel;
    3876             :                 }
    3877          20 :                 q = newStmtArgs(mb, malRef, multiplexRef, 15);
    3878          20 :                 if (q == NULL)
    3879           0 :                         goto bailout;
    3880          20 :                 setVarType(mb, getArg(q, 0), newBatType(type));
    3881          20 :                 q = pushStr(mb, q, convertMultiplexMod(mod, convert));
    3882          20 :                 q = pushStr(mb, q, convertMultiplexFcn(convert));
    3883             :         } else {
    3884       24900 :                 if (v->nrcols == 0 && sel && !pushed) {
    3885         549 :                         pushed = 1;
    3886         549 :                         v = stmt_project(be, sel, v);
    3887         549 :                         v->cand = sel;
    3888             :                 }
    3889       24900 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3890       24900 :                 if (q == NULL)
    3891           0 :                         goto bailout;
    3892             :         }
    3893             : 
    3894             :         /* convert to string is complex, we need full type info and mvc for the timezone */
    3895       33318 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
    3896        1757 :                 q = pushInt(mb, q, f->type->eclass);
    3897        1757 :                 q = pushInt(mb, q, f->digits);
    3898        1757 :                 q = pushInt(mb, q, f->scale);
    3899        1757 :                 q = pushInt(mb, q, type_has_tz(f));
    3900       31435 :         } else if (f->type->eclass == EC_DEC) {
    3901             :                 /* scale of the current decimal */
    3902        1453 :                 q = pushInt(mb, q, f->scale);
    3903       29982 :         } else if (f->type->eclass == EC_SEC && (EC_COMPUTE(t->type->eclass) || t->type->eclass == EC_DEC)) {
    3904             :                 /* scale of the current decimal */
    3905           0 :                 q = pushInt(mb, q, 3);
    3906             :         }
    3907       33192 :         q = pushArgument(mb, q, v->nr);
    3908       33192 :         if (add_tz)
    3909             :                         q = pushLng(mb, q, be->mvc->timezone);
    3910       33192 :         if (sel && !pushed && !v->cand) {
    3911        2603 :                 q = pushArgument(mb, q, sel->nr);
    3912        2603 :                 pushed = 1;
    3913       30589 :         } else if (v->nrcols > 0 && !no_candidates) {
    3914       22297 :                 q = pushNilBat(mb, q);
    3915             :         }
    3916       33192 :         if (!add_tz && (t->type->eclass == EC_DEC || EC_TEMP_FRAC(t->type->eclass) || EC_INTERVAL(t->type->eclass))) {
    3917             :                 /* digits, scale of the result decimal */
    3918        2927 :                 q = pushInt(mb, q, t->digits);
    3919        2927 :                 if (!EC_TEMP_FRAC(t->type->eclass))
    3920        2611 :                         q = pushInt(mb, q, t->scale);
    3921             :         }
    3922             :         /* convert to string, give error on to large strings */
    3923       33318 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
    3924        1757 :                 q = pushInt(mb, q, t->digits);
    3925             :         /* convert a string to a time(stamp) with time zone */
    3926       33192 :         if (EC_VARCHAR(f->type->eclass) && EC_TEMP_TZ(t->type->eclass))
    3927             :                 //q = pushInt(mb, q, type_has_tz(t));
    3928           0 :                 q = pushLng(mb, q, be->mvc->timezone);
    3929       33192 :         if (t->type->eclass == EC_GEOM) {
    3930             :                 /* push the type and coordinates of the column */
    3931         687 :                 q = pushInt(mb, q, t->digits);
    3932             :                 /* push the SRID of the whole columns */
    3933         687 :                 q = pushInt(mb, q, t->scale);
    3934             :                 /* push the type and coordinates of the inserted value */
    3935             :                 //q = pushInt(mb, q, f->digits);
    3936             :                 /* push the SRID of the inserted value */
    3937             :                 //q = pushInt(mb, q, f->scale);
    3938             :                 /* we decided to create the EWKB type also used by PostGIS and has the SRID provided by the user inside alreay */
    3939             :                 /* push the SRID provided for this value */
    3940             :                 /* GEOS library is able to store in the returned wkb the type an
    3941             :                  * number if coordinates but not the SRID so SRID should be provided
    3942             :                  * from this level */
    3943             : /*              if(be->argc > 1)
    3944             :                         f->scale = ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival;
    3945             : 
    3946             :                         q = pushInt(mb, q, f->digits);
    3947             :                         q = pushInt(mb, q, f->scale);
    3948             : */                      //q = pushInt(mb, q, ((ValRecord)((atom*)(be->mvc)->args[1])->data).val.ival);
    3949             :         }
    3950             : 
    3951       33192 :         bool enabled = be->mvc->sa->eb.enabled;
    3952       33192 :         be->mvc->sa->eb.enabled = false;
    3953       33192 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    3954       33192 :         be->mvc->sa->eb.enabled = enabled;
    3955       33192 :         if(!s) {
    3956           0 :                 freeInstruction(q);
    3957           0 :                 goto bailout;
    3958             :         }
    3959       33192 :         s->op1 = v;
    3960       33192 :         s->nrcols = 0;       /* function without arguments returns single value */
    3961       33192 :         s->key = v->key;
    3962       33192 :         s->nrcols = v->nrcols;
    3963       33192 :         s->aggr = v->aggr;
    3964       33192 :         s->op4.typeval = *t;
    3965       33192 :         s->nr = getDestVar(q);
    3966       33192 :         s->q = q;
    3967       33192 :         s->cand = pushed ? sel : NULL;
    3968       33192 :         pushInstruction(mb, q);
    3969       33192 :         if ((!type_has_tz(f) && type_has_tz(t)))
    3970          58 :                 return temporal_convert(be, s, NULL, f, t, false);
    3971             :         return s;
    3972             : 
    3973           0 :   bailout:
    3974           0 :         if (be->mvc->sa->eb.enabled)
    3975           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    3976             :         return NULL;
    3977             : }
    3978             : 
    3979             : stmt *
    3980       25179 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
    3981             : {
    3982       25179 :         list *ops = sa_list(be->mvc->sa);
    3983       25189 :         list_append(ops, op1);
    3984       25193 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    3985       25196 :         if (r && !r->cand)
    3986       25196 :                 r->cand = op1->cand;
    3987       25196 :         return r;
    3988             : }
    3989             : 
    3990             : stmt *
    3991       38300 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
    3992             : {
    3993       38300 :         list *ops = sa_list(be->mvc->sa);
    3994       38305 :         list_append(ops, op1);
    3995       38306 :         list_append(ops, op2);
    3996       38307 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    3997       38309 :         if (r && !r->cand)
    3998       38309 :                 r->cand = op1->cand?op1->cand:op2->cand;
    3999       38309 :         return r;
    4000             : }
    4001             : 
    4002             : #define LANG_INT_OR_MAL(l)  ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
    4003             : 
    4004             : stmt *
    4005      200535 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
    4006             : {
    4007      200535 :         MalBlkPtr mb = be->mb;
    4008      200535 :         InstrPtr q = NULL;
    4009      200535 :         const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
    4010      200550 :         sql_subtype *tpe = NULL;
    4011      200550 :         int push_cands = 0, default_nargs;
    4012      200550 :         stmt *o = NULL, *card = NULL;
    4013             : 
    4014      200550 :         if (ops == NULL)
    4015           0 :                 goto bailout;
    4016             : 
    4017      200550 :         if (rows) {
    4018          97 :                 if (sel) /* if there's a candidate list, use it instead of 'rows' */
    4019           0 :                         rows = sel;
    4020             :                 o = rows;
    4021      200453 :         } else if (list_length(ops->op4.lval)) {
    4022      198947 :                 o = ops->op4.lval->h->data;
    4023      594775 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4024      395828 :                         stmt *c = n->data;
    4025             : 
    4026      395828 :                         if (c && o->nrcols < c->nrcols)
    4027      395828 :                                 o = c;
    4028             :                 }
    4029             :         }
    4030             : 
    4031             :         /* handle nullif */
    4032      200554 :         if (list_length(ops->op4.lval) == 2 &&
    4033      124455 :                 strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
    4034          91 :                 stmt *e1 = ops->op4.lval->h->data;
    4035          91 :                 stmt *e2 = ops->op4.lval->h->next->data;
    4036          91 :                 int nrcols = 0;
    4037             : 
    4038          91 :                 nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols;
    4039             :                 /* nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) */
    4040          91 :                 if (strcmp(f->func->base.name, "nullif") == 0) {
    4041          91 :                         const char *mod = (!nrcols)?calcRef:batcalcRef;
    4042          91 :                         sql_subtype *t = tail_type(e1);
    4043          91 :                         int tt = t->type->localtype;
    4044          91 :                         q = newStmt(mb, mod, "==");
    4045          91 :                         if (q == NULL)
    4046           0 :                                 goto bailout;
    4047          91 :                         q = pushArgument(mb, q, e1->nr);
    4048          91 :                         q = pushArgument(mb, q, e2->nr);
    4049          91 :                         int nr = getDestVar(q);
    4050          91 :                         pushInstruction(mb, q);
    4051             : 
    4052          91 :                         q = newStmt(mb, mod, ifthenelseRef);
    4053          91 :                         if (q == NULL)
    4054           0 :                                 goto bailout;
    4055          91 :                         q = pushArgument(mb, q, nr);
    4056          91 :                         q = pushNil(mb, q, tt);
    4057          91 :                         q = pushArgument(mb, q, e1->nr);
    4058          91 :                         pushInstruction(mb, q);
    4059             :                 }
    4060          91 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4061             :         }
    4062          91 :         if (q == NULL) {
    4063      200468 :                 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
    4064           1 :                         goto bailout;
    4065      200455 :                 mod = sql_func_mod(f->func);
    4066      200470 :                 fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
    4067      200457 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4068      209122 :                 default_nargs = (f->res && list_length(f->res) ? list_length(f->res) : 1) + list_length(ops->op4.lval) + (o && o->nrcols > 0 ? 6 : 4);
    4069      200470 :                 if (rows) {
    4070          97 :                         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);
    4071          97 :                         default_nargs++;
    4072             :                 }
    4073             : 
    4074      200470 :                 if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
    4075      124746 :                         sql_subtype *res = f->res->h->data;
    4076             : 
    4077      124746 :                         q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
    4078      124746 :                         if (q == NULL)
    4079           0 :                                 goto bailout;
    4080      124746 :                         if (rows)
    4081          97 :                                 q = pushArgument(mb, q, card->nr);
    4082      124746 :                         q = pushStr(mb, q, mod);
    4083      124746 :                         q = pushStr(mb, q, fimp);
    4084      124746 :                         setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
    4085             :                 } else {
    4086       75724 :                         q = newStmtArgs(mb, mod, fimp, default_nargs);
    4087       75728 :                         if (q == NULL)
    4088           0 :                                 goto bailout;
    4089             : 
    4090       75728 :                         if (rows)
    4091           0 :                                 q = pushArgument(mb, q, card->nr);
    4092       75729 :                         if (f->res && list_length(f->res)) {
    4093       67066 :                                 sql_subtype *res = f->res->h->data;
    4094             : 
    4095       67066 :                                 setVarType(mb, getArg(q, 0), res->type->localtype);
    4096             :                         }
    4097             :                 }
    4098      200475 :                 if (LANG_EXT(f->func->lang)) {
    4099             :                         /* TODO LOADER functions still use information in sql_subfunc struct
    4100             :                            that won't be visible to other sessions if another function uses them.
    4101             :                            It has to be cleaned up */
    4102         219 :                         if (f->func->type == F_LOADER)
    4103          25 :                                 q = pushPtr(mb, q, f);
    4104             :                         else
    4105         194 :                                 q = pushPtr(mb, q, f->func);
    4106             :                 }
    4107      200475 :                 if (f->func->lang == FUNC_LANG_C) {
    4108          35 :                         q = pushBit(mb, q, 0);
    4109      200440 :                 } else if (f->func->lang == FUNC_LANG_CPP) {
    4110           1 :                         q = pushBit(mb, q, 1);
    4111             :                 }
    4112      200475 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY ||
    4113             :                         f->func->lang == FUNC_LANG_C || f->func->lang == FUNC_LANG_CPP) {
    4114         219 :                         q = pushStr(mb, q, f->func->query);
    4115             :                 }
    4116             :                 /* first dynamic output of copy* functions */
    4117      200475 :                 if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
    4118        2333 :                         q = table_func_create_result(mb, q, f->func, f->res);
    4119      200475 :                 if (list_length(ops->op4.lval))
    4120      198953 :                         tpe = tail_type(ops->op4.lval->h->data);
    4121             : 
    4122      596335 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4123      395860 :                         stmt *op = n->data;
    4124      395860 :                         q = pushArgument(mb, q, op->nr);
    4125             :                 }
    4126             :                 /* push candidate lists if that's the case */
    4127      200475 :                 if (push_cands) {
    4128       72250 :                         for (node *n = ops->op4.lval->h; n; n = n->next) {
    4129       47834 :                                 stmt *op = n->data;
    4130             : 
    4131       47834 :                                 if (op->nrcols > 0) {
    4132       26993 :                                         if (op->cand && op->cand == sel) {
    4133        3638 :                                                 q = pushNilBat(mb, q);
    4134             :                                         } else {
    4135       23355 :                                                 q = pushArgument(mb, q, sel->nr);
    4136             :                                         }
    4137             :                                 }
    4138             :                         }
    4139             :                 }
    4140             :                 /* special case for round function on decimals */
    4141      200475 :                 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) {
    4142          48 :                         q = pushInt(mb, q, tpe->digits);
    4143          48 :                         q = pushInt(mb, q, tpe->scale);
    4144             :                 }
    4145      200475 :                 pushInstruction(mb, q);
    4146             :         }
    4147             : 
    4148      200565 :         stmt *s = stmt_create(be->mvc->sa, st_Nop);
    4149      200566 :         if(!s) {
    4150           0 :                 goto bailout;
    4151             :         }
    4152      200566 :         s->op1 = ops;
    4153      200566 :         if (o) {
    4154      199056 :                 s->nrcols = o->nrcols;
    4155      199056 :                 s->key = o->key;
    4156      199056 :                 s->aggr = o->aggr;
    4157             :         } else {
    4158        1510 :                 s->nrcols = 0;
    4159        1510 :                 s->key = 1;
    4160             :         }
    4161      200566 :         s->op4.funcval = f;
    4162      200566 :         s->nr = getDestVar(q);
    4163      200566 :         s->q = q;
    4164      200566 :         if (sel && push_cands && s->nrcols)
    4165       23274 :                 s->cand = sel;
    4166             :         return s;
    4167             : 
    4168           1 :   bailout:
    4169           1 :         if (be->mvc->sa->eb.enabled)
    4170           1 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4171             :         return NULL;
    4172             : }
    4173             : 
    4174             : stmt *
    4175          11 : stmt_direct_func(backend *be, InstrPtr q)
    4176             : {
    4177          11 :         if (q) {
    4178          11 :                 stmt *s = stmt_create(be->mvc->sa, st_func);
    4179          11 :                 if(!s) {
    4180             :                         return NULL;
    4181             :                 }
    4182          11 :                 s->flag = op_union;
    4183          11 :                 s->nrcols = 3;
    4184          11 :                 s->nr = getDestVar(q);
    4185          11 :                 s->q = q;
    4186          11 :                 return s;
    4187             :         }
    4188             :         return NULL;
    4189             : }
    4190             : 
    4191             : stmt *
    4192         181 : stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
    4193             : {
    4194         181 :         MalBlkPtr mb = be->mb;
    4195         181 :         InstrPtr q = NULL;
    4196         181 :         prop *p = NULL;
    4197             : 
    4198             :         /* dump args */
    4199         181 :         if (ops && ops->nr < 0)
    4200           0 :                 goto bailout;
    4201             : 
    4202         181 :         if ((p = find_prop(rel->p, PROP_REMOTE)))
    4203         181 :                 rel->p = prop_remove(rel->p, p);
    4204             :         /* sql_processrelation may split projections, so make sure the topmost relation only contains references */
    4205         181 :         rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 1, 1));
    4206         181 :         if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
    4207           0 :                 goto bailout;
    4208         181 :         if (p) {
    4209         181 :                 p->p = rel->p;
    4210         181 :                 rel->p = p;
    4211             :         }
    4212             : 
    4213         181 :         if (monet5_create_relational_function(be->mvc, sql_private_module_name, name, rel, ops, NULL, 1) < 0)
    4214           0 :                 goto bailout;
    4215             : 
    4216         181 :         int nargs;
    4217         181 :         sql_rel *r = relational_func_create_result_part1(be->mvc, rel, &nargs);
    4218         181 :         if (ops)
    4219         181 :                 nargs += list_length(ops->op4.lval);
    4220         181 :         if (f_union)
    4221           0 :                 q = newStmt(mb, batmalRef, multiplexRef);
    4222             :         else
    4223         181 :                 q = newStmt(mb, sql_private_module_name, name);
    4224         181 :         if (q == NULL)
    4225           0 :                 goto bailout;
    4226         181 :         q = relational_func_create_result_part2(mb, q, r);
    4227         181 :         if (f_union) {
    4228           0 :                 q = pushStr(mb, q, sql_private_module_name);
    4229           0 :                 q = pushStr(mb, q, name);
    4230             :         }
    4231         181 :         if (ops) {
    4232         203 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4233          22 :                         stmt *op = n->data;
    4234             : 
    4235          22 :                         q = pushArgument(mb, q, op->nr);
    4236             :                 }
    4237             :         }
    4238             : 
    4239         181 :         allocator *sa = be->mvc->sa;
    4240         181 :         bool enabled = be->mvc->sa->eb.enabled;
    4241         181 :         be->mvc->sa->eb.enabled = false;
    4242         181 :         stmt *o = NULL, *s = stmt_create(sa, st_func);
    4243         181 :         be->mvc->sa->eb.enabled = enabled;
    4244         181 :         if(!s) {
    4245           0 :                 freeInstruction(q);
    4246           0 :                 goto bailout;
    4247             :         }
    4248         181 :         s->op1 = ops;
    4249         181 :         s->op2 = stmt_atom_string(be, name);
    4250         181 :         s->op4.rel = rel;
    4251         181 :         s->flag = f_union;
    4252         181 :         if (ops && list_length(ops->op4.lval)) {
    4253          10 :                 node *n;
    4254          32 :                 for (n = ops->op4.lval->h, o = n->data; n; n = n->next) {
    4255          22 :                         stmt *c = n->data;
    4256             : 
    4257          22 :                         if (o->nrcols < c->nrcols)
    4258           0 :                                 o = c;
    4259             :                 }
    4260             :         }
    4261             : 
    4262          10 :         if (o) {
    4263          10 :                 s->nrcols = o->nrcols;
    4264          10 :                 s->key = o->key;
    4265          10 :                 s->aggr = o->aggr;
    4266             :         } else {
    4267         171 :                 s->nrcols = 0;
    4268         171 :                 s->key = 1;
    4269             :         }
    4270         181 :         s->nr = getDestVar(q);
    4271         181 :         s->q = q;
    4272         181 :         pushInstruction(mb, q);
    4273         181 :         return s;
    4274             : 
    4275           0 :   bailout:
    4276           0 :         if (be->mvc->sa->eb.enabled)
    4277           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4278             :         return NULL;
    4279             : }
    4280             : 
    4281             : stmt *
    4282       82091 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
    4283             : {
    4284       82091 :         MalBlkPtr mb = be->mb;
    4285       82091 :         InstrPtr q = NULL;
    4286       82091 :         const char *mod, *aggrfunc;
    4287       82091 :         sql_subtype *res = op->res->h->data;
    4288       82091 :         int restype = res->type->localtype;
    4289       82091 :         bool complex_aggr = false;
    4290       82091 :         int *stmt_nr = NULL;
    4291       82091 :         int avg = 0;
    4292             : 
    4293       82091 :         if (op1->nr < 0)
    4294           0 :                 goto bailout;
    4295       82091 :         if (backend_create_subfunc(be, op, NULL) < 0)
    4296           0 :                 goto bailout;
    4297       82249 :         mod = sql_func_mod(op->func);
    4298       82258 :         aggrfunc = backend_function_imp(be, op->func);
    4299             : 
    4300       82277 :         if (LANG_INT_OR_MAL(op->func->lang)) {
    4301       81971 :                 if (strcmp(aggrfunc, "avg") == 0)
    4302             :                         avg = 1;
    4303       80622 :                 if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
    4304       74041 :                         || strcmp(aggrfunc, "str_group_concat") == 0)
    4305             :                         complex_aggr = true;
    4306       81971 :                 if (restype == TYPE_dbl)
    4307        1534 :                         avg = 0;
    4308             :         }
    4309             : 
    4310      164554 :         int argc = 1
    4311       82277 :                 + 2 * avg
    4312       82277 :                 + (LANG_EXT(op->func->lang) != 0)
    4313       82277 :                 + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
    4314       82277 :                 + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
    4315       82277 :                 + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
    4316       82277 :                 + (grp ? 4 : avg + 1);
    4317             : 
    4318       82277 :         if (grp) {
    4319        6158 :                 char *aggrF = SA_NEW_ARRAY(be->mvc->sa, char, strlen(aggrfunc) + 4);
    4320        6158 :                 if (!aggrF)
    4321           0 :                         goto bailout;
    4322        6158 :                 stpcpy(stpcpy(aggrF, "sub"), aggrfunc);
    4323        6158 :                 aggrfunc = aggrF;
    4324        6158 :                 if ((grp && grp->nr < 0) || (ext && ext->nr < 0))
    4325           0 :                         goto bailout;
    4326             : 
    4327        6158 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4328        6158 :                 if (q == NULL)
    4329           0 :                         goto bailout;
    4330        6158 :                 setVarType(mb, getArg(q, 0), newBatType(restype));
    4331        6158 :                 if (avg) { /* for avg also return rest and count */
    4332          95 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4333          95 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4334             :                 }
    4335             :         } else {
    4336       76119 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4337       76332 :                 if (q == NULL)
    4338           0 :                         goto bailout;
    4339       76332 :                 if (complex_aggr) {
    4340        6550 :                         setVarType(mb, getArg(q, 0), restype);
    4341        6550 :                         if (avg) { /* for avg also return rest and count */
    4342          56 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4343          56 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4344             :                         }
    4345             :                 }
    4346             :         }
    4347             : 
    4348       82490 :         if (LANG_EXT(op->func->lang))
    4349          44 :                 q = pushPtr(mb, q, op->func);
    4350       82489 :         if (op->func->lang == FUNC_LANG_R ||
    4351       82456 :                 op->func->lang >= FUNC_LANG_PY ||
    4352             :                 op->func->lang == FUNC_LANG_C ||
    4353             :                 op->func->lang == FUNC_LANG_CPP) {
    4354          44 :                 if (!grp) {
    4355          20 :                         setVarType(mb, getArg(q, 0), restype);
    4356             :                 }
    4357          44 :                 if (op->func->lang == FUNC_LANG_C) {
    4358          11 :                         q = pushBit(mb, q, 0);
    4359          33 :                 } else if (op->func->lang == FUNC_LANG_CPP) {
    4360           0 :                         q = pushBit(mb, q, 1);
    4361             :                 }
    4362          44 :                 q = pushStr(mb, q, op->func->query);
    4363             :         }
    4364             : 
    4365       82491 :         if (op1->type != st_list) {
    4366       76821 :                 q = pushArgument(mb, q, op1->nr);
    4367             :         } else {
    4368        5670 :                 int i;
    4369        5670 :                 node *n;
    4370             : 
    4371       11691 :                 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
    4372        6024 :                         stmt *op = n->data;
    4373             : 
    4374        6024 :                         if (stmt_nr)
    4375             :                                 q = pushArgument(mb, q, stmt_nr[i]);
    4376             :                         else
    4377        6024 :                                 q = pushArgument(mb, q, op->nr);
    4378             :                 }
    4379             :         }
    4380       82489 :         if (grp) {
    4381        6158 :                 q = pushArgument(mb, q, grp->nr);
    4382        6158 :                 q = pushArgument(mb, q, ext->nr);
    4383        6158 :                 if (LANG_INT_OR_MAL(op->func->lang)) {
    4384        6134 :                         if (avg) /* push nil candidates */
    4385          95 :                                 q = pushNilBat(mb, q);
    4386        6134 :                         q = pushBit(mb, q, no_nil);
    4387             :                 }
    4388       76331 :         } else if (LANG_INT_OR_MAL(op->func->lang) && no_nil && strncmp(aggrfunc, "count", 5) == 0) {
    4389        1703 :                 q = pushBit(mb, q, no_nil);
    4390       74628 :         } else if (LANG_INT_OR_MAL(op->func->lang) && !nil_if_empty && strncmp(aggrfunc, "sum", 3) == 0) {
    4391           0 :                 q = pushBit(mb, q, FALSE);
    4392       74628 :         } else if (LANG_INT_OR_MAL(op->func->lang) && avg) { /* push candidates */
    4393          56 :                 q = pushNilBat(mb, q);
    4394          56 :                 q = pushBit(mb, q, no_nil);
    4395             :         }
    4396             : 
    4397       82489 :         bool enabled = be->mvc->sa->eb.enabled;
    4398       82489 :         be->mvc->sa->eb.enabled = false;
    4399       82489 :         stmt *s = stmt_create(be->mvc->sa, st_aggr);
    4400       82483 :         be->mvc->sa->eb.enabled = enabled;
    4401       82483 :         if(!s) {
    4402           0 :                 freeInstruction(q);
    4403           0 :                 goto bailout;
    4404             :         }
    4405       82483 :         s->op1 = op1;
    4406       82483 :         if (grp) {
    4407        6158 :                 s->op2 = grp;
    4408        6158 :                 s->op3 = ext;
    4409        6158 :                 s->nrcols = 1;
    4410             :         } else {
    4411       76325 :                 if (!reduce)
    4412           0 :                         s->nrcols = 1;
    4413             :         }
    4414       82483 :         s->key = reduce;
    4415       82483 :         s->aggr = reduce;
    4416       82483 :         s->flag = no_nil;
    4417       82483 :         s->op4.funcval = op;
    4418       82483 :         s->nr = getDestVar(q);
    4419       82483 :         s->q = q;
    4420       82483 :         pushInstruction(mb, q);
    4421       82483 :         return s;
    4422             : 
    4423           0 :   bailout:
    4424           0 :         if (be->mvc->sa->eb.enabled)
    4425           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4426             :         return NULL;
    4427             : }
    4428             : 
    4429             : static stmt *
    4430     1213882 : stmt_alias_(backend *be, stmt *op1, const char *tname, const char *alias)
    4431             : {
    4432     1213882 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
    4433     1213822 :         if(!s) {
    4434             :                 return NULL;
    4435             :         }
    4436     1213822 :         s->op1 = op1;
    4437     1213822 :         s->nrcols = op1->nrcols;
    4438     1213822 :         s->key = op1->key;
    4439     1213822 :         s->aggr = op1->aggr;
    4440             : 
    4441     1213822 :         s->tname = tname;
    4442     1213822 :         s->cname = alias;
    4443     1213822 :         s->nr = op1->nr;
    4444     1213822 :         s->q = op1->q;
    4445     1213822 :         return s;
    4446             : }
    4447             : 
    4448             : stmt *
    4449     3833590 : stmt_alias(backend *be, stmt *op1, const char *tname, const char *alias)
    4450             : {
    4451     3833590 :         if (((!op1->tname && !tname) ||
    4452     2754045 :             (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
    4453     2639334 :             op1->cname && strcmp(op1->cname, alias)==0)
    4454             :                 return op1;
    4455     1213710 :         return stmt_alias_(be, op1, tname, alias);
    4456             : }
    4457             : 
    4458             : sql_subtype *
    4459     1101092 : tail_type(stmt *st)
    4460             : {
    4461     4247197 :         for (;;) {
    4462     4247197 :                 switch (st->type) {
    4463       25221 :                 case st_const:
    4464       25221 :                         st = st->op2;
    4465       25221 :                         continue;
    4466        2447 :                 case st_uselect:
    4467             :                 case st_semijoin:
    4468             :                 case st_limit:
    4469             :                 case st_limit2:
    4470             :                 case st_sample:
    4471             :                 case st_tunion:
    4472             :                 case st_tdiff:
    4473             :                 case st_tinter:
    4474        2447 :                         return sql_bind_localtype("oid");
    4475         568 :                 case st_uselect2:
    4476         568 :                         if (!st->reduce)
    4477          51 :                                 return sql_bind_localtype("bit");
    4478         517 :                         return sql_bind_localtype("oid");
    4479      897084 :                 case st_append:
    4480             :                 case st_append_bulk:
    4481             :                 case st_replace:
    4482             :                 case st_alias:
    4483             :                 case st_gen_group:
    4484             :                 case st_order:
    4485      897084 :                         st = st->op1;
    4486      897084 :                         continue;
    4487           0 :                 case st_list:
    4488           0 :                         st = st->op4.lval->h->data;
    4489           0 :                         continue;
    4490      540947 :                 case st_bat:
    4491      540947 :                         return &st->op4.cval->type;
    4492        1917 :                 case st_idxbat:
    4493        1917 :                         if (hash_index(st->op4.idxval->type)) {
    4494         262 :                                 return sql_bind_localtype("lng");
    4495        1655 :                         } else if (oid_index(st->op4.idxval->type)) {
    4496        1655 :                                 return sql_bind_localtype("oid");
    4497             :                         }
    4498             :                         /* fall through */
    4499             :                 case st_join:
    4500             :                 case st_join2:
    4501             :                 case st_joinN:
    4502     2223841 :                         if (st->flag == cmp_project) {
    4503     2223800 :                                 st = st->op2;
    4504     2223800 :                                 continue;
    4505             :                         }
    4506             :                         /* fall through */
    4507             :                 case st_reorder:
    4508             :                 case st_group:
    4509             :                 case st_tid:
    4510             :                 case st_mirror:
    4511       12216 :                         return sql_bind_localtype("oid");
    4512       28779 :                 case st_result:
    4513       28779 :                         return &st->op4.typeval;
    4514           0 :                 case st_table_clear:
    4515           0 :                         return sql_bind_localtype("lng");
    4516      147658 :                 case st_aggr:
    4517             :                 case st_Nop: {
    4518      147658 :                         list *res = st->op4.funcval->res;
    4519             : 
    4520      147658 :                         if (res && list_length(res) == 1)
    4521      147658 :                                 return res->h->data;
    4522             : 
    4523             :                         return NULL;
    4524             :                 }
    4525      128952 :                 case st_atom:
    4526      128952 :                         return atom_type(st->op4.aval);
    4527      235980 :                 case st_convert:
    4528             :                 case st_temp:
    4529             :                 case st_single:
    4530             :                 case st_rs_column:
    4531      235980 :                         return &st->op4.typeval;
    4532        1620 :                 case st_var:
    4533        1620 :                         if (st->op4.typeval.type)
    4534        1620 :                                 return &st->op4.typeval;
    4535             :                         /* fall through */
    4536             :                 case st_exception:
    4537             :                         return NULL;
    4538           8 :                 case st_table:
    4539           8 :                         return sql_bind_localtype("bat");
    4540             :                 default:
    4541           0 :                         assert(0);
    4542             :                         return NULL;
    4543             :                 }
    4544             :         }
    4545             : }
    4546             : 
    4547             : int
    4548        6524 : stmt_has_null(stmt *s)
    4549             : {
    4550       12485 :         switch (s->type) {
    4551             :         case st_aggr:
    4552             :         case st_Nop:
    4553             :         case st_semijoin:
    4554             :         case st_uselect:
    4555             :         case st_uselect2:
    4556             :         case st_atom:
    4557             :                 return 0;
    4558        5961 :         case st_join:
    4559        5961 :                 return stmt_has_null(s->op2);
    4560        4271 :         case st_bat:
    4561        4271 :                 return s->op4.cval->null;
    4562             : 
    4563        2253 :         default:
    4564        2253 :                 return 1;
    4565             :         }
    4566             : }
    4567             : 
    4568             : static const char *
    4569           0 : func_name(allocator *sa, const char *n1, const char *n2)
    4570             : {
    4571           0 :         size_t l1 = _strlen(n1), l2;
    4572             : 
    4573           0 :         if (!sa)
    4574             :                 return n1;
    4575           0 :         if (!n2)
    4576           0 :                 return sa_strdup(sa, n1);
    4577           0 :         l2 = _strlen(n2);
    4578             : 
    4579           0 :         if (l2 > 16) {               /* only support short names */
    4580           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l2 + 1);
    4581           0 :                 if(!ns)
    4582             :                         return NULL;
    4583           0 :                 snprintf(ns, l2 + 1, "%s", n2);
    4584           0 :                 return ns;
    4585             :         } else {
    4586           0 :                 char *ns = SA_NEW_ARRAY(sa, char, l1 + l2 + 2), *s = ns;
    4587           0 :                 if(!ns)
    4588             :                         return NULL;
    4589           0 :                 snprintf(ns, l1 + l2 + 2, "%s_%s", n1, n2);
    4590           0 :                 return s;
    4591             :         }
    4592             : }
    4593             : 
    4594             : static const char *_column_name(allocator *sa, stmt *st);
    4595             : 
    4596             : const char *
    4597     8175422 : column_name(allocator *sa, stmt *st)
    4598             : {
    4599     8175422 :         if (!st->cname)
    4600           2 :                 st->cname = _column_name(sa, st);
    4601     8175422 :         return st->cname;
    4602             : }
    4603             : 
    4604             : static const char *
    4605           2 : _column_name(allocator *sa, stmt *st)
    4606             : {
    4607           2 :         switch (st->type) {
    4608           0 :         case st_order:
    4609             :         case st_reorder:
    4610           0 :                 return column_name(sa, st->op1);
    4611           0 :         case st_const:
    4612             :         case st_join:
    4613             :         case st_join2:
    4614             :         case st_joinN:
    4615           0 :                 return column_name(sa, st->op2);
    4616             : 
    4617           2 :         case st_mirror:
    4618             :         case st_group:
    4619             :         case st_result:
    4620             :         case st_append:
    4621             :         case st_append_bulk:
    4622             :         case st_replace:
    4623             :         case st_gen_group:
    4624             :         case st_semijoin:
    4625             :         case st_uselect:
    4626             :         case st_uselect2:
    4627             :         case st_limit:
    4628             :         case st_limit2:
    4629             :         case st_sample:
    4630             :         case st_tunion:
    4631             :         case st_tdiff:
    4632             :         case st_tinter:
    4633             :         case st_convert:
    4634           2 :                 return column_name(sa, st->op1);
    4635           0 :         case st_Nop:
    4636             :         case st_aggr:
    4637             :         {
    4638           0 :                 const char *cn = column_name(sa, st->op1);
    4639           0 :                 return func_name(sa, st->op4.funcval->func->base.name, cn);
    4640             :         }
    4641           0 :         case st_alias:
    4642           0 :                 if (st->op3)
    4643           0 :                         return column_name(sa, st->op3);
    4644             :                 break;
    4645           0 :         case st_bat:
    4646           0 :                 return st->op4.cval->base.name;
    4647           0 :         case st_atom:
    4648           0 :                 if (st->op4.aval->data.vtype == TYPE_str)
    4649           0 :                         return atom2string(sa, st->op4.aval);
    4650             :                 /* fall through */
    4651             :         case st_var:
    4652             :         case st_temp:
    4653             :         case st_single:
    4654           0 :                 if (sa)
    4655           0 :                         return sa_strdup(sa, "single_value");
    4656             :                 return "single_value";
    4657             : 
    4658           0 :         case st_list:
    4659           0 :                 if (list_length(st->op4.lval))
    4660           0 :                         return column_name(sa, st->op4.lval->h->data);
    4661             :                 /* fall through */
    4662             :         case st_rs_column:
    4663             :                 return NULL;
    4664             :         default:
    4665             :                 return NULL;
    4666             :         }
    4667             :         return NULL;
    4668             : }
    4669             : 
    4670             : const char *
    4671     4050458 : table_name(allocator *sa, stmt *st)
    4672             : {
    4673     4050458 :         (void)sa;
    4674     4050458 :         return st->tname;
    4675             : }
    4676             : 
    4677             : const char *
    4678      312713 : schema_name(allocator *sa, stmt *st)
    4679             : {
    4680     1755762 :         switch (st->type) {
    4681     1146798 :         case st_const:
    4682             :         case st_semijoin:
    4683             :         case st_join:
    4684             :         case st_join2:
    4685             :         case st_joinN:
    4686     1146798 :                 return schema_name(sa, st->op2);
    4687      103597 :         case st_mirror:
    4688             :         case st_group:
    4689             :         case st_result:
    4690             :         case st_append:
    4691             :         case st_append_bulk:
    4692             :         case st_replace:
    4693             :         case st_gen_group:
    4694             :         case st_uselect:
    4695             :         case st_uselect2:
    4696             :         case st_limit:
    4697             :         case st_limit2:
    4698             :         case st_sample:
    4699             :         case st_tunion:
    4700             :         case st_tdiff:
    4701             :         case st_tinter:
    4702             :         case st_convert:
    4703             :         case st_Nop:
    4704             :         case st_aggr:
    4705             :                 /* there are no schema aliases, ie look into the base column */
    4706      103597 :                 if (st->op1)
    4707             :                         return schema_name(sa, st->op1);
    4708             :                 return NULL;
    4709      162400 :         case st_alias:
    4710      162400 :                 return schema_name(sa, st->op1);
    4711      195254 :         case st_bat:
    4712      195254 :                 return st->op4.cval->t->s->base.name;
    4713             :         case st_atom:
    4714             :                 return NULL;
    4715             :         case st_var:
    4716             :         case st_temp:
    4717             :         case st_single:
    4718             :                 return NULL;
    4719       30386 :         case st_list:
    4720       30386 :                 if (list_length(st->op4.lval))
    4721       30254 :                         return schema_name(sa, st->op4.lval->h->data);
    4722             :                 return NULL;
    4723             :         default:
    4724             :                 return NULL;
    4725             :         }
    4726             : }
    4727             : 
    4728             : stmt *
    4729         999 : stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
    4730             : {
    4731         999 :         MalBlkPtr mb = be->mb;
    4732         999 :         InstrPtr q = NULL;
    4733             : 
    4734         999 :         if (cond->nr < 0)
    4735           0 :                 goto bailout;
    4736         999 :         if (anti) {
    4737          23 :                 sql_subtype *bt = sql_bind_localtype("bit");
    4738          23 :                 sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    4739          23 :                 sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    4740          23 :                 sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    4741          23 :                 cond = stmt_binop(be,
    4742             :                         stmt_unop(be, cond, NULL, not),
    4743             :                         stmt_unop(be, cond, NULL, isnull), NULL, or);
    4744             :         }
    4745         999 :         if (!loop) {    /* if */
    4746         983 :                 q = newAssignment(mb);
    4747         983 :                 if (q == NULL)
    4748           0 :                         goto bailout;
    4749         983 :                 q->barrier = BARRIERsymbol;
    4750         983 :                 q = pushArgument(mb, q, cond->nr);
    4751             :         } else {        /* while */
    4752          16 :                 int c;
    4753             : 
    4754          16 :                 if (outer->nr < 0)
    4755           0 :                         goto bailout;
    4756             :                 /* leave barrier */
    4757          16 :                 q = newStmt(mb, calcRef, notRef);
    4758          16 :                 if (q == NULL)
    4759           0 :                         goto bailout;
    4760          16 :                 q = pushArgument(mb, q, cond->nr);
    4761          16 :                 c = getArg(q, 0);
    4762          16 :                 pushInstruction(mb, q);
    4763             : 
    4764          16 :                 q = newAssignment(mb);
    4765          16 :                 if (q == NULL)
    4766           0 :                         goto bailout;
    4767          16 :                 getArg(q, 0) = outer->nr;
    4768          16 :                 q->barrier = LEAVEsymbol;
    4769          16 :                 q = pushArgument(mb, q, c);
    4770             :         }
    4771             : 
    4772         999 :         bool enabled = be->mvc->sa->eb.enabled;
    4773         999 :         be->mvc->sa->eb.enabled = false;
    4774         999 :         stmt *s = stmt_create(be->mvc->sa, st_cond);
    4775         999 :         be->mvc->sa->eb.enabled = enabled;
    4776         999 :         if(!s) {
    4777           0 :                 freeInstruction(q);
    4778           0 :                 goto bailout;
    4779             :         }
    4780         999 :         s->flag = be->mvc_var; /* keep the mvc_var of the outer context */
    4781         999 :         s->loop = loop;
    4782         999 :         s->op1 = cond;
    4783         999 :         s->nr = getArg(q, 0);
    4784         999 :         pushInstruction(mb, q);
    4785         999 :         return s;
    4786             : 
    4787           0 :   bailout:
    4788           0 :         if (be->mvc->sa->eb.enabled)
    4789           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4790             :         return NULL;
    4791             : }
    4792             : 
    4793             : stmt *
    4794         999 : stmt_control_end(backend *be, stmt *cond)
    4795             : {
    4796         999 :         MalBlkPtr mb = be->mb;
    4797         999 :         InstrPtr q = NULL;
    4798             : 
    4799         999 :         if (cond->nr < 0)
    4800           0 :                 goto bailout;
    4801             : 
    4802         999 :         if (cond->loop) {    /* while */
    4803             :                 /* redo barrier */
    4804          16 :                 q = newAssignment(mb);
    4805          16 :                 if (q == NULL)
    4806           0 :                         goto bailout;
    4807          16 :                 getArg(q, 0) = cond->nr;
    4808          16 :                 q->argc = q->retc = 1;
    4809          16 :                 q->barrier = REDOsymbol;
    4810          16 :                 q = pushBit(mb, q, TRUE);
    4811             :         } else {
    4812         983 :                 q = newAssignment(mb);
    4813         984 :                 if (q == NULL)
    4814           0 :                         goto bailout;
    4815         984 :                 getArg(q, 0) = cond->nr;
    4816         984 :                 q->argc = q->retc = 1;
    4817         984 :                 q->barrier = EXITsymbol;
    4818             :         }
    4819        1000 :         be->mvc_var = cond->flag; /* restore old mvc_var from before the barrier */
    4820        1000 :         bool enabled = be->mvc->sa->eb.enabled;
    4821        1000 :         be->mvc->sa->eb.enabled = false;
    4822        1000 :         stmt *s = stmt_create(be->mvc->sa, st_control_end);
    4823        1000 :         be->mvc->sa->eb.enabled = enabled;
    4824        1000 :         if(!s) {
    4825           0 :                 freeInstruction(q);
    4826           0 :                 goto bailout;
    4827             :         }
    4828        1000 :         s->op1 = cond;
    4829        1000 :         s->nr = getArg(q, 0);
    4830        1000 :         pushInstruction(mb, q);
    4831        1000 :         return s;
    4832             : 
    4833           0 :   bailout:
    4834           0 :         if (be->mvc->sa->eb.enabled)
    4835           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4836             :         return NULL;
    4837             : }
    4838             : 
    4839             : 
    4840             : static InstrPtr
    4841         198 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
    4842             : {
    4843         198 :         int i;
    4844         198 :         node *n;
    4845             : 
    4846         198 :         if (q == NULL)
    4847             :                 return NULL;
    4848         198 :         q->retc = q->argc = 0;
    4849        1631 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4850        1433 :                 stmt *c = n->data;
    4851             : 
    4852        1433 :                 q = pushArgument(mb, q, c->nr);
    4853             :         }
    4854         198 :         if (q == NULL)
    4855             :                 return NULL;
    4856         198 :         q->retc = q->argc;
    4857             :         /* Lets make it a propper assignment */
    4858        1631 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4859        1433 :                 stmt *c = n->data;
    4860             : 
    4861        1433 :                 q = pushArgument(mb, q, c->nr);
    4862             :         }
    4863             :         return q;
    4864             : }
    4865             : 
    4866             : stmt *
    4867         569 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
    4868             : {
    4869         569 :         MalBlkPtr mb = be->mb;
    4870         569 :         InstrPtr q = NULL;
    4871             : 
    4872         569 :         if (val->nr < 0)
    4873           0 :                 goto bailout;
    4874         569 :         int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
    4875         198 :         if (args < MAXARG)
    4876             :                 args = MAXARG;
    4877         569 :         q = newInstructionArgs(mb, NULL, NULL, args);
    4878         569 :         if (q == NULL)
    4879           0 :                 goto bailout;
    4880         569 :         q->barrier= RETURNsymbol;
    4881         569 :         if (val->type == st_table) {
    4882         198 :                 list *l = val->op1->op4.lval;
    4883             : 
    4884         198 :                 q = dump_cols(mb, l, q);
    4885             :         } else {
    4886         371 :                 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
    4887         371 :                 q = pushArgument(mb, q, val->nr);
    4888             :         }
    4889             : 
    4890         569 :         bool enabled = be->mvc->sa->eb.enabled;
    4891         569 :         be->mvc->sa->eb.enabled = false;
    4892         569 :         stmt *s = stmt_create(be->mvc->sa, st_return);
    4893         569 :         be->mvc->sa->eb.enabled = enabled;
    4894         569 :         if(!s) {
    4895           0 :                 freeInstruction(q);
    4896           0 :                 goto bailout;
    4897             :         }
    4898         569 :         s->op1 = val;
    4899         569 :         s->flag = nr_declared_tables;
    4900         569 :         s->nr = getDestVar(q);
    4901         569 :         s->q = q;
    4902         569 :         pushInstruction(mb, q);
    4903         569 :         return s;
    4904             : 
    4905           0 :   bailout:
    4906           0 :         if (be->mvc->sa->eb.enabled)
    4907           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4908             :         return NULL;
    4909             : }
    4910             : 
    4911             : stmt *
    4912        1335 : stmt_assign(backend *be, const char *sname, const char *varname, stmt *val, int level)
    4913             : {
    4914        1335 :         MalBlkPtr mb = be->mb;
    4915        1335 :         InstrPtr q = NULL;
    4916             : 
    4917        1335 :         if (val && val->nr < 0)
    4918           0 :                 goto bailout;
    4919        1335 :         if (level != 0) {
    4920         982 :                 char *buf,  levelstr[16];
    4921             : 
    4922         982 :                 if (!val) {
    4923             :                         /* drop declared table */
    4924           0 :                         assert(0);
    4925             :                 }
    4926             : 
    4927         982 :                 assert(!sname);
    4928         982 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
    4929         982 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
    4930         982 :                 if (!buf)
    4931           0 :                         goto bailout;
    4932         982 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
    4933         982 :                 q = newInstruction(mb, NULL, NULL);
    4934         983 :                 if (q == NULL) {
    4935           0 :                         goto bailout;
    4936             :                 }
    4937         983 :                 q->argc = q->retc = 0;
    4938         983 :                 q = pushArgumentId(mb, q, buf);
    4939         983 :                 pushInstruction(mb, q);
    4940         983 :                 q->retc++;
    4941             :         } else {
    4942         353 :                 assert(sname); /* all global variables have a schema */
    4943         353 :                 q = newStmt(mb, sqlRef, setVariableRef);
    4944         353 :                 if (q == NULL)
    4945           0 :                         goto bailout;
    4946         353 :                 q = pushArgument(mb, q, be->mvc_var);
    4947         353 :                 q = pushStr(mb, q, sname);
    4948         353 :                 q = pushStr(mb, q, varname);
    4949         353 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    4950         353 :                 pushInstruction(mb, q);
    4951         353 :                 be->mvc_var = getDestVar(q);
    4952             :         }
    4953        1336 :         q = pushArgument(mb, q, val->nr);
    4954             : 
    4955        1336 :         bool enabled = be->mvc->sa->eb.enabled;
    4956        1336 :         be->mvc->sa->eb.enabled = false;
    4957        1336 :         stmt *s = stmt_create(be->mvc->sa, st_assign);
    4958        1336 :         be->mvc->sa->eb.enabled = enabled;
    4959        1336 :         if(!s) {
    4960           0 :                 goto bailout;
    4961             :         }
    4962        1336 :         s->op2 = val;
    4963        1336 :         s->flag = (level << 1);
    4964        1336 :         s->q = q;
    4965        1336 :         s->nr = 1;
    4966        1336 :         return s;
    4967             : 
    4968           0 :   bailout:
    4969           0 :         if (be->mvc->sa->eb.enabled)
    4970           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    4971             :         return NULL;
    4972             : }
    4973             : 
    4974             : stmt *
    4975       11441 : const_column(backend *be, stmt *val)
    4976             : {
    4977       11441 :         sql_subtype *ct = tail_type(val);
    4978       11440 :         MalBlkPtr mb = be->mb;
    4979       11440 :         InstrPtr q = NULL;
    4980       11440 :         int tt = ct->type->localtype;
    4981             : 
    4982       11440 :         if (val->nr < 0)
    4983           0 :                 goto bailout;
    4984       11440 :         q = newStmt(mb, batRef, singleRef);
    4985       11441 :         if (q == NULL)
    4986           0 :                 goto bailout;
    4987       11441 :         setVarType(mb, getArg(q, 0), newBatType(tt));
    4988       11441 :         q = pushArgument(mb, q, val->nr);
    4989             : 
    4990       11441 :         bool enabled = be->mvc->sa->eb.enabled;
    4991       11441 :         be->mvc->sa->eb.enabled = false;
    4992       11441 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    4993       11441 :         be->mvc->sa->eb.enabled = enabled;
    4994       11441 :         if(!s) {
    4995           0 :                 freeInstruction(q);
    4996           0 :                 goto bailout;
    4997             :         }
    4998       11441 :         s->op1 = val;
    4999       11441 :         s->op4.typeval = *ct;
    5000       11441 :         s->nrcols = 1;
    5001             : 
    5002       11441 :         s->tname = val->tname;
    5003       11441 :         s->cname = val->cname;
    5004       11441 :         s->nr = getDestVar(q);
    5005       11441 :         s->q = q;
    5006       11441 :         pushInstruction(mb, q);
    5007       11441 :         return s;
    5008             : 
    5009           0 :   bailout:
    5010           0 :         if (be->mvc->sa->eb.enabled)
    5011           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5012             :         return NULL;
    5013             : }
    5014             : 
    5015             : stmt *
    5016          10 : stmt_fetch(backend *be, stmt *val)
    5017             : {
    5018          10 :         sql_subtype *ct;
    5019          10 :         MalBlkPtr mb = be->mb;
    5020          10 :         InstrPtr q = NULL;
    5021          10 :         int tt;
    5022             : 
    5023          10 :         if (val->nr < 0)
    5024           0 :                 goto bailout;
    5025             :         /* pick from first column on a table case */
    5026          10 :         if (val->type == st_table) {
    5027           0 :                 if (list_length(val->op1->op4.lval) > 1)
    5028           0 :                         goto bailout;
    5029           0 :                 val = val->op1->op4.lval->h->data;
    5030             :         }
    5031          10 :         ct = tail_type(val);
    5032          10 :         tt = ct->type->localtype;
    5033             : 
    5034          10 :         q = newStmt(mb, algebraRef, fetchRef);
    5035          10 :         if (q == NULL)
    5036           0 :                 goto bailout;
    5037          10 :         setVarType(mb, getArg(q, 0), tt);
    5038          10 :         q = pushArgument(mb, q, val->nr);
    5039          10 :         q = pushOid(mb, q, 0);
    5040             : 
    5041          10 :         bool enabled = be->mvc->sa->eb.enabled;
    5042          10 :         be->mvc->sa->eb.enabled = false;
    5043          10 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    5044          10 :         be->mvc->sa->eb.enabled = enabled;
    5045          10 :         if(!s) {
    5046           0 :                 freeInstruction(q);
    5047           0 :                 goto bailout;
    5048             :         }
    5049          10 :         s->op1 = val;
    5050          10 :         s->op4.typeval = *ct;
    5051          10 :         s->nrcols = 0;
    5052             : 
    5053          10 :         s->tname = val->tname;
    5054          10 :         s->cname = val->cname;
    5055          10 :         s->nr = getDestVar(q);
    5056          10 :         s->q = q;
    5057          10 :         pushInstruction(mb, q);
    5058          10 :         return s;
    5059             : 
    5060           0 :   bailout:
    5061           0 :         if (be->mvc->sa->eb.enabled)
    5062           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    5063             :         return NULL;
    5064             : }
    5065             : 
    5066             : stmt *
    5067     1520008 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    5068             : {
    5069     1520008 :         const char *name = exp_name(exp);
    5070     1520203 :         const char *rname = exp_relname(exp);
    5071     1520000 :         stmt *o = s;
    5072             : 
    5073     1520000 :         if (!name && exp_is_atom(exp))
    5074           0 :                 name = sa_strdup(be->mvc->sa, "single_value");
    5075           0 :         assert(name);
    5076     1520000 :         s = stmt_alias(be, s, rname, name);
    5077     1520088 :         if (o->flag & OUTER_ZERO)
    5078         521 :                 s->flag |= OUTER_ZERO;
    5079     1520088 :         return s;
    5080             : }

Generated by: LCOV version 1.14