LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2839 3411 83.2 %
Date: 2024-04-25 23:25:41 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       16758 : convertMultiplexMod(const char *mod, const char *op)
      32             : {
      33       16758 :         if (strcmp(op, "=") == 0)
      34           0 :                 return "calc";
      35             :         return mod;
      36             : }
      37             : 
      38             : static const char *
      39      247161 : convertMultiplexFcn(const char *op)
      40             : {
      41      247161 :         if (strcmp(op, "=") == 0)
      42       30762 :                 return "==";
      43             :         return op;
      44             : }
      45             : 
      46             : static InstrPtr
      47       16683 : multiplex2(MalBlkPtr mb, const char *mod, const char *name, int o1, int o2, int rtype)
      48             : {
      49       16683 :         InstrPtr q = NULL;
      50             : 
      51       16683 :         q = newStmt(mb, malRef, multiplexRef);
      52       16683 :         if (q == NULL)
      53             :                 return NULL;
      54       16683 :         setVarType(mb, getArg(q, 0), newBatType(rtype));
      55       16683 :         q = pushStr(mb, q, convertMultiplexMod(mod, name));
      56       16683 :         q = pushStr(mb, q, convertMultiplexFcn(name));
      57       16683 :         q = pushArgument(mb, q, o1);
      58       16683 :         q = pushArgument(mb, q, o2);
      59       16683 :         pushInstruction(mb, q);
      60       16683 :         return q;
      61             : }
      62             : 
      63             : static InstrPtr
      64       47164 : dump_1(MalBlkPtr mb, const char *mod, const char *name, stmt *o1)
      65             : {
      66       47164 :         InstrPtr q = NULL;
      67             : 
      68       47164 :         if (o1 == NULL || o1->nr < 0)
      69             :                 return NULL;
      70       47164 :         q = newStmt(mb, mod, name);
      71       47164 :         q = pushArgument(mb, q, o1->nr);
      72       47164 :         pushInstruction(mb, q);
      73       47164 :         return q;
      74             : }
      75             : 
      76             : static InstrPtr
      77      162134 : dump_2(MalBlkPtr mb, const char *mod, const char *name, stmt *o1, stmt *o2)
      78             : {
      79      162134 :         InstrPtr q = NULL;
      80             : 
      81      162134 :         if (o1 == NULL || o2 == NULL || o1->nr < 0 || o2->nr < 0)
      82             :                 return NULL;
      83      162134 :         q = newStmt(mb, mod, name);
      84      162134 :         q = pushArgument(mb, q, o1->nr);
      85      162134 :         q = pushArgument(mb, q, o2->nr);
      86      162134 :         pushInstruction(mb, q);
      87      162134 :         return q;
      88             : }
      89             : 
      90             : static InstrPtr
      91         267 : pushPtr(MalBlkPtr mb, InstrPtr q, ptr val)
      92             : {
      93         267 :         int _t;
      94         267 :         ValRecord cst;
      95             : 
      96         267 :         if (q == NULL || mb->errors)
      97             :                 return q;
      98         267 :         cst.vtype= TYPE_ptr;
      99         267 :         cst.val.pval = val;
     100         267 :         cst.len = 0;
     101         267 :         _t = defConstant(mb, TYPE_ptr, &cst);
     102         267 :         if( _t >= 0)
     103         267 :                 return pushArgument(mb, q, _t);
     104             :         return q;
     105             : }
     106             : 
     107             : static InstrPtr
     108     2124603 : pushSchema(MalBlkPtr mb, InstrPtr q, sql_table *t)
     109             : {
     110     2124603 :         if (t->s)
     111     2124603 :                 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       13974 : stmt_key(stmt *s)
     118             : {
     119       13974 :         const char *nme = column_name(NULL, s);
     120             : 
     121       13974 :         return hash_key(nme);
     122             : }
     123             : 
     124             : /* #TODO make proper traversal operations */
     125             : stmt *
     126         208 : stmt_atom_string(backend *be, const char *S)
     127             : {
     128         208 :         const char *s = sa_strdup(be->mvc->sa, S);
     129         208 :         sql_subtype t;
     130             : 
     131         208 :         if (s == NULL)
     132             :                 return NULL;
     133         208 :         sql_find_subtype(&t, "varchar", _strlen(s), 0);
     134         208 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, s));
     135             : }
     136             : 
     137             : stmt *
     138       19207 : stmt_atom_string_nil(backend *be)
     139             : {
     140       19207 :         sql_subtype t;
     141             : 
     142       19207 :         sql_find_subtype(&t, "varchar", 0, 0);
     143       19207 :         return stmt_atom(be, atom_string(be->mvc->sa, &t, NULL));
     144             : }
     145             : 
     146             : stmt *
     147        5145 : stmt_atom_int(backend *be, int i)
     148             : {
     149        5145 :         sql_subtype t;
     150             : 
     151        5145 :         sql_find_subtype(&t, "int", 32, 0);
     152        5145 :         return stmt_atom(be, atom_int(be->mvc->sa, &t, i));
     153             : }
     154             : 
     155             : stmt *
     156      117343 : stmt_atom_lng(backend *be, lng i)
     157             : {
     158      117343 :         sql_subtype t;
     159             : 
     160      117343 :         sql_find_subtype(&t, "bigint", 64, 0);
     161      117343 :         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       37911 : stmt_bool(backend *be, int b)
     175             : {
     176       37911 :         sql_subtype t;
     177             : 
     178       37911 :         sql_find_subtype(&t, "boolean", 0, 0);
     179             : 
     180       37911 :         if (b == bit_nil) {
     181           0 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, bit_nil));
     182       37911 :         } else if (b) {
     183       36894 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, TRUE));
     184             :         } else {
     185        1017 :                 return stmt_atom(be, atom_bool(be->mvc->sa, &t, FALSE));
     186             :         }
     187             : }
     188             : 
     189             : static stmt *
     190    13643477 : stmt_create(allocator *sa, st_type type)
     191             : {
     192    13643477 :         stmt *s = SA_NEW(sa, stmt);
     193             : 
     194    13643454 :         if (!s)
     195             :                 return NULL;
     196    13643454 :         *s = (stmt) {
     197             :                 .type = type,
     198             :         };
     199    13643454 :         return s;
     200             : }
     201             : 
     202             : stmt *
     203       27465 : stmt_group(backend *be, stmt *s, stmt *grp, stmt *ext, stmt *cnt, int done)
     204             : {
     205       27465 :         MalBlkPtr mb = be->mb;
     206       27465 :         InstrPtr q = NULL;
     207             : 
     208       27465 :         if (s == NULL || s->nr < 0)
     209           0 :                 goto bailout;
     210       27465 :         if (grp && (grp->nr < 0 || ext->nr < 0 || cnt->nr < 0))
     211           0 :                 goto bailout;
     212             : 
     213       27465 :         q = newStmt(mb, groupRef, done ? grp ? subgroupdoneRef : groupdoneRef : grp ? subgroupRef : groupRef);
     214       27465 :         if (q == NULL)
     215           0 :                 goto bailout;
     216             : 
     217             :         /* output variables extent and hist */
     218       27465 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     219       27465 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
     220       27465 :         q = pushArgument(mb, q, s->nr);
     221       27465 :         if (grp)
     222        5988 :                 q = pushArgument(mb, q, grp->nr);
     223             : 
     224       27465 :         bool enabled = be->mvc->sa->eb.enabled;
     225       27465 :         be->mvc->sa->eb.enabled = false;
     226       27465 :         stmt *ns = stmt_create(be->mvc->sa, st_group);
     227       27465 :         be->mvc->sa->eb.enabled = enabled;
     228       27465 :         if (ns == NULL) {
     229           0 :                 freeInstruction(q);
     230           0 :                 goto bailout;
     231             :         }
     232             : 
     233       27465 :         ns->op1 = s;
     234             : 
     235       27465 :         if (grp) {
     236        5988 :                 ns->op2 = grp;
     237        5988 :                 ns->op3 = ext;
     238        5988 :                 ns->op4.stval = cnt;
     239             :         }
     240       27465 :         ns->nrcols = s->nrcols;
     241       27465 :         ns->key = 0;
     242       27465 :         ns->q = q;
     243       27465 :         ns->nr = getDestVar(q);
     244       27465 :         pushInstruction(mb, q);
     245       27465 :         return ns;
     246             : 
     247           0 :   bailout:
     248           0 :         if (be->mvc->sa->eb.enabled)
     249           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     250             :         return NULL;
     251             : }
     252             : 
     253             : stmt *
     254          76 : stmt_unique(backend *be, stmt *s)
     255             : {
     256          76 :         MalBlkPtr mb = be->mb;
     257          76 :         InstrPtr q = NULL;
     258             : 
     259          76 :         if (s == NULL || s->nr < 0)
     260           0 :                 goto bailout;
     261             : 
     262          76 :         q = newStmt(mb, algebraRef, uniqueRef);
     263          76 :         if (q == NULL)
     264           0 :                 goto bailout;
     265             : 
     266          76 :         q = pushArgument(mb, q, s->nr);
     267          76 :         q = pushNilBat(mb, q); /* candidate list */
     268             : 
     269          76 :         bool enabled = be->mvc->sa->eb.enabled;
     270          76 :         be->mvc->sa->eb.enabled = false;
     271          76 :         stmt *ns = stmt_create(be->mvc->sa, st_unique);
     272          76 :         be->mvc->sa->eb.enabled = enabled;
     273          76 :         if (ns == NULL) {
     274           0 :                 freeInstruction(q);
     275           0 :                 goto bailout;
     276             :         }
     277             : 
     278          76 :         ns->op1 = s;
     279          76 :         ns->nrcols = s->nrcols;
     280          76 :         ns->key = 1;
     281          76 :         ns->q = q;
     282          76 :         ns->nr = getDestVar(q);
     283          76 :         pushInstruction(mb, q);
     284          76 :         return ns;
     285             : 
     286           0 :   bailout:
     287           0 :         if (be->mvc->sa->eb.enabled)
     288           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     289             :         return NULL;
     290             : }
     291             : 
     292             : stmt *
     293           0 : stmt_none(backend *be)
     294             : {
     295           0 :         return stmt_create(be->mvc->sa, st_none);
     296             : }
     297             : 
     298             : static int
     299          55 : create_bat(MalBlkPtr mb, int tt)
     300             : {
     301          55 :         InstrPtr q = newStmt(mb, batRef, newRef);
     302             : 
     303          55 :         if (q == NULL)
     304             :                 return -1;
     305          55 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     306          55 :         q = pushType(mb, q, tt);
     307          55 :         pushInstruction(mb, q);
     308          55 :         return getDestVar(q);
     309             : }
     310             : 
     311             : static int *
     312          20 : dump_table(allocator *sa, MalBlkPtr mb, sql_table *t)
     313             : {
     314          20 :         int i = 0;
     315          20 :         node *n;
     316          20 :         int *l = SA_NEW_ARRAY(sa, int, ol_length(t->columns) + 1);
     317             : 
     318          20 :         if (!l)
     319             :                 return NULL;
     320             : 
     321             :         /* tid column */
     322          20 :         if ((l[i++] = create_bat(mb, TYPE_oid)) < 0)
     323             :                 return NULL;
     324             : 
     325          55 :         for (n = ol_first_node(t->columns); n; n = n->next) {
     326          35 :                 sql_column *c = n->data;
     327             : 
     328          35 :                 if ((l[i++] = create_bat(mb, c->type.type->localtype)) < 0)
     329             :                         return NULL;
     330             :         }
     331             :         return l;
     332             : }
     333             : 
     334             : stmt *
     335        2503 : stmt_var(backend *be, const char *sname, const char *varname, sql_subtype *t, int declare, int level)
     336             : {
     337        2503 :         MalBlkPtr mb = be->mb;
     338        2503 :         InstrPtr q = NULL;
     339        2503 :         char *buf;
     340             : 
     341        2503 :         if (level == 0) { /* global */
     342         339 :                 int tt = t->type->localtype;
     343             : 
     344         339 :                 assert(sname);
     345         339 :                 q = newStmt(mb, sqlRef, getVariableRef);
     346         339 :                 if (q == NULL)
     347           0 :                         goto bailout;
     348         339 :                 q = pushArgument(mb, q, be->mvc_var);
     349         339 :                 q = pushStr(mb, q, sname); /* all global variables have a schema */
     350         339 :                 q = pushStr(mb, q, varname);
     351         339 :                 setVarType(mb, getArg(q, 0), tt);
     352        2164 :         } else if (!declare) {
     353        1779 :                 char levelstr[16];
     354             : 
     355        1779 :                 assert(!sname);
     356        1779 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     357        1779 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     358        1779 :                 if (!buf)
     359           1 :                         goto bailout;
     360        1779 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     361        1779 :                 q = newAssignment(mb);
     362        1779 :                 if (q == NULL)
     363           1 :                         goto bailout;
     364        1778 :                 q = pushArgumentId(mb, q, buf);
     365             :         } else {
     366         385 :                 int tt = t->type->localtype;
     367         385 :                 char levelstr[16];
     368             : 
     369         385 :                 assert(!sname);
     370         385 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
     371         385 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
     372         385 :                 if (!buf)
     373           0 :                         goto bailout;
     374         385 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
     375             : 
     376         385 :                 q = newInstruction(mb, NULL, NULL);
     377         385 :                 if (q == NULL) {
     378           0 :                         goto bailout;
     379             :                 }
     380         385 :                 q->argc = q->retc = 0;
     381         385 :                 q = pushArgumentId(mb, q, buf);
     382         385 :                 q = pushNil(mb, q, tt);
     383         385 :                 q->retc++;
     384             :         }
     385        2502 :         bool enabled = be->mvc->sa->eb.enabled;
     386        2502 :         be->mvc->sa->eb.enabled = false;
     387        2502 :         stmt *s = stmt_create(be->mvc->sa, st_var);
     388        2502 :         be->mvc->sa->eb.enabled = enabled;
     389        2502 :         if (s == NULL) {
     390           0 :                 freeInstruction(q);
     391           0 :                 goto bailout;
     392             :         }
     393             : 
     394        2502 :         if (t)
     395        2502 :                 s->op4.typeval = *t;
     396             :         else
     397           0 :                 s->op4.typeval.type = NULL;
     398        2502 :         s->flag = declare + (level << 1);
     399        2502 :         s->key = 1;
     400        2502 :         s->q = q;
     401        2502 :         s->nr = getDestVar(q);
     402        2502 :         pushInstruction(mb, q);
     403        2502 :         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         675 : stmt_table(backend *be, stmt *cols, int temp)
     483             : {
     484         675 :         MalBlkPtr mb = be->mb;
     485             : 
     486         675 :         if (cols == NULL || cols->nr < 0)
     487           0 :                 goto bailout;
     488             : 
     489         675 :         stmt *s = stmt_create(be->mvc->sa, st_table);
     490             : 
     491         675 :         if (s == NULL)
     492           0 :                 goto bailout;
     493             : 
     494         675 :         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         675 :         s->op1 = cols;
     506         675 :         s->flag = temp;
     507         675 :         s->nr = cols->nr;
     508         675 :         s->nrcols = cols->nrcols;
     509         675 :         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      239637 : stmt_temp(backend *be, sql_subtype *t)
     519             : {
     520      239637 :         int tt = t->type->localtype;
     521      239637 :         MalBlkPtr mb = be->mb;
     522      239637 :         InstrPtr q = newStmt(mb, batRef, newRef);
     523             : 
     524      239690 :         if (q == NULL)
     525           0 :                 goto bailout;
     526      239690 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     527      239690 :         q = pushType(mb, q, tt);
     528      239662 :         bool enabled = be->mvc->sa->eb.enabled;
     529      239662 :         be->mvc->sa->eb.enabled = false;
     530      239662 :         stmt *s = stmt_create(be->mvc->sa, st_temp);
     531      239664 :         be->mvc->sa->eb.enabled = enabled;
     532             : 
     533      239664 :         if (s == NULL) {
     534           0 :                 freeInstruction(q);
     535           0 :                 goto bailout;
     536             :         }
     537      239664 :         s->op4.typeval = *t;
     538      239664 :         s->nrcols = 1;
     539      239664 :         s->q = q;
     540      239664 :         s->nr = getDestVar(q);
     541      239664 :         pushInstruction(mb, q);
     542      239664 :         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      199603 : stmt_tid(backend *be, sql_table *t, int partition)
     569             : {
     570      199603 :         int tt = TYPE_oid;
     571      199603 :         MalBlkPtr mb = be->mb;
     572      199603 :         InstrPtr q;
     573             : 
     574      199603 :         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      199587 :         q = newStmt(mb, sqlRef, tidRef);
     589      199587 :         if (q == NULL)
     590           0 :                 goto bailout;
     591      199587 :         setVarType(mb, getArg(q, 0), newBatType(tt));
     592      199587 :         q = pushArgument(mb, q, be->mvc_var);
     593      199586 :         q = pushSchema(mb, q, t);
     594      199586 :         q = pushStr(mb, q, t->base.name);
     595      199587 :         if (t && isTable(t) && partition) {
     596       73966 :                 sql_trans *tr = be->mvc->session->tr;
     597       73966 :                 sqlstore *store = tr->store;
     598       73966 :                 BUN rows = (BUN) store->storage_api.count_col(tr, ol_first_node(t->columns)->data, RDONLY);
     599       73966 :                 setRowCnt(mb,getArg(q,0),rows);
     600             :         }
     601             : 
     602      199587 :         bool enabled = be->mvc->sa->eb.enabled;
     603      199587 :         be->mvc->sa->eb.enabled = false;
     604      199587 :         stmt *s = stmt_create(be->mvc->sa, st_tid);
     605      199587 :         be->mvc->sa->eb.enabled = enabled;
     606      199587 :         if (s == NULL) {
     607           0 :                 freeInstruction(q);
     608           0 :                 goto bailout;
     609             :         }
     610             : 
     611      199587 :         s->partition = partition;
     612      199587 :         s->op4.tval = t;
     613      199587 :         s->nrcols = 1;
     614      199587 :         s->nr = getDestVar(q);
     615      199587 :         s->q = q;
     616      199587 :         pushInstruction(mb, q);
     617      199587 :         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      938024 : find_real_column(backend *be, sql_column *c)
     627             : {
     628      938024 :         if (c && c->t && c->t->s && c->t->persistence == SQL_DECLARED_TABLE) {
     629       36742 :                 sql_table *nt = find_sql_table_id(be->mvc->session->tr, c->t->s, c->t->base.id);
     630       36742 :                 if (nt) {
     631       36742 :                         node *n = ol_find_id(nt->columns, c->base.id);
     632       36742 :                         if (n)
     633       36742 :                                 return n->data;
     634             :                 }
     635             :         }
     636             :         return c;
     637             : }
     638             : 
     639             : stmt *
     640      938021 : stmt_bat(backend *be, sql_column *c, int access, int partition)
     641             : {
     642      938021 :         int tt = c->type.type->localtype;
     643      938021 :         MalBlkPtr mb = be->mb;
     644      938021 :         InstrPtr q;
     645             : 
     646      938021 :         c = find_real_column(be, c);
     647             : 
     648      938018 :         if (access == RD_EXT)
     649         172 :                 partition = 0;
     650             : 
     651             :         /* for read access tid.project(col) */
     652      938018 :         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      937995 :         q = newStmtArgs(mb, sqlRef, bindRef, 9);
     670      938002 :         if (q == NULL)
     671           0 :                 goto bailout;
     672      938002 :         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      937830 :         if (access == RD_UPD_ID) {
     683      455422 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     684             :         } else {
     685      482580 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     686             :         }
     687      938001 :         q = pushArgument(mb, q, be->mvc_var);
     688      938000 :         q = pushSchema(mb, q, c->t);
     689      938001 :         q = pushArgument(mb, q, getStrConstant(mb,c->t->base.name));
     690      937981 :         q = pushArgument(mb, q, getStrConstant(mb,c->base.name));
     691      937980 :         q = pushArgument(mb, q, getIntConstant(mb,access));
     692             : 
     693      937985 :         if (access == RD_UPD_ID) {
     694      455414 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     695             :         }
     696      937985 :         if (partition) {
     697      533328 :                 sql_trans *tr = be->mvc->session->tr;
     698      533328 :                 sqlstore *store = tr->store;
     699             : 
     700      533328 :                 if (c && isTable(c->t)) {
     701      533328 :                         BUN rows = (BUN) store->storage_api.count_col(tr, c, QUICK);
     702      533326 :                         setRowCnt(mb,getArg(q,0),rows);
     703             :                 }
     704             :         }
     705             : 
     706      937983 :         bool enabled = be->mvc->sa->eb.enabled;
     707      937983 :         be->mvc->sa->eb.enabled = false;
     708      937983 :         stmt *s = stmt_create(be->mvc->sa, st_bat);
     709      937972 :         be->mvc->sa->eb.enabled = enabled;
     710      937972 :         if (s == NULL) {
     711           0 :                 freeInstruction(q);
     712           0 :                 goto bailout;
     713             :         }
     714             : 
     715      937972 :         s->partition = partition;
     716      937972 :         s->op4.cval = c;
     717      937972 :         s->nrcols = 1;
     718      937972 :         s->flag = access;
     719      937972 :         s->nr = getDestVar(q);
     720      937972 :         s->q = q;
     721      937972 :         s->tname = c->t->base.name;
     722      937972 :         s->cname = c->base.name;
     723      937972 :         pushInstruction(mb, q);
     724      937972 :         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        6434 : stmt_idxbat(backend *be, sql_idx *i, int access, int partition)
     734             : {
     735        6434 :         int tt = hash_index(i->type)?TYPE_lng:TYPE_oid;
     736        6434 :         MalBlkPtr mb = be->mb;
     737        6434 :         InstrPtr q = newStmtArgs(mb, sqlRef, bindidxRef, 9);
     738             : 
     739        6434 :         if (q == NULL)
     740           0 :                 goto bailout;
     741             : 
     742        6434 :         if (access == RD_UPD_ID) {
     743        2855 :                 q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
     744             :         } else {
     745        3579 :                 setVarType(mb, getArg(q, 0), newBatType(tt));
     746             :         }
     747             : 
     748        6434 :         q = pushArgument(mb, q, be->mvc_var);
     749        6434 :         q = pushSchema(mb, q, i->t);
     750        6434 :         q = pushArgument(mb, q, getStrConstant(mb, i->t->base.name));
     751        6434 :         q = pushArgument(mb, q, getStrConstant(mb, i->base.name));
     752        6434 :         q = pushArgument(mb, q, getIntConstant(mb, access));
     753             : 
     754        6434 :         if (access == RD_UPD_ID) {
     755        2855 :                 setVarType(mb, getArg(q, 1), newBatType(tt));
     756             :         }
     757        6434 :         if (partition) {
     758        3528 :                 sql_trans *tr = be->mvc->session->tr;
     759        3528 :                 sqlstore *store = tr->store;
     760             : 
     761        3528 :                 if (i && isTable(i->t)) {
     762        3528 :                         BUN rows = (BUN) store->storage_api.count_idx(tr, i, QUICK);
     763        3528 :                         setRowCnt(mb,getArg(q,0),rows);
     764             :                 }
     765             :         }
     766             : 
     767        6434 :         bool enabled = be->mvc->sa->eb.enabled;
     768        6434 :         be->mvc->sa->eb.enabled = false;
     769        6434 :         stmt *s = stmt_create(be->mvc->sa, st_idxbat);
     770        6434 :         be->mvc->sa->eb.enabled = enabled;
     771        6434 :         if (s == NULL) {
     772           0 :                 freeInstruction(q);
     773           0 :                 goto bailout;
     774             :         }
     775             : 
     776        6434 :         s->partition = partition;
     777        6434 :         s->op4.idxval = i;
     778        6434 :         s->nrcols = 1;
     779        6434 :         s->flag = access;
     780        6434 :         s->nr = getDestVar(q);
     781        6434 :         s->q = q;
     782        6434 :         s->tname = i->t->base.name;
     783        6434 :         s->cname = i->base.name;
     784        6434 :         pushInstruction(mb, q);
     785        6434 :         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      661827 : stmt_append_col(backend *be, sql_column *c, stmt *offset, stmt *b, int *mvc_var_update, int fake)
     795             : {
     796      661827 :         MalBlkPtr mb = be->mb;
     797      661827 :         InstrPtr q = NULL;
     798             : 
     799      661827 :         if (b == NULL || b->nr < 0)
     800           0 :                 goto bailout;
     801             : 
     802      661827 :         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      661804 :         } else if (!fake) {     /* fake append */
     821      661804 :                 if (offset == NULL || offset->nr < 0)
     822           0 :                         goto bailout;
     823      661804 :                 q = newStmt(mb, sqlRef, appendRef);
     824      661809 :                 if (q == NULL)
     825           0 :                         goto bailout;
     826      661809 :                 q = pushArgument(mb, q, be->mvc_var);
     827      661811 :                 int tmpvar = newTmpVariable(mb, TYPE_int);
     828      661811 :                 getArg(q, 0) = tmpvar;
     829      661811 :                 if (mvc_var_update != NULL)
     830      661811 :                         *mvc_var_update = tmpvar;
     831      661811 :                 q = pushSchema(mb, q, c->t);
     832      661808 :                 q = pushStr(mb, q, c->t->base.name);
     833      661808 :                 q = pushStr(mb, q, c->base.name);
     834      661794 :                 q = pushArgument(mb, q, offset->nr);
     835             :                 /* also the offsets */
     836      661789 :                 assert(offset->q->retc == 2);
     837      661789 :                 q = pushArgument(mb, q, getArg(offset->q, 1));
     838      661792 :                 q = pushArgument(mb, q, b->nr);
     839      661790 :                 if (mvc_var_update != NULL)
     840      661790 :                         *mvc_var_update = getDestVar(q);
     841             :         } else {
     842             :                 return b;
     843             :         }
     844      661813 :         bool enabled = be->mvc->sa->eb.enabled;
     845      661813 :         be->mvc->sa->eb.enabled = false;
     846      661813 :         stmt *s = stmt_create(be->mvc->sa, st_append_col);
     847      661816 :         be->mvc->sa->eb.enabled = enabled;
     848             : 
     849      661816 :         if (s == NULL) {
     850           0 :                 freeInstruction(q);
     851           0 :                 goto bailout;
     852             :         }
     853      661816 :         s->op1 = b;
     854      661816 :         s->op2 = offset;
     855      661816 :         s->op4.cval = c;
     856      661816 :         s->q = q;
     857      661816 :         s->nr = getDestVar(q);
     858      661816 :         pushInstruction(mb, q);
     859      661816 :         return s;
     860             : 
     861           0 :   bailout:
     862           0 :         if (be->mvc->sa->eb.enabled)
     863           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     864             :         return NULL;
     865             : }
     866             : 
     867             : stmt *
     868        2220 : stmt_append_idx(backend *be, sql_idx *i, stmt *offset, stmt *b)
     869             : {
     870        2220 :         MalBlkPtr mb = be->mb;
     871        2220 :         InstrPtr q = NULL;
     872             : 
     873        2220 :         if (offset == NULL || b == NULL || offset->nr < 0 || b->nr < 0)
     874           0 :                 goto bailout;
     875             : 
     876        2220 :         q = newStmt(mb, sqlRef, appendRef);
     877        2220 :         if (q == NULL)
     878           0 :                 goto bailout;
     879        2220 :         q = pushArgument(mb, q, be->mvc_var);
     880        2220 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     881        2220 :         q = pushSchema(mb, q, i->t);
     882        2220 :         q = pushStr(mb, q, i->t->base.name);
     883        2220 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
     884        2220 :         q = pushArgument(mb, q, offset->nr);
     885             :         /* also the offsets */
     886        2220 :         assert(offset->q->retc == 2);
     887        2220 :         q = pushArgument(mb, q, getArg(offset->q, 1));
     888        2220 :         q = pushArgument(mb, q, b->nr);
     889        2220 :         be->mvc_var = getDestVar(q);
     890             : 
     891        2220 :         bool enabled = be->mvc->sa->eb.enabled;
     892        2220 :         be->mvc->sa->eb.enabled = false;
     893        2220 :         stmt *s = stmt_create(be->mvc->sa, st_append_idx);
     894        2220 :         be->mvc->sa->eb.enabled = enabled;
     895        2220 :         if (s == NULL) {
     896           0 :                 freeInstruction(q);
     897           0 :                 goto bailout;
     898             :         }
     899             : 
     900        2220 :         s->op1 = b;
     901        2220 :         s->op2 = offset;
     902        2220 :         s->op4.idxval = i;
     903        2220 :         s->q = q;
     904        2220 :         s->nr = getDestVar(q);
     905        2220 :         pushInstruction(mb, q);
     906        2220 :         return s;
     907             : 
     908           0 :   bailout:
     909           0 :         if (be->mvc->sa->eb.enabled)
     910           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     911             :         return NULL;
     912             : }
     913             : 
     914             : stmt *
     915        3367 : stmt_update_col(backend *be, sql_column *c, stmt *tids, stmt *upd)
     916             : {
     917        3367 :         MalBlkPtr mb = be->mb;
     918        3367 :         InstrPtr q = NULL;
     919             : 
     920        3367 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     921           0 :                 goto bailout;
     922             : 
     923        3368 :         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        3366 :                 q = newStmt(mb, sqlRef, updateRef);
     934        3366 :                 if (q == NULL)
     935           0 :                         goto bailout;
     936        3366 :                 q = pushArgument(mb, q, be->mvc_var);
     937        3366 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     938        3366 :                 q = pushSchema(mb, q, c->t);
     939        3366 :                 q = pushStr(mb, q, c->t->base.name);
     940        3366 :                 q = pushStr(mb, q, c->base.name);
     941        3366 :                 q = pushArgument(mb, q, tids->nr);
     942        3366 :                 q = pushArgument(mb, q, upd->nr);
     943        3366 :                 be->mvc_var = getDestVar(q);
     944             :         }
     945        3367 :         bool enabled = be->mvc->sa->eb.enabled;
     946        3367 :         be->mvc->sa->eb.enabled = false;
     947        3367 :         stmt *s = stmt_create(be->mvc->sa, st_update_col);
     948        3367 :         be->mvc->sa->eb.enabled = enabled;
     949             : 
     950        3367 :         if (s == NULL) {
     951           0 :                 freeInstruction(q);
     952           0 :                 goto bailout;
     953             :         }
     954        3367 :         s->op1 = tids;
     955        3367 :         s->op2 = upd;
     956        3367 :         s->op4.cval = c;
     957        3367 :         s->q = q;
     958        3367 :         s->nr = getDestVar(q);
     959        3367 :         pushInstruction(mb, q);
     960        3367 :         return s;
     961             : 
     962           0 :   bailout:
     963           0 :         if (be->mvc->sa->eb.enabled)
     964           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
     965             :         return NULL;
     966             : }
     967             : 
     968             : 
     969             : stmt *
     970         823 : stmt_update_idx(backend *be, sql_idx *i, stmt *tids, stmt *upd)
     971             : {
     972         823 :         MalBlkPtr mb = be->mb;
     973         823 :         InstrPtr q = NULL;
     974             : 
     975         823 :         if (tids == NULL || upd == NULL || tids->nr < 0 || upd->nr < 0)
     976           0 :                 goto bailout;
     977             : 
     978         823 :         q = newStmt(mb, sqlRef, updateRef);
     979         823 :         if (q == NULL)
     980           0 :                 goto bailout;
     981         823 :         q = pushArgument(mb, q, be->mvc_var);
     982         823 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
     983         823 :         q = pushSchema(mb, q, i->t);
     984         823 :         q = pushStr(mb, q, i->t->base.name);
     985         823 :         q = pushStr(mb, q, sa_strconcat(be->mvc->sa, "%", i->base.name));
     986         823 :         q = pushArgument(mb, q, tids->nr);
     987         823 :         q = pushArgument(mb, q, upd->nr);
     988         823 :         be->mvc_var = getDestVar(q);
     989         823 :         bool enabled = be->mvc->sa->eb.enabled;
     990         823 :         be->mvc->sa->eb.enabled = false;
     991         823 :         stmt *s = stmt_create(be->mvc->sa, st_update_idx);
     992         823 :         be->mvc->sa->eb.enabled = enabled;
     993         823 :         if (s == NULL) {
     994           0 :                 freeInstruction(q);
     995           0 :                 goto bailout;
     996             :         }
     997             : 
     998         823 :         s->op1 = tids;
     999         823 :         s->op2 = upd;
    1000         823 :         s->op4.idxval = i;
    1001         823 :         s->q = q;
    1002         823 :         s->nr = getDestVar(q);
    1003         823 :         pushInstruction(mb, q);
    1004         823 :         return s;
    1005             : 
    1006           0 :   bailout:
    1007           0 :         if (be->mvc->sa->eb.enabled)
    1008           0 :                 eb_error(&be->mvc->sa->eb, be->mvc->errstr[0] ? be->mvc->errstr : mb->errors ? mb->errors : *GDKerrbuf ? GDKerrbuf : "out of memory", 1000);
    1009             :         return NULL;
    1010             : }
    1011             : 
    1012             : stmt *
    1013         368 : stmt_delete(backend *be, sql_table *t, stmt *tids)
    1014             : {
    1015         368 :         MalBlkPtr mb = be->mb;
    1016         368 :         InstrPtr q = NULL;
    1017             : 
    1018         368 :         if (tids == NULL || tids->nr < 0)
    1019           0 :                 goto bailout;
    1020             : 
    1021         369 :         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         367 :                 q = newStmt(mb, sqlRef, deleteRef);
    1031         367 :                 if (q == NULL)
    1032           0 :                         goto bailout;
    1033         367 :                 q = pushArgument(mb, q, be->mvc_var);
    1034         367 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    1035         367 :                 q = pushSchema(mb, q, t);
    1036         367 :                 q = pushStr(mb, q, t->base.name);
    1037         367 :                 q = pushArgument(mb, q, tids->nr);
    1038         367 :                 be->mvc_var = getDestVar(q);
    1039             :         }
    1040         368 :         bool enabled = be->mvc->sa->eb.enabled;
    1041         368 :         be->mvc->sa->eb.enabled = false;
    1042         368 :         stmt *s = stmt_create(be->mvc->sa, st_delete);
    1043         368 :         be->mvc->sa->eb.enabled = enabled;
    1044         368 :         if (s == NULL) {
    1045           0 :                 freeInstruction(q);
    1046           0 :                 goto bailout;
    1047             :         }
    1048             : 
    1049         368 :         s->op1 = tids;
    1050         368 :         s->op4.tval = t;
    1051         368 :         s->q = q;
    1052         368 :         s->nr = getDestVar(q);
    1053         368 :         pushInstruction(mb, q);
    1054         368 :         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      107529 : stmt_const(backend *be, stmt *s, stmt *val)
    1064             : {
    1065      107529 :         InstrPtr q = NULL;
    1066      107529 :         MalBlkPtr mb = be->mb;
    1067             : 
    1068      107529 :         if (s == NULL)
    1069           0 :                 goto bailout;
    1070      107529 :         if (val)
    1071      107529 :                 q = dump_2(mb, algebraRef, projectRef, s, val);
    1072             :         else
    1073           0 :                 q = dump_1(mb, algebraRef, projectRef, s);
    1074      107529 :         if (q) {
    1075      107529 :                 stmt *ns = stmt_create(be->mvc->sa, st_const);
    1076      107529 :                 if (ns == NULL) {
    1077           0 :                         goto bailout;
    1078             :                 }
    1079             : 
    1080      107529 :                 ns->op1 = s;
    1081      107529 :                 ns->op2 = val;
    1082      107529 :                 ns->nrcols = s->nrcols;
    1083      107529 :                 ns->key = s->key;
    1084      107529 :                 ns->aggr = s->aggr;
    1085      107529 :                 ns->q = q;
    1086      107529 :                 ns->nr = getDestVar(q);
    1087      107529 :                 ns->tname = val->tname;
    1088      107529 :                 ns->cname = val->cname;
    1089      107529 :                 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        2396 : stmt_gen_group(backend *be, stmt *gids, stmt *cnts)
    1099             : {
    1100        2396 :         MalBlkPtr mb = be->mb;
    1101             : 
    1102        2396 :         if (gids == NULL || cnts == NULL)
    1103           0 :                 goto bailout;
    1104             : 
    1105        2396 :         InstrPtr q = dump_2(mb, algebraRef, groupbyRef, gids, cnts);
    1106             : 
    1107        2396 :         if (q) {
    1108        2396 :                 stmt *ns = stmt_create(be->mvc->sa, st_gen_group);
    1109        2396 :                 if (ns == NULL) {
    1110           0 :                         goto bailout;
    1111             :                 }
    1112             : 
    1113        2396 :                 ns->op1 = gids;
    1114        2396 :                 ns->op2 = cnts;
    1115             : 
    1116        2396 :                 ns->nrcols = gids->nrcols;
    1117        2396 :                 ns->key = 0;
    1118        2396 :                 ns->aggr = 0;
    1119        2396 :                 ns->q = q;
    1120        2396 :                 ns->nr = getDestVar(q);
    1121        2396 :                 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       47164 : stmt_mirror(backend *be, stmt *s)
    1131             : {
    1132       47164 :         MalBlkPtr mb = be->mb;
    1133             : 
    1134       47164 :         if (s == NULL)
    1135           0 :                 goto bailout;
    1136             : 
    1137       47164 :         InstrPtr q = dump_1(mb, batRef, mirrorRef, s);
    1138             : 
    1139       47164 :         if (q) {
    1140       47164 :                 stmt *ns = stmt_create(be->mvc->sa, st_mirror);
    1141       47164 :                 if (ns == NULL) {
    1142           0 :                         goto bailout;
    1143             :                 }
    1144             : 
    1145       47164 :                 ns->op1 = s;
    1146       47164 :                 ns->nrcols = 2;
    1147       47164 :                 ns->key = s->key;
    1148       47164 :                 ns->aggr = s->aggr;
    1149       47164 :                 ns->q = q;
    1150       47164 :                 ns->nr = getDestVar(q);
    1151       47164 :                 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      309463 : stmt_result(backend *be, stmt *s, int nr)
    1162             : {
    1163      309463 :         stmt *ns;
    1164             : 
    1165      309463 :         if (s == NULL)
    1166             :                 return NULL;
    1167             : 
    1168      309463 :         if (s->type == st_join && s->flag == cmp_joined) {
    1169        5140 :                 if (nr)
    1170        2288 :                         return s->op2;
    1171        2852 :                 return s->op1;
    1172             :         }
    1173             : 
    1174      304323 :         if (s->op1->nr < 0)
    1175             :                 return NULL;
    1176             : 
    1177      304323 :         ns = stmt_create(be->mvc->sa, st_result);
    1178      304323 :         if(!ns) {
    1179             :                 return NULL;
    1180             :         }
    1181      304323 :         if (s->op1->type == st_join && s->op1->flag == cmp_joined) {
    1182           0 :                 assert(0);
    1183      304323 :         } else if (nr) {
    1184      174138 :                 int v = getArg(s->q, nr);
    1185             : 
    1186      174138 :                 assert(s->q->retc > nr);
    1187      174138 :                 ns->nr = v;
    1188             :         } else {
    1189      130185 :                 ns->nr = s->nr;
    1190             :         }
    1191      304323 :         ns->op1 = s;
    1192      304323 :         if (!nr && (s->type == st_order || s->type == st_reorder))
    1193       22481 :                 ns->op4.typeval = *tail_type(s->op1);
    1194      174138 :         else if (nr && ((s->type == st_join && s->flag == MARKJOIN) || (s->type == st_uselect2 && s->flag == MARKJOIN)))
    1195        2873 :                 ns->op4.typeval = *sql_bind_localtype("bit");
    1196             :         else
    1197      278969 :                 ns->op4.typeval = *sql_bind_localtype("oid");
    1198      304323 :         ns->flag = nr;
    1199      304323 :         ns->nrcols = s->nrcols;
    1200      304323 :         ns->key = s->key;
    1201      304323 :         ns->aggr = s->aggr;
    1202      304323 :         return ns;
    1203             : }
    1204             : 
    1205             : 
    1206             : /* limit maybe atom nil */
    1207             : stmt *
    1208       17947 : 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       17947 :         MalBlkPtr mb = be->mb;
    1211       17947 :         InstrPtr q = NULL;
    1212       17947 :         int l, p, g, c;
    1213             : 
    1214       17947 :         if (col == NULL || offset == NULL || limit == NULL || col->nr < 0 || offset->nr < 0 || limit->nr < 0)
    1215           0 :                 goto bailout;
    1216       17947 :         if (piv && (piv->nr < 0 || gid->nr < 0))
    1217           0 :                 goto bailout;
    1218             : 
    1219       17947 :         c = (col) ? col->nr : 0;
    1220       17947 :         p = (piv) ? piv->nr : 0;
    1221       17947 :         g = (gid) ? gid->nr : 0;
    1222             : 
    1223             :         /* first insert single value into a bat */
    1224       17947 :         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       17947 :         if (order) {
    1244         899 :                 int topn = 0;
    1245             : 
    1246         899 :                 q = newStmt(mb, calcRef, plusRef);
    1247         899 :                 if (q == NULL)
    1248           0 :                         goto bailout;
    1249         899 :                 q = pushArgument(mb, q, offset->nr);
    1250         899 :                 q = pushArgument(mb, q, limit->nr);
    1251         899 :                 topn = getDestVar(q);
    1252         899 :                 pushInstruction(mb, q);
    1253             : 
    1254         899 :                 q = newStmtArgs(mb, algebraRef, firstnRef, 9);
    1255         899 :                 if (q == NULL)
    1256           0 :                         goto bailout;
    1257         899 :                 if (!last) /* we need the groups for the next firstn */
    1258         493 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1259         899 :                 q = pushArgument(mb, q, c);
    1260         899 :                 if (p)
    1261         493 :                         q = pushArgument(mb, q, p);
    1262             :                 else
    1263         406 :                         q = pushNilBat(mb, q);
    1264         899 :                 if (g)
    1265         493 :                         q = pushArgument(mb, q, g);
    1266             :                 else
    1267         406 :                         q = pushNilBat(mb, q);
    1268         899 :                 q = pushArgument(mb, q, topn);
    1269         899 :                 q = pushBit(mb, q, dir);
    1270         899 :                 q = pushBit(mb, q, nullslast);
    1271         899 :                 q = pushBit(mb, q, distinct != 0);
    1272             : 
    1273         899 :                 l = getArg(q, 0);
    1274         899 :                 l = getDestVar(q);
    1275         899 :                 pushInstruction(mb, q);
    1276             :         } else {
    1277       17048 :                 int len;
    1278             : 
    1279       17048 :                 q = newStmt(mb, calcRef, plusRef);
    1280       17049 :                 if (q == NULL)
    1281           0 :                         goto bailout;
    1282       17049 :                 q = pushArgument(mb, q, offset->nr);
    1283       17049 :                 q = pushArgument(mb, q, limit->nr);
    1284       17049 :                 len = getDestVar(q);
    1285       17049 :                 pushInstruction(mb, q);
    1286             : 
    1287             :                 /* since both arguments of algebra.subslice are
    1288             :                    inclusive correct the LIMIT value by
    1289             :                    subtracting 1 */
    1290       17049 :                 q = newStmt(mb, calcRef, minusRef);
    1291       17049 :                 if (q == NULL)
    1292           0 :                         goto bailout;
    1293       17049 :                 q = pushArgument(mb, q, len);
    1294       17049 :                 q = pushInt(mb, q, 1);
    1295       17049 :                 len = getDestVar(q);
    1296       17049 :                 pushInstruction(mb, q);
    1297             : 
    1298       17049 :                 q = newStmt(mb, algebraRef, subsliceRef);
    1299       17049 :                 if (q == NULL)
    1300           0 :                         goto bailout;
    1301       17049 :                 q = pushArgument(mb, q, c);
    1302       17049 :                 q = pushArgument(mb, q, offset->nr);
    1303       17049 :                 q = pushArgument(mb, q, len);
    1304       17049 :                 l = getDestVar(q);
    1305       17049 :                 pushInstruction(mb, q);
    1306             :         }
    1307             :         /* retrieve the single values again */
    1308       17948 :         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       35403 :         stmt *ns = stmt_create(be->mvc->sa, piv?st_limit2:st_limit);
    1319       17948 :         if (ns == NULL) {
    1320           0 :                 goto bailout;
    1321             :         }
    1322             : 
    1323       17948 :         ns->op1 = col;
    1324       17948 :         ns->op2 = offset;
    1325       17948 :         ns->op3 = limit;
    1326       17948 :         ns->nrcols = col->nrcols;
    1327       17948 :         ns->key = col->key;
    1328       17948 :         ns->aggr = col->aggr;
    1329       17948 :         ns->q = q;
    1330       17948 :         ns->nr = l;
    1331       17948 :         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       10104 : stmt_order(backend *be, stmt *s, int direction, int nullslast)
    1394             : {
    1395       10104 :         MalBlkPtr mb = be->mb;
    1396       10104 :         InstrPtr q = NULL;
    1397             : 
    1398       10104 :         if (s == NULL || s->nr < 0)
    1399           0 :                 goto bailout;
    1400       10104 :         q = newStmt(mb, algebraRef, sortRef);
    1401       10104 :         if (q == NULL)
    1402           0 :                 goto bailout;
    1403             :         /* both ordered result and oid's order en subgroups */
    1404       10104 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1405       10104 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1406       10104 :         q = pushArgument(mb, q, s->nr);
    1407       10104 :         q = pushBit(mb, q, !direction);
    1408       10104 :         q = pushBit(mb, q, nullslast);
    1409       10104 :         q = pushBit(mb, q, FALSE);
    1410             : 
    1411       10104 :         bool enabled = be->mvc->sa->eb.enabled;
    1412       10104 :         be->mvc->sa->eb.enabled = false;
    1413       10104 :         stmt *ns = stmt_create(be->mvc->sa, st_order);
    1414       10104 :         be->mvc->sa->eb.enabled = enabled;
    1415       10104 :         if (ns == NULL) {
    1416           0 :                 freeInstruction(q);
    1417           0 :                 goto bailout;
    1418             :         }
    1419             : 
    1420       10104 :         ns->op1 = s;
    1421       10104 :         ns->flag = direction;
    1422       10104 :         ns->nrcols = s->nrcols;
    1423       10104 :         ns->key = s->key;
    1424       10104 :         ns->aggr = s->aggr;
    1425       10104 :         ns->q = q;
    1426       10104 :         ns->nr = getDestVar(q);
    1427       10104 :         pushInstruction(mb, q);
    1428       10104 :         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       12892 : stmt_reorder(backend *be, stmt *s, int direction, int nullslast, stmt *orderby_ids, stmt *orderby_grp)
    1438             : {
    1439       12892 :         MalBlkPtr mb = be->mb;
    1440       12892 :         InstrPtr q = NULL;
    1441             : 
    1442       12892 :         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       12892 :         q = newStmtArgs(mb, algebraRef, sortRef, 9);
    1445       12892 :         if (q == NULL)
    1446           0 :                 goto bailout;
    1447             :         /* both ordered result and oid's order en subgroups */
    1448       12892 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1449       12892 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1450       12892 :         q = pushArgument(mb, q, s->nr);
    1451       12892 :         q = pushArgument(mb, q, orderby_ids->nr);
    1452       12892 :         q = pushArgument(mb, q, orderby_grp->nr);
    1453       12892 :         q = pushBit(mb, q, !direction);
    1454       12892 :         q = pushBit(mb, q, nullslast);
    1455       12892 :         q = pushBit(mb, q, FALSE);
    1456             : 
    1457       12892 :         bool enabled = be->mvc->sa->eb.enabled;
    1458       12892 :         be->mvc->sa->eb.enabled = false;
    1459       12892 :         stmt *ns = stmt_create(be->mvc->sa, st_reorder);
    1460       12892 :         be->mvc->sa->eb.enabled = enabled;
    1461       12892 :         if (ns == NULL) {
    1462           0 :                 freeInstruction(q);
    1463           0 :                 goto bailout;
    1464             :         }
    1465             : 
    1466       12892 :         ns->op1 = s;
    1467       12892 :         ns->op2 = orderby_ids;
    1468       12892 :         ns->op3 = orderby_grp;
    1469       12892 :         ns->flag = direction;
    1470       12892 :         ns->nrcols = s->nrcols;
    1471       12892 :         ns->key = s->key;
    1472       12892 :         ns->aggr = s->aggr;
    1473       12892 :         ns->nr = getDestVar(q);
    1474       12892 :         ns->q = q;
    1475       12892 :         pushInstruction(mb, q);
    1476       12892 :         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     3343586 : stmt_atom(backend *be, atom *a)
    1486             : {
    1487     3343586 :         MalBlkPtr mb = be->mb;
    1488             : 
    1489     3343586 :         if (a == NULL)
    1490           0 :                 goto bailout;
    1491             : 
    1492     3343586 :         InstrPtr q = EC_TEMP_FRAC(atom_type(a)->type->eclass) ? newStmt(mb, calcRef, atom_type(a)->type->impl) : newAssignment(mb);
    1493             : 
    1494     3343644 :         if (q == NULL)
    1495           0 :                 goto bailout;
    1496     3343644 :         if (atom_null(a)) {
    1497      141135 :                 q = pushNil(mb, q, atom_type(a)->type->localtype);
    1498             :         } else {
    1499     3202509 :                 int k;
    1500     3202509 :                 if ((k = constantAtom(be, mb, a)) == -1) {
    1501           0 :                         freeInstruction(q);
    1502           0 :                         goto bailout;
    1503             :                 }
    1504     3202335 :                 q = pushArgument(mb, q, k);
    1505             :         }
    1506             :         /* digits of the result timestamp/daytime */
    1507     3343440 :         if (EC_TEMP_FRAC(atom_type(a)->type->eclass))
    1508       47438 :                 q = pushInt(mb, q, atom_type(a)->digits);
    1509     3343423 :         bool enabled = be->mvc->sa->eb.enabled;
    1510     3343423 :         be->mvc->sa->eb.enabled = false;
    1511     3343423 :         stmt *s = stmt_create(be->mvc->sa, st_atom);
    1512     3343420 :         be->mvc->sa->eb.enabled = enabled;
    1513     3343420 :         if (s == NULL) {
    1514           0 :                 freeInstruction(q);
    1515           0 :                 goto bailout;
    1516             :         }
    1517             : 
    1518     3343420 :         s->op4.aval = a;
    1519     3343420 :         s->key = 1;          /* values are also unique */
    1520     3343420 :         s->q = q;
    1521     3343420 :         s->nr = getDestVar(q);
    1522     3343420 :         pushInstruction(mb, q);
    1523     3343420 :         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        3615 : stmt_genselect(backend *be, stmt *lops, stmt *rops, sql_subfunc *f, stmt *sub, int anti)
    1533             : {
    1534        3615 :         MalBlkPtr mb = be->mb;
    1535        3615 :         InstrPtr q = NULL;
    1536        3615 :         const char *mod, *op;
    1537        3615 :         node *n;
    1538        3615 :         int k;
    1539             : 
    1540        3615 :         if (lops == NULL || rops == NULL)
    1541           0 :                 goto bailout;
    1542             : 
    1543        3615 :         if (backend_create_subfunc(be, f, NULL) < 0)
    1544           0 :                 goto bailout;
    1545        3615 :         op = backend_function_imp(be, f->func);
    1546        3615 :         mod = sql_func_mod(f->func);
    1547             : 
    1548        3615 :         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        3561 :                 node *n;
    1588             : 
    1589        3561 :                 op = sa_strconcat(be->mvc->sa, op, selectRef);
    1590        3561 :                 q = newStmtArgs(mb, mod, convertMultiplexFcn(op), 9);
    1591        3561 :                 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        3561 :                 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        3561 :                 if (f->func->lang == FUNC_LANG_R || f->func->lang >= FUNC_LANG_PY)
    1599           0 :                         q = pushStr(mb, q, f->func->query);
    1600             : 
    1601        7122 :                 for (n = lops->op4.lval->h; n; n = n->next) {
    1602        3561 :                         stmt *op = n->data;
    1603             : 
    1604        3561 :                         q = pushArgument(mb, q, op->nr);
    1605             :                 }
    1606             :                 /* candidate lists */
    1607        3561 :                 if (sub)
    1608        3497 :                         q = pushArgument(mb, q, sub->nr);
    1609             :                 else
    1610          64 :                         q = pushNilBat(mb, q);
    1611             : 
    1612       14229 :                 for (n = rops->op4.lval->h; n; n = n->next) {
    1613       10668 :                         stmt *op = n->data;
    1614             : 
    1615       10668 :                         q = pushArgument(mb, q, op->nr);
    1616             :                 }
    1617             : 
    1618        3561 :                 q = pushBit(mb, q, anti);
    1619             :         }
    1620             : 
    1621        3615 :         bool enabled = be->mvc->sa->eb.enabled;
    1622        3615 :         be->mvc->sa->eb.enabled = false;
    1623        3615 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1624        3615 :         be->mvc->sa->eb.enabled = enabled;
    1625        3615 :         if (s == NULL) {
    1626           0 :                 freeInstruction(q);
    1627           0 :                 goto bailout;
    1628             :         }
    1629             : 
    1630        3615 :         s->op1 = lops;
    1631        3615 :         s->op2 = rops;
    1632        3615 :         s->op3 = sub;
    1633        3615 :         s->key = lops->nrcols == 0 && rops->nrcols == 0;
    1634        3615 :         s->flag = cmp_filter;
    1635        3615 :         s->nrcols = lops->nrcols;
    1636        3615 :         s->nr = getDestVar(q);
    1637        3615 :         s->q = q;
    1638        3615 :         s->cand = sub;
    1639        3615 :         pushInstruction(mb, q);
    1640        3615 :         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      210846 : stmt_uselect(backend *be, stmt *op1, stmt *op2, comp_type cmptype, stmt *sub, int anti, int is_semantics)
    1650             : {
    1651      210846 :         MalBlkPtr mb = be->mb;
    1652      210846 :         InstrPtr q = NULL;
    1653      210846 :         int l, r;
    1654      210846 :         stmt *sel = sub;
    1655             : 
    1656      210846 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0 || (sub && sub->nr < 0))
    1657           0 :                 goto bailout;
    1658      210846 :         l = op1->nr;
    1659      210846 :         r = op2->nr;
    1660             : 
    1661      210846 :         if (op2->nrcols >= 1 && op1->nrcols == 0) { /* swap */
    1662          81 :                 stmt *v = op1;
    1663          81 :                 op1 = op2;
    1664          81 :                 op2 = v;
    1665          81 :                 int n = l;
    1666          81 :                 l = r;
    1667          81 :                 r = n;
    1668          81 :                 cmptype = swap_compare(cmptype);
    1669             :         }
    1670      210846 :         if (op2->nrcols >= 1) {
    1671       16683 :                 bit need_not = FALSE;
    1672       16683 :                 const char *mod = calcRef;
    1673       16683 :                 const char *op = "=";
    1674       16683 :                 int k;
    1675             : 
    1676       16683 :                 switch (cmptype) {
    1677             :                 case cmp_equal:
    1678             :                         op = "=";
    1679             :                         break;
    1680             :                 case cmp_notequal:
    1681       16683 :                         op = "!=";
    1682             :                         break;
    1683         866 :                 case cmp_lt:
    1684         866 :                         op = "<";
    1685         866 :                         break;
    1686         760 :                 case cmp_lte:
    1687         760 :                         op = "<=";
    1688         760 :                         break;
    1689        4806 :                 case cmp_gt:
    1690        4806 :                         op = ">";
    1691        4806 :                         break;
    1692         758 :                 case cmp_gte:
    1693         758 :                         op = ">=";
    1694         758 :                         break;
    1695           0 :                 default:
    1696           0 :                         TRC_ERROR(SQL_EXECUTION, "Unknown operator\n");
    1697             :                 }
    1698             : 
    1699       26046 :                 if ((q = multiplex2(mb, mod, convertMultiplexFcn(op), l, r, TYPE_bit)) == NULL)
    1700           0 :                         goto bailout;
    1701       16683 :                 if (sub && (op1->cand || op2->cand)) {
    1702        1300 :                         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        1272 :                         } else if (!op1->cand && op2->cand) {
    1707        1260 :                                 q = pushArgument(mb, q, sub->nr);
    1708        1260 :                                 if (op2->nrcols > 0)
    1709        1260 :                                         q = pushNilBat(mb, q);
    1710             :                         }
    1711             :                         sub = NULL;
    1712             :                 }
    1713       16683 :                 if (is_semantics)
    1714        2943 :                         q = pushBit(mb, q, TRUE);
    1715       16683 :                 k = getDestVar(q);
    1716             : 
    1717       16683 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1718       16683 :                 if (q == NULL)
    1719           0 :                         goto bailout;
    1720       16683 :                 q = pushArgument(mb, q, k);
    1721       16683 :                 if (sub)
    1722        4393 :                         q = pushArgument(mb, q, sub->nr);
    1723       16683 :                 q = pushBit(mb, q, !need_not);
    1724       16683 :                 q = pushBit(mb, q, !need_not);
    1725       16683 :                 q = pushBit(mb, q, TRUE);
    1726       16683 :                 q = pushBit(mb, q, TRUE);
    1727       16683 :                 q = pushBit(mb, q, anti);
    1728       16683 :                 k = getDestVar(q);
    1729             :         } else {
    1730      194163 :                 assert (cmptype != cmp_filter);
    1731      194163 :                 if (is_semantics) {
    1732       19626 :                         assert(cmptype == cmp_equal || cmptype == cmp_notequal);
    1733       19626 :                         if (cmptype == cmp_notequal)
    1734          71 :                                 anti = !anti;
    1735       19626 :                         q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1736       19626 :                         if (q == NULL)
    1737           0 :                                 goto bailout;
    1738       19626 :                         q = pushArgument(mb, q, l);
    1739       19626 :                         if (sub && !op1->cand) {
    1740        2151 :                                 q = pushArgument(mb, q, sub->nr);
    1741             :                         } else {
    1742          14 :                                 assert(!sub || op1->cand == sub);
    1743             :                                 sub = NULL;
    1744             :                         }
    1745       19626 :                         q = pushArgument(mb, q, r);
    1746       19626 :                         q = pushArgument(mb, q, r);
    1747       19626 :                         q = pushBit(mb, q, TRUE);
    1748       19626 :                         q = pushBit(mb, q, TRUE);
    1749       19626 :                         q = pushBit(mb, q, anti);
    1750             :                 } else {
    1751      174537 :                         q = newStmt(mb, algebraRef, thetaselectRef);
    1752      174537 :                         if (q == NULL)
    1753           0 :                                 goto bailout;
    1754      174537 :                         q = pushArgument(mb, q, l);
    1755      174537 :                         if (sub && !op1->cand) {
    1756      127054 :                                 q = pushArgument(mb, q, sub->nr);
    1757             :                         } else {
    1758         327 :                                 assert(!sub || op1->cand == sub);
    1759       47483 :                                 q = pushNilBat(mb, q);
    1760       47483 :                                 sub = NULL;
    1761             :                         }
    1762      174536 :                         q = pushArgument(mb, q, r);
    1763      174536 :                         switch (cmptype) {
    1764      136893 :                         case cmp_equal:
    1765      136893 :                                 q = pushStr(mb, q, anti?"!=":"==");
    1766      136893 :                                 break;
    1767       34754 :                         case cmp_notequal:
    1768       34754 :                                 q = pushStr(mb, q, anti?"==":"!=");
    1769       34754 :                                 break;
    1770         440 :                         case cmp_lt:
    1771         440 :                                 q = pushStr(mb, q, anti?">=":"<");
    1772         440 :                                 break;
    1773          88 :                         case cmp_lte:
    1774          88 :                                 q = pushStr(mb, q, anti?">":"<=");
    1775          88 :                                 break;
    1776        2052 :                         case cmp_gt:
    1777        2052 :                                 q = pushStr(mb, q, anti?"<=":">");
    1778        2052 :                                 break;
    1779         309 :                         case cmp_gte:
    1780         309 :                                 q = pushStr(mb, q, anti?"<":">=");
    1781         309 :                                 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      210846 :         bool enabled = be->mvc->sa->eb.enabled;
    1793      210846 :         be->mvc->sa->eb.enabled = false;
    1794      210846 :         stmt *s = stmt_create(be->mvc->sa, st_uselect);
    1795      210845 :         be->mvc->sa->eb.enabled = enabled;
    1796      210845 :         if (s == NULL) {
    1797           0 :                 freeInstruction(q);
    1798           0 :                 goto bailout;
    1799             :         }
    1800             : 
    1801      210845 :         s->op1 = op1;
    1802      210845 :         s->op2 = op2;
    1803      210845 :         s->op3 = sub;
    1804      210845 :         s->flag = cmptype;
    1805      210845 :         s->key = op1->nrcols == 0 && op2->nrcols == 0;
    1806      210845 :         s->nrcols = op1->nrcols;
    1807      210845 :         s->nr = getDestVar(q);
    1808      210845 :         s->q = q;
    1809      210845 :         s->cand = sub;
    1810      210845 :         pushInstruction(mb, q);
    1811      210845 :         if (!sub && sel) /* project back the old ids */
    1812        1641 :                 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        5115 : 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        5115 :         MalBlkPtr mb = be->mb;
    1873        5115 :         InstrPtr p, q;
    1874        5115 :         int l;
    1875        5115 :         const char *cmd = (type == st_uselect2) ? selectRef : rangejoinRef;
    1876        5115 :         stmt *sub = (Sub)?*Sub:NULL;
    1877             : 
    1878        5115 :         if (op1 == NULL || op2 == NULL || op3 == NULL || op1->nr < 0 || (sub && sub->nr < 0))
    1879           0 :                 goto bailout;
    1880        5115 :         l = op1->nr;
    1881        8485 :         if ((symmetric || op2->nrcols > 0 || op3->nrcols > 0 || !reduce) && (type == st_uselect2)) {
    1882        3605 :                 int k;
    1883        3605 :                 int nrcols = (op1->nrcols || op2->nrcols || op3->nrcols);
    1884             : 
    1885        3605 :                 if (op2->nr < 0 || op3->nr < 0)
    1886           0 :                         goto bailout;
    1887             : 
    1888        3605 :                 if (nrcols)
    1889        3567 :                         p = newStmtArgs(mb, batcalcRef, betweenRef, 12);
    1890             :                 else
    1891          38 :                         p = newStmtArgs(mb, calcRef, betweenRef, 9);
    1892        3605 :                 if (p == NULL)
    1893           0 :                         goto bailout;
    1894        3605 :                 p = pushArgument(mb, p, l);
    1895        3605 :                 p = pushArgument(mb, p, op2->nr);
    1896        3605 :                 p = pushArgument(mb, p, op3->nr);
    1897             : 
    1898             :                 /* cands */
    1899        3605 :                 if ((sub && !reduce) || op1->cand || op2->cand || op3->cand) { /* some already handled the previous selection */
    1900        1494 :                         if (op1->cand && op1->nrcols)
    1901        1214 :                                 p = pushNilBat(mb, p);
    1902         280 :                         else if (op1->nrcols)
    1903         280 :                                 p = pushArgument(mb, p, sub->nr);
    1904        1494 :                         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        1494 :                         if (op3->nrcols) {
    1911        1385 :                                 if (op3->cand)
    1912        1297 :                                         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        3605 :                 p = pushBit(mb, p, (symmetric)?TRUE:FALSE); /* symmetric */
    1920        3605 :                 p = pushBit(mb, p, (cmp & 1) != 0);     /* lo inclusive */
    1921        3605 :                 p = pushBit(mb, p, (cmp & 2) != 0);     /* hi inclusive */
    1922        3605 :                 p = pushBit(mb, p, FALSE);                  /* nils_false */
    1923        3605 :                 p = pushBit(mb, p, (anti)?TRUE:FALSE);      /* anti */
    1924        3605 :                 pushInstruction(mb, p);
    1925        3605 :                 if (!reduce)
    1926             :                         return p;
    1927        3370 :                 k = getDestVar(p);
    1928             : 
    1929        3370 :                 q = newStmtArgs(mb, algebraRef, selectRef, 9);
    1930        3370 :                 if (q == NULL)
    1931           0 :                         goto bailout;
    1932        3370 :                 q = pushArgument(mb, q, k);
    1933        3370 :                 if (sub)
    1934         898 :                         q = pushArgument(mb, q, sub->nr);
    1935        3370 :                 q = pushBit(mb, q, TRUE);
    1936        3370 :                 q = pushBit(mb, q, TRUE);
    1937        3370 :                 q = pushBit(mb, q, TRUE);
    1938        3370 :                 q = pushBit(mb, q, TRUE);
    1939        3370 :                 q = pushBit(mb, q, FALSE);
    1940        3370 :                 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        1510 :                 int r1 = op2->nr;
    1968        1510 :                 int r2 = op3->nr;
    1969        1510 :                 int rs = 0;
    1970        1510 :                 q = newStmtArgs(mb, algebraRef, cmd, 12);
    1971        1510 :                 if (q == NULL)
    1972           0 :                         goto bailout;
    1973        1510 :                 if (type == st_join2)
    1974          59 :                         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    1975        1510 :                 q = pushArgument(mb, q, l);
    1976        1510 :                 if (sub) {
    1977        1188 :                         int cand = op1->cand || op2->cand || op3->cand;
    1978        1176 :                         if (cand) {
    1979          12 :                                 assert(!op1->nrcols || op1->cand);
    1980          12 :                                 assert(!op2->nrcols || op2->cand);
    1981          12 :                                 assert(!op3->nrcols || op3->cand);
    1982             :                                 sub = NULL;
    1983             :                         }
    1984             :                 }
    1985        1176 :                 if (sub) /* only for uselect2 */
    1986        1176 :                         q = pushArgument(mb, q, sub->nr);
    1987        1510 :                 if (rs) {
    1988             :                         q = pushArgument(mb, q, rs);
    1989             :                 } else {
    1990        1510 :                         q = pushArgument(mb, q, r1);
    1991        1510 :                         q = pushArgument(mb, q, r2);
    1992             :                 }
    1993        1510 :                 if (type == st_join2) {
    1994          59 :                         q = pushNilBat(mb, q);
    1995          59 :                         q = pushNilBat(mb, q);
    1996             :                 }
    1997             : 
    1998        1510 :                 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         230 :                 case 1:
    2004         230 :                         q = pushBit(mb, q, TRUE);
    2005         230 :                         q = pushBit(mb, q, FALSE);
    2006         230 :                         break;
    2007          11 :                 case 2:
    2008          11 :                         q = pushBit(mb, q, FALSE);
    2009          11 :                         q = pushBit(mb, q, TRUE);
    2010          11 :                         break;
    2011        1216 :                 case 3:
    2012        1216 :                         q = pushBit(mb, q, TRUE);
    2013        1216 :                         q = pushBit(mb, q, TRUE);
    2014        1216 :                         break;
    2015             :                 }
    2016        1510 :                 q = pushBit(mb, q, anti);
    2017        1510 :                 if (type == st_uselect2) {
    2018        1451 :                         q = pushBit(mb, q, TRUE); /* all nil's are != */
    2019             :                 } else {
    2020          59 :                         q = pushBit(mb, q, (symmetric)?TRUE:FALSE);
    2021             :                 }
    2022        1510 :                 if (type == st_join2)
    2023          59 :                         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2024        1510 :                 pushInstruction(mb, q);
    2025        1510 :                 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        4880 :         if (Sub)
    2038        4821 :                 *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         392 : stmt_markselect(backend *be, stmt *g, stmt *m, stmt *p, bool any)
    2081             : {
    2082         392 :         MalBlkPtr mb = be->mb;
    2083         392 :         InstrPtr q;
    2084             : 
    2085         392 :         q = newStmtArgs(mb, algebraRef, markselectRef, 6);
    2086         392 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2087         392 :         q = pushArgument(mb, q, g->nr); /* left ids */
    2088         392 :         q = pushArgument(mb, q, m->nr); /* mark info mask */
    2089         392 :         q = pushArgument(mb, q, p->nr);      /* predicate */
    2090         392 :         q = pushBit(mb, q, (any)?TRUE:FALSE);
    2091         392 :         pushInstruction(mb, q);
    2092             : 
    2093         392 :         if (!q)
    2094             :                 return NULL;
    2095         392 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2096         392 :         if (s == NULL) {
    2097           0 :                 freeInstruction(q);
    2098           0 :                 return NULL;
    2099             :         }
    2100             : 
    2101         392 :         s->op1 = g;
    2102         392 :         s->op2 = m;
    2103         392 :         s->flag = MARKJOIN;
    2104         392 :         s->key = 0;
    2105         392 :         s->nrcols = g->nrcols;
    2106         392 :         s->nr = getDestVar(q);
    2107         392 :         s->q = q;
    2108         392 :         return s;
    2109             : }
    2110             : 
    2111             : stmt *
    2112        2440 : stmt_markjoin(backend *be, stmt *l, stmt *r, bool final)
    2113             : {
    2114        2440 :         MalBlkPtr mb = be->mb;
    2115        2440 :         InstrPtr q;
    2116             : 
    2117        2440 :         q = newStmtArgs(mb, algebraRef, markjoinRef, 8);
    2118        2440 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2119        2440 :         if (!final)
    2120           5 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2121        2440 :         q = pushArgument(mb, q, l->nr); /* left ids */
    2122        2440 :         q = pushArgument(mb, q, r->nr); /* mark info mask */
    2123        2440 :         q = pushNilBat(mb, q);
    2124        2440 :         q = pushNilBat(mb, q);
    2125        2440 :         q = pushNil(mb, q, TYPE_lng);
    2126        2440 :         pushInstruction(mb, q);
    2127             : 
    2128        2440 :         if (!q)
    2129             :                 return NULL;
    2130        2440 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2131        2440 :         if (s == NULL) {
    2132           0 :                 freeInstruction(q);
    2133           0 :                 return NULL;
    2134             :         }
    2135             : 
    2136        2440 :         s->op1 = l;
    2137        2440 :         s->op2 = r;
    2138        2440 :         s->flag = MARKJOIN;
    2139        2440 :         s->key = 0;
    2140        2440 :         s->nrcols = l->nrcols;
    2141        2440 :         s->nr = getDestVar(q);
    2142        2440 :         s->q = q;
    2143        2440 :         return s;
    2144             : }
    2145             : 
    2146             : stmt *
    2147        5056 : stmt_uselect2(backend *be, stmt *op1, stmt *op2, stmt *op3, int cmp, stmt *sub, int anti, int symmetric, int reduce)
    2148             : {
    2149        5056 :         stmt *sel = sub;
    2150        5056 :         InstrPtr q = select2_join2(be, op1, op2, op3, cmp, &sub, anti, symmetric, 0, st_uselect2, reduce);
    2151             : 
    2152        5056 :         if (q == NULL)
    2153             :                 return NULL;
    2154             : 
    2155        5056 :         stmt *s = stmt_create(be->mvc->sa, st_uselect2);
    2156        5056 :         if (s == NULL) {
    2157             :                 return NULL;
    2158             :         }
    2159             : 
    2160        5056 :         s->op1 = op1;
    2161        5056 :         s->op2 = op2;
    2162        5056 :         s->op3 = op3;
    2163        5056 :         s->op4.stval = sub;
    2164        5056 :         s->flag = cmp;
    2165        5056 :         s->nrcols = op1->nrcols;
    2166        5056 :         s->key = op1->nrcols == 0 && op2->nrcols == 0 && op3->nrcols == 0;
    2167        5056 :         s->nr = getDestVar(q);
    2168        5056 :         s->q = q;
    2169        5056 :         s->cand = sub;
    2170        5056 :         s->reduce = reduce;
    2171        5056 :         if (!sub && sel) /* project back the old ids */
    2172        1382 :                 return stmt_project(be, s, sel);
    2173             :         return s;
    2174             : }
    2175             : 
    2176             : stmt *
    2177       52209 : stmt_tunion(backend *be, stmt *op1, stmt *op2)
    2178             : {
    2179       52209 :         InstrPtr q = NULL;
    2180       52209 :         MalBlkPtr mb = be->mb;
    2181             : 
    2182       52209 :         q = dump_2(mb, batRef, mergecandRef, op1, op2);
    2183       52209 :         if (q) {
    2184       52209 :                 stmt *s = stmt_create(be->mvc->sa, st_tunion);
    2185       52209 :                 if (s == NULL) {
    2186             :                         return NULL;
    2187             :                 }
    2188             : 
    2189       52209 :                 s->op1 = op1;
    2190       52209 :                 s->op2 = op2;
    2191       52209 :                 s->nrcols = op1->nrcols;
    2192       52209 :                 s->key = op1->key;
    2193       52209 :                 s->aggr = op1->aggr;
    2194       52209 :                 s->nr = getDestVar(q);
    2195       52209 :                 s->q = q;
    2196       52209 :                 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       42617 : stmt_tdiff(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2206             : {
    2207       42617 :         InstrPtr q = NULL;
    2208       42617 :         MalBlkPtr mb = be->mb;
    2209             : 
    2210       42617 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2211           0 :                 goto bailout;
    2212       42617 :         q = newStmt(mb, algebraRef, differenceRef);
    2213       42617 :         if (q == NULL)
    2214           0 :                 goto bailout;
    2215       42617 :         q = pushArgument(mb, q, op1->nr); /* left */
    2216       42617 :         q = pushArgument(mb, q, op2->nr); /* right */
    2217       42617 :         if (lcand)
    2218           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2219             :         else
    2220       42617 :                 q = pushNilBat(mb, q); /* left candidate */
    2221       42617 :         q = pushNilBat(mb, q); /* right candidate */
    2222       42617 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2223       42617 :         q = pushBit(mb, q, FALSE);    /* do not clear nils */
    2224       42617 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2225             : 
    2226       42617 :         bool enabled = be->mvc->sa->eb.enabled;
    2227       42617 :         be->mvc->sa->eb.enabled = false;
    2228       42617 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2229       42617 :         be->mvc->sa->eb.enabled = enabled;
    2230       42617 :         if (s == NULL) {
    2231           0 :                 freeInstruction(q);
    2232           0 :                 goto bailout;
    2233             :         }
    2234             : 
    2235       42617 :         s->op1 = op1;
    2236       42617 :         s->op2 = op2;
    2237       42617 :         s->nrcols = op1->nrcols;
    2238       42617 :         s->key = op1->key;
    2239       42617 :         s->aggr = op1->aggr;
    2240       42617 :         s->nr = getDestVar(q);
    2241       42617 :         s->q = q;
    2242       42617 :         pushInstruction(mb, q);
    2243       42617 :         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        1667 : stmt_tdiff2(backend *be, stmt *op1, stmt *op2, stmt *lcand)
    2253             : {
    2254        1667 :         InstrPtr q = NULL;
    2255        1667 :         MalBlkPtr mb = be->mb;
    2256             : 
    2257        1667 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2258           0 :                 goto bailout;
    2259        1667 :         q = newStmt(mb, algebraRef, differenceRef);
    2260        1667 :         if (q == NULL)
    2261           0 :                 goto bailout;
    2262        1667 :         q = pushArgument(mb, q, op1->nr); /* left */
    2263        1667 :         q = pushArgument(mb, q, op2->nr); /* right */
    2264        1667 :         if (lcand)
    2265           0 :                 q = pushArgument(mb, q, lcand->nr); /* left */
    2266             :         else
    2267        1667 :                 q = pushNilBat(mb, q); /* left candidate */
    2268        1667 :         q = pushNilBat(mb, q); /* right candidate */
    2269        1667 :         q = pushBit(mb, q, FALSE);     /* nil matches */
    2270        1667 :         q = pushBit(mb, q, TRUE);     /* not in */
    2271        1667 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2272             : 
    2273        1667 :         bool enabled = be->mvc->sa->eb.enabled;
    2274        1667 :         be->mvc->sa->eb.enabled = false;
    2275        1667 :         stmt *s = stmt_create(be->mvc->sa, st_tdiff);
    2276        1667 :         be->mvc->sa->eb.enabled = enabled;
    2277        1667 :         if (s == NULL) {
    2278           0 :                 freeInstruction(q);
    2279           0 :                 goto bailout;
    2280             :         }
    2281             : 
    2282        1667 :         s->op1 = op1;
    2283        1667 :         s->op2 = op2;
    2284        1667 :         s->nrcols = op1->nrcols;
    2285        1667 :         s->key = op1->key;
    2286        1667 :         s->aggr = op1->aggr;
    2287        1667 :         s->nr = getDestVar(q);
    2288        1667 :         s->q = q;
    2289        1667 :         pushInstruction(mb, q);
    2290        1667 :         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        1504 : stmt_tinter(backend *be, stmt *op1, stmt *op2, bool single)
    2300             : {
    2301        1504 :         InstrPtr q = NULL;
    2302        1504 :         MalBlkPtr mb = be->mb;
    2303             : 
    2304        1504 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2305           0 :                 goto bailout;
    2306        1504 :         q = newStmt(mb, algebraRef, intersectRef);
    2307        1504 :         if (q == NULL)
    2308           0 :                 goto bailout;
    2309        1504 :         q = pushArgument(mb, q, op1->nr); /* left */
    2310        1504 :         q = pushArgument(mb, q, op2->nr); /* right */
    2311        1504 :         q = pushNilBat(mb, q); /* left candidate */
    2312        1504 :         q = pushNilBat(mb, q); /* right candidate */
    2313        1504 :         q = pushBit(mb, q, FALSE);    /* nil matches */
    2314        1504 :         q = pushBit(mb, q, single?TRUE:FALSE);    /* max_one */
    2315        1504 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2316             : 
    2317        1504 :         bool enabled = be->mvc->sa->eb.enabled;
    2318        1504 :         be->mvc->sa->eb.enabled = false;
    2319        1504 :         stmt *s = stmt_create(be->mvc->sa, st_tinter);
    2320        1504 :         be->mvc->sa->eb.enabled = enabled;
    2321        1504 :         if (s == NULL) {
    2322           0 :                 freeInstruction(q);
    2323           0 :                 goto bailout;
    2324             :         }
    2325             : 
    2326        1504 :         s->op1 = op1;
    2327        1504 :         s->op2 = op2;
    2328        1504 :         s->nrcols = op1->nrcols;
    2329        1504 :         s->key = op1->key;
    2330        1504 :         s->aggr = op1->aggr;
    2331        1504 :         s->nr = getDestVar(q);
    2332        1504 :         s->q = q;
    2333        1504 :         pushInstruction(mb, q);
    2334        1504 :         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       90229 : 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       90229 :         MalBlkPtr mb = be->mb;
    2346       90229 :         InstrPtr q = NULL;
    2347       90229 :         const char *sjt = inner?joinRef:outerjoinRef;
    2348             : 
    2349       90229 :         (void)anti;
    2350       90229 :         (void)inner;
    2351             : 
    2352       90229 :         if (need_left) {
    2353         653 :                 cmptype = cmp_equal;
    2354         653 :                 sjt = leftjoinRef;
    2355             :         }
    2356       90229 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2357           0 :                 goto bailout;
    2358             : 
    2359       90229 :         assert (!single || cmptype == cmp_all);
    2360             : 
    2361       90229 :         switch (cmptype) {
    2362       72808 :         case cmp_equal:
    2363       72808 :                 q = newStmtArgs(mb, algebraRef, sjt, 9);
    2364       72808 :                 if (q == NULL)
    2365           0 :                         goto bailout;
    2366       72808 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2367       72808 :                 q = pushArgument(mb, q, op1->nr);
    2368       72808 :                 q = pushArgument(mb, q, op2->nr);
    2369       72808 :                 if (!lcand)
    2370       71838 :                         q = pushNilBat(mb, q);
    2371             :                 else
    2372         970 :                         q = pushArgument(mb, q, lcand->nr);
    2373       72808 :                 if (!rcand)
    2374       72808 :                         q = pushNilBat(mb, q);
    2375             :                 else
    2376           0 :                         q = pushArgument(mb, q, rcand->nr);
    2377       72808 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2378       72808 :                 if (!inner)
    2379          59 :                         q = pushBit(mb, q, FALSE); /* not match_one */
    2380       72808 :                 q = pushNil(mb, q, TYPE_lng);
    2381       72808 :                 pushInstruction(mb, q);
    2382       72808 :                 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        2584 :         case cmp_lt:
    2409             :         case cmp_lte:
    2410             :         case cmp_gt:
    2411             :         case cmp_gte:
    2412        2584 :                 q = newStmtArgs(mb, algebraRef, thetajoinRef, 9);
    2413        2584 :                 if (q == NULL)
    2414           0 :                         goto bailout;
    2415        2584 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2416        2584 :                 q = pushArgument(mb, q, op1->nr);
    2417        2584 :                 q = pushArgument(mb, q, op2->nr);
    2418        2584 :                 if (!lcand)
    2419        2584 :                         q = pushNilBat(mb, q);
    2420             :                 else
    2421           0 :                         q = pushArgument(mb, q, lcand->nr);
    2422        2584 :                 if (!rcand)
    2423        2584 :                         q = pushNilBat(mb, q);
    2424             :                 else
    2425           0 :                         q = pushArgument(mb, q, rcand->nr);
    2426        2584 :                 if (cmptype == cmp_lt)
    2427        2067 :                         q = pushInt(mb, q, JOIN_LT);
    2428         517 :                 else if (cmptype == cmp_lte)
    2429           8 :                         q = pushInt(mb, q, JOIN_LE);
    2430         509 :                 else if (cmptype == cmp_gt)
    2431         504 :                         q = pushInt(mb, q, JOIN_GT);
    2432           5 :                 else if (cmptype == cmp_gte)
    2433           5 :                         q = pushInt(mb, q, JOIN_GE);
    2434        2584 :                 q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2435        2584 :                 q = pushNil(mb, q, TYPE_lng);
    2436        2584 :                 pushInstruction(mb, q);
    2437        2584 :                 break;
    2438       11952 :         case cmp_all:   /* aka cross table */
    2439       11952 :                 q = newStmt(mb, algebraRef, inner?crossRef:outercrossRef);
    2440       11952 :                 if (q == NULL)
    2441           0 :                         goto bailout;
    2442       11952 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2443       11952 :                 q = pushArgument(mb, q, op1->nr);
    2444       11952 :                 q = pushArgument(mb, q, op2->nr);
    2445       11952 :                 if (!inner) {
    2446         424 :                         q = pushNilBat(mb, q);
    2447         424 :                         q = pushNilBat(mb, q);
    2448             :                 }
    2449       11952 :                 q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2450       11952 :                 assert(!lcand && !rcand);
    2451       11952 :                 pushInstruction(mb, q);
    2452       11952 :                 break;
    2453        2852 :         case cmp_joined:
    2454        2852 :                 q = op1->q;
    2455        2852 :                 if (q == NULL)
    2456           0 :                         goto bailout;
    2457             :                 break;
    2458           0 :         default:
    2459           0 :                 TRC_ERROR(SQL_EXECUTION, "Impossible action\n");
    2460             :         }
    2461             : 
    2462       90229 :         stmt *s = stmt_create(be->mvc->sa, st_join);
    2463       90229 :         if (s == NULL) {
    2464           0 :                 goto bailout;
    2465             :         }
    2466             : 
    2467       90229 :         s->op1 = op1;
    2468       90229 :         s->op2 = op2;
    2469       90229 :         s->flag = cmptype;
    2470       90229 :         s->key = 0;
    2471       90229 :         s->nrcols = 2;
    2472       90229 :         s->nr = getDestVar(q);
    2473       90229 :         s->q = q;
    2474       90229 :         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       87182 : stmt_join(backend *be, stmt *l, stmt *r, int anti, comp_type cmptype, int need_left, int is_semantics, bool single)
    2484             : {
    2485       87182 :         return stmt_join_cand(be, l, r, NULL, NULL, anti, cmptype, need_left, is_semantics, single, true);
    2486             : }
    2487             : 
    2488             : stmt *
    2489        1344 : stmt_semijoin(backend *be, stmt *op1, stmt *op2, stmt *lcand, stmt *rcand, int is_semantics, bool single)
    2490             : {
    2491        1344 :         MalBlkPtr mb = be->mb;
    2492        1344 :         InstrPtr q = NULL;
    2493             : 
    2494        1344 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2495           0 :                 goto bailout;
    2496             : 
    2497        1344 :         if (single) {
    2498         279 :                 q = newStmtArgs(mb, algebraRef, semijoinRef, 9);
    2499         279 :                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2500             :         } else
    2501        1065 :                 q = newStmt(mb, algebraRef, intersectRef);
    2502        1344 :         if (q == NULL)
    2503           0 :                 goto bailout;
    2504        1344 :         q = pushArgument(mb, q, op1->nr);
    2505        1344 :         q = pushArgument(mb, q, op2->nr);
    2506        1344 :         if (lcand)
    2507        1062 :                 q = pushArgument(mb, q, lcand->nr);
    2508             :         else
    2509         282 :                 q = pushNilBat(mb, q);
    2510        1344 :         if (rcand)
    2511           0 :                 q = pushArgument(mb, q, rcand->nr);
    2512             :         else
    2513        1344 :                 q = pushNilBat(mb, q);
    2514        1344 :         q = pushBit(mb, q, is_semantics?TRUE:FALSE);
    2515        1344 :         q = pushBit(mb, q, single?TRUE:FALSE); /* max_one */
    2516        1344 :         q = pushNil(mb, q, TYPE_lng);
    2517             : 
    2518        1344 :         bool enabled = be->mvc->sa->eb.enabled;
    2519        1344 :         be->mvc->sa->eb.enabled = false;
    2520        1344 :         stmt *s = stmt_create(be->mvc->sa, st_semijoin);
    2521        1344 :         be->mvc->sa->eb.enabled = enabled;
    2522        1344 :         if (s == NULL) {
    2523           0 :                 freeInstruction(q);
    2524           0 :                 goto bailout;
    2525             :         }
    2526             : 
    2527        1344 :         s->op1 = op1;
    2528        1344 :         s->op2 = op2;
    2529        1344 :         s->flag = cmp_equal;
    2530        1344 :         s->key = 0;
    2531        1344 :         s->nrcols = 1;
    2532        1344 :         if (single)
    2533         279 :                 s->nrcols = 2;
    2534        1344 :         s->nr = getDestVar(q);
    2535        1344 :         s->q = q;
    2536        1344 :         pushInstruction(mb, q);
    2537        1344 :         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     3412453 : stmt_project_join(backend *be, stmt *op1, stmt *op2, bool delta)
    2547             : {
    2548     3412453 :         MalBlkPtr mb = be->mb;
    2549     3412453 :         InstrPtr q = NULL;
    2550             : 
    2551     3412453 :         if (op1 == NULL || op2 == NULL || op1->nr < 0 || op2->nr < 0)
    2552             :                 return NULL;
    2553             :         /* delta bat */
    2554     3412453 :         if (delta) {
    2555      458267 :                 int uval = getArg(op2->q, 1);
    2556             : 
    2557      458267 :                 q = newStmt(mb, sqlRef, deltaRef);
    2558      458276 :                 q = pushArgument(mb, q, op1->nr);
    2559      458278 :                 q = pushArgument(mb, q, op2->nr);
    2560      458278 :                 q = pushArgument(mb, q, uval);
    2561             :         } else {
    2562             :                 /* projections, ie left is void headed */
    2563     2954186 :                 q = newStmt(mb, algebraRef, projectionRef);
    2564     2954187 :                 q = pushArgument(mb, q, op1->nr);
    2565     2954190 :                 q = pushArgument(mb, q, op2->nr);
    2566             :         }
    2567     3412467 :         pushInstruction(mb, q);
    2568     3412467 :         return q;
    2569             : }
    2570             : 
    2571             : stmt *
    2572     2963401 : stmt_project(backend *be, stmt *op1, stmt *op2)
    2573             : {
    2574     2963401 :         if (op1 == NULL || op2 == NULL)
    2575             :                 return NULL;
    2576     2963401 :         if (!op2->nrcols)
    2577        9217 :                 return stmt_const(be, op1, op2);
    2578     2954184 :         InstrPtr q = stmt_project_join(be, op1, op2, false);
    2579     2954189 :         if (q) {
    2580     2954189 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2581     2954177 :                 if (s == NULL) {
    2582             :                         return NULL;
    2583             :                 }
    2584             : 
    2585     2954177 :                 s->op1 = op1;
    2586     2954177 :                 s->op2 = op2;
    2587     2954177 :                 s->flag = cmp_project;
    2588     2954177 :                 s->key = 0;
    2589     2954177 :                 s->nrcols = MAX(op1->nrcols,op2->nrcols);
    2590     2954177 :                 s->nr = getDestVar(q);
    2591     2954177 :                 s->q = q;
    2592     2954177 :                 s->tname = op2->tname;
    2593     2954177 :                 s->cname = op2->cname;
    2594     2954177 :                 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      458266 : stmt_project_delta(backend *be, stmt *col, stmt *upd)
    2603             : {
    2604      458266 :         InstrPtr q = stmt_project_join(be, col, upd, true);
    2605      458278 :         if (q) {
    2606      458278 :                 stmt *s = stmt_create(be->mvc->sa, st_join);
    2607      458278 :                 if (s == NULL) {
    2608             :                         return NULL;
    2609             :                 }
    2610             : 
    2611      458278 :                 s->op1 = col;
    2612      458278 :                 s->op2 = upd;
    2613      458278 :                 s->flag = cmp_project;
    2614      458278 :                 s->key = 0;
    2615      458278 :                 s->nrcols = 2;
    2616      458278 :                 s->nr = getDestVar(q);
    2617      458278 :                 s->q = q;
    2618      458278 :                 s->tname = col->tname;
    2619      458278 :                 s->cname = col->cname;
    2620      458278 :                 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          59 : stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int symmetric, int swapped)
    2755             : {
    2756          59 :         InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, swapped, st_join2, 1/*reduce semantics*/);
    2757          59 :         if (q == NULL)
    2758             :                 return NULL;
    2759             : 
    2760          59 :         stmt *s = stmt_create(be->mvc->sa, st_join2);
    2761          59 :         if (s == NULL) {
    2762             :                 return NULL;
    2763             :         }
    2764             : 
    2765          59 :         s->op1 = l;
    2766          59 :         s->op2 = ra;
    2767          59 :         s->op3 = rb;
    2768          59 :         s->flag = cmp;
    2769          59 :         s->nrcols = 2;
    2770          59 :         s->nr = getDestVar(q);
    2771          59 :         s->q = q;
    2772          59 :         s->reduce = 1;
    2773          59 :         return s;
    2774             : }
    2775             : 
    2776             : stmt *
    2777          46 : stmt_genjoin(backend *be, stmt *l, stmt *r, sql_subfunc *op, int anti, int swapped)
    2778             : {
    2779          46 :         MalBlkPtr mb = be->mb;
    2780          46 :         InstrPtr q = NULL;
    2781          46 :         const char *mod, *fimp;
    2782          46 :         node *n;
    2783             : 
    2784          46 :         if (l == NULL || r == NULL)
    2785           0 :                 goto bailout;
    2786          46 :         if (backend_create_subfunc(be, op, NULL) < 0)
    2787           0 :                 goto bailout;
    2788          46 :         mod = sql_func_mod(op->func);
    2789          46 :         fimp = backend_function_imp(be, op->func);
    2790          46 :         fimp = sa_strconcat(be->mvc->sa, fimp, "join");
    2791             : 
    2792             :         /* filter qualifying tuples, return oids of h and tail */
    2793          46 :         q = newStmtArgs(mb, mod, fimp, list_length(l->op4.lval) + list_length(r->op4.lval) + 7);
    2794          46 :         if (q == NULL)
    2795           0 :                 goto bailout;
    2796          46 :         q = pushReturn(mb, q, newTmpVariable(mb, TYPE_any));
    2797          92 :         for (n = l->op4.lval->h; n; n = n->next) {
    2798          46 :                 stmt *op = n->data;
    2799             : 
    2800          46 :                 q = pushArgument(mb, q, op->nr);
    2801             :         }
    2802             : 
    2803         152 :         for (n = r->op4.lval->h; n; n = n->next) {
    2804         106 :                 stmt *op = n->data;
    2805             : 
    2806         106 :                 q = pushArgument(mb, q, op->nr);
    2807             :         }
    2808          46 :         q = pushNilBat(mb, q); /* candidate lists */
    2809          46 :         q = pushNilBat(mb, q); /* candidate lists */
    2810          46 :         q = pushBit(mb, q, TRUE);     /* nil_matches */
    2811          46 :         q = pushNil(mb, q, TYPE_lng); /* estimate */
    2812          46 :         q = pushBit(mb, q, anti?TRUE:FALSE); /* 'not' matching */
    2813          46 :         pushInstruction(mb, q);
    2814             : 
    2815          46 :         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          46 :         stmt *s = stmt_create(be->mvc->sa, st_joinN);
    2828          46 :         if (s == NULL) {
    2829           0 :                 goto bailout;
    2830             :         }
    2831             : 
    2832          46 :         s->op1 = l;
    2833          46 :         s->op2 = r;
    2834          46 :         s->op4.funcval = op;
    2835          46 :         s->nrcols = 2;
    2836          46 :         if (swapped)
    2837           6 :                 s->flag |= SWAPPED;
    2838          46 :         s->nr = getDestVar(q);
    2839          46 :         s->q = q;
    2840          46 :         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       22506 : stmt_rs_column(backend *be, stmt *rs, int i, sql_subtype *tpe)
    2850             : {
    2851       22506 :         InstrPtr q = NULL;
    2852             : 
    2853       22506 :         if (rs == NULL || rs->nr < 0)
    2854             :                 return NULL;
    2855       22506 :         q = rs->q;
    2856       22506 :         if (q) {
    2857       22290 :                 stmt *s = stmt_create(be->mvc->sa, st_rs_column);
    2858       22290 :                 if (s == NULL) {
    2859             :                         return NULL;
    2860             :                 }
    2861             : 
    2862       22290 :                 s->op1 = rs;
    2863       22290 :                 s->op4.typeval = *tpe;
    2864       22290 :                 s->flag = i;
    2865       22290 :                 s->nrcols = 1;
    2866       22290 :                 s->key = 0;
    2867       22290 :                 s->q = q;
    2868       22290 :                 s->nr = getArg(q, s->flag);
    2869       22290 :                 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        3164 : stmt_trans(backend *be, int type, stmt *chain, stmt *name)
    3050             : {
    3051        3164 :         MalBlkPtr mb = be->mb;
    3052        3164 :         InstrPtr q = NULL;
    3053             : 
    3054        3164 :         if (chain == NULL || chain->nr < 0)
    3055           0 :                 goto bailout;
    3056             : 
    3057        3164 :         switch(type){
    3058          13 :         case ddl_release:
    3059          13 :                 q = newStmt(mb, sqlRef, transaction_releaseRef);
    3060          13 :                 break;
    3061         567 :         case ddl_commit:
    3062         567 :                 q = newStmt(mb, sqlRef, transaction_commitRef);
    3063         567 :                 break;
    3064        1079 :         case ddl_rollback:
    3065        1079 :                 q = newStmt(mb, sqlRef, transaction_rollbackRef);
    3066        1079 :                 break;
    3067        1505 :         case ddl_trans:
    3068        1505 :                 q = newStmt(mb, sqlRef, transaction_beginRef);
    3069        1505 :                 break;
    3070           0 :         default:
    3071           0 :                 TRC_ERROR(SQL_EXECUTION, "Unknown transaction type\n");
    3072           0 :                 goto bailout;
    3073             :         }
    3074        3164 :         if (q == NULL)
    3075           0 :                 goto bailout;
    3076        3164 :         q = pushArgument(mb, q, chain->nr);
    3077        3164 :         if (name)
    3078          79 :                 q = pushArgument(mb, q, name->nr);
    3079             :         else
    3080        3085 :                 q = pushNil(mb, q, TYPE_str);
    3081             : 
    3082        3164 :         bool enabled = be->mvc->sa->eb.enabled;
    3083        3164 :         be->mvc->sa->eb.enabled = false;
    3084        3164 :         stmt *s = stmt_create(be->mvc->sa, st_trans);
    3085        3164 :         be->mvc->sa->eb.enabled = enabled;
    3086        3164 :         if(!s) {
    3087           0 :                 freeInstruction(q);
    3088           0 :                 goto bailout;
    3089             :         }
    3090        3164 :         s->op1 = chain;
    3091        3164 :         s->op2 = name;
    3092        3164 :         s->flag = type;
    3093        3164 :         s->q = q;
    3094        3164 :         s->nr = getDestVar(q);
    3095        3164 :         pushInstruction(mb, q);
    3096        3164 :         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      279508 : stmt_catalog(backend *be, int type, stmt *args)
    3106             : {
    3107      279508 :         MalBlkPtr mb = be->mb;
    3108      279508 :         InstrPtr q = NULL;
    3109      279508 :         node *n;
    3110             : 
    3111      279508 :         if (args == NULL || args->nr < 0)
    3112           0 :                 goto bailout;
    3113             : 
    3114             :         /* cast them into properly named operations */
    3115      279508 :         const char *ref;
    3116      279508 :         switch(type){
    3117         312 :         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        1092 :         case ddl_create_schema:                 ref = create_schemaRef;         break;
    3121         187 :         case ddl_drop_schema:                   ref = drop_schemaRef;           break;
    3122        9805 :         case ddl_create_table:                  ref = create_tableRef;          break;
    3123       22618 :         case ddl_create_view:                   ref = create_viewRef;           break;
    3124        3612 :         case ddl_drop_table:                    ref = drop_tableRef;            break;
    3125         384 :         case ddl_drop_view:                             ref = drop_viewRef;                     break;
    3126         146 :         case ddl_drop_constraint:               ref = drop_constraintRef;       break;
    3127        1354 :         case ddl_alter_table:                   ref = alter_tableRef;           break;
    3128         910 :         case ddl_create_type:                   ref = create_typeRef;           break;
    3129           4 :         case ddl_drop_type:                             ref = drop_typeRef;                     break;
    3130          38 :         case ddl_grant_roles:                   ref = grant_rolesRef;           break;
    3131          10 :         case ddl_revoke_roles:                  ref = revoke_rolesRef;          break;
    3132       18196 :         case ddl_grant:                                 ref = grantRef;                         break;
    3133          15 :         case ddl_revoke:                                ref = revokeRef;                        break;
    3134       95317 :         case ddl_grant_func:                    ref = grant_functionRef;        break;
    3135           1 :         case ddl_revoke_func:                   ref = revoke_functionRef;       break;
    3136         338 :         case ddl_create_user:                   ref = create_userRef;           break;
    3137         104 :         case ddl_drop_user:                             ref = drop_userRef;                     break;
    3138          79 :         case ddl_alter_user:                    ref = alter_userRef;            break;
    3139           5 :         case ddl_rename_user:                   ref = rename_userRef;           break;
    3140          25 :         case ddl_create_role:                   ref = create_roleRef;           break;
    3141          19 :         case ddl_drop_role:                             ref = drop_roleRef;                     break;
    3142         161 :         case ddl_drop_index:                    ref = drop_indexRef;            break;
    3143         799 :         case ddl_drop_function:                 ref = drop_functionRef;         break;
    3144      120196 :         case ddl_create_function:               ref = create_functionRef;       break;
    3145         341 :         case ddl_create_trigger:                ref = create_triggerRef;        break;
    3146          81 :         case ddl_drop_trigger:                  ref = drop_triggerRef;          break;
    3147         302 :         case ddl_alter_table_add_table: ref = alter_add_tableRef;       break;
    3148         180 :         case ddl_alter_table_del_table: ref = alter_del_tableRef;       break;
    3149        2094 :         case ddl_alter_table_set_access:ref = alter_set_tableRef;       break;
    3150         215 :         case ddl_alter_table_add_range_partition: ref = alter_add_range_partitionRef; break;
    3151          60 :         case ddl_alter_table_add_list_partition: ref = alter_add_value_partitionRef; break;
    3152         363 :         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      279508 :         q = newStmtArgs(mb, sqlcatalogRef, ref, list_length(args->op4.lval) + 1);
    3161      279508 :         if (q == NULL)
    3162           0 :                 goto bailout;
    3163             :         // pass all arguments as before
    3164     1667834 :         for (n = args->op4.lval->h; n; n = n->next) {
    3165     1388326 :                 stmt *c = n->data;
    3166             : 
    3167     1388326 :                 q = pushArgument(mb, q, c->nr);
    3168             :         }
    3169             : 
    3170      279508 :         bool enabled = be->mvc->sa->eb.enabled;
    3171      279508 :         be->mvc->sa->eb.enabled = false;
    3172      279508 :         stmt *s = stmt_create(be->mvc->sa, st_catalog);
    3173      279508 :         be->mvc->sa->eb.enabled = enabled;
    3174      279508 :         if(!s) {
    3175           0 :                 freeInstruction(q);
    3176           0 :                 goto bailout;
    3177             :         }
    3178      279508 :         s->op1 = args;
    3179      279508 :         s->flag = type;
    3180      279508 :         s->q = q;
    3181      279508 :         s->nr = getDestVar(q);
    3182      279508 :         pushInstruction(mb, q);
    3183      279508 :         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     1806929 : stmt_set_nrcols(stmt *s)
    3193             : {
    3194     1806929 :         unsigned nrcols = 0;
    3195     1806929 :         int key = 1;
    3196     1806929 :         node *n;
    3197     1806929 :         list *l = s->op4.lval;
    3198             : 
    3199     1806929 :         assert(s->type == st_list);
    3200     8796759 :         for (n = l->h; n; n = n->next) {
    3201     6989830 :                 stmt *f = n->data;
    3202             : 
    3203     6989830 :                 if (!f)
    3204           0 :                         continue;
    3205     6989830 :                 if (f->nrcols > nrcols)
    3206             :                         nrcols = f->nrcols;
    3207     6989830 :                 key &= f->key;
    3208     6989830 :                 s->nr = f->nr;
    3209             :         }
    3210     1806929 :         s->nrcols = nrcols;
    3211     1806929 :         s->key = key;
    3212     1806929 : }
    3213             : 
    3214             : stmt *
    3215     1411862 : stmt_list(backend *be, list *l)
    3216             : {
    3217     1411862 :         if (l == NULL)
    3218             :                 return NULL;
    3219     1411862 :         stmt *s = stmt_create(be->mvc->sa, st_list);
    3220     1411849 :         if(!s) {
    3221             :                 return NULL;
    3222             :         }
    3223     1411849 :         s->op4.lval = l;
    3224     1411849 :         stmt_set_nrcols(s);
    3225     1411849 :         return s;
    3226             : }
    3227             : 
    3228             : static InstrPtr
    3229       62439 : dump_header(mvc *sql, MalBlkPtr mb, list *l)
    3230             : {
    3231       62439 :         node *n;
    3232             :         // gather the meta information
    3233       62439 :         int tblId, nmeId, tpeId, lenId, scaleId;
    3234       62439 :         int args;
    3235       62439 :         InstrPtr list;
    3236       62439 :         InstrPtr tblPtr, nmePtr, tpePtr, lenPtr, scalePtr;
    3237             : 
    3238       62439 :         args = list_length(l) + 1;
    3239             : 
    3240       62439 :         list = newInstructionArgs(mb,sqlRef, resultSetRef, args + 5);
    3241       62439 :         if(!list) {
    3242             :                 return NULL;
    3243             :         }
    3244       62439 :         getArg(list,0) = newTmpVariable(mb,TYPE_int);
    3245       62439 :         meta(tblPtr, tblId, TYPE_str, args);
    3246       62439 :         meta(nmePtr, nmeId, TYPE_str, args);
    3247       62438 :         meta(tpePtr, tpeId, TYPE_str, args);
    3248       62439 :         meta(lenPtr, lenId, TYPE_int, args);
    3249       62439 :         meta(scalePtr, scaleId, TYPE_int, args);
    3250       62439 :         if(tblPtr == NULL || nmePtr == NULL || tpePtr == NULL || lenPtr == NULL || scalePtr == NULL)
    3251             :                 return NULL;
    3252             : 
    3253      320137 :         for (n = l->h; n; n = n->next) {
    3254      257698 :                 stmt *c = n->data;
    3255      257698 :                 sql_subtype *t = tail_type(c);
    3256      257700 :                 const char *tname = table_name(sql->sa, c);
    3257      257700 :                 const char *sname = schema_name(sql->sa, c);
    3258      257699 :                 const char *_empty = "";
    3259      257699 :                 const char *tn = (tname) ? tname : _empty;
    3260      257699 :                 const char *sn = (sname) ? sname : _empty;
    3261      257699 :                 const char *cn = column_name(sql->sa, c);
    3262      257695 :                 const char *ntn = sql_escape_ident(sql->ta, tn);
    3263      257699 :                 const char *nsn = sql_escape_ident(sql->ta, sn);
    3264      257708 :                 size_t fqtnl;
    3265             : 
    3266      257708 :                 if (ntn && nsn && (fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1) ){
    3267      257708 :                         char *fqtn = SA_NEW_ARRAY(sql->ta, char, fqtnl);
    3268      257708 :                         if (fqtn == NULL)
    3269             :                                 return NULL;
    3270      257708 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3271      257708 :                         tblPtr = pushStr(mb, tblPtr, fqtn);
    3272      257708 :                         nmePtr = pushStr(mb, nmePtr, cn);
    3273      257702 :                         tpePtr = pushStr(mb, tpePtr, (t->type->localtype == TYPE_void ? "char" : t->type->base.name));
    3274      257706 :                         lenPtr = pushInt(mb, lenPtr, t->digits);
    3275      257705 :                         scalePtr = pushInt(mb, scalePtr, t->scale);
    3276      257698 :                         list = pushArgument(mb,list,c->nr);
    3277             :                 } else
    3278             :                         return NULL;
    3279             :         }
    3280       62439 :         sa_reset(sql->ta);
    3281       62439 :         pushInstruction(mb,list);
    3282       62439 :         return list;
    3283             : }
    3284             : 
    3285             : int
    3286      122883 : stmt_output(backend *be, stmt *lst)
    3287             : {
    3288      122883 :         MalBlkPtr mb = be->mb;
    3289      122883 :         InstrPtr q = NULL;
    3290      122883 :         list *l = lst->op4.lval;
    3291      122883 :         int cnt = list_length(l), ok = 0;
    3292      122882 :         node *n = l->h;
    3293      122882 :         stmt *first = n->data;
    3294             : 
    3295             :         /* single value result, has a fast exit */
    3296      122882 :         if (cnt == 1 && first->nrcols <= 0 ){
    3297       60444 :                 stmt *c = n->data;
    3298       60444 :                 sql_subtype *t = tail_type(c);
    3299       60447 :                 const char *tname = table_name(be->mvc->sa, c);
    3300       60447 :                 const char *sname = schema_name(be->mvc->sa, c);
    3301       60447 :                 const char *_empty = "";
    3302       60447 :                 const char *tn = (tname) ? tname : _empty;
    3303       60447 :                 const char *sn = (sname) ? sname : _empty;
    3304       60447 :                 const char *cn = column_name(be->mvc->sa, c);
    3305       60443 :                 const char *ntn = sql_escape_ident(be->mvc->ta, tn);
    3306       60443 :                 const char *nsn = sql_escape_ident(be->mvc->ta, sn);
    3307             : 
    3308       60446 :                 if (ntn && nsn) {
    3309       60446 :                         size_t fqtnl = strlen(ntn) + 1 + strlen(nsn) + 1;
    3310       60446 :                         char *fqtn = SA_NEW_ARRAY(be->mvc->ta, char, fqtnl);
    3311       60446 :                         if (fqtn == NULL)
    3312             :                                 return -1;
    3313       60446 :                         ok = 1;
    3314       60446 :                         snprintf(fqtn, fqtnl, "%s.%s", nsn, ntn);
    3315             : 
    3316       60446 :                         q = newStmt(mb, sqlRef, resultSetRef);
    3317       60448 :                         if (q == NULL)
    3318             :                                 return -1;
    3319       60448 :                         getArg(q,0) = newTmpVariable(mb,TYPE_int);
    3320       60447 :                         q = pushStr(mb, q, fqtn);
    3321       60448 :                         q = pushStr(mb, q, cn);
    3322       60447 :                         q = pushStr(mb, q, t->type->localtype == TYPE_void ? "char" : t->type->base.name);
    3323       60448 :                         q = pushInt(mb, q, t->digits);
    3324       60445 :                         q = pushInt(mb, q, t->scale);
    3325       60445 :                         q = pushInt(mb, q, t->type->eclass);
    3326       60445 :                         q = pushArgument(mb, q, c->nr);
    3327       60444 :                         pushInstruction(mb, q);
    3328             :                 }
    3329       60445 :                 sa_reset(be->mvc->ta);
    3330       60445 :                 if (!ok)
    3331             :                         return -1;
    3332             :         } else {
    3333       62438 :                 if ((q = dump_header(be->mvc, mb, l)) == NULL)
    3334             :                         return -1;
    3335             :         }
    3336             :         return 0;
    3337             : }
    3338             : 
    3339             : int
    3340      149323 : stmt_affected_rows(backend *be, int lastnr)
    3341             : {
    3342      149323 :         MalBlkPtr mb = be->mb;
    3343      149323 :         InstrPtr q = NULL;
    3344             : 
    3345      149323 :         q = newStmt(mb, sqlRef, affectedRowsRef);
    3346      149322 :         if (q == NULL)
    3347             :                 return -1;
    3348      149322 :         q = pushArgument(mb, q, be->mvc_var);
    3349      149321 :         getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    3350      149321 :         q = pushArgument(mb, q, lastnr);
    3351      149320 :         pushInstruction(mb, q);
    3352      149321 :         be->mvc_var = getDestVar(q);
    3353      149321 :         return 0;
    3354             : }
    3355             : 
    3356             : stmt *
    3357      210648 : stmt_append(backend *be, stmt *c, stmt *a)
    3358             : {
    3359      210648 :         MalBlkPtr mb = be->mb;
    3360      210648 :         InstrPtr q = NULL;
    3361             : 
    3362      210648 :         if (c == NULL || a == NULL || c->nr < 0 || a->nr < 0)
    3363           0 :                 goto bailout;
    3364      210648 :         q = newStmt(mb, batRef, appendRef);
    3365      210648 :         if (q == NULL)
    3366           0 :                 goto bailout;
    3367      210648 :         q = pushArgument(mb, q, c->nr);
    3368      210648 :         q = pushArgument(mb, q, a->nr);
    3369      210648 :         q = pushBit(mb, q, TRUE);
    3370      210648 :         bool enabled = be->mvc->sa->eb.enabled;
    3371      210648 :         be->mvc->sa->eb.enabled = false;
    3372      210648 :         stmt *s = stmt_create(be->mvc->sa, st_append);
    3373      210648 :         be->mvc->sa->eb.enabled = enabled;
    3374      210648 :         if(!s) {
    3375           0 :                 freeInstruction(q);
    3376           0 :                 goto bailout;
    3377             :         }
    3378      210648 :         s->op1 = c;
    3379      210648 :         s->op2 = a;
    3380      210648 :         s->nrcols = c->nrcols;
    3381      210648 :         s->key = c->key;
    3382      210648 :         s->nr = getDestVar(q);
    3383      210648 :         s->q = q;
    3384      210648 :         pushInstruction(mb, q);
    3385      210648 :         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      137483 : stmt_append_bulk(backend *be, stmt *c, list *l)
    3395             : {
    3396      137483 :         MalBlkPtr mb = be->mb;
    3397      137483 :         InstrPtr q = NULL;
    3398      137483 :         bool needs_columns = false;
    3399             : 
    3400      137483 :         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      885600 :         for (node *n = l->h; n; n = n->next) {
    3406      748117 :                 stmt *t = n->data;
    3407      748117 :                 needs_columns |= t->nrcols > 0;
    3408             :         }
    3409      137483 :         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      137483 :         q = newStmtArgs(mb, batRef, appendBulkRef, list_length(l) + 3);
    3418      137486 :         if (q == NULL)
    3419           0 :                 goto bailout;
    3420      137486 :         q = pushArgument(mb, q, c->nr);
    3421      137484 :         q = pushBit(mb, q, TRUE);
    3422      885480 :         for (node *n = l->h ; n ; n = n->next) {
    3423      748018 :                 stmt *a = n->data;
    3424      748018 :                 q = pushArgument(mb, q, a->nr);
    3425             :         }
    3426      137462 :         bool enabled = be->mvc->sa->eb.enabled;
    3427      137462 :         be->mvc->sa->eb.enabled = false;
    3428      137462 :         stmt *s = stmt_create(be->mvc->sa, st_append_bulk);
    3429      137464 :         be->mvc->sa->eb.enabled = enabled;
    3430      137464 :         if(!s) {
    3431           0 :                 freeInstruction(q);
    3432           0 :                 goto bailout;
    3433             :         }
    3434      137464 :         s->op1 = c;
    3435      137464 :         s->op4.lval = l;
    3436      137464 :         s->nrcols = c->nrcols;
    3437      137464 :         s->key = c->key;
    3438      137464 :         s->nr = getDestVar(q);
    3439      137464 :         s->q = q;
    3440      137464 :         pushInstruction(mb, q);
    3441      137464 :         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      105854 : stmt_claim(backend *be, sql_table *t, stmt *cnt)
    3451             : {
    3452      105854 :         MalBlkPtr mb = be->mb;
    3453      105854 :         InstrPtr q = NULL;
    3454             : 
    3455      105854 :         if (!t || cnt->nr < 0)
    3456           0 :                 goto bailout;
    3457      105854 :         assert(t->s);                                /* declared table */
    3458      105854 :         q = newStmtArgs(mb, sqlRef, claimRef, 6);
    3459      105854 :         if (q == NULL)
    3460           0 :                 goto bailout;
    3461             :         /* returns offset or offsets */
    3462      105854 :         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_oid)));
    3463      105854 :         q = pushArgument(mb, q, be->mvc_var);
    3464      105854 :         q = pushSchema(mb, q, t);
    3465      105854 :         q = pushStr(mb, q, t->base.name);
    3466      105854 :         q = pushArgument(mb, q, cnt->nr);
    3467      105854 :         bool enabled = be->mvc->sa->eb.enabled;
    3468      105854 :         be->mvc->sa->eb.enabled = false;
    3469      105854 :         stmt *s = stmt_create(be->mvc->sa, st_claim);
    3470      105854 :         be->mvc->sa->eb.enabled = enabled;
    3471      105854 :         if(!s) {
    3472           0 :                 freeInstruction(q);
    3473           0 :                 goto bailout;
    3474             :         }
    3475      105854 :         s->op1 = cnt;
    3476      105854 :         s->op4.tval = t;
    3477      105854 :         s->nr = getDestVar(q);
    3478      105854 :         s->q = q;
    3479      105854 :         pushInstruction(mb, q);
    3480      105854 :         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      149554 : stmt_add_dependency_change(backend *be, sql_table *t, stmt *cnt)
    3490             : {
    3491      149554 :         MalBlkPtr mb = be->mb;
    3492      149554 :         InstrPtr q = NULL;
    3493             : 
    3494      149554 :         if (!t || cnt->nr < 0)
    3495           0 :                 goto bailout;
    3496      149554 :         q = newStmtArgs(mb, sqlRef, dependRef, 4);
    3497      149555 :         if (q == NULL)
    3498           0 :                 goto bailout;
    3499      149555 :         q = pushSchema(mb, q, t);
    3500      149553 :         q = pushStr(mb, q, t->base.name);
    3501      149555 :         q = pushArgument(mb, q, cnt->nr);
    3502      149554 :         pushInstruction(mb, q);
    3503      149554 :         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       14786 : stmt_add_column_predicate(backend *be, sql_column *c)
    3512             : {
    3513       14786 :         MalBlkPtr mb = be->mb;
    3514       14786 :         InstrPtr q = NULL;
    3515             : 
    3516       14786 :         if (!c)
    3517           0 :                 goto bailout;
    3518       14786 :         q = newStmtArgs(mb, sqlRef, predicateRef, 4);
    3519       14786 :         if (q == NULL)
    3520           0 :                 goto bailout;
    3521       14786 :         q = pushSchema(mb, q, c->t);
    3522       14786 :         q = pushStr(mb, q, c->t->base.name);
    3523       14786 :         q = pushStr(mb, q, c->base.name);
    3524       14786 :         pushInstruction(mb, q);
    3525       14786 :         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       52548 : stmt_replace(backend *be, stmt *r, stmt *id, stmt *val)
    3534             : {
    3535       52548 :         MalBlkPtr mb = be->mb;
    3536       52548 :         InstrPtr q = NULL;
    3537             : 
    3538       52548 :         if (r->nr < 0)
    3539           0 :                 goto bailout;
    3540             : 
    3541       52548 :         q = newStmt(mb, batRef, replaceRef);
    3542       52548 :         if (q == NULL)
    3543           0 :                 goto bailout;
    3544       52548 :         q = pushArgument(mb, q, r->nr);
    3545       52548 :         q = pushArgument(mb, q, id->nr);
    3546       52548 :         q = pushArgument(mb, q, val->nr);
    3547       52548 :         q = pushBit(mb, q, TRUE); /* forced */
    3548       52548 :         bool enabled = be->mvc->sa->eb.enabled;
    3549       52548 :         be->mvc->sa->eb.enabled = false;
    3550       52548 :         stmt *s = stmt_create(be->mvc->sa, st_replace);
    3551       52548 :         be->mvc->sa->eb.enabled = enabled;
    3552       52548 :         if(!s) {
    3553           0 :                 freeInstruction(q);
    3554           0 :                 goto bailout;
    3555             :         }
    3556       52548 :         s->op1 = r;
    3557       52548 :         s->op2 = id;
    3558       52548 :         s->op3 = val;
    3559       52548 :         s->nrcols = r->nrcols;
    3560       52548 :         s->key = r->key;
    3561       52548 :         s->nr = getDestVar(q);
    3562       52548 :         s->q = q;
    3563       52548 :         s->cand = r->cand;
    3564       52548 :         pushInstruction(mb, q);
    3565       52548 :         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       41825 : stmt_table_clear(backend *be, sql_table *t, int restart_sequences)
    3575             : {
    3576       41825 :         MalBlkPtr mb = be->mb;
    3577       41825 :         InstrPtr q = NULL;
    3578             : 
    3579       41825 :         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       41823 :                 q = newStmt(mb, sqlRef, clear_tableRef);
    3592       41822 :                 if (q == NULL)
    3593           0 :                         goto bailout;
    3594       41822 :                 q = pushSchema(mb, q, t);
    3595       41823 :                 q = pushStr(mb, q, t->base.name);
    3596       41823 :                 q = pushInt(mb, q, restart_sequences);
    3597       41823 :                 pushInstruction(mb, q);
    3598             :         }
    3599       41825 :         stmt *s = stmt_create(be->mvc->sa, st_table_clear);
    3600             : 
    3601       41825 :         if(!s) {
    3602           0 :                 goto bailout;
    3603             :         }
    3604       41825 :         s->op4.tval = t;
    3605       41825 :         s->nrcols = 0;
    3606       41825 :         s->nr = getDestVar(q);
    3607       41825 :         s->q = q;
    3608       41825 :         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       38742 : stmt_exception(backend *be, stmt *cond, const char *errstr, int errcode)
    3618             : {
    3619       38742 :         MalBlkPtr mb = be->mb;
    3620       38742 :         InstrPtr q = NULL;
    3621             : 
    3622       38742 :         if (cond->nr < 0)
    3623             :                 return NULL;
    3624             : 
    3625             :         /* if(bit(l)) { error(r);}  ==raising an exception */
    3626       38742 :         q = newStmt(mb, sqlRef, assertRef);
    3627       38743 :         if (q == NULL)
    3628           0 :                 goto bailout;
    3629       38743 :         q = pushArgument(mb, q, cond->nr);
    3630       38743 :         q = pushStr(mb, q, errstr);
    3631       38743 :         bool enabled = be->mvc->sa->eb.enabled;
    3632       38743 :         be->mvc->sa->eb.enabled = false;
    3633       38743 :         stmt *s = stmt_create(be->mvc->sa, st_exception);
    3634       38743 :         be->mvc->sa->eb.enabled = enabled;
    3635       38743 :         if(!s) {
    3636           0 :                 freeInstruction(q);
    3637           0 :                 return NULL;
    3638             :         }
    3639       38743 :         assert(cond);
    3640       38743 :         s->op1 = cond;
    3641       38743 :         (void)errcode;
    3642       38743 :         s->nrcols = 0;
    3643       38743 :         s->q = q;
    3644       38743 :         s->nr = getDestVar(q);
    3645       38743 :         pushInstruction(mb, q);
    3646       38743 :         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       12519 : tail_set_type(mvc *m, stmt *st, sql_subtype *t)
    3658             : {
    3659       29109 :         for (;;) {
    3660       29109 :                 switch (st->type) {
    3661        2937 :                 case st_const:
    3662        2937 :                         st = st->op2;
    3663        2937 :                         continue;
    3664        9869 :                 case st_alias:
    3665             :                 case st_gen_group:
    3666             :                 case st_order:
    3667        9869 :                         st = st->op1;
    3668        9869 :                         continue;
    3669           0 :                 case st_list:
    3670           0 :                         st = st->op4.lval->h->data;
    3671           0 :                         continue;
    3672        3784 :                 case st_join:
    3673             :                 case st_join2:
    3674             :                 case st_joinN:
    3675        3784 :                         if (st->flag == cmp_project) {
    3676        3784 :                                 st = st->op2;
    3677        3784 :                                 continue;
    3678             :                         }
    3679             :                         return;
    3680        2297 :                 case st_aggr:
    3681             :                 case st_Nop: {
    3682        2297 :                         list *res = st->op4.funcval->res;
    3683             : 
    3684        2297 :                         if (res && list_length(res) == 1)
    3685        2297 :                                 res->h->data = t;
    3686             :                         return;
    3687             :                 }
    3688        4654 :                 case st_atom:
    3689        4654 :                         st->op4.aval = atom_set_type(m->sa, st->op4.aval, t);
    3690        4654 :                         return;
    3691          62 :                 case st_convert:
    3692             :                 case st_temp:
    3693             :                 case st_single:
    3694          62 :                         st->op4.typeval = *t;
    3695          62 :                         return;
    3696          69 :                 case st_var:
    3697          69 :                         if (st->op4.typeval.type)
    3698          69 :                                 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         351 : temporal_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t, bool before)
    3711             : {
    3712         351 :         MalBlkPtr mb = be->mb;
    3713         351 :         InstrPtr q = NULL;
    3714         351 :         const char *convert = t->type->impl, *mod = mtimeRef;
    3715         351 :         bool add_tz = false, pushed = (v->cand && v->cand == sel);
    3716             : 
    3717         351 :         if (before) {
    3718         290 :                 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         211 :                 } 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         198 :                 } 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          61 :                 if (f->type->eclass == EC_DATE && t->type->eclass == EC_TIMESTAMP_TZ) {
    3751             :                         convert = "timestamp_sub_msec_interval";
    3752             :                         add_tz = true;
    3753          56 :                 } 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         288 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3762         200 :                 q = newStmtArgs(mb, mod, convert, 13);
    3763         200 :                 if (q == NULL)
    3764           0 :                         goto bailout;
    3765             :         } else {
    3766          88 :                 if (sel && !pushed && v->nrcols == 0) {
    3767           1 :                         pushed = 1;
    3768           1 :                         v = stmt_project(be, sel, v);
    3769           1 :                         v->cand = sel;
    3770             :                 }
    3771          88 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3772          88 :                 if (q == NULL)
    3773           0 :                         goto bailout;
    3774             :         }
    3775         288 :         q = pushArgument(mb, q, v->nr);
    3776             : 
    3777         288 :         if (EC_VARCHAR(f->type->eclass))
    3778         124 :                 q = pushInt(mb, q, t->digits);
    3779             : 
    3780         288 :         if (add_tz)
    3781         288 :                         q = pushLng(mb, q, be->mvc->timezone);
    3782             : 
    3783         288 :         if (sel && !pushed && !v->cand) {
    3784           2 :                 q = pushArgument(mb, q, sel->nr);
    3785           2 :                 pushed = 1;
    3786         286 :         } else if (v->nrcols > 0) {
    3787          86 :                 q = pushNilBat(mb, q);
    3788             :         }
    3789             : 
    3790         288 :         bool enabled = be->mvc->sa->eb.enabled;
    3791         288 :         be->mvc->sa->eb.enabled = false;
    3792         288 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    3793         288 :         be->mvc->sa->eb.enabled = enabled;
    3794         288 :         if(!s) {
    3795           0 :                 freeInstruction(q);
    3796           0 :                 goto bailout;
    3797             :         }
    3798         288 :         s->op1 = v;
    3799         288 :         s->nrcols = 0;       /* function without arguments returns single value */
    3800         288 :         s->key = v->key;
    3801         288 :         s->nrcols = v->nrcols;
    3802         288 :         s->aggr = v->aggr;
    3803         288 :         s->op4.typeval = *t;
    3804         288 :         s->nr = getDestVar(q);
    3805         288 :         s->q = q;
    3806         288 :         s->cand = pushed ? sel : NULL;
    3807         288 :         pushInstruction(mb, q);
    3808         288 :         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       47984 : stmt_convert(backend *be, stmt *v, stmt *sel, sql_subtype *f, sql_subtype *t)
    3818             : {
    3819       47984 :         MalBlkPtr mb = be->mb;
    3820       47984 :         InstrPtr q = NULL;
    3821       47984 :         const char *convert = t->type->impl, *mod = calcRef;
    3822       47984 :         int pushed = (v->cand && v->cand == sel), no_candidates = 0;
    3823       47984 :         bool add_tz = false;
    3824             :         /* convert types and make sure they are rounded up correctly */
    3825             : 
    3826       47984 :         if (v->nr < 0)
    3827           0 :                 goto bailout;
    3828             : 
    3829       47984 :         if (f->type->eclass != EC_EXTERNAL && t->type->eclass != EC_EXTERNAL &&
    3830             :                 /* general cases */
    3831       47634 :                 ((t->type->localtype == f->type->localtype && t->type->eclass == f->type->eclass &&
    3832       47634 :                 !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        1731 :                 (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       41459 :                 (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       12519 :                 tail_set_type(be->mvc, v, t);
    3839       12519 :                 return v;
    3840             :         }
    3841             : 
    3842             :         /* external types have sqlname convert functions,
    3843             :            these can generate errors (fromstr cannot) */
    3844       35465 :         if (t->type->eclass == EC_EXTERNAL)
    3845         323 :                 convert = t->type->base.name;
    3846       35142 :         else if (t->type->eclass == EC_MONTH)
    3847             :                 convert = "month_interval";
    3848       35131 :         else if (t->type->eclass == EC_SEC)
    3849          93 :                 convert = "second_interval";
    3850             : 
    3851       35465 :         no_candidates = t->type->eclass == EC_EXTERNAL && strcmp(convert, "uuid") != 0; /* uuids conversions support candidate lists */
    3852             : 
    3853       35465 :         if ((type_has_tz(f) && !type_has_tz(t) && !EC_VARCHAR(t->type->eclass)) || (!type_has_tz(f) && type_has_tz(t))) {
    3854         290 :                 v = temporal_convert(be, v, sel, f, t, true);
    3855         290 :                 sel = NULL;
    3856         290 :                 pushed = 0;
    3857         290 :                 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       35341 :         if (v->nrcols == 0 && (!sel || sel->nrcols == 0)) {       /* simple calc */
    3865        8655 :                 q = newStmtArgs(mb, mod, convert, 13);
    3866        8655 :                 if (q == NULL)
    3867           0 :                         goto bailout;
    3868       26707 :         } else if ((v->nrcols > 0 || (sel && sel->nrcols > 0)) && no_candidates) {
    3869          21 :                 int type = t->type->localtype;
    3870             : 
    3871             :                 /* with our current implementation, all internal SQL types have candidate list support on their conversions */
    3872          21 :                 if (sel && !pushed) {
    3873           0 :                         pushed = 1;
    3874           0 :                         v = stmt_project(be, sel, v);
    3875           0 :                         v->cand = sel;
    3876             :                 }
    3877          21 :                 q = newStmtArgs(mb, malRef, multiplexRef, 15);
    3878          21 :                 if (q == NULL)
    3879           0 :                         goto bailout;
    3880          21 :                 setVarType(mb, getArg(q, 0), newBatType(type));
    3881          21 :                 q = pushStr(mb, q, convertMultiplexMod(mod, convert));
    3882          21 :                 q = pushStr(mb, q, convertMultiplexFcn(convert));
    3883             :         } else {
    3884       26665 :                 if (v->nrcols == 0 && sel && !pushed) {
    3885         891 :                         pushed = 1;
    3886         891 :                         v = stmt_project(be, sel, v);
    3887         891 :                         v->cand = sel;
    3888             :                 }
    3889       26665 :                 q = newStmtArgs(mb, mod==calcRef?batcalcRef:batmtimeRef, convert, 13);
    3890       26665 :                 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       35485 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0)) {
    3896        1880 :                 q = pushInt(mb, q, f->type->eclass);
    3897        1880 :                 q = pushInt(mb, q, f->digits);
    3898        1880 :                 q = pushInt(mb, q, f->scale);
    3899        1880 :                 q = pushInt(mb, q, type_has_tz(f));
    3900       33461 :         } else if (f->type->eclass == EC_DEC) {
    3901             :                 /* scale of the current decimal */
    3902        1513 :                 q = pushInt(mb, q, f->scale);
    3903       31948 :         } 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       35341 :         q = pushArgument(mb, q, v->nr);
    3908       35341 :         if (add_tz)
    3909             :                         q = pushLng(mb, q, be->mvc->timezone);
    3910       35341 :         if (sel && !pushed && !v->cand) {
    3911        2720 :                 q = pushArgument(mb, q, sel->nr);
    3912        2720 :                 pushed = 1;
    3913       32621 :         } else if (v->nrcols > 0 && !no_candidates) {
    3914       23945 :                 q = pushNilBat(mb, q);
    3915             :         }
    3916       35341 :         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        3011 :                 q = pushInt(mb, q, t->digits);
    3919        3011 :                 if (!EC_TEMP_FRAC(t->type->eclass))
    3920        2668 :                         q = pushInt(mb, q, t->scale);
    3921             :         }
    3922             :         /* convert to string, give error on to large strings */
    3923       35485 :         if (EC_VARCHAR(t->type->eclass) && !(trivial_string_conversion(f->type->eclass) && t->digits == 0))
    3924        1880 :                 q = pushInt(mb, q, t->digits);
    3925             :         /* convert a string to a time(stamp) with time zone */
    3926       35341 :         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       35341 :         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       35341 :         bool enabled = be->mvc->sa->eb.enabled;
    3952       35341 :         be->mvc->sa->eb.enabled = false;
    3953       35341 :         stmt *s = stmt_create(be->mvc->sa, st_convert);
    3954       35341 :         be->mvc->sa->eb.enabled = enabled;
    3955       35341 :         if(!s) {
    3956           0 :                 freeInstruction(q);
    3957           0 :                 goto bailout;
    3958             :         }
    3959       35341 :         s->op1 = v;
    3960       35341 :         s->nrcols = 0;       /* function without arguments returns single value */
    3961       35341 :         s->key = v->key;
    3962       35341 :         s->nrcols = v->nrcols;
    3963       35341 :         s->aggr = v->aggr;
    3964       35341 :         s->op4.typeval = *t;
    3965       35341 :         s->nr = getDestVar(q);
    3966       35341 :         s->q = q;
    3967       35341 :         s->cand = pushed ? sel : NULL;
    3968       35341 :         pushInstruction(mb, q);
    3969       35341 :         if ((!type_has_tz(f) && type_has_tz(t)))
    3970          61 :                 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       26305 : stmt_unop(backend *be, stmt *op1, stmt *sel, sql_subfunc *op)
    3981             : {
    3982       26305 :         list *ops = sa_list(be->mvc->sa);
    3983       26305 :         list_append(ops, op1);
    3984       26305 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    3985       26306 :         if (r && !r->cand)
    3986       26306 :                 r->cand = op1->cand;
    3987       26306 :         return r;
    3988             : }
    3989             : 
    3990             : stmt *
    3991       43908 : stmt_binop(backend *be, stmt *op1, stmt *op2, stmt *sel, sql_subfunc *op)
    3992             : {
    3993       43908 :         list *ops = sa_list(be->mvc->sa);
    3994       43908 :         list_append(ops, op1);
    3995       43907 :         list_append(ops, op2);
    3996       43907 :         stmt *r = stmt_Nop(be, stmt_list(be, ops), sel, op, NULL);
    3997       43908 :         if (r && !r->cand)
    3998       43908 :                 r->cand = op1->cand?op1->cand:op2->cand;
    3999       43908 :         return r;
    4000             : }
    4001             : 
    4002             : #define LANG_INT_OR_MAL(l)  ((l)==FUNC_LANG_INT || (l)==FUNC_LANG_MAL)
    4003             : 
    4004             : stmt *
    4005      210262 : stmt_Nop(backend *be, stmt *ops, stmt *sel, sql_subfunc *f, stmt* rows)
    4006             : {
    4007      210262 :         MalBlkPtr mb = be->mb;
    4008      210262 :         InstrPtr q = NULL;
    4009      210262 :         const char *mod = sql_func_mod(f->func), *fimp = backend_function_imp(be, f->func);
    4010      210260 :         sql_subtype *tpe = NULL;
    4011      210260 :         int push_cands = 0, default_nargs;
    4012      210260 :         stmt *o = NULL, *card = NULL;
    4013             : 
    4014      210260 :         if (ops == NULL)
    4015           0 :                 goto bailout;
    4016             : 
    4017      210260 :         if (rows) {
    4018         101 :                 if (sel) /* if there's a candidate list, use it instead of 'rows' */
    4019           0 :                         rows = sel;
    4020             :                 o = rows;
    4021      210159 :         } else if (list_length(ops->op4.lval)) {
    4022      208623 :                 o = ops->op4.lval->h->data;
    4023      623031 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4024      414408 :                         stmt *c = n->data;
    4025             : 
    4026      414408 :                         if (c && o->nrcols < c->nrcols)
    4027      414408 :                                 o = c;
    4028             :                 }
    4029             :         }
    4030             : 
    4031             :         /* handle nullif */
    4032      210262 :         if (list_length(ops->op4.lval) == 2 &&
    4033      131533 :                 strcmp(mod, "") == 0 && strcmp(fimp, "") == 0) {
    4034         102 :                 stmt *e1 = ops->op4.lval->h->data;
    4035         102 :                 stmt *e2 = ops->op4.lval->h->next->data;
    4036         102 :                 int nrcols = 0;
    4037             : 
    4038         102 :                 nrcols = e1->nrcols>e2->nrcols ? e1->nrcols:e2->nrcols;
    4039             :                 /* nullif(e1,e2) -> ifthenelse(e1==e2),NULL,e1) */
    4040         102 :                 if (strcmp(f->func->base.name, "nullif") == 0) {
    4041         102 :                         const char *mod = (!nrcols)?calcRef:batcalcRef;
    4042         102 :                         sql_subtype *t = tail_type(e1);
    4043         102 :                         int tt = t->type->localtype;
    4044         102 :                         q = newStmt(mb, mod, "==");
    4045         102 :                         if (q == NULL)
    4046           0 :                                 goto bailout;
    4047         102 :                         q = pushArgument(mb, q, e1->nr);
    4048         102 :                         q = pushArgument(mb, q, e2->nr);
    4049         102 :                         int nr = getDestVar(q);
    4050         102 :                         pushInstruction(mb, q);
    4051             : 
    4052         102 :                         q = newStmt(mb, mod, ifthenelseRef);
    4053         102 :                         if (q == NULL)
    4054           0 :                                 goto bailout;
    4055         102 :                         q = pushArgument(mb, q, nr);
    4056         102 :                         q = pushNil(mb, q, tt);
    4057         102 :                         q = pushArgument(mb, q, e1->nr);
    4058         102 :                         pushInstruction(mb, q);
    4059             :                 }
    4060         102 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4061             :         }
    4062         102 :         if (q == NULL) {
    4063      210162 :                 if (backend_create_subfunc(be, f, ops->op4.lval) < 0)
    4064           1 :                         goto bailout;
    4065      210159 :                 mod = sql_func_mod(f->func);
    4066      210159 :                 fimp = convertMultiplexFcn(backend_function_imp(be, f->func));
    4067      210159 :                 push_cands = f->func->type == F_FUNC && can_push_cands(sel, mod, fimp);
    4068      219059 :                 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      210159 :                 if (rows) {
    4070         101 :                         card = stmt_aggr(be, rows, NULL, NULL, sql_bind_func(be->mvc, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
    4071         101 :                         default_nargs++;
    4072             :                 }
    4073             : 
    4074      210159 :                 if (o && o->nrcols > 0 && f->func->type != F_LOADER && f->func->type != F_PROC) {
    4075      131548 :                         sql_subtype *res = f->res->h->data;
    4076             : 
    4077      131548 :                         q = newStmtArgs(mb, f->func->type == F_UNION ? batmalRef : malRef, multiplexRef, default_nargs);
    4078      131548 :                         if (q == NULL)
    4079           0 :                                 goto bailout;
    4080      131548 :                         if (rows)
    4081         101 :                                 q = pushArgument(mb, q, card->nr);
    4082      131548 :                         q = pushStr(mb, q, mod);
    4083      131548 :                         q = pushStr(mb, q, fimp);
    4084      131548 :                         setVarType(mb, getArg(q, 0), newBatType(res->type->localtype));
    4085             :                 } else {
    4086       78611 :                         q = newStmtArgs(mb, mod, fimp, default_nargs);
    4087       78614 :                         if (q == NULL)
    4088           0 :                                 goto bailout;
    4089             : 
    4090       78614 :                         if (rows)
    4091           0 :                                 q = pushArgument(mb, q, card->nr);
    4092       78614 :                         if (f->res && list_length(f->res)) {
    4093       69714 :                                 sql_subtype *res = f->res->h->data;
    4094             : 
    4095       69714 :                                 setVarType(mb, getArg(q, 0), res->type->localtype);
    4096             :                         }
    4097             :                 }
    4098      210162 :                 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         221 :                         if (f->func->type == F_LOADER)
    4103          25 :                                 q = pushPtr(mb, q, f);
    4104             :                         else
    4105         196 :                                 q = pushPtr(mb, q, f->func);
    4106             :                 }
    4107      210162 :                 if (f->func->lang == FUNC_LANG_C) {
    4108          35 :                         q = pushBit(mb, q, 0);
    4109      210127 :                 } else if (f->func->lang == FUNC_LANG_CPP) {
    4110           1 :                         q = pushBit(mb, q, 1);
    4111             :                 }
    4112      210162 :                 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         221 :                         q = pushStr(mb, q, f->func->query);
    4115             :                 }
    4116             :                 /* first dynamic output of copy* functions */
    4117      210162 :                 if (f->func->type == F_UNION || (f->func->type == F_LOADER && f->res != NULL))
    4118        2395 :                         q = table_func_create_result(mb, q, f->func, f->res);
    4119      210162 :                 if (list_length(ops->op4.lval))
    4120      208609 :                         tpe = tail_type(ops->op4.lval->h->data);
    4121             : 
    4122      624540 :                 for (node *n = ops->op4.lval->h; n; n = n->next) {
    4123      414379 :                         stmt *op = n->data;
    4124      414379 :                         q = pushArgument(mb, q, op->nr);
    4125             :                 }
    4126             :                 /* push candidate lists if that's the case */
    4127      210161 :                 if (push_cands) {
    4128       73921 :                         for (node *n = ops->op4.lval->h; n; n = n->next) {
    4129       48830 :                                 stmt *op = n->data;
    4130             : 
    4131       48830 :                                 if (op->nrcols > 0) {
    4132       27391 :                                         if (op->cand && op->cand == sel) {
    4133        3786 :                                                 q = pushNilBat(mb, q);
    4134             :                                         } else {
    4135       23605 :                                                 q = pushArgument(mb, q, sel->nr);
    4136             :                                         }
    4137             :                                 }
    4138             :                         }
    4139             :                 }
    4140             :                 /* special case for round function on decimals */
    4141      210161 :                 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      210161 :                 pushInstruction(mb, q);
    4146             :         }
    4147             : 
    4148      210264 :         stmt *s = stmt_create(be->mvc->sa, st_Nop);
    4149      210264 :         if(!s) {
    4150           0 :                 goto bailout;
    4151             :         }
    4152      210264 :         s->op1 = ops;
    4153      210264 :         if (o) {
    4154      208727 :                 s->nrcols = o->nrcols;
    4155      208727 :                 s->key = o->key;
    4156      208727 :                 s->aggr = o->aggr;
    4157             :         } else {
    4158        1537 :                 s->nrcols = 0;
    4159        1537 :                 s->key = 1;
    4160             :         }
    4161      210264 :         s->op4.funcval = f;
    4162      210264 :         s->nr = getDestVar(q);
    4163      210264 :         s->q = q;
    4164      210264 :         if (sel && push_cands && s->nrcols)
    4165       23591 :                 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         185 : stmt_func(backend *be, stmt *ops, const char *name, sql_rel *rel, int f_union)
    4193             : {
    4194         185 :         MalBlkPtr mb = be->mb;
    4195         185 :         InstrPtr q = NULL;
    4196         185 :         prop *p = NULL;
    4197             : 
    4198             :         /* dump args */
    4199         185 :         if (ops && ops->nr < 0)
    4200           0 :                 goto bailout;
    4201             : 
    4202         185 :         if ((p = find_prop(rel->p, PROP_REMOTE)))
    4203         185 :                 rel->p = prop_remove(rel->p, p);
    4204             :         /* sql_processrelation may split projections, so make sure the topmost relation only contains references */
    4205         185 :         rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 1, 1));
    4206         185 :         if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
    4207           0 :                 goto bailout;
    4208         185 :         if (p) {
    4209         185 :                 p->p = rel->p;
    4210         185 :                 rel->p = p;
    4211             :         }
    4212             : 
    4213         185 :         if (monet5_create_relational_function(be->mvc, sql_private_module_name, name, rel, ops, NULL, 1) < 0)
    4214           0 :                 goto bailout;
    4215             : 
    4216         185 :         int nargs;
    4217         185 :         sql_rel *r = relational_func_create_result_part1(be->mvc, rel, &nargs);
    4218         185 :         if (ops)
    4219         185 :                 nargs += list_length(ops->op4.lval);
    4220         185 :         if (f_union)
    4221           0 :                 q = newStmt(mb, batmalRef, multiplexRef);
    4222             :         else
    4223         185 :                 q = newStmt(mb, sql_private_module_name, name);
    4224         185 :         if (q == NULL)
    4225           0 :                 goto bailout;
    4226         185 :         q = relational_func_create_result_part2(mb, q, r);
    4227         185 :         if (f_union) {
    4228           0 :                 q = pushStr(mb, q, sql_private_module_name);
    4229           0 :                 q = pushStr(mb, q, name);
    4230             :         }
    4231         185 :         if (ops) {
    4232         207 :                 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         185 :         allocator *sa = be->mvc->sa;
    4240         185 :         bool enabled = be->mvc->sa->eb.enabled;
    4241         185 :         be->mvc->sa->eb.enabled = false;
    4242         185 :         stmt *o = NULL, *s = stmt_create(sa, st_func);
    4243         185 :         be->mvc->sa->eb.enabled = enabled;
    4244         185 :         if(!s) {
    4245           0 :                 freeInstruction(q);
    4246           0 :                 goto bailout;
    4247             :         }
    4248         185 :         s->op1 = ops;
    4249         185 :         s->op2 = stmt_atom_string(be, name);
    4250         185 :         s->op4.rel = rel;
    4251         185 :         s->flag = f_union;
    4252         185 :         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         175 :                 s->nrcols = 0;
    4268         175 :                 s->key = 1;
    4269             :         }
    4270         185 :         s->nr = getDestVar(q);
    4271         185 :         s->q = q;
    4272         185 :         pushInstruction(mb, q);
    4273         185 :         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       84351 : stmt_aggr(backend *be, stmt *op1, stmt *grp, stmt *ext, sql_subfunc *op, int reduce, int no_nil, int nil_if_empty)
    4283             : {
    4284       84351 :         MalBlkPtr mb = be->mb;
    4285       84351 :         InstrPtr q = NULL;
    4286       84351 :         const char *mod, *aggrfunc;
    4287       84351 :         sql_subtype *res = op->res->h->data;
    4288       84351 :         int restype = res->type->localtype;
    4289       84351 :         bool complex_aggr = false;
    4290       84351 :         int *stmt_nr = NULL;
    4291       84351 :         int avg = 0;
    4292             : 
    4293       84351 :         if (op1->nr < 0)
    4294           0 :                 goto bailout;
    4295       84351 :         if (backend_create_subfunc(be, op, NULL) < 0)
    4296           0 :                 goto bailout;
    4297       84351 :         mod = sql_func_mod(op->func);
    4298       84351 :         aggrfunc = backend_function_imp(be, op->func);
    4299             : 
    4300       84351 :         if (LANG_INT_OR_MAL(op->func->lang)) {
    4301       84305 :                 if (strcmp(aggrfunc, "avg") == 0)
    4302             :                         avg = 1;
    4303       82933 :                 if (avg || strcmp(aggrfunc, "sum") == 0 || strcmp(aggrfunc, "prod") == 0
    4304       75730 :                         || strcmp(aggrfunc, "str_group_concat") == 0)
    4305             :                         complex_aggr = true;
    4306       84305 :                 if (restype == TYPE_dbl)
    4307        1562 :                         avg = 0;
    4308             :         }
    4309             : 
    4310      168702 :         int argc = 1
    4311       84351 :                 + 2 * avg
    4312       84351 :                 + (LANG_EXT(op->func->lang) != 0)
    4313       84351 :                 + 2 * (op->func->lang == FUNC_LANG_C || op->func->lang == FUNC_LANG_CPP)
    4314       84351 :                 + (op->func->lang == FUNC_LANG_PY || op->func->lang == FUNC_LANG_R)
    4315       84351 :                 + (op1->type != st_list ? 1 : list_length(op1->op4.lval))
    4316       84351 :                 + (grp ? 4 : avg + 1);
    4317             : 
    4318       84351 :         if (grp) {
    4319        6365 :                 char *aggrF = SA_NEW_ARRAY(be->mvc->sa, char, strlen(aggrfunc) + 4);
    4320        6365 :                 if (!aggrF)
    4321           0 :                         goto bailout;
    4322        6365 :                 stpcpy(stpcpy(aggrF, "sub"), aggrfunc);
    4323        6365 :                 aggrfunc = aggrF;
    4324        6365 :                 if ((grp && grp->nr < 0) || (ext && ext->nr < 0))
    4325           0 :                         goto bailout;
    4326             : 
    4327        6365 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4328        6365 :                 if (q == NULL)
    4329           0 :                         goto bailout;
    4330        6365 :                 setVarType(mb, getArg(q, 0), newBatType(restype));
    4331        6365 :                 if (avg) { /* for avg also return rest and count */
    4332          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4333          96 :                         q = pushReturn(mb, q, newTmpVariable(mb, newBatType(TYPE_lng)));
    4334             :                 }
    4335             :         } else {
    4336       77986 :                 q = newStmtArgs(mb, mod, aggrfunc, argc);
    4337       77986 :                 if (q == NULL)
    4338           0 :                         goto bailout;
    4339       77986 :                 if (complex_aggr) {
    4340        6716 :                         setVarType(mb, getArg(q, 0), restype);
    4341        6716 :                         if (avg) { /* for avg also return rest and count */
    4342          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4343          57 :                                 q = pushReturn(mb, q, newTmpVariable(mb, TYPE_lng));
    4344             :                         }
    4345             :                 }
    4346             :         }
    4347             : 
    4348       84351 :         if (LANG_EXT(op->func->lang))
    4349          46 :                 q = pushPtr(mb, q, op->func);
    4350       84351 :         if (op->func->lang == FUNC_LANG_R ||
    4351       84316 :                 op->func->lang >= FUNC_LANG_PY ||
    4352             :                 op->func->lang == FUNC_LANG_C ||
    4353             :                 op->func->lang == FUNC_LANG_CPP) {
    4354          46 :                 if (!grp) {
    4355          20 :                         setVarType(mb, getArg(q, 0), restype);
    4356             :                 }
    4357          46 :                 if (op->func->lang == FUNC_LANG_C) {
    4358          11 :                         q = pushBit(mb, q, 0);
    4359          35 :                 } else if (op->func->lang == FUNC_LANG_CPP) {
    4360           0 :                         q = pushBit(mb, q, 1);
    4361             :                 }
    4362          46 :                 q = pushStr(mb, q, op->func->query);
    4363             :         }
    4364             : 
    4365       84351 :         if (op1->type != st_list) {
    4366       78332 :                 q = pushArgument(mb, q, op1->nr);
    4367             :         } else {
    4368        6019 :                 int i;
    4369        6019 :                 node *n;
    4370             : 
    4371       12389 :                 for (i=0, n = op1->op4.lval->h; n; n = n->next, i++) {
    4372        6370 :                         stmt *op = n->data;
    4373             : 
    4374        6370 :                         if (stmt_nr)
    4375             :                                 q = pushArgument(mb, q, stmt_nr[i]);
    4376             :                         else
    4377        6370 :                                 q = pushArgument(mb, q, op->nr);
    4378             :                 }
    4379             :         }
    4380       84351 :         if (grp) {
    4381        6365 :                 q = pushArgument(mb, q, grp->nr);
    4382        6365 :                 q = pushArgument(mb, q, ext->nr);
    4383        6365 :                 if (LANG_INT_OR_MAL(op->func->lang)) {
    4384        6339 :                         if (avg) /* push nil candidates */
    4385          96 :                                 q = pushNilBat(mb, q);
    4386        6339 :                         q = pushBit(mb, q, no_nil);
    4387             :                 }
    4388       77986 :         } else if (LANG_INT_OR_MAL(op->func->lang) && no_nil && strncmp(aggrfunc, "count", 5) == 0) {
    4389        1715 :                 q = pushBit(mb, q, no_nil);
    4390       76271 :         } 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       76271 :         } else if (LANG_INT_OR_MAL(op->func->lang) && avg) { /* push candidates */
    4393          57 :                 q = pushNilBat(mb, q);
    4394          57 :                 q = pushBit(mb, q, no_nil);
    4395             :         }
    4396             : 
    4397       84351 :         bool enabled = be->mvc->sa->eb.enabled;
    4398       84351 :         be->mvc->sa->eb.enabled = false;
    4399       84351 :         stmt *s = stmt_create(be->mvc->sa, st_aggr);
    4400       84351 :         be->mvc->sa->eb.enabled = enabled;
    4401       84351 :         if(!s) {
    4402           0 :                 freeInstruction(q);
    4403           0 :                 goto bailout;
    4404             :         }
    4405       84351 :         s->op1 = op1;
    4406       84351 :         if (grp) {
    4407        6365 :                 s->op2 = grp;
    4408        6365 :                 s->op3 = ext;
    4409        6365 :                 s->nrcols = 1;
    4410             :         } else {
    4411       77986 :                 if (!reduce)
    4412           0 :                         s->nrcols = 1;
    4413             :         }
    4414       84351 :         s->key = reduce;
    4415       84351 :         s->aggr = reduce;
    4416       84351 :         s->flag = no_nil;
    4417       84351 :         s->op4.funcval = op;
    4418       84351 :         s->nr = getDestVar(q);
    4419       84351 :         s->q = q;
    4420       84351 :         pushInstruction(mb, q);
    4421       84351 :         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     1238139 : stmt_alias_(backend *be, stmt *op1, const char *tname, const char *alias)
    4431             : {
    4432     1238139 :         stmt *s = stmt_create(be->mvc->sa, st_alias);
    4433     1238115 :         if(!s) {
    4434             :                 return NULL;
    4435             :         }
    4436     1238115 :         s->op1 = op1;
    4437     1238115 :         s->nrcols = op1->nrcols;
    4438     1238115 :         s->key = op1->key;
    4439     1238115 :         s->aggr = op1->aggr;
    4440             : 
    4441     1238115 :         s->tname = tname;
    4442     1238115 :         s->cname = alias;
    4443     1238115 :         s->nr = op1->nr;
    4444     1238115 :         s->q = op1->q;
    4445     1238115 :         return s;
    4446             : }
    4447             : 
    4448             : stmt *
    4449     3947339 : stmt_alias(backend *be, stmt *op1, const char *tname, const char *alias)
    4450             : {
    4451     3947339 :         if (((!op1->tname && !tname) ||
    4452     2837009 :             (op1->tname && tname && strcmp(op1->tname, tname)==0)) &&
    4453     2732099 :             op1->cname && strcmp(op1->cname, alias)==0)
    4454             :                 return op1;
    4455     1238148 :         return stmt_alias_(be, op1, tname, alias);
    4456             : }
    4457             : 
    4458             : sql_subtype *
    4459     1158124 : tail_type(stmt *st)
    4460             : {
    4461     4462248 :         for (;;) {
    4462     4462248 :                 switch (st->type) {
    4463       26824 :                 case st_const:
    4464       26824 :                         st = st->op2;
    4465       26824 :                         continue;
    4466        3132 :                 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        3132 :                         return sql_bind_localtype("oid");
    4475         572 :                 case st_uselect2:
    4476         572 :                         if (!st->reduce)
    4477          54 :                                 return sql_bind_localtype("bit");
    4478         518 :                         return sql_bind_localtype("oid");
    4479      942657 :                 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      942657 :                         st = st->op1;
    4486      942657 :                         continue;
    4487           0 :                 case st_list:
    4488           0 :                         st = st->op4.lval->h->data;
    4489           0 :                         continue;
    4490      563186 :                 case st_bat:
    4491      563186 :                         return &st->op4.cval->type;
    4492        1936 :                 case st_idxbat:
    4493        1936 :                         if (hash_index(st->op4.idxval->type)) {
    4494         281 :                                 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     2334686 :                         if (st->flag == cmp_project) {
    4503     2334643 :                                 st = st->op2;
    4504     2334643 :                                 continue;
    4505             :                         }
    4506             :                         /* fall through */
    4507             :                 case st_reorder:
    4508             :                 case st_group:
    4509             :                 case st_tid:
    4510             :                 case st_mirror:
    4511       13951 :                         return sql_bind_localtype("oid");
    4512       29632 :                 case st_result:
    4513       29632 :                         return &st->op4.typeval;
    4514           0 :                 case st_table_clear:
    4515           0 :                         return sql_bind_localtype("lng");
    4516      151473 :                 case st_aggr:
    4517             :                 case st_Nop: {
    4518      151473 :                         list *res = st->op4.funcval->res;
    4519             : 
    4520      151473 :                         if (res && list_length(res) == 1)
    4521      151473 :                                 return res->h->data;
    4522             : 
    4523             :                         return NULL;
    4524             :                 }
    4525      133001 :                 case st_atom:
    4526      133001 :                         return atom_type(st->op4.aval);
    4527      259557 :                 case st_convert:
    4528             :                 case st_temp:
    4529             :                 case st_single:
    4530             :                 case st_rs_column:
    4531      259557 :                         return &st->op4.typeval;
    4532        1676 :                 case st_var:
    4533        1676 :                         if (st->op4.typeval.type)
    4534        1676 :                                 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        6974 : stmt_has_null(stmt *s)
    4549             : {
    4550       14002 :         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        7028 :         case st_join:
    4559        7028 :                 return stmt_has_null(s->op2);
    4560        4467 :         case st_bat:
    4561        4467 :                 return s->op4.cval->null;
    4562             : 
    4563        2507 :         default:
    4564        2507 :                 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     8430845 : column_name(allocator *sa, stmt *st)
    4598             : {
    4599     8430845 :         if (!st->cname)
    4600           2 :                 st->cname = _column_name(sa, st);
    4601     8430845 :         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     4193135 : table_name(allocator *sa, stmt *st)
    4672             : {
    4673     4193135 :         (void)sa;
    4674     4193135 :         return st->tname;
    4675             : }
    4676             : 
    4677             : const char *
    4678      318286 : schema_name(allocator *sa, stmt *st)
    4679             : {
    4680     1777415 :         switch (st->type) {
    4681     1161838 :         case st_const:
    4682             :         case st_semijoin:
    4683             :         case st_join:
    4684             :         case st_join2:
    4685             :         case st_joinN:
    4686     1161838 :                 return schema_name(sa, st->op2);
    4687      104688 :         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      104688 :                 if (st->op1)
    4707             :                         return schema_name(sa, st->op1);
    4708             :                 return NULL;
    4709      162045 :         case st_alias:
    4710      162045 :                 return schema_name(sa, st->op1);
    4711      199475 :         case st_bat:
    4712      199475 :                 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       30692 :         case st_list:
    4720       30692 :                 if (list_length(st->op4.lval))
    4721       30558 :                         return schema_name(sa, st->op4.lval->h->data);
    4722             :                 return NULL;
    4723             :         default:
    4724             :                 return NULL;
    4725             :         }
    4726             : }
    4727             : 
    4728             : stmt *
    4729        1050 : stmt_cond(backend *be, stmt *cond, stmt *outer, int loop /* 0 if, 1 while */, int anti )
    4730             : {
    4731        1050 :         MalBlkPtr mb = be->mb;
    4732        1050 :         InstrPtr q = NULL;
    4733             : 
    4734        1050 :         if (cond->nr < 0)
    4735           0 :                 goto bailout;
    4736        1050 :         if (anti) {
    4737          25 :                 sql_subtype *bt = sql_bind_localtype("bit");
    4738          25 :                 sql_subfunc *not = sql_bind_func(be->mvc, "sys", "not", bt, NULL, F_FUNC, true, true);
    4739          25 :                 sql_subfunc *or = sql_bind_func(be->mvc, "sys", "or", bt, bt, F_FUNC, true, true);
    4740          25 :                 sql_subfunc *isnull = sql_bind_func(be->mvc, "sys", "isnull", bt, NULL, F_FUNC, true, true);
    4741          25 :                 cond = stmt_binop(be,
    4742             :                         stmt_unop(be, cond, NULL, not),
    4743             :                         stmt_unop(be, cond, NULL, isnull), NULL, or);
    4744             :         }
    4745        1050 :         if (!loop) {    /* if */
    4746        1033 :                 q = newAssignment(mb);
    4747        1033 :                 if (q == NULL)
    4748           0 :                         goto bailout;
    4749        1033 :                 q->barrier = BARRIERsymbol;
    4750        1033 :                 q = pushArgument(mb, q, cond->nr);
    4751             :         } else {        /* while */
    4752          17 :                 int c;
    4753             : 
    4754          17 :                 if (outer->nr < 0)
    4755           0 :                         goto bailout;
    4756             :                 /* leave barrier */
    4757          17 :                 q = newStmt(mb, calcRef, notRef);
    4758          17 :                 if (q == NULL)
    4759           0 :                         goto bailout;
    4760          17 :                 q = pushArgument(mb, q, cond->nr);
    4761          17 :                 c = getArg(q, 0);
    4762          17 :                 pushInstruction(mb, q);
    4763             : 
    4764          17 :                 q = newAssignment(mb);
    4765          17 :                 if (q == NULL)
    4766           0 :                         goto bailout;
    4767          17 :                 getArg(q, 0) = outer->nr;
    4768          17 :                 q->barrier = LEAVEsymbol;
    4769          17 :                 q = pushArgument(mb, q, c);
    4770             :         }
    4771             : 
    4772        1050 :         bool enabled = be->mvc->sa->eb.enabled;
    4773        1050 :         be->mvc->sa->eb.enabled = false;
    4774        1050 :         stmt *s = stmt_create(be->mvc->sa, st_cond);
    4775        1050 :         be->mvc->sa->eb.enabled = enabled;
    4776        1050 :         if(!s) {
    4777           0 :                 freeInstruction(q);
    4778           0 :                 goto bailout;
    4779             :         }
    4780        1050 :         s->flag = be->mvc_var; /* keep the mvc_var of the outer context */
    4781        1050 :         s->loop = loop;
    4782        1050 :         s->op1 = cond;
    4783        1050 :         s->nr = getArg(q, 0);
    4784        1050 :         pushInstruction(mb, q);
    4785        1050 :         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        1050 : stmt_control_end(backend *be, stmt *cond)
    4795             : {
    4796        1050 :         MalBlkPtr mb = be->mb;
    4797        1050 :         InstrPtr q = NULL;
    4798             : 
    4799        1050 :         if (cond->nr < 0)
    4800           0 :                 goto bailout;
    4801             : 
    4802        1050 :         if (cond->loop) {    /* while */
    4803             :                 /* redo barrier */
    4804          17 :                 q = newAssignment(mb);
    4805          17 :                 if (q == NULL)
    4806           0 :                         goto bailout;
    4807          17 :                 getArg(q, 0) = cond->nr;
    4808          17 :                 q->argc = q->retc = 1;
    4809          17 :                 q->barrier = REDOsymbol;
    4810          17 :                 q = pushBit(mb, q, TRUE);
    4811             :         } else {
    4812        1033 :                 q = newAssignment(mb);
    4813        1033 :                 if (q == NULL)
    4814           0 :                         goto bailout;
    4815        1033 :                 getArg(q, 0) = cond->nr;
    4816        1033 :                 q->argc = q->retc = 1;
    4817        1033 :                 q->barrier = EXITsymbol;
    4818             :         }
    4819        1050 :         be->mvc_var = cond->flag; /* restore old mvc_var from before the barrier */
    4820        1050 :         bool enabled = be->mvc->sa->eb.enabled;
    4821        1050 :         be->mvc->sa->eb.enabled = false;
    4822        1050 :         stmt *s = stmt_create(be->mvc->sa, st_control_end);
    4823        1049 :         be->mvc->sa->eb.enabled = enabled;
    4824        1049 :         if(!s) {
    4825           0 :                 freeInstruction(q);
    4826           0 :                 goto bailout;
    4827             :         }
    4828        1049 :         s->op1 = cond;
    4829        1049 :         s->nr = getArg(q, 0);
    4830        1049 :         pushInstruction(mb, q);
    4831        1049 :         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         205 : dump_cols(MalBlkPtr mb, list *l, InstrPtr q)
    4842             : {
    4843         205 :         int i;
    4844         205 :         node *n;
    4845             : 
    4846         205 :         if (q == NULL)
    4847             :                 return NULL;
    4848         205 :         q->retc = q->argc = 0;
    4849        1647 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4850        1442 :                 stmt *c = n->data;
    4851             : 
    4852        1442 :                 q = pushArgument(mb, q, c->nr);
    4853             :         }
    4854         205 :         if (q == NULL)
    4855             :                 return NULL;
    4856         205 :         q->retc = q->argc;
    4857             :         /* Lets make it a propper assignment */
    4858        1647 :         for (i = 0, n = l->h; n; n = n->next, i++) {
    4859        1442 :                 stmt *c = n->data;
    4860             : 
    4861        1442 :                 q = pushArgument(mb, q, c->nr);
    4862             :         }
    4863             :         return q;
    4864             : }
    4865             : 
    4866             : stmt *
    4867         578 : stmt_return(backend *be, stmt *val, int nr_declared_tables)
    4868             : {
    4869         578 :         MalBlkPtr mb = be->mb;
    4870         578 :         InstrPtr q = NULL;
    4871             : 
    4872         578 :         if (val->nr < 0)
    4873           0 :                 goto bailout;
    4874         578 :         int args = val->type == st_table ? 2 * list_length(val->op1->op4.lval) : 0;
    4875         205 :         if (args < MAXARG)
    4876             :                 args = MAXARG;
    4877         578 :         q = newInstructionArgs(mb, NULL, NULL, args);
    4878         578 :         if (q == NULL)
    4879           0 :                 goto bailout;
    4880         578 :         q->barrier= RETURNsymbol;
    4881         578 :         if (val->type == st_table) {
    4882         205 :                 list *l = val->op1->op4.lval;
    4883             : 
    4884         205 :                 q = dump_cols(mb, l, q);
    4885             :         } else {
    4886         373 :                 getArg(q, 0) = getArg(getInstrPtr(mb, 0), 0);
    4887         373 :                 q = pushArgument(mb, q, val->nr);
    4888             :         }
    4889             : 
    4890         578 :         bool enabled = be->mvc->sa->eb.enabled;
    4891         578 :         be->mvc->sa->eb.enabled = false;
    4892         578 :         stmt *s = stmt_create(be->mvc->sa, st_return);
    4893         578 :         be->mvc->sa->eb.enabled = enabled;
    4894         578 :         if(!s) {
    4895           0 :                 freeInstruction(q);
    4896           0 :                 goto bailout;
    4897             :         }
    4898         578 :         s->op1 = val;
    4899         578 :         s->flag = nr_declared_tables;
    4900         578 :         s->nr = getDestVar(q);
    4901         578 :         s->q = q;
    4902         578 :         pushInstruction(mb, q);
    4903         578 :         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        1402 : stmt_assign(backend *be, const char *sname, const char *varname, stmt *val, int level)
    4913             : {
    4914        1402 :         MalBlkPtr mb = be->mb;
    4915        1402 :         InstrPtr q = NULL;
    4916             : 
    4917        1402 :         if (val && val->nr < 0)
    4918           0 :                 goto bailout;
    4919        1402 :         if (level != 0) {
    4920        1029 :                 char *buf,  levelstr[16];
    4921             : 
    4922        1029 :                 if (!val) {
    4923             :                         /* drop declared table */
    4924           0 :                         assert(0);
    4925             :                 }
    4926             : 
    4927        1029 :                 assert(!sname);
    4928        1029 :                 snprintf(levelstr, sizeof(levelstr), "%d", level);
    4929        1029 :                 buf = SA_NEW_ARRAY(be->mvc->sa, char, strlen(levelstr) + strlen(varname) + 3);
    4930        1028 :                 if (!buf)
    4931           0 :                         goto bailout;
    4932        1028 :                 stpcpy(stpcpy(stpcpy(stpcpy(buf, "A"), levelstr), "%"), varname); /* mangle variable name */
    4933        1028 :                 q = newInstruction(mb, NULL, NULL);
    4934        1029 :                 if (q == NULL) {
    4935           0 :                         goto bailout;
    4936             :                 }
    4937        1029 :                 q->argc = q->retc = 0;
    4938        1029 :                 q = pushArgumentId(mb, q, buf);
    4939        1029 :                 pushInstruction(mb, q);
    4940        1029 :                 q->retc++;
    4941             :         } else {
    4942         373 :                 assert(sname); /* all global variables have a schema */
    4943         373 :                 q = newStmt(mb, sqlRef, setVariableRef);
    4944         373 :                 if (q == NULL)
    4945           0 :                         goto bailout;
    4946         373 :                 q = pushArgument(mb, q, be->mvc_var);
    4947         373 :                 q = pushStr(mb, q, sname);
    4948         373 :                 q = pushStr(mb, q, varname);
    4949         373 :                 getArg(q, 0) = be->mvc_var = newTmpVariable(mb, TYPE_int);
    4950         373 :                 pushInstruction(mb, q);
    4951         373 :                 be->mvc_var = getDestVar(q);
    4952             :         }
    4953        1402 :         q = pushArgument(mb, q, val->nr);
    4954             : 
    4955        1402 :         bool enabled = be->mvc->sa->eb.enabled;
    4956        1402 :         be->mvc->sa->eb.enabled = false;
    4957        1402 :         stmt *s = stmt_create(be->mvc->sa, st_assign);
    4958        1402 :         be->mvc->sa->eb.enabled = enabled;
    4959        1402 :         if(!s) {
    4960           0 :                 goto bailout;
    4961             :         }
    4962        1402 :         s->op2 = val;
    4963        1402 :         s->flag = (level << 1);
    4964        1402 :         s->q = q;
    4965        1402 :         s->nr = 1;
    4966        1402 :         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       12299 : const_column(backend *be, stmt *val)
    4976             : {
    4977       12299 :         sql_subtype *ct = tail_type(val);
    4978       12299 :         MalBlkPtr mb = be->mb;
    4979       12299 :         InstrPtr q = NULL;
    4980       12299 :         int tt = ct->type->localtype;
    4981             : 
    4982       12299 :         if (val->nr < 0)
    4983           0 :                 goto bailout;
    4984       12299 :         q = newStmt(mb, batRef, singleRef);
    4985       12299 :         if (q == NULL)
    4986           0 :                 goto bailout;
    4987       12299 :         setVarType(mb, getArg(q, 0), newBatType(tt));
    4988       12299 :         q = pushArgument(mb, q, val->nr);
    4989             : 
    4990       12299 :         bool enabled = be->mvc->sa->eb.enabled;
    4991       12299 :         be->mvc->sa->eb.enabled = false;
    4992       12299 :         stmt *s = stmt_create(be->mvc->sa, st_single);
    4993       12299 :         be->mvc->sa->eb.enabled = enabled;
    4994       12299 :         if(!s) {
    4995           0 :                 freeInstruction(q);
    4996           0 :                 goto bailout;
    4997             :         }
    4998       12299 :         s->op1 = val;
    4999       12299 :         s->op4.typeval = *ct;
    5000       12299 :         s->nrcols = 1;
    5001             : 
    5002       12299 :         s->tname = val->tname;
    5003       12299 :         s->cname = val->cname;
    5004       12299 :         s->nr = getDestVar(q);
    5005       12299 :         s->q = q;
    5006       12299 :         pushInstruction(mb, q);
    5007       12299 :         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     1559091 : stmt_rename(backend *be, sql_exp *exp, stmt *s )
    5068             : {
    5069     1559091 :         const char *name = exp_name(exp);
    5070     1559075 :         const char *rname = exp_relname(exp);
    5071     1559056 :         stmt *o = s;
    5072             : 
    5073     1559056 :         if (!name && exp_is_atom(exp))
    5074           0 :                 name = sa_strdup(be->mvc->sa, "single_value");
    5075           0 :         assert(name);
    5076     1559056 :         s = stmt_alias(be, s, rname, name);
    5077     1559034 :         if (o->flag & OUTER_ZERO)
    5078         521 :                 s->flag |= OUTER_ZERO;
    5079     1559034 :         return s;
    5080             : }

Generated by: LCOV version 1.14