LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_mergetable.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1117 1445 77.3 %
Date: 2021-10-13 02:24:04 Functions: 35 36 97.2 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "opt_mergetable.h"
      11             : 
      12             : typedef enum mat_type_t {
      13             :         mat_none = 0,   /* Simple mat aligned operations (ie batcalc etc) */
      14             :         mat_grp = 1,    /* result of phase one of a mat - group.new/derive */
      15             :         mat_ext = 2,    /* mat_grp extend */
      16             :         mat_cnt = 3,    /* mat_grp count */
      17             :         mat_tpn = 4,    /* Phase one of topn on a mat */
      18             :         mat_slc = 5,    /* Last phase of topn (or just slice) on a mat */
      19             :         mat_rdr = 6     /* Phase one of sorting, ie sorted the parts sofar */
      20             : } mat_type_t;
      21             : 
      22             : typedef struct mat {
      23             :         InstrPtr mi;            /* mat instruction */
      24             :         InstrPtr org;           /* orignal instruction */
      25             :         int mv;                 /* mat variable */
      26             :         int im;                 /* input mat, for attribute of sub relations */
      27             :         int pm;                 /* parent mat, for sub relations */
      28             :         mat_type_t type;        /* type of operation */
      29             :         int packed;
      30             :         int pushed;              /* set if instruction pushed and shouldn't be freed */
      31             : } mat_t;
      32             : 
      33             : typedef struct matlist {
      34             :         mat_t *v;
      35             :         int *vars;              /* result variable is a mat */
      36             :         int top;
      37             :         int size;
      38             : 
      39             :         int *horigin;
      40             :         int *torigin;
      41             :         int vsize;
      42             : } matlist_t;
      43             : 
      44             : static inline mat_type_t
      45             : mat_type( mat_t *mat, int n)
      46             : {
      47             :         mat_type_t type = mat_none;
      48             :         (void)mat;
      49             :         (void)n;
      50             :         return type;
      51             : }
      52             : 
      53             : static inline int
      54    36300796 : is_a_mat(int idx, const matlist_t *ml)
      55             : {
      56    36300796 :         if (ml->vars[idx] >= 0 && !ml->v[ml->vars[idx]].packed)
      57    10721222 :                 return ml->vars[idx];
      58             :         return -1;
      59             : }
      60             : 
      61             : static int
      62     6998235 : nr_of_mats(InstrPtr p, const matlist_t *ml)
      63             : {
      64             :         int j,cnt=0;
      65    33790726 :         for(j=p->retc; j<p->argc; j++)
      66    26792491 :                 if (is_a_mat(getArg(p,j), ml) >= 0)
      67     3069772 :                         cnt++;
      68     6998235 :         return cnt;
      69             : }
      70             : 
      71             : static int
      72     1649082 : nr_of_bats(MalBlkPtr mb, InstrPtr p)
      73             : {
      74             :         int j,cnt=0;
      75     6031005 :         for(j=p->retc; j<p->argc; j++)
      76     4381923 :                 if (isaBatType(getArgType(mb,p,j)) && !isVarConstant(mb, getArg(p,j)))
      77     3474757 :                         cnt++;
      78     1649082 :         return cnt;
      79             : }
      80             : 
      81             : static int
      82     1649082 : nr_of_nilbats(MalBlkPtr mb, InstrPtr p)
      83             : {
      84             :         int j,cnt=0;
      85     6030997 :         for(j=p->retc; j<p->argc; j++)
      86     4381915 :                 if (getArgType(mb,p,j) == TYPE_bat || (isaBatType(getArgType(mb, p, j)) && isVarConstant(mb, getArg(p,j)) && getVarConstant(mb, getArg(p,j)).val.bval == bat_nil))
      87      273409 :                         cnt++;
      88     1649082 :         return cnt;
      89             : }
      90             : 
      91             : /* some mat's have intermediates (with intermediate result variables), therefor
      92             :  * we pass the old output mat variable */
      93             : inline static int
      94     1940909 : mat_add_var(matlist_t *ml, InstrPtr q, InstrPtr p, int var, mat_type_t type, int inputmat, int parentmat, int pushed)
      95             : {
      96     1940909 :         if (ml->top == ml->size) {
      97           0 :                 int s = ml->size * 2;
      98           0 :                 mat_t *v = (mat_t*)GDKzalloc(s * sizeof(mat_t));
      99           0 :                 if (!v)
     100             :                         return -1;
     101           0 :                 memcpy(v, ml->v, ml->top * sizeof(mat_t));
     102           0 :                 GDKfree(ml->v);
     103           0 :                 ml->size = s;
     104           0 :                 ml->v = v;
     105             :         }
     106     1940909 :         mat_t *dst = &ml->v[ml->top];
     107     1940909 :         dst->mi = q;
     108     1940909 :         dst->org = p;
     109     1940909 :         dst->mv = var;
     110     1940909 :         dst->type = type;
     111     1940909 :         dst->im = inputmat;
     112     1940909 :         dst->pm = parentmat;
     113     1940909 :         dst->packed = 0;
     114     1940909 :         dst->pushed = pushed;
     115     1940909 :         if (ml->vars[var] < 0 || dst->type != mat_ext) {
     116     1927858 :                 if (ml->vars[var] >= 0) {
     117           0 :                         ml->v[ml->vars[var]].packed = 1;
     118             :                 }
     119     1927858 :                 ml->vars[var] = ml->top;
     120             :         }
     121     1940909 :         ++ml->top;
     122     1940909 :         return 0;
     123             : }
     124             : 
     125             : inline static int
     126     1169443 : mat_add(matlist_t *ml, InstrPtr q, mat_type_t type, const char *func)
     127             : {
     128             :         (void)func;
     129             :         //printf (" ml.top %d %s\n", ml.top, func);
     130     1169443 :         return mat_add_var(ml, q, NULL, getArg(q,0), type, -1, -1, 0);
     131             : }
     132             : 
     133             : static void
     134      224097 : matlist_pack(matlist_t *ml, int m)
     135             : {
     136      224097 :         int i, idx = ml->v[m].mv;
     137             : 
     138      224097 :         assert(ml->v[m].packed  == 0);
     139      224097 :         ml->v[m].packed = 1;
     140      224097 :         ml->vars[idx] = -1;
     141             : 
     142    39804924 :         for(i =0; i<ml->top; i++)
     143    39580828 :                 if (!ml->v[i].packed && ml->v[i].mv == idx) {
     144           1 :                         ml->vars[idx] = i;
     145           1 :                         break;
     146             :                 }
     147      224097 : }
     148             : 
     149             : static void
     150      224097 : mat_pack(MalBlkPtr mb, matlist_t *ml, int m)
     151             : {
     152             :         InstrPtr r;
     153             : 
     154      224097 :         if (ml->v[m].packed)
     155             :                 return ;
     156             : 
     157      224097 :         if((ml->v[m].mi->argc-ml->v[m].mi->retc) == 1){
     158             :                 /* simple assignment is sufficient */
     159           0 :                 r = newInstruction(mb, NULL, NULL);
     160           0 :                 getArg(r,0) = getArg(ml->v[m].mi,0);
     161           0 :                 getArg(r,1) = getArg(ml->v[m].mi,1);
     162           0 :                 r->retc = 1;
     163           0 :                 r->argc = 2;
     164             :         } else {
     165             :                 int l;
     166             : 
     167      224097 :                 r = newInstructionArgs(mb, matRef, packRef, ml->v[m].mi->argc);
     168      224097 :                 getArg(r,0) = getArg(ml->v[m].mi, 0);
     169     1114748 :                 for(l=ml->v[m].mi->retc; l< ml->v[m].mi->argc; l++)
     170      890651 :                         r= addArgument(mb,r, getArg(ml->v[m].mi,l));
     171             :         }
     172      224097 :         matlist_pack(ml, m);
     173      224097 :         pushInstruction(mb, r);
     174             : }
     175             : 
     176             : static int
     177    35698739 : checksize(matlist_t *ml, int v)
     178             : {
     179    35698739 :         if (v >= ml->vsize) {
     180             :                 int sz = ml->vsize, i, *nhorigin, *ntorigin, *nvars;
     181             : 
     182       18066 :                 unsigned int nvsize = ml->vsize * 2;
     183       18066 :                 nhorigin = (int*) GDKrealloc(ml->horigin, sizeof(int)* nvsize);
     184       18066 :                 if (nhorigin == NULL)
     185             :                         return -1;
     186       18066 :                 ml->horigin = nhorigin;
     187       18066 :                 ntorigin = (int*) GDKrealloc(ml->torigin, sizeof(int)* nvsize);
     188       18066 :                 if (ntorigin == NULL)
     189             :                         return -1;
     190       18066 :                 ml->torigin = ntorigin;
     191       18066 :                 nvars = (int*) GDKrealloc(ml->vars, sizeof(int)* nvsize);
     192       18066 :                 if (nvars == NULL)
     193             :                         return -1;
     194       18066 :                 ml->vars = nvars;
     195       18066 :                 ml->vsize = nvsize;
     196             : 
     197    12261266 :                 for (i = sz; i < ml->vsize; i++) {
     198    12243200 :                         ml->horigin[i] = ml->torigin[i] = -1;
     199    12243200 :                         ml->vars[i] = -1;
     200             :                 }
     201             :         }
     202             :         return 0;
     203             : }
     204             : 
     205             : static int
     206     7164749 : setPartnr(matlist_t *ml, int ivar, int ovar, int pnr)
     207             : {
     208             :         int tpnr = -1;
     209             : 
     210     7164749 :         if(checksize(ml, ivar) || checksize(ml, ovar))
     211           0 :                 return -1;
     212     7164744 :         if (ivar >= 0)
     213     4273812 :                 tpnr = ml->torigin[ivar];
     214     4273812 :         if (tpnr >= 0)
     215      158898 :                 ml->torigin[ovar] = tpnr;
     216     7164744 :         ml->horigin[ovar] = pnr;
     217             :         //printf("%d %d ", pnr, tpnr);
     218     7164744 :         return 0;
     219             : }
     220             : 
     221             : static int
     222      610660 : propagatePartnr(matlist_t *ml, int ivar, int ovar, int pnr)
     223             : {
     224             :         /* prop head ids to tail */
     225             :         int tpnr = -1;
     226             : 
     227      610660 :         if(checksize(ml, ivar) || checksize(ml, ovar))
     228           0 :                 return -1;
     229      610660 :         if (ivar >= 0)
     230      610660 :                 tpnr = ml->horigin[ivar];
     231      610660 :         if (tpnr >= 0)
     232      318171 :                 ml->torigin[ovar] = tpnr;
     233      610660 :         ml->horigin[ovar] = pnr;
     234             :         //printf("%d %d ", pnr, tpnr);
     235      610660 :         return 0;
     236             : }
     237             : 
     238             : static int
     239      627362 : propagateMirror(matlist_t *ml, int ivar, int ovar)
     240             : {
     241             :         /* prop head ids to head and tail */
     242             :         int tpnr;
     243             : 
     244      627362 :         if(checksize(ml, ivar) || checksize(ml, ovar))
     245           0 :                 return -1;
     246      627363 :         tpnr = ml->horigin[ivar];
     247      627363 :         if (tpnr >= 0) {
     248      627363 :                 ml->horigin[ovar] = tpnr;
     249      627363 :                 ml->torigin[ovar] = tpnr;
     250             :         }
     251             :         return 0;
     252             : }
     253             : 
     254             : static int
     255     9446613 : overlap(matlist_t *ml, int lv, int rv, int lnr, int rnr, int ontails)
     256             : {
     257             :         int lpnr, rpnr;
     258             : 
     259     9446613 :         if (checksize(ml, lv) || checksize(ml, rv))
     260           0 :                 return -1;
     261     9446613 :         lpnr = ml->torigin[lv];
     262     9446613 :         rpnr = (ontails)?ml->torigin[rv]:ml->horigin[rv];
     263             : 
     264     9446613 :         if (lpnr < 0 && rpnr < 0)
     265           0 :                 return lnr == rnr;
     266     9446613 :         if (rpnr < 0)
     267       94472 :                 return lpnr == rnr;
     268     9352141 :         if (lpnr < 0)
     269     1043597 :                 return rpnr == lnr;
     270     8308544 :         return lpnr == rpnr;
     271             : }
     272             : 
     273             : static int
     274      388819 : mat_set_prop(matlist_t *ml, MalBlkPtr mb, InstrPtr p)
     275             : {
     276      388819 :         int k, tpe = getArgType(mb, p, 0);
     277             : 
     278      388819 :         tpe = getBatType(tpe);
     279     1928620 :         for(k=1; k < p->argc; k++) {
     280     1539803 :                 if(setPartnr(ml, -1, getArg(p,k), k))
     281             :                         return -1;
     282     1539801 :                 if (tpe == TYPE_oid && propagateMirror(ml, getArg(p,k), getArg(p,k)))
     283             :                         return -1;
     284             :         }
     285             :         return 0;
     286             : }
     287             : 
     288             : static InstrPtr
     289      150873 : mat_delta(matlist_t *ml, MalBlkPtr mb, InstrPtr p, mat_t *mat, int m, int n, int o, int e, int mvar, int nvar, int ovar, int evar)
     290             : {
     291      150873 :         int tpe, k, j, is_subdelta = (getFunctionId(p) == subdeltaRef), is_projectdelta = (getFunctionId(p) == projectdeltaRef);
     292             :         InstrPtr r = NULL;
     293             :         int pushed = 0;
     294             : 
     295             :         //printf("# %s.%s(%d,%d,%d,%d)", getModuleId(p), getFunctionId(p), m, n, o, e);
     296             : 
     297      150873 :         if((r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc)) == NULL)
     298             :                 return NULL;
     299      150874 :         getArg(r, 0) = getArg(p,0);
     300      150874 :         tpe = getArgType(mb,p,0);
     301             : 
     302             :         /* Handle like mat_projection, ie overlapping partitions */
     303      150874 :         if (evar == 1 && mat[e].mi->argc != mat[m].mi->argc) {
     304             :                 int nr = 1;
     305           0 :                 for(k=1; k < mat[e].mi->argc; k++) {
     306           0 :                         for(j=1; j < mat[m].mi->argc; j++) {
     307             :                                 InstrPtr q;
     308           0 :                                 switch (overlap(ml, getArg(mat[e].mi, k), getArg(mat[m].mi, j), k, j, 0)) {
     309           0 :                                 case 0:
     310           0 :                                         continue;
     311             :                                 case -1:
     312             :                                         return NULL;
     313           0 :                                 case 1:
     314           0 :                                         q = copyInstruction(p);
     315           0 :                                         if(!q){
     316           0 :                                                 freeInstruction(r);
     317           0 :                                                 return NULL;
     318             :                                         }
     319           0 :                                         getArg(q, 0) = newTmpVariable(mb, tpe);
     320           0 :                                         getArg(q, mvar) = getArg(mat[m].mi, j);
     321           0 :                                         getArg(q, nvar) = getArg(mat[n].mi, j);
     322           0 :                                         getArg(q, ovar) = getArg(mat[o].mi, j);
     323           0 :                                         getArg(q, evar) = getArg(mat[e].mi, k);
     324           0 :                                         pushInstruction(mb, q);
     325           0 :                                         if(setPartnr(ml, getArg(mat[m].mi, j), getArg(q,0), nr)) {
     326           0 :                                                 freeInstruction(r);
     327           0 :                                                 return NULL;
     328             :                                         }
     329           0 :                                         r = addArgument(mb, r, getArg(q, 0));
     330             : 
     331           0 :                                         nr++;
     332           0 :                                         break;
     333             :                                 }
     334           0 :                         }
     335             :                 }
     336             :         } else {
     337      747464 :                 for(k=1; k < mat[m].mi->argc; k++) {
     338      596590 :                         InstrPtr q = copyInstruction(p);
     339      596594 :                         if(!q) {
     340           0 :                                 freeInstruction(r);
     341           0 :                                 return NULL;
     342             :                         }
     343      596594 :                         getArg(q, 0) = newTmpVariable(mb, tpe);
     344      596592 :                         getArg(q, mvar) = getArg(mat[m].mi, k);
     345      596592 :                         getArg(q, nvar) = getArg(mat[n].mi, k);
     346      596592 :                         getArg(q, ovar) = getArg(mat[o].mi, k);
     347      596592 :                         if (e >= 0)
     348      192437 :                                 getArg(q, evar) = getArg(mat[e].mi, k);
     349      596592 :                         pushInstruction(mb, q);
     350      596589 :                         if(setPartnr(ml, is_subdelta?getArg(mat[m].mi, k):-1, getArg(q,0), k)) {
     351           0 :                                 freeInstruction(r);
     352           0 :                                 return NULL;
     353             :                         }
     354      596590 :                         r = addArgument(mb, r, getArg(q, 0));
     355             :                 }
     356      150874 :                 if (evar == 1 && e >= 0 && mat[e].type == mat_slc && is_projectdelta) {
     357           0 :                         InstrPtr q = newInstruction(mb, algebraRef, projectionRef);
     358           0 :                         getArg(q, 0) = getArg(r, 0);
     359           0 :                         q = addArgument(mb, q, getArg(mat[e].mi, 0));
     360           0 :                         getArg(r, 0) = newTmpVariable(mb, tpe);
     361           0 :                         q = addArgument(mb, q, getArg(r, 0));
     362           0 :                         pushInstruction(mb, r);
     363           0 :                         pushInstruction(mb, q);
     364             :                         pushed = 1;
     365             :                         r = q;
     366             :                 }
     367             :         }
     368      150874 :         if(mat_add_var(ml, r, NULL, getArg(r, 0), mat_type(mat, m),  -1, -1, pushed))
     369             :                 return NULL;
     370      150874 :         if (pushed)
     371           0 :                 matlist_pack(ml, ml->top-1);
     372             :         return r;
     373             : }
     374             : 
     375             : static InstrPtr
     376           2 : mat_assign(MalBlkPtr mb, InstrPtr p, matlist_t *ml)
     377             : {
     378             :         InstrPtr r = NULL;
     379           2 :         mat_t *mat = ml->v;
     380             : 
     381           6 :         for(int i = 0; i<p->retc; i++) {
     382           4 :                 int m = is_a_mat(getArg(p,p->retc+i), ml);
     383           4 :                 assert(is_a_mat(getArg(p,i), ml) < 0 && m >= 0);
     384             : 
     385           4 :                 if((r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc)) == NULL)
     386             :                         return NULL;
     387           4 :                 getArg(r, 0) = getArg(p,i);
     388          20 :                 for(int k=1; k < mat[m].mi->argc; k++) {
     389             :                         /* reuse inputs of old mat */
     390          16 :                         r = addArgument(mb, r, getArg(mat[m].mi, k));
     391          16 :                         (void)setPartnr(ml, -1, getArg(mat[m].mi, k), k);
     392             :                 }
     393           4 :                 if (mat_add(ml, r, mat_none, getFunctionId(p))) {
     394           0 :                         freeInstruction(r);
     395           0 :                         return NULL;
     396             :                 }
     397             :         }
     398             :         return r;
     399             : }
     400             : 
     401             : static int
     402       14095 : mat_apply1(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m, int var)
     403             : {
     404       14095 :         int tpe, k, is_select = isSelect(p), is_mirror = (getFunctionId(p) == mirrorRef);
     405       14095 :         int is_identity = (getFunctionId(p) == identityRef && getModuleId(p) == batcalcRef);
     406       14095 :         int ident_var = 0, is_assign = (getFunctionId(p) == NULL), n = 0;
     407             :         InstrPtr r = NULL, q;
     408       14095 :         mat_t *mat = ml->v;
     409             : 
     410       14095 :         assert(!is_assign);
     411             : 
     412       14095 :         assert (p->retc == 1);
     413             : 
     414             :         /* Find the mat we overwrite */
     415             :         if (is_assign) {
     416             :                 n = is_a_mat(getArg(p, 0), ml);
     417             :                 is_assign = (n >= 0);
     418             :         }
     419             : 
     420       14095 :         if((r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc)) == NULL)
     421             :                 return -1;
     422       14095 :         getArg(r, 0) = getArg(p,0);
     423       14095 :         tpe = getArgType(mb,p,0);
     424             : 
     425       14095 :         if (is_identity) {
     426         264 :                 if((q = newInstruction(mb,  NULL,NULL)) == NULL) {
     427           0 :                         freeInstruction(r);
     428           0 :                         return -1;
     429             :                 }
     430         264 :                 getArg(q, 0) = newTmpVariable(mb, TYPE_oid);
     431         264 :                 q->retc = 1;
     432         264 :                 q->argc = 1;
     433         264 :                 q = pushOid(mb, q, 0);
     434         264 :                 ident_var = getArg(q, 0);
     435         264 :                 pushInstruction(mb, q);
     436             :         }
     437       71396 :         for(k=1; k < mat[m].mi->argc; k++) {
     438             :                 int res = 0;
     439       57301 :                 if((q = copyInstruction(p)) == NULL) {
     440           0 :                         freeInstruction(r);
     441           0 :                         return -1;
     442             :                 }
     443             : 
     444       57301 :                 if (is_assign)
     445           0 :                         getArg(q, 0) = getArg(mat[n].mi, k);
     446             :                 else
     447       57301 :                         getArg(q, 0) = newTmpVariable(mb, tpe);
     448       57301 :                 if (is_identity)
     449        1066 :                         getArg(q, 1) = newTmpVariable(mb, TYPE_oid);
     450       57301 :                 getArg(q, var+is_identity) = getArg(mat[m].mi, k);
     451       57301 :                 if (is_identity) {
     452        1066 :                         getArg(q, 3) = ident_var;
     453        1066 :                         q->retc = 2;
     454        1066 :                         q->argc = 4;
     455             :                         /* make sure to resolve again */
     456        1066 :                         q->token = ASSIGNsymbol;
     457        1066 :                         q->typechk = TYPE_UNKNOWN;
     458        1066 :                         q->fcn = NULL;
     459        1066 :                         q->blk = NULL;
     460             :                 }
     461       57301 :                 ident_var = getArg(q, 1);
     462       57301 :                 pushInstruction(mb, q);
     463       57301 :                 if (is_mirror || is_identity) {
     464       57301 :                         res = propagateMirror(ml, getArg(mat[m].mi, k), getArg(q,0));
     465           0 :                 } else if (is_select)
     466           0 :                         res = propagatePartnr(ml, getArg(mat[m].mi, k), getArg(q,0), k);
     467             :                 else
     468           0 :                         res = setPartnr(ml, -1, getArg(q,0), k);
     469       57301 :                 if(res) {
     470           0 :                         freeInstruction(r);
     471           0 :                         return -1;
     472             :                 }
     473       57301 :                 r = addArgument(mb, r, getArg(q, 0));
     474             :         }
     475       14095 :         if(!r || mat_add(ml, r, mat_type(ml->v, m), getFunctionId(p))) {
     476           0 :                 return -1;
     477             :         }
     478             :         return 0;
     479             : }
     480             : 
     481             : static int
     482      208024 : mat_apply(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int nrmats)
     483             : {
     484             :         int matvar[8], fargument[8], k, l, parts = 0;
     485             : 
     486      208024 :         if (nrmats == 1 &&
     487      104046 :                 ((getModuleId(p) == batcalcRef && getFunctionId(p) == identityRef) || (getModuleId(p) == batRef && getFunctionId(p) == mirrorRef)))
     488       14095 :                 return mat_apply1(mb, p, ml, is_a_mat(getArg(p,1),ml), 1);
     489      193929 :         assert(nrmats <= 8);
     490             : 
     491      832084 :         for(k=p->retc, l=0; k < p->argc; k++) {
     492      638155 :                 int mv = is_a_mat(getArg(p,k), ml);
     493      638155 :                 if (mv >=0) {
     494      315294 :                         matvar[l] = mv;
     495      315294 :                         fargument[l] = k;
     496      315294 :                         l++;
     497      315294 :                         if (parts==0)
     498      193927 :                                 parts = ml->v[mv].mi->argc;
     499      315294 :                         if (parts != ml->v[mv].mi->argc)
     500             :                                 return -1;
     501             :                 }
     502             :         }
     503             : 
     504      193929 :         InstrPtr *r = (InstrPtr*) GDKmalloc(sizeof(InstrPtr)* p->retc);
     505      193928 :         if(!r)
     506             :                 return -1;
     507      387858 :         for(k=0; k < p->retc; k++) {
     508      193928 :                 if((r[k] = newInstructionArgs(mb, matRef, packRef, parts)) == NULL) {
     509           0 :                         for(l=0; l < k; l++)
     510           0 :                                 freeInstruction(r[l]);
     511           0 :                         GDKfree(r);
     512           0 :                         return -1;
     513             :                 }
     514      193930 :                 getArg(r[k],0) = getArg(p,k);
     515             :         }
     516             : 
     517      989622 :         for(k = 1; k < ml->v[matvar[0]].mi->argc; k++) {
     518             :                 int tpe;
     519      795695 :                 InstrPtr q = copyInstruction(p);
     520      795696 :                 if(!q) {
     521           0 :                         GDKfree(r);
     522           0 :                         return -1;
     523             :                 }
     524             : 
     525     1591393 :                 for(l=0; l < p->retc; l++) {
     526      795697 :                         tpe = getArgType(mb,p,l);
     527      795697 :                         getArg(q, l) = newTmpVariable(mb, tpe);
     528             :                 }
     529     2088220 :                 for (l = 0; l<nrmats; l++)
     530     1292524 :                         getArg(q, fargument[l]) = getArg(ml->v[matvar[l]].mi, k);
     531      795696 :                 pushInstruction(mb, q);
     532     1591385 :                 for(l=0; l < p->retc; l++) {
     533      795693 :                         if(setPartnr(ml, -1, getArg(q,l), k)) {
     534           0 :                                 for(l=0; l < k; l++)
     535           0 :                                         freeInstruction(r[l]);
     536           0 :                                 GDKfree(r);
     537           0 :                                 return -1;
     538             :                         }
     539      795692 :                         r[l] = addArgument(mb, r[l], getArg(q, l));
     540             :                 }
     541             :         }
     542      387854 :         for(k=0; k < p->retc; k++) {
     543      193927 :                 if(mat_add_var(ml, r[k], NULL, getArg(r[k], 0), mat_type(ml->v, matvar[0]),  -1, -1, 0)) {
     544           0 :                         for(l=0; l < k; l++)
     545           0 :                                 freeInstruction(r[l]);
     546           0 :                         GDKfree(r);
     547           0 :                         return -1;
     548             :                 }
     549             :         }
     550      193927 :         GDKfree(r);
     551      193928 :         return 0;
     552             : }
     553             : 
     554             : 
     555             : static int
     556       16156 : mat_setop(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m, int n, int o)
     557             : {
     558       16156 :         int tpe = getArgType(mb,p, 0), k, j;
     559       16156 :         mat_t *mat = ml->v;
     560       16156 :         InstrPtr r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
     561             : 
     562       16156 :         if(!r)
     563             :                 return -1;
     564             : 
     565       16156 :         getArg(r,0) = getArg(p,0);
     566             : 
     567             :         //printf("# %s.%s(%d,%d)", getModuleId(p), getFunctionId(p), m, n);
     568       16156 :         assert(m>=0 || n>=0);
     569       16156 :         if (m >= 0 && n >= 0) {
     570             :                 int nr = 1;
     571             : 
     572       15851 :                 assert(o < 0 || mat[m].mi->argc == mat[o].mi->argc);
     573             : 
     574       80127 :                 for(k=1; k<mat[m].mi->argc; k++) {
     575       64276 :                         InstrPtr q = copyInstruction(p);
     576       64276 :                         InstrPtr s = newInstructionArgs(mb, matRef, packRef, mat[n].mi->argc);
     577             :                         int ttpe = 0;
     578             : 
     579       64276 :                         if(!q || !s) {
     580           0 :                                 freeInstruction(q);
     581           0 :                                 freeInstruction(s);
     582           0 :                                 freeInstruction(r);
     583           0 :                                 return -1;
     584             :                         }
     585             : 
     586       64276 :                         getArg(s,0) = newTmpVariable(mb, getArgType(mb, mat[n].mi, k));
     587             : 
     588       64276 :                         ttpe = getArgType(mb, mat[n].mi, 0);
     589      386952 :                         for (j=1; j<mat[n].mi->argc; j++) {
     590             :                                 int ov = 0;
     591      322676 :                                 if (getBatType(ttpe) != TYPE_oid || (ov = overlap(ml, getArg(mat[m].mi, k), getArg(mat[n].mi, j), k, j, 1)) == 1){
     592       74504 :                                         s = addArgument(mb,s,getArg(mat[n].mi,j));
     593             :                                 }
     594      322676 :                                 if (ov == -1)
     595             :                                         return -1;
     596             :                         }
     597       64276 :                         if (s->retc == 1 && s->argc == 2){ /* only one input, change into an assignment */
     598       61103 :                                 getFunctionId(s) = NULL;
     599       61103 :                                 getModuleId(s) = NULL;
     600       61103 :                                 s->token = ASSIGNsymbol;
     601       61103 :                                 s->typechk = TYPE_UNKNOWN;
     602       61103 :                                 s->fcn = NULL;
     603       61103 :                                 s->blk = NULL;
     604             :                         }
     605       64276 :                         pushInstruction(mb,s);
     606             : 
     607       64276 :                         getArg(q,0) = newTmpVariable(mb, tpe);
     608       64276 :                         getArg(q,1) = getArg(mat[m].mi,k);
     609       64276 :                         getArg(q,2) = getArg(s,0);
     610       64276 :                         if (o >= 0)
     611        2325 :                                 getArg(q,3) = getArg(mat[o].mi, k);
     612       64276 :                         if(setPartnr(ml, getArg(mat[m].mi,k), getArg(q,0), nr)) {
     613           0 :                                 freeInstruction(q);
     614           0 :                                 freeInstruction(r);
     615           0 :                                 return -1;
     616             :                         }
     617       64276 :                         pushInstruction(mb,q);
     618             : 
     619       64276 :                         r = addArgument(mb,r,getArg(q,0));
     620       64276 :                         nr++;
     621             :                 }
     622             :         } else {
     623         305 :                 assert(m >= 0);
     624         305 :                 assert(o < 0 || mat[m].mi->argc == mat[o].mi->argc);
     625             : 
     626        1525 :                 for(k=1; k<mat[m].mi->argc; k++) {
     627        1220 :                         InstrPtr q = copyInstruction(p);
     628        1220 :                         if(!q) {
     629           0 :                                 freeInstruction(r);
     630           0 :                                 return -1;
     631             :                         }
     632             : 
     633        1220 :                         getArg(q,0) = newTmpVariable(mb, tpe);
     634        1220 :                         getArg(q,1) = getArg(mat[m].mi, k);
     635        1220 :                         if (o >= 0)
     636           4 :                                 getArg(q,3) = getArg(mat[o].mi, k);
     637        1220 :                         pushInstruction(mb,q);
     638             : 
     639        1220 :                         if(setPartnr(ml, getArg(q, 2), getArg(q,0), k)) {
     640           0 :                                 freeInstruction(r);
     641           0 :                                 return -1;
     642             :                         }
     643        1220 :                         r = addArgument(mb, r, getArg(q,0));
     644             :                 }
     645             :         }
     646             : 
     647       16156 :         return mat_add(ml, r, mat_none, getFunctionId(p));
     648             : }
     649             : 
     650             : static int
     651      990050 : mat_projection(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m, int n)
     652             : {
     653      990050 :         int tpe = getArgType(mb,p, 0), k, j;
     654      990050 :         mat_t *mat = ml->v;
     655             :         InstrPtr r;
     656             : 
     657             :         //printf("# %s.%s(%d,%d)", getModuleId(p), getFunctionId(p), m, n);
     658      990050 :         assert(m>=0 || n>=0);
     659      990050 :         if (m >= 0 && n >= 0) {
     660             :                 int nr = 1;
     661      875807 :                 r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc * mat[n].mi->argc);
     662             : 
     663      875807 :                 if(!r)
     664             :                         return -1;
     665             : 
     666      875807 :                 getArg(r,0) = getArg(p,0);
     667             : 
     668     4403203 :                 for(k=1; k<mat[m].mi->argc; k++) {
     669     9124529 :                         for (j=1; j<mat[n].mi->argc; j++) {
     670             :                                 InstrPtr q;
     671     9124529 :                                 switch (overlap(ml, getArg(mat[m].mi, k), getArg(mat[n].mi, j), k, j, 0)) {
     672     5597133 :                                 case 0:
     673     5597133 :                                         continue;
     674             :                                 case -1:
     675             :                                         return -1;
     676     3527396 :                                 case 1:
     677     3527396 :                                         q = copyInstruction(p);
     678             : 
     679     3527396 :                                         if(!q) {
     680           0 :                                                 freeInstruction(r);
     681           0 :                                                 return -1;
     682             :                                         }
     683             : 
     684     3527396 :                                         getArg(q,0) = newTmpVariable(mb, tpe);
     685     3527396 :                                         getArg(q,1) = getArg(mat[m].mi,k);
     686     3527396 :                                         getArg(q,2) = getArg(mat[n].mi,j);
     687     3527396 :                                         pushInstruction(mb,q);
     688             : 
     689     3527396 :                                         if(setPartnr(ml, getArg(mat[n].mi, j), getArg(q,0), nr)) {
     690           0 :                                                 freeInstruction(r);
     691           0 :                                                 return -1;
     692             :                                         }
     693     3527396 :                                         r = addArgument(mb,r,getArg(q,0));
     694             : 
     695     3527396 :                                         nr++;
     696     3527396 :                                         break;
     697             :                                 }
     698             :                                 break;                  /* only in case of overlap */
     699             :                         }
     700             :                 }
     701             :         } else {
     702      114243 :                 assert(m >= 0);
     703      114243 :                 r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
     704             : 
     705      114243 :                 if(!r)
     706             :                         return -1;
     707             : 
     708      114243 :                 getArg(r,0) = getArg(p,0);
     709             : 
     710      575385 :                 for(k=1; k<mat[m].mi->argc; k++) {
     711      461142 :                         InstrPtr q = copyInstruction(p);
     712             : 
     713      461142 :                         if(!q) {
     714           0 :                                 freeInstruction(r);
     715           0 :                                 return -1;
     716             :                         }
     717             : 
     718      461142 :                         getArg(q,0) = newTmpVariable(mb, tpe);
     719      461142 :                         getArg(q,1) = getArg(mat[m].mi, k);
     720      461142 :                         pushInstruction(mb,q);
     721             : 
     722      461142 :                         if(setPartnr(ml, getArg(q, 2), getArg(q,0), k)) {
     723           0 :                                 freeInstruction(r);
     724           0 :                                 return -1;
     725             :                         }
     726      461142 :                         r = addArgument(mb, r, getArg(q,0));
     727             :                 }
     728             :         }
     729             : 
     730      990050 :         return mat_add(ml, r, mat_none, getFunctionId(p));
     731             : }
     732             : 
     733             : static int
     734       74534 : mat_join2(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m, int n, int lc, int rc)
     735             : {
     736       74534 :         int tpe = getArgType(mb,p, 0), j,k, nr = 1;
     737       74534 :         mat_t *mat = ml->v;
     738             :         InstrPtr l;
     739             :         InstrPtr r;
     740             : 
     741             :         //printf("# %s.%s(%d,%d)", getModuleId(p), getFunctionId(p), m, n);
     742             : 
     743       74534 :         assert(m>=0 || n>=0);
     744       74534 :         if (m >= 0 && n >= 0) {
     745         748 :                 l = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc * mat[n].mi->argc);
     746         748 :                 r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc * mat[n].mi->argc);
     747         748 :                 if(!l || !r) {
     748           0 :                         freeInstruction(l);
     749           0 :                         freeInstruction(r);
     750           0 :                         return -1;
     751             :                 }
     752             : 
     753         748 :                 getArg(l,0) = getArg(p,0);
     754         748 :                 getArg(r,0) = getArg(p,1);
     755             : 
     756        3769 :                 for(k=1; k<mat[m].mi->argc; k++) {
     757       15826 :                         for (j=1; j<mat[n].mi->argc; j++) {
     758       12805 :                                 InstrPtr q = copyInstruction(p);
     759             : 
     760       12805 :                                 if(!q) {
     761           0 :                                         freeInstruction(l);
     762           0 :                                         freeInstruction(r);
     763           0 :                                         return -1;
     764             :                                 }
     765             : 
     766       12805 :                                 getArg(q,0) = newTmpVariable(mb, tpe);
     767       12805 :                                 getArg(q,1) = newTmpVariable(mb, tpe);
     768       12805 :                                 getArg(q,2) = getArg(mat[m].mi,k);
     769       12805 :                                 getArg(q,3) = getArg(mat[n].mi,j);
     770       12805 :                                 if (lc>=0)
     771         171 :                                         getArg(q,4) = getArg(mat[lc].mi,k);
     772       12805 :                                 if (rc>=0)
     773           0 :                                         getArg(q,5) = getArg(mat[rc].mi,j);
     774       12805 :                                 pushInstruction(mb,q);
     775             : 
     776       25610 :                                 if(propagatePartnr(ml, getArg(mat[m].mi, k), getArg(q,0), nr) ||
     777       12805 :                                    propagatePartnr(ml, getArg(mat[n].mi, j), getArg(q,1), nr)) {
     778           0 :                                         freeInstruction(r);
     779           0 :                                         freeInstruction(l);
     780           0 :                                         return -1;
     781             :                                 }
     782             : 
     783             :                                 /* add result to mat */
     784       12805 :                                 l = addArgument(mb,l,getArg(q,0));
     785       12805 :                                 r = addArgument(mb,r,getArg(q,1));
     786       12805 :                                 nr++;
     787             :                         }
     788             :                 }
     789             :         } else {
     790       73786 :                 int mv = (m>=0)?m:n;
     791       73786 :                 int av = (m<0);
     792       73786 :                 int bv = (m>=0);
     793       73786 :                 int mc = (lc>=0)?lc:rc;
     794             : 
     795       73786 :                 l = newInstructionArgs(mb, matRef, packRef, mat[mv].mi->argc);
     796       73786 :                 r = newInstructionArgs(mb, matRef, packRef, mat[mv].mi->argc);
     797       73786 :                 if(!l || !r) {
     798           0 :                         freeInstruction(l);
     799           0 :                         freeInstruction(r);
     800           0 :                         return -1;
     801             :                 }
     802             : 
     803       73786 :                 getArg(l,0) = getArg(p,0);
     804       73786 :                 getArg(r,0) = getArg(p,1);
     805             : 
     806      366175 :                 for(k=1; k<mat[mv].mi->argc; k++) {
     807      292389 :                         InstrPtr q = copyInstruction(p);
     808             : 
     809      292389 :                         if(!q) {
     810           0 :                                 freeInstruction(l);
     811           0 :                                 freeInstruction(r);
     812           0 :                                 return -1;
     813             :                         }
     814             : 
     815      292389 :                         getArg(q,0) = newTmpVariable(mb, tpe);
     816      292389 :                         getArg(q,1) = newTmpVariable(mb, tpe);
     817      292389 :                         getArg(q,p->retc+av) = getArg(mat[mv].mi, k);
     818      292389 :                         if (mc>=0)
     819        2274 :                                 getArg(q,p->retc+2+av) = getArg(mat[mc].mi, k);
     820      292389 :                         pushInstruction(mb,q);
     821             : 
     822      584778 :                         if(propagatePartnr(ml, getArg(mat[mv].mi, k), getArg(q,av), k) ||
     823      292389 :                            propagatePartnr(ml, getArg(p, p->retc+bv), getArg(q,bv), k)) {
     824           0 :                                 freeInstruction(l);
     825           0 :                                 freeInstruction(r);
     826           0 :                                 return -1;
     827             :                         }
     828             : 
     829             :                         /* add result to mat */
     830      292389 :                         l = addArgument(mb, l, getArg(q,0));
     831      292389 :                         r = addArgument(mb, r, getArg(q,1));
     832             :                 }
     833             :         }
     834       74534 :         if (mat_add(ml, l, mat_none, getFunctionId(p))) {
     835           0 :                 freeInstruction(l);
     836           0 :                 freeInstruction(r);
     837           0 :                 return -1;
     838       74534 :         } else if (mat_add(ml, r, mat_none, getFunctionId(p))) {
     839           0 :                 freeInstruction(r);
     840           0 :                 return -1;
     841             :         }
     842             :         return 0;
     843             : }
     844             : 
     845             : static int
     846           4 : join_split(Client cntxt, InstrPtr p, int args)
     847             : {
     848             :         char *name = NULL;
     849             :         size_t len;
     850             :         int i, res = 0;
     851             :         Symbol sym;
     852             :         MalBlkPtr mb;
     853             :         InstrPtr q;
     854             : 
     855           4 :         if (args <= 3) /* we asume there are no 2x1 joins! */
     856             :                 return 1;
     857             : 
     858           0 :         len = strlen( getFunctionId(p) );
     859           0 :         name = GDKmalloc(len+3);
     860           0 :         if (!name)
     861             :                 return -1;
     862           0 :         strncpy(name, getFunctionId(p), len-7);
     863           0 :         strcpy(name+len-7, "join");
     864             : 
     865           0 :         sym = findSymbol(cntxt->usermodule, getModuleId(p), name);
     866           0 :         assert(sym);
     867           0 :         mb = sym->def;
     868             : 
     869           0 :         q = mb->stmt[0];
     870           0 :         for(i = q->retc; i<q->argc; i++ ) {
     871           0 :                 if (isaBatType(getArgType(mb,q,i)))
     872           0 :                         res++;
     873             :                 else
     874             :                         break;
     875             :         }
     876           0 :         GDKfree(name);
     877           0 :         return res-1;
     878             : }
     879             : 
     880             : /* 1 or 2 mat lists:
     881             :  *      in case of one take the second half of the code
     882             :  *      in case of two we need to detect the list lengths.
     883             :  *
     884             :  * input is one list of arguments (just total length of mats)
     885             :  */
     886             : static int
     887          35 : mat_joinNxM(Client cntxt, MalBlkPtr mb, InstrPtr p, matlist_t *ml, int args)
     888             : {
     889          35 :         int tpe = getArgType(mb,p, 0), j,k, nr = 1;
     890             :         InstrPtr l;
     891             :         InstrPtr r;
     892          35 :         mat_t *mat = ml->v;
     893          35 :         int *mats = (int*)GDKzalloc(sizeof(int) * args);
     894             :         int nr_mats = 0, first = -1, res = 0;
     895             : 
     896          35 :         if (!mats) {
     897             :                 return -1;
     898             :         }
     899             : 
     900         149 :         for(j=0;j<args;j++) {
     901         114 :                 mats[j] = is_a_mat(getArg(p,p->retc+j), ml);
     902         114 :                 if (mats[j] != -1) {
     903          45 :                         nr_mats++;
     904          45 :                         if (first < 0)
     905             :                                 first = j;
     906             :                 }
     907             :         }
     908             : 
     909             :         //printf("# %s.%s(%d,%d)", getModuleId(p), getFunctionId(p), m, n);
     910             : 
     911          35 :         if (args == nr_mats) {
     912           4 :                 int mv1 = mats[0], i;
     913           4 :                 int mv2 = mats[args-1];
     914           4 :                 int split = join_split(cntxt, p, args);
     915             :                 int nr_mv1 = split;
     916             : 
     917           4 :                 l = newInstructionArgs(mb, matRef, packRef, mat[mv1].mi->argc * mat[mv2].mi->argc);
     918           4 :                 r = newInstructionArgs(mb, matRef, packRef, mat[mv1].mi->argc * mat[mv2].mi->argc);
     919           4 :                 getArg(l,0) = getArg(p,0);
     920           4 :                 getArg(r,0) = getArg(p,1);
     921             : 
     922           4 :                 if (split < 0) {
     923           0 :                         freeInstruction(r);
     924           0 :                         freeInstruction(l);
     925           0 :                         GDKfree(mats);
     926           0 :                         mb->errors= createException(MAL,"mergetable.join", SQLSTATE(42000) " incorrect split level");
     927           0 :                         return 0;
     928             :                 }
     929             :                 /* now detect split point */
     930          16 :                 for(k=1; k<mat[mv1].mi->argc; k++) {
     931          48 :                         for (j=1; j<mat[mv2].mi->argc; j++) {
     932          36 :                                 InstrPtr q = copyInstruction(p);
     933          36 :                                 if(!q) {
     934           0 :                                         freeInstruction(r);
     935           0 :                                         freeInstruction(l);
     936           0 :                                         GDKfree(mats);
     937           0 :                                         return -1;
     938             :                                 }
     939             : 
     940          36 :                                 getArg(q,0) = newTmpVariable(mb, tpe);
     941          36 :                                 getArg(q,1) = newTmpVariable(mb, tpe);
     942          72 :                                 for (i = 0; i < nr_mv1; i++ )
     943          36 :                                         getArg(q,q->retc+i) = getArg(mat[mats[i]].mi,k);
     944         108 :                                 for (; i < nr_mats; i++ )
     945          72 :                                         getArg(q,q->retc+i) = getArg(mat[mats[i]].mi,j);
     946          36 :                                 pushInstruction(mb,q);
     947             : 
     948          72 :                                 if(propagatePartnr(ml, getArg(mat[mv1].mi, k), getArg(q,0), nr) ||
     949          36 :                                    propagatePartnr(ml, getArg(mat[mv2].mi, j), getArg(q,1), nr)) {
     950           0 :                                         freeInstruction(r);
     951           0 :                                         freeInstruction(l);
     952           0 :                                         GDKfree(mats);
     953           0 :                                         return -1;
     954             :                                 }
     955             : 
     956             :                                 /* add result to mat */
     957          36 :                                 l = addArgument(mb,l,getArg(q,0));
     958          36 :                                 r = addArgument(mb,r,getArg(q,1));
     959          36 :                                 nr++;
     960             :                         }
     961             :                 }
     962             :         } else {
     963             :                 /* only one side
     964             :                  * mats from first..first+nr_mats
     965             :                  */
     966          31 :                 int mv = mats[first];
     967             : 
     968          31 :                 l = newInstructionArgs(mb, matRef, packRef, mat[mv].mi->argc);
     969          31 :                 r = newInstructionArgs(mb, matRef, packRef, mat[mv].mi->argc);
     970          31 :                 getArg(l,0) = getArg(p,0);
     971          31 :                 getArg(r,0) = getArg(p,1);
     972             : 
     973         131 :                 for(k=1; k<mat[mv].mi->argc; k++) {
     974         100 :                         InstrPtr q = copyInstruction(p);
     975         100 :                         if(!q) {
     976           0 :                                 freeInstruction(r);
     977           0 :                                 freeInstruction(l);
     978           0 :                                 GDKfree(mats);
     979           0 :                                 return -1;
     980             :                         }
     981             : 
     982         100 :                         getArg(q,0) = newTmpVariable(mb, tpe);
     983         100 :                         getArg(q,1) = newTmpVariable(mb, tpe);
     984         206 :                         for (j=0;j<nr_mats;j++) {
     985         106 :                                 assert(mat[mats[first]].mi->argc == mat[mats[first+j]].mi->argc);
     986         106 :                                 getArg(q,p->retc+first+j) = getArg(mat[mats[first+j]].mi, k);
     987             :                         }
     988         200 :                         if(propagatePartnr(ml, getArg(mat[mv].mi, k), getArg(q,(first!=0)), k) ||
     989         200 :                            propagatePartnr(ml, getArg(p, p->retc+(first)?nr_mats:0), getArg(q,(first==0)), k)) {
     990           0 :                                 freeInstruction(q);
     991           0 :                                 freeInstruction(r);
     992           0 :                                 freeInstruction(l);
     993           0 :                                 GDKfree(mats);
     994           0 :                                 return -1;
     995             :                         }
     996         100 :                         pushInstruction(mb,q);
     997             : 
     998             :                         /* add result to mat */
     999         100 :                         l = addArgument(mb, l, getArg(q,0));
    1000         100 :                         r = addArgument(mb, r, getArg(q,1));
    1001             :                 }
    1002             :         }
    1003          35 :         res = mat_add(ml, l, mat_none, getFunctionId(p)) || mat_add(ml, r, mat_none, getFunctionId(p));
    1004          35 :         GDKfree(mats);
    1005          35 :         return res;
    1006             : }
    1007             : 
    1008             : 
    1009             : static const char *
    1010        5385 : aggr_phase2(const char *aggr, int type_dbl)
    1011             : {
    1012        5385 :         if (aggr == countRef || aggr == count_no_nilRef || (aggr == avgRef && type_dbl))
    1013        1718 :                 return sumRef;
    1014        3667 :         if (aggr == subcountRef || (aggr == subavgRef && type_dbl))
    1015        2971 :                 return subsumRef;
    1016             :         /* min/max/sum/prod and unique are fine */
    1017             :         return aggr;
    1018             : }
    1019             : 
    1020             : static void
    1021        1986 : mat_aggr(MalBlkPtr mb, InstrPtr p, mat_t *mat, int m)
    1022             : {
    1023        1986 :         int tp = getArgType(mb,p,0), k, tp2 = TYPE_lng, i;
    1024        1986 :         int battp = (getModuleId(p)==aggrRef)?newBatType(tp):tp, battp2 = 0;
    1025        1986 :         int isAvg = (getFunctionId(p) == avgRef);
    1026             :         InstrPtr r = NULL, s = NULL, q = NULL, u = NULL, v = NULL;
    1027             : 
    1028             :         /* we pack the partitial result */
    1029        1986 :         r = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
    1030        1986 :         getArg(r,0) = newTmpVariable(mb, battp);
    1031             : 
    1032        1986 :         if (isAvg) { /* remainders or counts */
    1033             :                 battp2 = newBatType( tp2);
    1034        1026 :                 u = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
    1035        1026 :                 getArg(u,0) = newTmpVariable(mb, battp2);
    1036             :         }
    1037        1986 :         if (isAvg && tp != TYPE_dbl) { /* counts */
    1038             :                 battp2 = newBatType( tp2);
    1039          23 :                 v = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
    1040          23 :                 getArg(v,0) = newTmpVariable(mb, battp2);
    1041             :         }
    1042       10739 :         for(k=1; k< mat[m].mi->argc; k++) {
    1043        8753 :                 q = newInstruction(mb, NULL, NULL);
    1044        8753 :                 if (isAvg && tp == TYPE_dbl)
    1045        4003 :                         setModuleId(q,batcalcRef);
    1046             :                 else
    1047        4750 :                         setModuleId(q,getModuleId(p));
    1048        8753 :                 setFunctionId(q,getFunctionId(p));
    1049        8753 :                 getArg(q,0) = newTmpVariable(mb, tp);
    1050        8753 :                 if (isAvg)
    1051        4310 :                         q = pushReturn(mb, q, newTmpVariable(mb, tp2));
    1052        8753 :                 if (isAvg && tp != TYPE_dbl)
    1053         307 :                         q = pushReturn(mb, q, newTmpVariable(mb, tp2));
    1054        8753 :                 q = addArgument(mb,q,getArg(mat[m].mi,k));
    1055        9604 :                 for (i = q->argc; i<p->argc; i++)
    1056         851 :                         q = addArgument(mb,q,getArg(p,i));
    1057        8753 :                 pushInstruction(mb,q);
    1058             : 
    1059        8753 :                 r = addArgument(mb,r,getArg(q,0));
    1060        8753 :                 if (isAvg)
    1061        4310 :                         u = addArgument(mb,u,getArg(q,1));
    1062        8753 :                 if (isAvg && tp != TYPE_dbl)
    1063         307 :                         v = addArgument(mb,v,getArg(q,2));
    1064             :         }
    1065        1986 :         pushInstruction(mb,r);
    1066        1986 :         if (isAvg)
    1067        1026 :                 pushInstruction(mb, u);
    1068        1986 :         if (isAvg && tp != TYPE_dbl)
    1069          23 :                 pushInstruction(mb, v);
    1070             : 
    1071             :         /* Filter empty partitions */
    1072        1986 :         if (getModuleId(p) == aggrRef && !isAvg) {
    1073         960 :                 s = newInstruction(mb, algebraRef, selectNotNilRef);
    1074         960 :                 getArg(s,0) = newTmpVariable(mb, battp);
    1075         960 :                 s = addArgument(mb, s, getArg(r,0));
    1076         960 :                 pushInstruction(mb, s);
    1077             :                 r = s;
    1078             :         }
    1079             : 
    1080             :         /* for avg we do sum (avg*(count/sumcount) ) */
    1081        1986 :         if (isAvg && tp == TYPE_dbl) {
    1082             :                 InstrPtr v,w,x,y,cond;
    1083             : 
    1084             :                 /* lng w = sum counts */
    1085        1003 :                 w = newInstruction(mb, aggrRef, sumRef);
    1086        1003 :                 getArg(w,0) = newTmpVariable(mb, tp2);
    1087        1003 :                 w = addArgument(mb, w, getArg(u, 0));
    1088        1003 :                 pushInstruction(mb, w);
    1089             : 
    1090             :                 /*  y=count = ifthenelse(w=count==0,NULL,w=count)  */
    1091        1003 :                 cond = newInstruction(mb, calcRef, eqRef);
    1092        1003 :                 getArg(cond,0) = newTmpVariable(mb, TYPE_bit);
    1093        1003 :                 cond = addArgument(mb, cond, getArg(w, 0));
    1094        1003 :                 cond = pushLng(mb, cond, 0);
    1095        1003 :                 pushInstruction(mb,cond);
    1096             : 
    1097        1003 :                 y = newInstruction(mb, calcRef, ifthenelseRef);
    1098        1003 :                 getArg(y,0) = newTmpVariable(mb, tp2);
    1099        1003 :                 y = addArgument(mb, y, getArg(cond, 0));
    1100        1003 :                 y = pushNil(mb, y, tp2);
    1101        1003 :                 y = addArgument(mb, y, getArg(w, 0));
    1102        1003 :                 pushInstruction(mb,y);
    1103             : 
    1104             :                 /* dbl v = double(count) */
    1105        1003 :                 v = newInstruction(mb,  batcalcRef, dblRef);
    1106        1003 :                 getArg(v,0) = newTmpVariable(mb, newBatType(TYPE_dbl));
    1107        1003 :                 v = addArgument(mb, v, getArg(u, 0));
    1108        1003 :                 pushInstruction(mb, v);
    1109             : 
    1110             :                 /* dbl x = v / y */
    1111        1003 :                 x = newInstruction(mb, batcalcRef, divRef);
    1112        1003 :                 getArg(x,0) = newTmpVariable(mb, newBatType(TYPE_dbl));
    1113        1003 :                 x = addArgument(mb, x, getArg(v, 0));
    1114        1003 :                 x = addArgument(mb, x, getArg(y, 0));
    1115        1003 :                 if (isaBatType(getArgType(mb,x,0)))
    1116        1003 :                         x = pushNil(mb, x, TYPE_bat);
    1117        1003 :                 if (isaBatType(getArgType(mb,y,0)))
    1118           0 :                         x = pushNil(mb, x, TYPE_bat);
    1119        1003 :                 pushInstruction(mb, x);
    1120             : 
    1121             :                 /* dbl w = avg * x */
    1122        1003 :                 w = newInstruction(mb, batcalcRef, mulRef);
    1123        1003 :                 getArg(w,0) = newTmpVariable(mb, battp);
    1124        1003 :                 w = addArgument(mb, w, getArg(r, 0));
    1125        1003 :                 w = addArgument(mb, w, getArg(x, 0));
    1126        1003 :                 if (isaBatType(getArgType(mb,r,0)))
    1127        1003 :                         w = pushNil(mb, w, TYPE_bat);
    1128        1003 :                 if (isaBatType(getArgType(mb,x,0)))
    1129        1003 :                         w = pushNil(mb, w, TYPE_bat);
    1130        1003 :                 pushInstruction(mb, w);
    1131             : 
    1132             :                 r = w;
    1133             : 
    1134             :                 /* filter nils */
    1135        1003 :                 s = newInstruction(mb, algebraRef, selectNotNilRef);
    1136        1003 :                 getArg(s,0) = newTmpVariable(mb, battp);
    1137        1003 :                 s = addArgument(mb, s, getArg(r,0));
    1138        1003 :                 pushInstruction(mb, s);
    1139             :                 r = s;
    1140             :         }
    1141             : 
    1142        1986 :         s = newInstruction(mb, getModuleId(p), aggr_phase2(getFunctionId(p), tp == TYPE_dbl));
    1143        1986 :         getArg(s,0) = getArg(p,0);
    1144        1986 :         s = addArgument(mb, s, getArg(r,0));
    1145        1986 :         if (isAvg && tp != TYPE_dbl) {
    1146          23 :                 s = addArgument(mb, s, getArg(u,0));
    1147          23 :                 s = addArgument(mb, s, getArg(v,0));
    1148             :         }
    1149        1986 :         pushInstruction(mb, s);
    1150        1986 : }
    1151             : 
    1152             : static int
    1153             : chain_by_length(mat_t *mat, int g)
    1154             : {
    1155             :         int cnt = 0;
    1156       21369 :         while(g >= 0) {
    1157       13103 :                 g = mat[g].pm;
    1158       13103 :                 cnt++;
    1159             :         }
    1160             :         return cnt;
    1161             : }
    1162             : 
    1163             : static int
    1164             : walk_n_back(mat_t *mat, int g, int cnt)
    1165             : {
    1166       22026 :         while(cnt > 0){
    1167        8923 :                 g = mat[g].pm;
    1168        8923 :                 cnt--;
    1169             :         }
    1170             :         return g;
    1171             : }
    1172             : 
    1173             : static int
    1174             : group_by_ext(matlist_t *ml, int g)
    1175             : {
    1176             :         int i;
    1177             : 
    1178       26102 :         for(i=g; i< ml->top; i++){
    1179       26102 :                 if (ml->v[i].pm == g)
    1180             :                         return i;
    1181             :         }
    1182             :         return 0;
    1183             : }
    1184             : 
    1185             : /* In some cases we have non groupby attribute columns, these require
    1186             :  * gext.projection(mat.pack(per partition ext.projections(x)))
    1187             :  */
    1188             : 
    1189             : static int
    1190        8101 : mat_group_project(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int e, int a)
    1191             : {
    1192        8101 :         int tp = getArgType(mb,p,0), k;
    1193        8101 :         mat_t *mat = ml->v;
    1194        8101 :         InstrPtr ai1 = newInstructionArgs(mb, matRef, packRef, mat[a].mi->argc), r;
    1195             : 
    1196        8101 :         if(!ai1)
    1197             :                 return -1;
    1198             : 
    1199        8101 :         getArg(ai1,0) = newTmpVariable(mb, tp);
    1200             : 
    1201        8101 :         assert(mat[e].mi->argc == mat[a].mi->argc);
    1202       43106 :         for(k=1; k<mat[a].mi->argc; k++) {
    1203       35005 :                 InstrPtr q = copyInstruction(p);
    1204       35005 :                 if(!q) {
    1205           0 :                         freeInstruction(ai1);
    1206           0 :                         return -1;
    1207             :                 }
    1208             : 
    1209       35005 :                 getArg(q,0) = newTmpVariable(mb, tp);
    1210       35005 :                 getArg(q,1) = getArg(mat[e].mi,k);
    1211       35005 :                 getArg(q,2) = getArg(mat[a].mi,k);
    1212       35005 :                 pushInstruction(mb,q);
    1213       35005 :                 if(setPartnr(ml, getArg(mat[a].mi,k), getArg(q,0), k)){
    1214           0 :                         freeInstruction(ai1);
    1215           0 :                         return -1;
    1216             :                 }
    1217             : 
    1218             :                 /* pack the result into a mat */
    1219       35005 :                 ai1 = addArgument(mb,ai1,getArg(q,0));
    1220             :         }
    1221        8101 :         pushInstruction(mb, ai1);
    1222             : 
    1223        8101 :         if((r = copyInstruction(p)) == NULL)
    1224             :                 return -1;
    1225        8101 :         getArg(r,1) = mat[e].mv;
    1226        8101 :         getArg(r,2) = getArg(ai1,0);
    1227        8101 :         pushInstruction(mb,r);
    1228        8101 :         return 0;
    1229             : }
    1230             : 
    1231             : /* Per partition aggregates are merged and aggregated together. For
    1232             :  * most (handled) aggregates thats relatively simple. AVG is somewhat
    1233             :  * more complex. */
    1234             : static int
    1235        3399 : mat_group_aggr(MalBlkPtr mb, InstrPtr p, mat_t *mat, int b, int g, int e)
    1236             : {
    1237        3399 :         int tp = getArgType(mb,p,0), k, tp2 = 0, tpe = getBatType(tp);
    1238        3399 :         const char *aggr2 = aggr_phase2(getFunctionId(p), tpe == TYPE_dbl);
    1239        3399 :         int isAvg = (getFunctionId(p) == subavgRef);
    1240        3399 :         InstrPtr ai1 = newInstructionArgs(mb, matRef, packRef, mat[b].mi->argc), ai10 = NULL, ai11 = NULL, ai2;
    1241             : 
    1242        3399 :         if(!ai1)
    1243             :                 return -1;
    1244             : 
    1245        3399 :         getArg(ai1,0) = newTmpVariable(mb, tp);
    1246             : 
    1247        3399 :         if (isAvg) { /* remainders or counts */
    1248             :                 tp2 = newBatType(TYPE_lng);
    1249          40 :                 ai10 = newInstructionArgs(mb, matRef, packRef, mat[b].mi->argc);
    1250          40 :                 if(!ai10) {
    1251           0 :                         freeInstruction(ai1);
    1252           0 :                         return -1;
    1253             :                 }
    1254          40 :                 getArg(ai10,0) = newTmpVariable(mb, tp2);
    1255             :         }
    1256        3399 :         if (isAvg && tpe != TYPE_dbl) { /* counts */
    1257             :                 tp2 = newBatType(TYPE_lng);
    1258          19 :                 ai11 = newInstructionArgs(mb, matRef, packRef, mat[b].mi->argc);
    1259          19 :                 if(!ai11) {
    1260           0 :                         freeInstruction(ai1);
    1261           0 :                         freeInstruction(ai10);
    1262           0 :                         return -1;
    1263             :                 }
    1264          19 :                 getArg(ai11,0) = newTmpVariable(mb, tp2);
    1265             :         }
    1266             : 
    1267       18697 :         for(k=1; k<mat[b].mi->argc; k++) {
    1268             :                 int off = 0;
    1269       15298 :                 InstrPtr q = copyInstructionArgs(p, p->argc + (isAvg && tpe == TYPE_dbl));
    1270       15298 :                 if(!q) {
    1271           0 :                         freeInstruction(ai1);
    1272           0 :                         freeInstruction(ai10);
    1273           0 :                         return -1;
    1274             :                 }
    1275             : 
    1276       15298 :                 getArg(q,0) = newTmpVariable(mb, tp);
    1277       15298 :                 if (isAvg && tpe == TYPE_dbl) {
    1278             :                         off = 1;
    1279         113 :                         getArg(q,1) = newTmpVariable(mb, tp2);
    1280         113 :                         q = addArgument(mb, q, getArg(q,1)); /* push at end, create space */
    1281         113 :                         q->retc = 2;
    1282         113 :                         getArg(q,q->argc-1) = getArg(q,q->argc-2);
    1283         113 :                         getArg(q,q->argc-2) = getArg(q,q->argc-3);
    1284       15185 :                 } else if (isAvg) {
    1285         244 :                         getArg(q,1) = newTmpVariable(mb, tp2);
    1286         244 :                         getArg(q,2) = newTmpVariable(mb, tp2);
    1287             :                         off = 2;
    1288             :                 }
    1289       15298 :                 getArg(q,1+off) = getArg(mat[b].mi,k);
    1290       15298 :                 getArg(q,2+off) = getArg(mat[g].mi,k);
    1291       15298 :                 getArg(q,3+off) = getArg(mat[e].mi,k);
    1292       15298 :                 pushInstruction(mb,q);
    1293             : 
    1294             :                 /* pack the result into a mat */
    1295       15298 :                 ai1 = addArgument(mb,ai1,getArg(q,0));
    1296       15298 :                 if (isAvg)
    1297         357 :                         ai10 = addArgument(mb,ai10,getArg(q,1));
    1298       15298 :                 if (isAvg && tpe != TYPE_dbl)
    1299         244 :                         ai11 = addArgument(mb,ai11,getArg(q,2));
    1300             :         }
    1301        3399 :         pushInstruction(mb, ai1);
    1302        3399 :         if (isAvg)
    1303          40 :                 pushInstruction(mb, ai10);
    1304        3399 :         if (isAvg && tpe != TYPE_dbl)
    1305          19 :                 pushInstruction(mb, ai11);
    1306             : 
    1307             :         /* for avg we do sum (avg*(count/sumcount) ) */
    1308        3399 :         if (isAvg && tpe == TYPE_dbl) {
    1309             :                 InstrPtr r,s,v,w, cond;
    1310             : 
    1311             :                 /* lng s = sum counts */
    1312          21 :                 s = newInstruction(mb, aggrRef, subsumRef);
    1313          21 :                 getArg(s,0) = newTmpVariable(mb, tp2);
    1314          21 :                 s = addArgument(mb, s, getArg(ai10, 0));
    1315          21 :                 s = addArgument(mb, s, mat[g].mv);
    1316          21 :                 s = addArgument(mb, s, mat[e].mv);
    1317          21 :                 s = pushBit(mb, s, 1); /* skip nils */
    1318          21 :                 s = pushBit(mb, s, 1);
    1319          21 :                 pushInstruction(mb,s);
    1320             : 
    1321             :                 /*  w=count = ifthenelse(s=count==0,NULL,s=count)  */
    1322          21 :                 cond = newInstruction(mb, batcalcRef, eqRef);
    1323          21 :                 getArg(cond,0) = newTmpVariable(mb, newBatType(TYPE_bit));
    1324          21 :                 cond = addArgument(mb, cond, getArg(s, 0));
    1325          21 :                 cond = pushLng(mb, cond, 0);
    1326          21 :                 pushInstruction(mb,cond);
    1327             : 
    1328          21 :                 w = newInstruction(mb, batcalcRef, ifthenelseRef);
    1329          21 :                 getArg(w,0) = newTmpVariable(mb, tp2);
    1330          21 :                 w = addArgument(mb, w, getArg(cond, 0));
    1331          21 :                 w = pushNil(mb, w, TYPE_lng);
    1332          21 :                 w = addArgument(mb, w, getArg(s, 0));
    1333          21 :                 pushInstruction(mb,w);
    1334             : 
    1335             :                 /* fetchjoin with groups */
    1336          21 :                 r = newInstruction(mb, algebraRef, projectionRef);
    1337          21 :                 getArg(r, 0) = newTmpVariable(mb, tp2);
    1338          21 :                 r = addArgument(mb, r, mat[g].mv);
    1339          21 :                 r = addArgument(mb, r, getArg(w,0));
    1340          21 :                 pushInstruction(mb,r);
    1341             :                 s = r;
    1342             : 
    1343             :                 /* dbl v = double(count) */
    1344          21 :                 v = newInstruction(mb, batcalcRef, dblRef);
    1345          21 :                 getArg(v,0) = newTmpVariable(mb, newBatType(TYPE_dbl));
    1346          21 :                 v = addArgument(mb, v, getArg(ai10, 0));
    1347          21 :                 pushInstruction(mb, v);
    1348             : 
    1349             :                 /* dbl r = v / s */
    1350          21 :                 r = newInstruction(mb, batcalcRef, divRef);
    1351          21 :                 getArg(r,0) = newTmpVariable(mb, newBatType(TYPE_dbl));
    1352          21 :                 r = addArgument(mb, r, getArg(v, 0));
    1353          21 :                 r = addArgument(mb, r, getArg(s, 0));
    1354          21 :                 if (isaBatType(getArgType(mb,v,0)))
    1355          21 :                         r = pushNil(mb, r, TYPE_bat);
    1356          21 :                 if (isaBatType(getArgType(mb,s,0)))
    1357          21 :                         r = pushNil(mb, r, TYPE_bat);
    1358          21 :                 pushInstruction(mb,r);
    1359             : 
    1360             :                 /* dbl s = avg * r */
    1361          21 :                 s = newInstruction(mb, batcalcRef, mulRef);
    1362          21 :                 getArg(s,0) = newTmpVariable(mb, tp);
    1363          21 :                 s = addArgument(mb, s, getArg(ai1, 0));
    1364          21 :                 s = addArgument(mb, s, getArg(r, 0));
    1365          21 :                 if (isaBatType(getArgType(mb,ai1,0)))
    1366          21 :                         s = pushNil(mb, s, TYPE_bat);
    1367          21 :                 if (isaBatType(getArgType(mb,r,0)))
    1368          21 :                         s = pushNil(mb, s, TYPE_bat);
    1369          21 :                 pushInstruction(mb,s);
    1370             : 
    1371             :                 ai1 = s;
    1372             :         }
    1373        3399 :         ai2 = newInstruction(mb, aggrRef, aggr2);
    1374        3399 :         getArg(ai2,0) = getArg(p,0);
    1375        3399 :         if (isAvg && tpe != TYPE_dbl) {
    1376          19 :                 getArg(ai2,1) = getArg(p,1);
    1377          19 :                 getArg(ai2,2) = getArg(p,2);
    1378             :         }
    1379        3399 :         ai2 = addArgument(mb, ai2, getArg(ai1, 0));
    1380        3399 :         if (isAvg && tpe != TYPE_dbl) {
    1381          19 :                 ai2 = addArgument(mb, ai2, getArg(ai10, 0));
    1382          19 :                 ai2 = addArgument(mb, ai2, getArg(ai11, 0));
    1383             :         }
    1384        3399 :         ai2 = addArgument(mb, ai2, mat[g].mv);
    1385        3399 :         ai2 = addArgument(mb, ai2, mat[e].mv);
    1386        3399 :         ai2 = pushBit(mb, ai2, 1); /* skip nils */
    1387        3399 :         if (getFunctionId(p) != subminRef && getFunctionId(p) != submaxRef && !(isAvg && tpe != TYPE_dbl))
    1388        3314 :                 ai2 = pushBit(mb, ai2, 1);
    1389        3399 :         pushInstruction(mb, ai2);
    1390        3399 :         return 0;
    1391             : }
    1392             : 
    1393             : /* The mat_group_{new,derive} keep an ext,attr1..attrn table.
    1394             :  * This is the input for the final second phase group by.
    1395             :  */
    1396             : static void
    1397        5138 : mat_pack_group(MalBlkPtr mb, matlist_t *ml, int g)
    1398             : {
    1399        5138 :         mat_t *mat = ml->v;
    1400             :         int cnt = chain_by_length(mat, g), i;
    1401             :         InstrPtr cur = NULL;
    1402             : 
    1403       13366 :         for(i=cnt-1; i>=0; i--) {
    1404             :                 /* if cur is non-NULL, it's a subgroup; if i is zero, it's "done" */
    1405        8228 :                 InstrPtr grp = newInstruction(mb, groupRef,cur?i?subgroupRef:subgroupdoneRef:i?groupRef:groupdoneRef);
    1406             :                 int ogrp = walk_n_back(mat, g, i);
    1407             :                 int oext = group_by_ext(ml, ogrp);
    1408        8228 :                 int attr = mat[oext].im;
    1409             : 
    1410        8228 :                 getArg(grp,0) = mat[ogrp].mv;
    1411        8228 :                 grp = pushReturn(mb, grp, mat[oext].mv);
    1412        8228 :                 grp = pushReturn(mb, grp, newTmpVariable(mb, newBatType(TYPE_lng)));
    1413        8228 :                 grp = addArgument(mb, grp, getArg(mat[attr].mi, 0));
    1414        8228 :                 if (cur)
    1415        3090 :                         grp = addArgument(mb, grp, getArg(cur, 0));
    1416        8228 :                 pushInstruction(mb, grp);
    1417             :                 cur = grp;
    1418             :         }
    1419        5138 :         mat[g].im = -1; /* only pack once */
    1420        5138 : }
    1421             : 
    1422             : /*
    1423             :  * foreach parent subgroup, do the
    1424             :  *      e2.projection(grp.projection((ext.projection(b)))
    1425             :  * and one for the current group
    1426             :  */
    1427             : static int
    1428        3090 : mat_group_attr(MalBlkPtr mb, matlist_t *ml, int g, InstrPtr cext, int push )
    1429             : {
    1430        3090 :         int cnt = chain_by_length(ml->v, g), i;      /* number of attributes */
    1431             :         int ogrp = g;                           /* previous group */
    1432             : 
    1433        7913 :         for(i = 0; i < cnt; i++) {
    1434        4823 :                 int agrp = walk_n_back(ml->v, ogrp, i);
    1435        4823 :                 int b = ml->v[agrp].im;
    1436             :                 int aext = group_by_ext(ml, agrp);
    1437        4823 :                 int a = ml->v[aext].im;
    1438        4823 :                 int atp = getArgType(mb,ml->v[a].mi,0), k;
    1439        4823 :                 InstrPtr attr = newInstructionArgs(mb, matRef, packRef, ml->v[a].mi->argc);
    1440             : 
    1441             :                 //getArg(attr,0) = newTmpVariable(mb, atp);
    1442        4823 :                 getArg(attr,0) = getArg(ml->v[b].mi,0);
    1443             : 
    1444       31042 :                 for (k = 1; k<ml->v[a].mi->argc; k++ ) {
    1445       26219 :                         InstrPtr r = newInstruction(mb, algebraRef, projectionRef);
    1446       26219 :                         InstrPtr q = newInstruction(mb, algebraRef, projectionRef);
    1447             : 
    1448       26219 :                         getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
    1449       26219 :                         r = addArgument(mb, r, getArg(cext,k));
    1450       26219 :                         r = addArgument(mb, r, getArg(ml->v[ogrp].mi,k));
    1451       26219 :                         pushInstruction(mb,r);
    1452             : 
    1453       26219 :                         getArg(q, 0) = newTmpVariable(mb, atp);
    1454       26219 :                         q = addArgument(mb, q, getArg(r,0));
    1455       26219 :                         q = addArgument(mb, q, getArg(ml->v[a].mi,k));
    1456       26219 :                         pushInstruction(mb,q);
    1457             : 
    1458       26219 :                         attr = addArgument(mb, attr, getArg(q, 0));
    1459             :                 }
    1460        4823 :                 if (push)
    1461        3090 :                         pushInstruction(mb,attr);
    1462        4823 :                 if(mat_add_var(ml, attr, NULL, getArg(attr, 0), mat_ext,  -1, -1, push))
    1463             :                         return -1;
    1464             :                 /* keep new attribute with the group extend */
    1465        4823 :                 ml->v[aext].im = ml->top-1;
    1466             :         }
    1467             :         return 0;
    1468             : }
    1469             : 
    1470             : static int
    1471        5138 : mat_group_new(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int b)
    1472             : {
    1473        5138 :         int tp0 = getArgType(mb,p,0);
    1474        5138 :         int tp1 = getArgType(mb,p,1);
    1475        5138 :         int tp2 = getArgType(mb,p,2);
    1476        5138 :         int atp = getArgType(mb,p,3), i, a, g, push = 0;
    1477             :         InstrPtr r0, r1, r2, attr;
    1478             : 
    1479        5138 :         if (getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupdoneRef)
    1480             :                 push = 1;
    1481             : 
    1482        5138 :         r0 = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1483        5138 :         getArg(r0,0) = newTmpVariable(mb, tp0);
    1484             : 
    1485        5138 :         r1 = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1486        5138 :         getArg(r1,0) = newTmpVariable(mb, tp1);
    1487             : 
    1488        5138 :         r2 = newInstructionArgs(mb,  matRef, packRef, ml->v[b].mi->argc);
    1489        5138 :         getArg(r2,0) = newTmpVariable(mb, tp2);
    1490             : 
    1491             :         /* we keep an extend, attr table result, which will later be used
    1492             :          * when we pack the group result */
    1493        5138 :         attr = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1494        5138 :         getArg(attr,0) = getArg(ml->v[b].mi,0);
    1495             : 
    1496       26480 :         for(i=1; i<ml->v[b].mi->argc; i++) {
    1497       21342 :                 InstrPtr q = copyInstruction(p), r;
    1498       21342 :                 if(!q) {
    1499           0 :                         freeInstruction(r0);
    1500           0 :                         freeInstruction(r1);
    1501           0 :                         freeInstruction(r2);
    1502           0 :                         freeInstruction(attr);
    1503           0 :                         return -1;
    1504             :                 }
    1505             : 
    1506       21342 :                 getArg(q, 0) = newTmpVariable(mb, tp0);
    1507       21342 :                 getArg(q, 1) = newTmpVariable(mb, tp1);
    1508       21342 :                 getArg(q, 2) = newTmpVariable(mb, tp2);
    1509       21342 :                 getArg(q, 3) = getArg(ml->v[b].mi, i);
    1510       21342 :                 pushInstruction(mb, q);
    1511       42684 :                 if(setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,0), i) ||
    1512       42684 :                    setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,1), i) ||
    1513       21342 :                    setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,2), i)){
    1514           0 :                         freeInstruction(r0);
    1515           0 :                         freeInstruction(r1);
    1516           0 :                         freeInstruction(r2);
    1517           0 :                         freeInstruction(attr);
    1518           0 :                         return -1;
    1519             :                 }
    1520             : 
    1521             :                 /* add result to mats */
    1522       21342 :                 r0 = addArgument(mb,r0,getArg(q,0));
    1523       21342 :                 r1 = addArgument(mb,r1,getArg(q,1));
    1524       21342 :                 r2 = addArgument(mb,r2,getArg(q,2));
    1525             : 
    1526       21342 :                 r = newInstruction(mb, algebraRef, projectionRef);
    1527       21342 :                 getArg(r, 0) = newTmpVariable(mb, atp);
    1528       21342 :                 r = addArgument(mb, r, getArg(q,1));
    1529       21342 :                 r = addArgument(mb, r, getArg(ml->v[b].mi,i));
    1530       21342 :                 if(setPartnr(ml, getArg(ml->v[b].mi,i), getArg(r,0), i)){
    1531           0 :                         freeInstruction(r0);
    1532           0 :                         freeInstruction(r1);
    1533           0 :                         freeInstruction(r2);
    1534           0 :                         freeInstruction(attr);
    1535           0 :                         freeInstruction(r);
    1536           0 :                         return -1;
    1537             :                 }
    1538       21342 :                 pushInstruction(mb,r);
    1539             : 
    1540       21342 :                 attr = addArgument(mb, attr, getArg(r, 0));
    1541             :         }
    1542        5138 :         pushInstruction(mb,r0);
    1543        5138 :         pushInstruction(mb,r1);
    1544        5138 :         pushInstruction(mb,r2);
    1545        5138 :         if (push)
    1546        2760 :                 pushInstruction(mb,attr);
    1547             : 
    1548             :         /* create mat's for the intermediates */
    1549        5138 :         a = ml->top;
    1550        5138 :         if(mat_add_var(ml, attr, NULL, getArg(attr, 0), mat_ext,  -1, -1, push))
    1551             :                 return -1;
    1552        5138 :         g = ml->top;
    1553       10276 :         if(mat_add_var(ml, r0, p, getArg(p, 0), mat_grp, b, -1, 1) ||
    1554       10276 :            mat_add_var(ml, r1, p, getArg(p, 1), mat_ext, a, ml->top-1, 1) || /* point back at group */
    1555        5138 :            mat_add_var(ml, r2, p, getArg(p, 2), mat_cnt, -1, ml->top-1, 1)) /* point back at ext */
    1556           0 :                 return -1;
    1557        5138 :         if (push)
    1558        2760 :                 mat_pack_group(mb, ml, g);
    1559             :         return 0;
    1560             : }
    1561             : 
    1562             : static int
    1563        3090 : mat_group_derive(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int b, int g)
    1564             : {
    1565        3090 :         int tp0 = getArgType(mb,p,0);
    1566        3090 :         int tp1 = getArgType(mb,p,1);
    1567        3090 :         int tp2 = getArgType(mb,p,2);
    1568        3090 :         int atp = getArgType(mb,p,3), i, a, push = 0;
    1569             :         InstrPtr r0, r1, r2, attr;
    1570             : 
    1571        3090 :         if (getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupdoneRef)
    1572             :                 push = 1;
    1573             : 
    1574        3090 :         if (ml->v[g].im == -1){ /* already packed */
    1575           0 :                 InstrPtr q = copyInstruction(p);
    1576           0 :                 if(!q)
    1577             :                         return -1;
    1578           0 :                 pushInstruction(mb, q);
    1579           0 :                 return 0;
    1580             :         }
    1581             : 
    1582        3090 :         r0 = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1583        3090 :         getArg(r0,0) = newTmpVariable(mb, tp0);
    1584             : 
    1585        3090 :         r1 = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1586        3090 :         getArg(r1,0) = newTmpVariable(mb, tp1);
    1587             : 
    1588        3090 :         r2 = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1589        3090 :         getArg(r2,0) = newTmpVariable(mb, tp2);
    1590             : 
    1591             :         /* we keep an extend, attr table result, which will later be used
    1592             :          * when we pack the group result */
    1593        3090 :         attr = newInstructionArgs(mb, matRef, packRef, ml->v[b].mi->argc);
    1594        3090 :         getArg(attr,0) = getArg(ml->v[b].mi,0);
    1595             : 
    1596             :         /* we need overlapping ranges */
    1597       17650 :         for(i=1; i<ml->v[b].mi->argc; i++) {
    1598       14560 :                 InstrPtr q = copyInstruction(p), r;
    1599       14560 :                 if(!q) {
    1600           0 :                         freeInstruction(r0);
    1601           0 :                         freeInstruction(r1);
    1602           0 :                         freeInstruction(r2);
    1603           0 :                         freeInstruction(attr);
    1604           0 :                         return -1;
    1605             :                 }
    1606             : 
    1607       14560 :                 getArg(q,0) = newTmpVariable(mb, tp0);
    1608       14560 :                 getArg(q,1) = newTmpVariable(mb, tp1);
    1609       14560 :                 getArg(q,2) = newTmpVariable(mb, tp2);
    1610       14560 :                 getArg(q,3) = getArg(ml->v[b].mi,i);
    1611       14560 :                 getArg(q,4) = getArg(ml->v[g].mi,i);
    1612       14560 :                 pushInstruction(mb,q);
    1613       29120 :                 if(setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,0), i) ||
    1614       29120 :                    setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,1), i) ||
    1615       14560 :                    setPartnr(ml, getArg(ml->v[b].mi,i), getArg(q,2), i)){
    1616           0 :                         freeInstruction(r0);
    1617           0 :                         freeInstruction(r1);
    1618           0 :                         freeInstruction(r2);
    1619           0 :                         freeInstruction(attr);
    1620           0 :                         return -1;
    1621             :                 }
    1622             : 
    1623             :                 /* add result to mats */
    1624       14560 :                 r0 = addArgument(mb,r0,getArg(q,0));
    1625       14560 :                 r1 = addArgument(mb,r1,getArg(q,1));
    1626       14560 :                 r2 = addArgument(mb,r2,getArg(q,2));
    1627             : 
    1628       14560 :                 r = newInstruction(mb, algebraRef, projectionRef);
    1629       14560 :                 getArg(r, 0) = newTmpVariable(mb, atp);
    1630       14560 :                 r = addArgument(mb, r, getArg(q,1));
    1631       14560 :                 r = addArgument(mb, r, getArg(ml->v[b].mi,i));
    1632       14560 :                 if(setPartnr(ml, getArg(ml->v[b].mi,i), getArg(r,0), i)){
    1633           0 :                         freeInstruction(r0);
    1634           0 :                         freeInstruction(r1);
    1635           0 :                         freeInstruction(r2);
    1636           0 :                         freeInstruction(attr);
    1637           0 :                         freeInstruction(r);
    1638           0 :                         return -1;
    1639             :                 }
    1640       14560 :                 pushInstruction(mb,r);
    1641             : 
    1642       14560 :                 attr = addArgument(mb, attr, getArg(r, 0));
    1643             :         }
    1644        3090 :         pushInstruction(mb,r0);
    1645        3090 :         pushInstruction(mb,r1);
    1646        3090 :         pushInstruction(mb,r2);
    1647        3090 :         if (push)
    1648        2378 :                 pushInstruction(mb,attr);
    1649             : 
    1650        3090 :         if(mat_group_attr(mb, ml, g, r1, push))
    1651             :                 return -1;
    1652             : 
    1653             :         /* create mat's for the intermediates */
    1654        3090 :         a = ml->top;
    1655        6180 :         if(mat_add_var(ml, attr, NULL, getArg(attr, 0), mat_ext,  -1, -1, push) ||
    1656        3090 :            mat_add_var(ml, r0, p, getArg(p, 0), mat_grp, b, g, 1))
    1657           0 :                 return -1;
    1658        3090 :         g = ml->top-1;
    1659        6180 :         if(mat_add_var(ml, r1, p, getArg(p, 1), mat_ext, a, ml->top-1, 1) || /* point back at group */
    1660        3090 :            mat_add_var(ml, r2, p, getArg(p, 2), mat_cnt, -1, ml->top-1, 1)) /* point back at ext */
    1661           0 :                 return -1;
    1662        3090 :         if (push)
    1663        2378 :                 mat_pack_group(mb, ml, g);
    1664             :         return 0;
    1665             : }
    1666             : 
    1667             : static int
    1668         526 : mat_topn_project(MalBlkPtr mb, InstrPtr p, mat_t *mat, int m, int n)
    1669             : {
    1670         526 :         int tpe = getArgType(mb, p, 0), k;
    1671             :         InstrPtr pck, q;
    1672             : 
    1673         526 :         pck = newInstructionArgs(mb, matRef, packRef, mat[m].mi->argc);
    1674         526 :         getArg(pck,0) = newTmpVariable(mb, tpe);
    1675             : 
    1676        5804 :         for(k=1; k<mat[m].mi->argc; k++) {
    1677        5278 :                 InstrPtr q = copyInstruction(p);
    1678        5278 :                 if(!q) {
    1679           0 :                         freeInstruction(pck);
    1680           0 :                         return -1;
    1681             :                 }
    1682             : 
    1683        5278 :                 getArg(q,0) = newTmpVariable(mb, tpe);
    1684        5278 :                 getArg(q,1) = getArg(mat[m].mi, k);
    1685        5278 :                 getArg(q,2) = getArg(mat[n].mi, k);
    1686        5278 :                 pushInstruction(mb, q);
    1687             : 
    1688        5278 :                 pck = addArgument(mb, pck, getArg(q, 0));
    1689             :         }
    1690         526 :         pushInstruction(mb, pck);
    1691             : 
    1692         526 :         if((q = copyInstruction(p)) == NULL)
    1693             :                 return -1;
    1694         526 :         getArg(q,2) = getArg(pck,0);
    1695         526 :         pushInstruction(mb, q);
    1696         526 :         return 0;
    1697             : }
    1698             : 
    1699             : static int
    1700          38 : mat_pack_topn(MalBlkPtr mb, InstrPtr slc, mat_t *mat, int m)
    1701             : {
    1702             :         /* find chain of topn's */
    1703             :         int cnt = chain_by_length(mat, m), i;
    1704             :         InstrPtr cur = NULL;
    1705             : 
    1706          90 :         for(i=cnt-1; i>=0; i--) {
    1707             :                 int otpn = walk_n_back(mat, m, i), var = 1, k;
    1708          52 :                 int attr = mat[otpn].im;
    1709          52 :                 int tpe = getVarType(mb, getArg(mat[attr].mi,0));
    1710          52 :                 InstrPtr pck, tpn, otopn = mat[otpn].org, a;
    1711             : 
    1712          52 :                 pck = newInstructionArgs(mb, matRef, packRef, mat[attr].mi->argc);
    1713          52 :                 getArg(pck,0) = newTmpVariable(mb, tpe);
    1714             : 
    1715             :                 /* m.projection(attr); */
    1716         266 :                 for(k=1; k < mat[attr].mi->argc; k++) {
    1717         214 :                         InstrPtr q = newInstruction(mb, algebraRef, projectionRef);
    1718         214 :                         getArg(q, 0) = newTmpVariable(mb, tpe);
    1719             : 
    1720         214 :                         q = addArgument(mb, q, getArg(slc, k));
    1721         214 :                         q = addArgument(mb, q, getArg(mat[attr].mi, k));
    1722         214 :                         pushInstruction(mb, q);
    1723             : 
    1724         214 :                         pck = addArgument(mb, pck, getArg(q,0));
    1725             :                 }
    1726          52 :                 pushInstruction(mb, pck);
    1727             : 
    1728             :                 a = pck;
    1729             : 
    1730          52 :                 if((tpn = copyInstruction(otopn)) == NULL)
    1731             :                         return -1;
    1732             :                 var = 1;
    1733          52 :                 if (cur) {
    1734          14 :                         getArg(tpn, tpn->retc+var) = getArg(cur, 0);
    1735             :                         var++;
    1736          14 :                         if (cur->retc == 2) {
    1737          14 :                                 getArg(tpn, tpn->retc+var) = getArg(cur, 1);
    1738             :                                 var++;
    1739             :                         }
    1740             :                 }
    1741          52 :                 getArg(tpn, tpn->retc) = getArg(a,0);
    1742          52 :                 pushInstruction(mb, tpn);
    1743             :                 cur = tpn;
    1744             :         }
    1745             :         return 0;
    1746             : }
    1747             : 
    1748             : static int
    1749          98 : mat_topn(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m, int n, int o)
    1750             : {
    1751          98 :         int tpe = getArgType(mb,p,0), k, is_slice = isSlice(p), zero = -1;
    1752             :         InstrPtr pck, gpck = NULL, q, r;
    1753          98 :         int with_groups = (p->retc == 2), piv = 0, topn2 = (n >= 0);
    1754             : 
    1755          98 :         assert( topn2 || o < 0);
    1756             :         /* dummy mat instruction (needed to share result of p) */
    1757          98 :         pck = newInstructionArgs(mb, matRef, packRef, ml->v[m].mi->argc);
    1758          98 :         getArg(pck,0) = getArg(p,0);
    1759             : 
    1760          98 :         if (with_groups) {
    1761          14 :                 gpck = newInstructionArgs(mb, matRef, packRef, ml->v[m].mi->argc);
    1762          14 :                 getArg(gpck,0) = getArg(p,1);
    1763             :         }
    1764             : 
    1765          98 :         if (is_slice) {
    1766             :                 ValRecord cst;
    1767          46 :                 cst.vtype= getArgType(mb,p,2);
    1768          46 :                 cst.val.lval= 0;
    1769          46 :                 cst.len = 0;
    1770          46 :                 zero = defConstant(mb, cst.vtype, &cst);
    1771          46 :                 if( zero < 0){
    1772           0 :                         freeInstruction(pck);
    1773           0 :                         return -1;
    1774             :                 }
    1775             :         }
    1776          98 :         assert( (n<0 && o<0) ||
    1777             :                 (ml->v[m].mi->argc == ml->v[n].mi->argc &&
    1778             :                  ml->v[m].mi->argc == ml->v[o].mi->argc));
    1779             : 
    1780         778 :         for(k=1; k< ml->v[m].mi->argc; k++) {
    1781         680 :                 if((q = copyInstruction(p)) == NULL) {
    1782           0 :                         freeInstruction(gpck);
    1783           0 :                         freeInstruction(pck);
    1784           0 :                         return -1;
    1785             :                 }
    1786         680 :                 getArg(q,0) = newTmpVariable(mb, tpe);
    1787         680 :                 if (with_groups)
    1788          53 :                         getArg(q,1) = newTmpVariable(mb, tpe);
    1789         680 :                 getArg(q,q->retc) = getArg(ml->v[m].mi,k);
    1790         680 :                 if (is_slice) /* lower bound should always be 0 on partial slices */
    1791         466 :                         getArg(q,q->retc+1) = zero;
    1792         214 :                 else if (topn2) {
    1793          53 :                         getArg(q,q->retc+1) = getArg(ml->v[n].mi,k);
    1794          53 :                         getArg(q,q->retc+2) = getArg(ml->v[o].mi,k);
    1795             :                 }
    1796         680 :                 pushInstruction(mb,q);
    1797             : 
    1798         680 :                 pck = addArgument(mb, pck, getArg(q,0));
    1799         680 :                 if (with_groups)
    1800          53 :                         gpck = addArgument(mb, gpck, getArg(q,1));
    1801             :         }
    1802             : 
    1803          98 :         piv = ml->top;
    1804         150 :         if(mat_add_var(ml, pck, p, getArg(p,0), is_slice?mat_slc:mat_tpn, m, n, 0)) {
    1805           0 :                 freeInstruction(gpck);
    1806           0 :                 return -1;
    1807             :         }
    1808          98 :         if (with_groups && mat_add_var(ml, gpck, p, getArg(p,1), is_slice?mat_slc:mat_tpn, m, piv, 0)) {
    1809           0 :                 freeInstruction(gpck);
    1810           0 :                 return -1;
    1811             :         }
    1812             : 
    1813          98 :         if (is_slice || p->retc ==1 /* single result, ie last of the topn's */) {
    1814          84 :                 if (ml->v[m].type == mat_tpn || !is_slice) {
    1815          38 :                         if(mat_pack_topn(mb, pck, ml->v, (!is_slice)?piv:m))
    1816             :                                 return -1;
    1817             :                 }
    1818             : 
    1819             :                 /* topn/slice over merged parts */
    1820          84 :                 if (is_slice) {
    1821             :                         /* real instruction */
    1822          46 :                         r = newInstructionArgs(mb, matRef, packRef, pck->argc);
    1823          46 :                         getArg(r,0) = newTmpVariable(mb, tpe);
    1824             : 
    1825         512 :                         for(k=1; k< pck->argc; k++)
    1826         466 :                                 r = addArgument(mb, r, getArg(pck,k));
    1827          46 :                         pushInstruction(mb,r);
    1828             : 
    1829          46 :                         if((q = copyInstruction(p)) == NULL)
    1830             :                                 return -1;
    1831          46 :                         setFunctionId(q, subsliceRef);
    1832             :                         if (ml->v[m].type != mat_tpn || is_slice)
    1833          46 :                                 getArg(q,1) = getArg(r,0);
    1834          46 :                         pushInstruction(mb,q);
    1835             :                 }
    1836             : 
    1837          84 :                 ml->v[piv].type = mat_slc;
    1838             :         }
    1839             :         return 0;
    1840             : }
    1841             : 
    1842             : static int
    1843           0 : mat_sample(MalBlkPtr mb, InstrPtr p, matlist_t *ml, int m)
    1844             : {
    1845             :         /* transform
    1846             :          * a := sample.subuniform(b,n);
    1847             :          * into
    1848             :          * t1 := sample.subuniform(b1,n);
    1849             :          * t2 := sample.subuniform(b2,n);
    1850             :          * ...
    1851             :          * t0 := mat.pack(t1,t2,...);
    1852             :          * tn := sample.subuniform(t0,n);
    1853             :          * a := algebra.projection(tn,t0);
    1854             :          *
    1855             :          * Note that this does *not* give a uniform sample of the original
    1856             :          * bat b!
    1857             :          */
    1858             : 
    1859           0 :         int tpe = getArgType(mb,p,0), k, piv;
    1860             :         InstrPtr pck, q, r;
    1861             : 
    1862           0 :         pck = newInstructionArgs(mb,matRef,packRef, ml->v[m].mi->argc);
    1863           0 :         getArg(pck,0) = newTmpVariable(mb, tpe);
    1864             : 
    1865           0 :         for(k=1; k< ml->v[m].mi->argc; k++) {
    1866           0 :                 if((q = copyInstruction(p)) == NULL) {
    1867           0 :                         freeInstruction(pck);
    1868           0 :                         return -1;
    1869             :                 }
    1870           0 :                 getArg(q,0) = newTmpVariable(mb, tpe);
    1871           0 :                 getArg(q,q->retc) = getArg(ml->v[m].mi,k);
    1872           0 :                 pushInstruction(mb,q);
    1873           0 :                 pck = addArgument(mb, pck, getArg(q,0));
    1874             :         }
    1875             : 
    1876           0 :         piv = ml->top;
    1877           0 :         if(mat_add_var(ml, pck, p, getArg(p,0), mat_slc, m, -1, 1)) {
    1878           0 :                 freeInstruction(pck);
    1879           0 :                 return -1;
    1880             :         }
    1881           0 :         pushInstruction(mb,pck);
    1882             : 
    1883           0 :         if((q = copyInstruction(p)) == NULL)
    1884             :                 return -1;
    1885           0 :         getArg(q,0) = newTmpVariable(mb, tpe);
    1886           0 :         getArg(q,q->retc) = getArg(pck,0);
    1887           0 :         pushInstruction(mb,q);
    1888             : 
    1889           0 :         r = newInstruction(mb, algebraRef, projectionRef);
    1890           0 :         getArg(r,0) = getArg(p,0);
    1891           0 :         r = addArgument(mb, r, getArg(q, 0));
    1892           0 :         r = addArgument(mb, r, getArg(pck, 0));
    1893           0 :         pushInstruction(mb, r);
    1894             : 
    1895           0 :         matlist_pack(ml, piv);
    1896           0 :         ml->v[piv].type = mat_slc;
    1897           0 :         return 0;
    1898             : }
    1899             : 
    1900             : str
    1901      353096 : OPTmergetableImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1902             : {
    1903             :         InstrPtr p, *old;
    1904             :         matlist_t ml;
    1905             :         int oldtop, fm, fn, fo, fe, i, k, m, n, o, e, slimit, bailout = 0;
    1906             :         int size=0, match, actions=0, distinct_topn = 0, /*topn_res = 0,*/ groupdone = 0, *vars;//, maxvars;
    1907             :         char *group_input;
    1908             :         str msg = MAL_SUCCEED;
    1909             : 
    1910      353096 :         if( isOptimizerUsed(mb, pci, mitosisRef) <= 0)
    1911        1734 :                 goto cleanup2;
    1912      351362 :         old = mb->stmt;
    1913      351362 :         oldtop= mb->stop;
    1914             : 
    1915      351362 :         vars = (int*) GDKmalloc(sizeof(int)* mb->vtop);
    1916             :         //maxvars = mb->vtop;
    1917      351362 :         group_input = (char*) GDKzalloc(sizeof(char)* mb->vtop);
    1918      351362 :         if (vars == NULL || group_input == NULL){
    1919           0 :                 if (vars)
    1920           0 :                         GDKfree(vars);
    1921           0 :                 throw(MAL, "optimizer.mergetable", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1922             :         }
    1923             :         /* check for bailout conditions */
    1924    18302322 :         for (i = 1; i < oldtop && !bailout; i++) {
    1925             :                 int j;
    1926             : 
    1927    17950960 :                 p = old[i];
    1928             : 
    1929    36444823 :                 for (j = 0; j<p->retc; j++) {
    1930    18493863 :                         int res = getArg(p, j);
    1931    18493863 :                         vars[res] = i;
    1932             :                 }
    1933             : 
    1934             :                 /* pack if there is a group statement following a groupdone (ie aggr(distinct)) */
    1935    17950960 :                 if (getModuleId(p) == groupRef && p->argc == 5 &&
    1936        8789 :                    (getFunctionId(p) == subgroupRef ||
    1937        4665 :                         getFunctionId(p) == subgroupdoneRef ||
    1938           0 :                         getFunctionId(p) == groupRef ||
    1939           0 :                         getFunctionId(p) == groupdoneRef)) {
    1940        8789 :                         InstrPtr q = old[vars[getArg(p, p->argc-1)]]; /* group result from a previous group(done) */
    1941             : 
    1942        8789 :                         if (getFunctionId(q) == subgroupdoneRef || getFunctionId(q) == groupdoneRef)
    1943             :                                 groupdone = 1;
    1944             :                 }
    1945             :                 /* bail out if there is a input for a group, which has been used for a group already (solves problems with cube like groupings) */
    1946    17950960 :                 if (getModuleId(p) == groupRef &&
    1947       30771 :                    (getFunctionId(p) == subgroupRef ||
    1948       26647 :                         getFunctionId(p) == subgroupdoneRef ||
    1949       17287 :                         getFunctionId(p) == groupRef ||
    1950       17287 :                         getFunctionId(p) == groupdoneRef)) {
    1951       30771 :                         int input = getArg(p, p->retc); /* argument one is first input */
    1952             : 
    1953       30771 :                         if (group_input[input]) {
    1954         115 :                                 TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout on group input reuse in group statement\n");
    1955             :                                 bailout = 1;
    1956             :                         }
    1957             : 
    1958       30771 :                         group_input[input] = 1;
    1959             :                 }
    1960    17950960 :                 if (getModuleId(p) == algebraRef &&
    1961     2131779 :                         getFunctionId(p) == selectNotNilRef ) {
    1962           0 :                         TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout not nil ref\n");
    1963             :                         bailout = 1;
    1964             :                 }
    1965    17950960 :                 if (getModuleId(p) == algebraRef &&
    1966     2131779 :                         getFunctionId(p) == semijoinRef ) {
    1967         171 :                         TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout semijoin ref\n");
    1968             :                         bailout = 1;
    1969             :                 }
    1970    17950960 :                 if (getModuleId(p) == algebraRef &&
    1971     2131779 :                         getFunctionId(p) == thetajoinRef) {
    1972        2869 :                           assert(p->argc == 9);
    1973        2869 :                           if (p->argc == 9 && getVarConstant(mb,getArg(p,6)).val.ival == 6 /* op == '<>' */) {
    1974           0 :                         TRC_INFO(MAL_OPTIMIZER, "Mergetable bailout thetajoin ref\n");
    1975             :                         bailout = 1;
    1976             :                           }
    1977             :                 }
    1978    17950960 :                 if (isSample(p)) {
    1979             :                         bailout = 1;
    1980             :                 }
    1981             :                 /*
    1982             :                 if (isTopn(p))
    1983             :                         topn_res = getArg(p, 0);
    1984             :                         */
    1985             :                 /* not idea how to detect this yet */
    1986             :                         //distinct_topn = 1;
    1987             :         }
    1988      351362 :         GDKfree(group_input);
    1989             : 
    1990      351362 :         ml.horigin = 0;
    1991      351362 :         ml.torigin = 0;
    1992      351362 :         ml.v = 0;
    1993      351362 :         ml.vars = 0;
    1994      351362 :         if (bailout)
    1995         307 :                 goto cleanup;
    1996             : 
    1997             :         /* the number of MATs is limited to the variable stack*/
    1998      351055 :         ml.size = mb->vtop;
    1999      351055 :         ml.top = 0;
    2000      351055 :         ml.v = (mat_t*) GDKzalloc(ml.size * sizeof(mat_t));
    2001      351055 :         ml.vsize = mb->vsize;
    2002      351055 :         ml.horigin = (int*) GDKmalloc(sizeof(int)* ml.vsize);
    2003      351055 :         ml.torigin = (int*) GDKmalloc(sizeof(int)* ml.vsize);
    2004      351055 :         ml.vars = (int*) GDKzalloc(sizeof(int)* ml.vsize);
    2005      351055 :         if ( ml.v == NULL || ml.horigin == NULL || ml.torigin == NULL || ml.vars == NULL) {
    2006           0 :                 goto cleanup;
    2007             :         }
    2008   100255311 :         for (i=0; i<ml.vsize; i++) {
    2009    99904256 :                 ml.horigin[i] = ml.torigin[i] = -1;
    2010    99904256 :                 ml.vars[i] = -1;
    2011             :         }
    2012             : 
    2013      351055 :         slimit = mb->ssize;
    2014      351055 :         size = (mb->stop * 1.2 < mb->ssize)? mb->ssize:(int)(mb->stop * 1.2);
    2015      351055 :         mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr));
    2016      351055 :         if ( mb->stmt == NULL) {
    2017           0 :                 mb->stmt = old;
    2018           0 :                 msg = createException(MAL,"optimizer.mergetable", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2019           0 :                 goto cleanup;
    2020             :         }
    2021      351055 :         mb->ssize = size;
    2022      351055 :         mb->stop = 0;
    2023             : 
    2024     7738105 :         for( i=0; i<oldtop; i++){
    2025             :                 int bats = 0, nilbats = 0;
    2026             :                 InstrPtr r, cp;
    2027             : 
    2028     7738105 :                 p = old[i];
    2029             : 
    2030     7738105 :                 if (p->token == ENDsymbol) /* don't copy the optimizer pipeline added after final instruction */
    2031             :                         break;
    2032     7387050 :                 if (getModuleId(p) == matRef &&
    2033      388819 :                    (getFunctionId(p) == newRef || getFunctionId(p) == packRef)){
    2034      388819 :                         if(mat_set_prop(&ml, mb, p) || mat_add_var(&ml, p, NULL, getArg(p,0), mat_none, -1, -1, 1)) {
    2035           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2036           0 :                                 goto cleanup;
    2037             :                         }
    2038      388818 :                         continue;
    2039             :                 }
    2040             : 
    2041             :                 /*
    2042             :                  * If the instruction does not contain MAT references it can simply be added.
    2043             :                  * Otherwise we have to decide on either packing them or replacement.
    2044             :                  */
    2045     6998231 :                 if ((match = nr_of_mats(p, &ml)) == 0) {
    2046     5349152 :                         cp = copyInstruction(p);
    2047     5349152 :                         if(!cp) {
    2048           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2049           0 :                                 goto cleanup;
    2050             :                         }
    2051     5349152 :                         pushInstruction(mb, cp);
    2052     5349152 :                         continue;
    2053             :                 }
    2054     1649079 :                 bats = nr_of_bats(mb, p);
    2055     1649079 :                 nilbats = nr_of_nilbats(mb, p);
    2056             : 
    2057             :                 /* left joins can match at isMatJoinOp, so run this check beforehand */
    2058     1649079 :                 if (match > 0 && isMatLeftJoinOp(p) && p->argc >= 5 && p->retc == 2 &&
    2059           0 :                         (match == 1 || match == 2) && bats+nilbats == 4) {
    2060           0 :                         m = is_a_mat(getArg(p,p->retc), &ml);
    2061           0 :                         o = is_a_mat(getArg(p,p->retc+2), &ml);
    2062             : 
    2063           0 :                         if ((match == 1 && m >= 0) || (match == 2 && m >= 0 && o >= 0)) {
    2064           0 :                                 if(mat_join2(mb, p, &ml, m, -1, o, -1)) {
    2065           0 :                                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2066           0 :                                         goto cleanup;
    2067             :                                 }
    2068           0 :                                 actions++;
    2069           0 :                                 continue;
    2070             :                         }
    2071             :                 }
    2072             : 
    2073             :                 /* (l,r) Join (L, R, ..)
    2074             :                  * 2 -> (l,r) equi/theta joins (l,r)
    2075             :                  * 3 -> (l,r) range-joins (l,r1,r2)
    2076             :                  * NxM -> (l,r) filter-joins (l1,..,ln,r1,..,rm)
    2077             :                  */
    2078     1649080 :                 if (match > 0 && isMatJoinOp(p) &&
    2079       80251 :                         p->argc >= 5 && p->retc == 2 && bats+nilbats >= 4) {
    2080       74569 :                         if (bats+nilbats == 4) {
    2081       74534 :                                 m = is_a_mat(getArg(p,p->retc), &ml);
    2082       74534 :                                 n = is_a_mat(getArg(p,p->retc+1), &ml);
    2083       74534 :                                 o = is_a_mat(getArg(p,p->retc+2), &ml);
    2084       74534 :                                 e = is_a_mat(getArg(p,p->retc+3), &ml);
    2085       74534 :                                 if(mat_join2(mb, p, &ml, m, n, o, e)) {
    2086           0 :                                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2087           0 :                                         goto cleanup;
    2088             :                                 }
    2089             :                         } else {
    2090          35 :                                 if ( mat_joinNxM(cntxt, mb, p, &ml, bats)) {
    2091           0 :                                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2092           0 :                                         goto cleanup;
    2093             :                                 }
    2094             :                         }
    2095       74569 :                         actions++;
    2096       74569 :                         continue;
    2097             :                 }
    2098             :                 /*
    2099             :                  * Aggregate handling is a prime target for optimization.
    2100             :                  * The simple cases are dealt with first.
    2101             :                  * Handle the rewrite v:=aggr.count(b) and sum()
    2102             :                  * And the min/max is as easy
    2103             :                  */
    2104     1574510 :                 if (match == 1 && p->argc >= 2 &&
    2105      406077 :                    ((getModuleId(p)==aggrRef &&
    2106        2108 :                         (getFunctionId(p)== countRef ||
    2107        1393 :                          getFunctionId(p)== count_no_nilRef ||
    2108        1393 :                          getFunctionId(p)== minRef ||
    2109        1362 :                          getFunctionId(p)== maxRef ||
    2110        1324 :                          getFunctionId(p)== avgRef ||
    2111         298 :                          getFunctionId(p)== sumRef ||
    2112         127 :                          getFunctionId(p) == prodRef))) &&
    2113        1986 :                         (m=is_a_mat(getArg(p,p->retc+0), &ml)) >= 0) {
    2114        1986 :                         mat_aggr(mb, p, ml.v, m);
    2115        1986 :                         actions++;
    2116        1986 :                         continue;
    2117             :                 }
    2118             : 
    2119     1572524 :                 if (match == 1 && bats == 1 && p->argc == 4 && isSlice(p) && ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0)) {
    2120          46 :                         if(mat_topn(mb, p, &ml, m, -1, -1)) {
    2121           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2122           0 :                                 goto cleanup;
    2123             :                         }
    2124          46 :                         actions++;
    2125          46 :                         continue;
    2126             :                 }
    2127             : 
    2128     1572478 :                 if (match == 1 && bats == 1 && p->argc == 3 && isSample(p) && ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0)) {
    2129           0 :                         if(mat_sample(mb, p, &ml, m)) {
    2130           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2131           0 :                                 goto cleanup;
    2132             :                         }
    2133           0 :                         actions++;
    2134           0 :                         continue;
    2135             :                 }
    2136             : 
    2137     1572478 :                 if (!distinct_topn && match == 1 && bats == 1 && isTopn(p) && ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0)) {
    2138          38 :                         if(mat_topn(mb, p, &ml, m, -1, -1)) {
    2139           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2140           0 :                                 goto cleanup;
    2141             :                         }
    2142          38 :                         actions++;
    2143          38 :                         continue;
    2144             :                 }
    2145     1572440 :                 if (!distinct_topn && match == 3 && bats == 3 && isTopn(p) &&
    2146          14 :                    ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0) &&
    2147          14 :                    ((n=is_a_mat(getArg(p,p->retc+1), &ml)) >= 0) &&
    2148          14 :                    ((o=is_a_mat(getArg(p,p->retc+2), &ml)) >= 0)) {
    2149          14 :                         if(mat_topn(mb, p, &ml, m, n, o)) {
    2150           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2151           0 :                                 goto cleanup;
    2152             :                         }
    2153          14 :                         actions++;
    2154          14 :                         continue;
    2155             :                 }
    2156             : 
    2157             :                 /* Now we handle subgroup and aggregation statements. */
    2158     1572427 :                 if (!groupdone && match == 1 && bats == 1 && p->argc == 4 && getModuleId(p) == groupRef &&
    2159        5138 :                    (getFunctionId(p) == subgroupRef || getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupRef || getFunctionId(p) == groupdoneRef) &&
    2160        5138 :                    ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0)) {
    2161        5138 :                         if(mat_group_new(mb, p, &ml, m)) {
    2162           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2163           0 :                                 goto cleanup;
    2164             :                         }
    2165        5138 :                         actions++;
    2166        5138 :                         continue;
    2167             :                 }
    2168     1567289 :                 if (!groupdone && match == 2 && bats == 2 && p->argc == 5 && getModuleId(p) == groupRef &&
    2169        3090 :                    (getFunctionId(p) == subgroupRef || getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupRef || getFunctionId(p) == groupdoneRef) &&
    2170        3090 :                    ((m=is_a_mat(getArg(p,p->retc), &ml)) >= 0) &&
    2171        3090 :                    ((n=is_a_mat(getArg(p,p->retc+1), &ml)) >= 0) &&
    2172        3090 :                          ml.v[n].im >= 0 /* not packed */) {
    2173        3090 :                         if(mat_group_derive(mb, p, &ml, m, n)) {
    2174           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2175           0 :                                 goto cleanup;
    2176             :                         }
    2177        3090 :                         actions++;
    2178        3090 :                         continue;
    2179             :                 }
    2180             :                 /* TODO sub'aggr' with cand list */
    2181     1564199 :                 if (match == 3 && bats == 3 && getModuleId(p) == aggrRef && p->argc >= 4 &&
    2182        3399 :                    (getFunctionId(p) == subcountRef ||
    2183         449 :                         getFunctionId(p) == subminRef ||
    2184         413 :                         getFunctionId(p) == submaxRef ||
    2185         383 :                         getFunctionId(p) == subavgRef ||
    2186         343 :                         getFunctionId(p) == subsumRef ||
    2187           2 :                         getFunctionId(p) == subprodRef) &&
    2188        3399 :                    ((m=is_a_mat(getArg(p,p->retc+0), &ml)) >= 0) &&
    2189        3399 :                    ((n=is_a_mat(getArg(p,p->retc+1), &ml)) >= 0) &&
    2190        3399 :                    ((o=is_a_mat(getArg(p,p->retc+2), &ml)) >= 0)) {
    2191        3399 :                         if(mat_group_aggr(mb, p, ml.v, m, n, o)) {
    2192           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2193           0 :                                 goto cleanup;
    2194             :                         }
    2195        3399 :                         actions++;
    2196        3399 :                         continue;
    2197             :                 }
    2198             :                 /* Handle cases of ext.projection and .projection(grp) */
    2199     1560800 :                 if (match == 2 && getModuleId(p) == algebraRef &&
    2200      935295 :                         getFunctionId(p) == projectionRef &&
    2201      884434 :                    (m=is_a_mat(getArg(p,1), &ml)) >= 0 &&
    2202      884434 :                    (n=is_a_mat(getArg(p,2), &ml)) >= 0 &&
    2203      884434 :                    (ml.v[m].type == mat_ext || ml.v[n].type == mat_grp)) {
    2204        8101 :                         assert(ml.v[m].pushed);
    2205        8101 :                         if (!ml.v[n].pushed) {
    2206        8101 :                                 if(mat_group_project(mb, p, &ml, m, n)) {
    2207           0 :                                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2208           0 :                                         goto cleanup;
    2209             :                                 }
    2210             :                         } else {
    2211           0 :                                 cp = copyInstruction(p);
    2212           0 :                                 if(!cp) {
    2213           0 :                                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2214           0 :                                         goto cleanup;
    2215             :                                 }
    2216           0 :                                 pushInstruction(mb, cp);
    2217             :                         }
    2218        8101 :                         continue;
    2219             :                 }
    2220     1552699 :                 if (match == 1 && getModuleId(p) == algebraRef &&
    2221      217865 :                         getFunctionId(p) == projectRef &&
    2222       18331 :                    (m=is_a_mat(getArg(p,1), &ml)) >= 0 &&
    2223       18331 :                    (ml.v[m].type == mat_ext)) {
    2224           2 :                         assert(ml.v[m].pushed);
    2225           2 :                         cp = copyInstruction(p);
    2226           2 :                         if(!cp) {
    2227           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2228           0 :                                 goto cleanup;
    2229             :                         }
    2230           2 :                         pushInstruction(mb, cp);
    2231           2 :                         continue;
    2232             :                 }
    2233             : 
    2234             :                 /* Handle cases of slice.projection */
    2235     1552697 :                 if (match == 2 && getModuleId(p) == algebraRef &&
    2236      927194 :                         getFunctionId(p) == projectionRef &&
    2237      876333 :                    (m=is_a_mat(getArg(p,1), &ml)) >= 0 &&
    2238      876333 :                    (n=is_a_mat(getArg(p,2), &ml)) >= 0 &&
    2239      876333 :                    (ml.v[m].type == mat_slc)) {
    2240         526 :                         if(mat_topn_project(mb, p, ml.v, m, n)) {
    2241           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2242           0 :                                 goto cleanup;
    2243             :                         }
    2244         526 :                         actions++;
    2245         526 :                         continue;
    2246             :                 }
    2247             : 
    2248             :                 /* Handle projection */
    2249     1552171 :                 if (match > 0 && getModuleId(p) == algebraRef &&
    2250     1145108 :                         getFunctionId(p) == projectionRef &&
    2251     1020809 :                    (m=is_a_mat(getArg(p,1), &ml)) >= 0) {
    2252      990050 :                         n=is_a_mat(getArg(p,2), &ml);
    2253      990050 :                         if(mat_projection(mb, p, &ml, m, n)) {
    2254           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2255           0 :                                 goto cleanup;
    2256             :                         }
    2257      990050 :                         actions++;
    2258      990050 :                         continue;
    2259             :                 }
    2260             :                 /* Handle setops */
    2261      562121 :                 if (match > 0 && getModuleId(p) == algebraRef &&
    2262      155058 :                         (getFunctionId(p) == differenceRef ||
    2263      135719 :                          getFunctionId(p) == intersectRef) &&
    2264       20730 :                    (m=is_a_mat(getArg(p,1), &ml)) >= 0) {
    2265       16156 :                         n=is_a_mat(getArg(p,2), &ml);
    2266       16156 :                         o=is_a_mat(getArg(p,3), &ml);
    2267       16156 :                         if(mat_setop(mb, p, &ml, m, n, o)) {
    2268           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2269           0 :                                 goto cleanup;
    2270             :                         }
    2271       16156 :                         actions++;
    2272       16156 :                         continue;
    2273             :                 }
    2274             : 
    2275      545965 :                 if (match == p->retc && p->argc == (p->retc*2) && getFunctionId(p) == NULL) {
    2276           2 :                         if ((r = mat_assign(mb, p, &ml)) == NULL) {
    2277           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2278           0 :                                 goto cleanup;
    2279             :                         }
    2280           2 :                         actions++;
    2281           2 :                         continue;
    2282             :                 }
    2283             : 
    2284             :                 m = n = o = e = -1;
    2285     1079173 :                 for( fm= p->argc-1; fm>=p->retc ; fm--)
    2286     1079173 :                         if ((m=is_a_mat(getArg(p,fm), &ml)) >= 0)
    2287             :                                 break;
    2288             : 
    2289      717369 :                 for( fn= fm-1; fn>=p->retc ; fn--)
    2290      433050 :                         if ((n=is_a_mat(getArg(p,fn), &ml)) >= 0)
    2291             :                                 break;
    2292             : 
    2293      557345 :                 for( fo= fn-1; fo>=p->retc ; fo--)
    2294      183452 :                         if ((o=is_a_mat(getArg(p,fo), &ml)) >= 0)
    2295             :                                 break;
    2296             : 
    2297      560054 :                 for( fe= fo-1; fe>=p->retc ; fe--)
    2298       64638 :                         if ((e=is_a_mat(getArg(p,fe), &ml)) >= 0)
    2299             :                                 break;
    2300             : 
    2301             :                 /* delta* operator */
    2302      545963 :                 if (match == 3 && bats == 3 && isDelta(p) &&
    2303      102704 :                    (m=is_a_mat(getArg(p,fm), &ml)) >= 0 &&
    2304      102704 :                    (n=is_a_mat(getArg(p,fn), &ml)) >= 0 &&
    2305      102704 :                    (o=is_a_mat(getArg(p,fo), &ml)) >= 0){
    2306      102704 :                         if ((r = mat_delta(&ml, mb, p, ml.v, m, n, o, -1, fm, fn, fo, 0)) != NULL) {
    2307      102704 :                                 actions++;
    2308             :                         } else {
    2309           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2310           0 :                                 goto cleanup;
    2311             :                         }
    2312             : 
    2313      102704 :                         continue;
    2314             :                 }
    2315      443260 :                 if (match == 4 && bats == 4 && isDelta(p) &&
    2316       48168 :                    (m=is_a_mat(getArg(p,fm), &ml)) >= 0 &&
    2317       48169 :                    (n=is_a_mat(getArg(p,fn), &ml)) >= 0 &&
    2318       48169 :                    (o=is_a_mat(getArg(p,fo), &ml)) >= 0 &&
    2319       48169 :                    (e=is_a_mat(getArg(p,fe), &ml)) >= 0){
    2320       48169 :                         if ((r = mat_delta(&ml, mb, p, ml.v, m, n, o, e, fm, fn, fo, fe)) != NULL) {
    2321       48170 :                                 actions++;
    2322             :                         } else {
    2323           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2324           0 :                                 goto cleanup;
    2325             :                         }
    2326       48170 :                         continue;
    2327             :                 }
    2328             : 
    2329             :                 /* select on insert, should use last tid only */
    2330             : #if 0
    2331             :                 if (match == 1 && fm == 2 && isSelect(p) && p->retc == 1 &&
    2332             :                    (m=is_a_mat(getArg(p,fm), &ml)) >= 0 &&
    2333             :                    !ml.v[m].packed && /* not packed yet */
    2334             :                    (getArg(p,fm-1) > maxvars || getModuleId(old[vars[getArg(p,fm-1)]]) == sqlRef)){
    2335             :                         if((r = copyInstruction(p)) == NULL) {
    2336             :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2337             :                                 goto cleanup;
    2338             :                         }
    2339             :                         getArg(r, fm) = getArg(ml.v[m].mi, ml.v[m].mi->argc-1);
    2340             :                         pushInstruction(mb, r);
    2341             :                         actions++;
    2342             :                         continue;
    2343             :                 }
    2344             : #endif
    2345             : 
    2346             :                 /* select on update, with nil bat */
    2347      395091 :                 if (match == 1 && fm == 1 && isSelect(p) && p->retc == 1 &&
    2348       29124 :                    (m=is_a_mat(getArg(p,fm), &ml)) >= 0 && bats == 2 &&
    2349           0 :                         isaBatType(getArgType(mb,p,2)) && isVarConstant(mb,getArg(p,2)) &&
    2350           0 :                         is_bat_nil(getVarConstant(mb,getArg(p,2)).val.bval)) {
    2351           0 :                         if (mat_apply1(mb, p, &ml, m, fm)) {
    2352           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2353           0 :                                 goto cleanup;
    2354             :                         }
    2355           0 :                         actions++;
    2356           0 :                         continue;
    2357             :                 }
    2358             : 
    2359      395091 :                 if (match == bats && p->retc == 1 && (isMap2Op(p) || isMapOp(p) || isFragmentGroup(p) || isFragmentGroup2(p))) {
    2360      208024 :                         if(mat_apply(mb, p, &ml, match)) {
    2361           0 :                                 msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2362           0 :                                 goto cleanup;
    2363             :                         }
    2364      208023 :                         actions++;
    2365      208023 :                         continue;
    2366             :                 }
    2367             : 
    2368             :                 /*
    2369             :                  * All other instructions should be checked for remaining MAT dependencies.
    2370             :                  * It requires MAT materialization.
    2371             :                  */
    2372             : 
    2373      827262 :                 for (k = p->retc; k<p->argc; k++) {
    2374      640194 :                         if((m=is_a_mat(getArg(p,k), &ml)) >= 0){
    2375      224097 :                                 mat_pack(mb, &ml, m);
    2376             :                         }
    2377             :                 }
    2378             : 
    2379      187068 :                 cp = copyInstruction(p);
    2380      187068 :                 if(!cp) {
    2381           0 :                         msg = createException(MAL,"optimizer.mergetable",SQLSTATE(HY013) MAL_MALLOC_FAIL);
    2382           0 :                         goto cleanup;
    2383             :                 }
    2384      187068 :                 pushInstruction(mb, cp);
    2385             :         }
    2386             :         (void) stk;
    2387             : 
    2388    11233731 :         for (; i<oldtop; i++) { /* add optimizer pipeline back again */
    2389    10882676 :                 pushInstruction(mb, old[i]);
    2390             :         }
    2391             : 
    2392      351055 :         if ( mb->errors == MAL_SUCCEED) {
    2393     7738114 :                 for(i=0; i<slimit; i++) {
    2394     7738114 :                         if (old[i] && old[i]->token == ENDsymbol) /* don't free optimizer calls */
    2395             :                                 break;
    2396     7387059 :                         freeInstruction(old[i]);
    2397             :                 }
    2398      351055 :                 GDKfree(old);
    2399             :         }
    2400     2291969 :         for (i=0; i<ml.top; i++) {
    2401     1940914 :                 if (ml.v[i].mi && !ml.v[i].pushed)
    2402     1519182 :                         freeInstruction(ml.v[i].mi);
    2403             :         }
    2404      351055 : cleanup:
    2405      351362 :         if (vars) GDKfree(vars);
    2406      351362 :         if (ml.v) GDKfree(ml.v);
    2407      351362 :         if (ml.horigin) GDKfree(ml.horigin);
    2408      351362 :         if (ml.torigin) GDKfree(ml.torigin);
    2409      351362 :         if (ml.vars) GDKfree(ml.vars);
    2410             :         /* Defense line against incorrect plans */
    2411      351362 :         if( actions > 0 && msg == MAL_SUCCEED){
    2412             :                 if (!msg)
    2413       37377 :                         msg = chkTypes(cntxt->usermodule, mb, FALSE);
    2414       37377 :                 if (!msg)
    2415       37377 :                         msg = chkFlow(mb);
    2416       37377 :                 if (!msg)
    2417       37377 :                         msg = chkDeclarations(mb);
    2418             :         }
    2419      313985 : cleanup2:
    2420             :         /* keep actions taken as a fake argument */
    2421      353096 :         (void) pushInt(mb, pci, actions);
    2422             : 
    2423             : #ifndef NDEBUG
    2424      353096 :         if( bailout)
    2425         307 :                 TRC_INFO(MAL_OPTIMIZER, "Merge table bailout\n");
    2426             : #endif
    2427             :         return msg;
    2428             : }

Generated by: LCOV version 1.14