LCOV - code coverage report
Current view: top level - sql/backends/monet5 - sql_statement.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2900 3501 82.8 %
Date: 2025-03-24 23:16:36 Functions: 109 113 96.5 %

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

Generated by: LCOV version 1.14