LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_pushselect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 288 525 54.9 %
Date: 2024-11-12 19:36:54 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "opt_pushselect.h"
      15             : #include "mal_interpreter.h"  /* for showErrors() */
      16             : 
      17             : static InstrPtr
      18       81519 : PushArgument(MalBlkPtr mb, InstrPtr p, int arg, int pos)
      19             : {
      20       81519 :         int i;
      21             : 
      22       81519 :         p = pushArgument(mb, p, arg);   /* push at end */
      23       81519 :         if (mb->errors == NULL) {
      24      326076 :                 for (i = p->argc - 1; i > pos; i--)
      25      244557 :                         getArg(p, i) = getArg(p, i - 1);
      26       81519 :                 getArg(p, pos) = arg;
      27             :         }
      28       81519 :         return p;
      29             : }
      30             : 
      31             : static InstrPtr
      32       31253 : ReplaceWithNil(MalBlkPtr mb, InstrPtr p, int pos)
      33             : {
      34       31253 :         p = pushNilBat(mb, p);  /* push at end */
      35       31253 :         getArg(p, pos) = getArg(p, p->argc - 1);
      36       31253 :         p->argc--;
      37       31253 :         return p;
      38             : }
      39             : 
      40             : 
      41             : #define MAX_TABLES 64
      42             : 
      43             : typedef struct subselect_t {
      44             :         int nr;
      45             :         int tid[MAX_TABLES];
      46             :         int subselect[MAX_TABLES];
      47             : } subselect_t;
      48             : 
      49             : static int
      50        6737 : subselect_add(subselect_t *subselects, int tid, int subselect)
      51             : {
      52        6737 :         int i;
      53             : 
      54        6969 :         for (i = 0; i < subselects->nr; i++) {
      55         543 :                 if (subselects->tid[i] == tid) {
      56         311 :                         if (subselects->subselect[i] == subselect)
      57             :                                 return i;
      58             :                         else
      59         311 :                                 return -1;
      60             :                 }
      61             :         }
      62        6426 :         if (i >= MAX_TABLES)
      63             :                 return -1;
      64        6426 :         subselects->nr++;
      65        6426 :         subselects->tid[i] = tid;
      66        6426 :         subselects->subselect[i] = subselect;
      67        6426 :         return i;
      68             : }
      69             : 
      70             : static int
      71    35433893 : lastbat_arg(MalBlkPtr mb, InstrPtr p)
      72             : {
      73    35433893 :         int i = 0;
      74    43719573 :         for (i = p->retc; i < p->argc; i++) {
      75    19998624 :                 int type = getArgType(mb, p, i);
      76    19998624 :                 if (!isaBatType(type))
      77             :                         break;
      78             :         }
      79    35433893 :         if (i < p->argc)
      80    11713045 :                 return i - 1;
      81             :         return 0;
      82             : }
      83             : 
      84             : /* check for updates in between assignment to variables newv and oldv */
      85             : static int
      86             : no_updates(InstrPtr *old, int *vars, int oldv, int newv)
      87             : {
      88             :         while (newv > oldv) {
      89             :                 InstrPtr q = old[vars[newv]];
      90             : 
      91             :                 if (isUpdateInstruction(q))
      92             :                         return 0;
      93             :                 newv = getArg(q, 1);
      94             :         }
      95             :         return 1;
      96             : }
      97             : 
      98             : #define isIntersect(p) (getModuleId(p) == algebraRef && getFunctionId(p) == intersectRef)
      99             : 
     100             : str
     101      483512 : OPTpushselectImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
     102             :                                                         InstrPtr pci)
     103             : {
     104      483512 :         int i, j, limit, slimit, actions = 0, *vars, *nvars = NULL,
     105      483512 :                 *slices = NULL, push_down_delta = 0, nr_topn = 0, nr_likes = 0,
     106      483512 :                 no_mito = 0;
     107      483512 :         bool *rslices = NULL, *oclean = NULL;
     108      483512 :         InstrPtr p, *old = NULL;
     109      483512 :         subselect_t subselects;
     110      483512 :         str msg = MAL_SUCCEED;
     111             : 
     112      483512 :         subselects = (subselect_t) { 0 };
     113      483512 :         if (mb->errors)
     114           0 :                 throw(MAL, "optimizer.pushselect", "%s", mb->errors);
     115             : 
     116      483512 :         no_mito = !isOptimizerEnabled(mb, mitosisRef);
     117      483561 :         (void) stk;
     118      483561 :         vars = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     119      483551 :         if (vars == NULL)
     120           0 :                 throw(MAL, "optimizer.pushselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     121             : 
     122      483551 :         limit = mb->stop;
     123      483551 :         slimit = mb->ssize;
     124      483551 :         old = mb->stmt;
     125             : 
     126             :         /* check for bailout conditions */
     127    18652463 :         for (i = 1; mb->errors == NULL && i < limit; i++) {
     128    18183086 :                 int lastbat;
     129    18183086 :                 p = old[i];
     130             : 
     131    36267179 :                 for (j = 0; j < p->retc; j++) {
     132    18084093 :                         int res = getArg(p, j);
     133    18084093 :                         vars[res] = i;
     134             :                 }
     135             : 
     136    18183086 :                 if (getModuleId(p) == algebraRef
     137     1500011 :                         && ((!no_mito && getFunctionId(p) == intersectRef)
     138     1497962 :                                 || getFunctionId(p) == differenceRef)) {
     139       13869 :                         GDKfree(vars);
     140       13869 :                         goto wrapup;
     141             :                 }
     142             : 
     143    18169217 :                 if (isSlice(p))
     144       16544 :                         nr_topn++;
     145             : 
     146    18169060 :                 if (isLikeOp(p))
     147         318 :                         nr_likes++;
     148             : 
     149    18169208 :                 if (no_mito && isIntersect(p))
     150           8 :                         push_down_delta++;
     151             : 
     152    18169208 :                 if ((getModuleId(p) == sqlRef && getFunctionId(p) == deltaRef)
     153    18014695 :                         || (no_mito && getModuleId(p) == matRef
     154          14 :                                 && getFunctionId(p) == packRef && p->argc == (p->retc + 2)))
     155      154513 :                         push_down_delta++;
     156             : 
     157    18169208 :                 if ( /* DISABLES CODE */ (0) && getModuleId(p) == sqlRef && getFunctionId(p) == tidRef) {       /* rewrite equal table ids */
     158             :                         int sname = getArg(p, 2), tname = getArg(p, 3), s;
     159             : 
     160             :                         for (s = 0; s < subselects.nr; s++) {
     161             :                                 InstrPtr q = old[vars[subselects.tid[s]]];
     162             :                                 int Qsname = getArg(q, 2), Qtname = getArg(q, 3);
     163             : 
     164             :                                 if (no_updates(old, vars, getArg(q, 1), getArg(p, 1))
     165             :                                         && ((sname == Qsname && tname == Qtname)
     166             :                                                 || ( /* DISABLES CODE */ (0)
     167             :                                                         && strcmp(getVarConstant(mb, sname).val.sval,
     168             :                                                                           getVarConstant(mb, Qsname).val.sval) == 0
     169             :                                                         &&
     170             :                                                         strcmp(getVarConstant(mb, tname).val.sval,
     171             :                                                                    getVarConstant(mb,
     172             :                                                                                                   Qtname).val.sval) == 0))) {
     173             :                                         clrFunction(p);
     174             :                                         p->retc = 1;
     175             :                                         p->argc = 2;
     176             :                                         getArg(p, 1) = getArg(q, 0);
     177             :                                         break;
     178             :                                 }
     179             :                         }
     180             :                 }
     181    18169208 :                 lastbat = lastbat_arg(mb, p);
     182    18169208 :                 if (isSelect(p) && p->retc == 1 &&
     183      590173 :                         /* no cand list */ getArgType(mb, p,
     184             :                                                                                   lastbat) != newBatType(TYPE_oid)) {
     185      479247 :                         int i1 = getArg(p, 1), tid = 0;
     186      479247 :                         InstrPtr q = old[vars[i1]];
     187             : 
     188             :                         /* find the table ids */
     189      479247 :                         while (!tid) {
     190      498298 :                                 if (getModuleId(q) == algebraRef
     191       23667 :                                         && getFunctionId(q) == projectionRef) {
     192       20578 :                                         int i1 = getArg(q, 1);
     193       20578 :                                         InstrPtr s = old[vars[i1]];
     194             : 
     195       20578 :                                         if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef)
     196       20578 :                                                 tid = getArg(q, 1);
     197       20578 :                                         if (s->argc == 2 && s->retc == 1) {
     198           0 :                                                 int i1 = getArg(s, 1);
     199           0 :                                                 InstrPtr s = old[vars[i1]];
     200           0 :                                                 if (getModuleId(s) == sqlRef
     201           0 :                                                         && getFunctionId(s) == tidRef)
     202      479243 :                                                         tid = getArg(q, 1);
     203             :                                         }
     204             :                                         break;
     205      477720 :                                 } else if (isMapOp(q) && q->retc == 1 && q->argc >= 2
     206       19122 :                                                    && isaBatType(getArgType(mb, q, 1))) {
     207       18945 :                                         int i1 = getArg(q, 1);
     208       18945 :                                         q = old[vars[i1]];
     209      458684 :                                 } else if (isMapOp(q) && q->retc == 1 && q->argc >= 3
     210         177 :                                                    && isaBatType(getArgType(mb, q, 2))) {
     211         106 :                                         int i2 = getArg(q, 2);
     212         106 :                                         q = old[vars[i2]];
     213             :                                 } else {
     214             :                                         break;
     215             :                                 }
     216             :                         }
     217      479243 :                         if (tid && subselect_add(&subselects, tid, getArg(p, 0)) < 0) {
     218         311 :                                 GDKfree(vars);
     219         311 :                                 goto wrapup;
     220             :                         }
     221             :                 }
     222             :                 /* left hand side */
     223    18168912 :                 if ((ATOMIC_GET(&GDKdebug) & PUSHCANDMASK) && isMatJoinOp(p)
     224           0 :                         && p->retc == 2) {
     225           0 :                         int i1 = getArg(p, 2), tid = 0;
     226           0 :                         InstrPtr q = old[vars[i1]];
     227             : 
     228             :                         /* find the table ids */
     229           0 :                         while (!tid) {
     230           0 :                                 if (getModuleId(q) == algebraRef
     231           0 :                                         && getFunctionId(q) == projectionRef) {
     232           0 :                                         int i1 = getArg(q, 1);
     233           0 :                                         InstrPtr s = old[vars[i1]];
     234             : 
     235           0 :                                         if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef)
     236             :                                                 tid = getArg(q, 1);
     237             :                                         break;
     238           0 :                                 } else if (isMapOp(q) && q->argc >= 2
     239           0 :                                                    && isaBatType(getArgType(mb, q, 1))) {
     240           0 :                                         int i1 = getArg(q, 1);
     241           0 :                                         q = old[vars[i1]];
     242           0 :                                 } else if (isMapOp(q) && q->argc >= 3
     243           0 :                                                    && isaBatType(getArgType(mb, q, 2))) {
     244           0 :                                         int i2 = getArg(q, 2);
     245           0 :                                         q = old[vars[i2]];
     246             :                                 } else {
     247             :                                         break;
     248             :                                 }
     249             :                         }
     250           0 :                         if (tid && subselect_add(&subselects, tid, getArg(p, 0)) < 0) {
     251           0 :                                 GDKfree(vars);
     252           0 :                                 goto wrapup;
     253             :                         }
     254             :                 }
     255             :                 /* right hand side */
     256    18168912 :                 if ((ATOMIC_GET(&GDKdebug) & PUSHCANDMASK) && isMatJoinOp(p)
     257           0 :                         && p->retc == 2) {
     258           0 :                         int i1 = getArg(p, 3), tid = 0;
     259           0 :                         InstrPtr q = old[vars[i1]];
     260             : 
     261             :                         /* find the table ids */
     262           0 :                         while (!tid) {
     263           0 :                                 if (getModuleId(q) == algebraRef
     264           0 :                                         && getFunctionId(q) == projectionRef) {
     265           0 :                                         int i1 = getArg(q, 1);
     266           0 :                                         InstrPtr s = old[vars[i1]];
     267             : 
     268           0 :                                         if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef)
     269             :                                                 tid = getArg(q, 1);
     270             :                                         break;
     271           0 :                                 } else if (isMapOp(q) && q->argc >= 2
     272           0 :                                                    && isaBatType(getArgType(mb, q, 1))) {
     273           0 :                                         int i1 = getArg(q, 1);
     274           0 :                                         q = old[vars[i1]];
     275           0 :                                 } else if (isMapOp(q) && q->argc >= 3
     276           0 :                                                    && isaBatType(getArgType(mb, q, 2))) {
     277           0 :                                         int i2 = getArg(q, 2);
     278           0 :                                         q = old[vars[i2]];
     279             :                                 } else {
     280             :                                         break;
     281             :                                 }
     282             :                         }
     283           0 :                         if (tid && subselect_add(&subselects, tid, getArg(p, 1)) < 0) {
     284           0 :                                 GDKfree(vars);
     285           0 :                                 goto wrapup;
     286             :                         }
     287             :                 }
     288             :         }
     289             : 
     290      469377 :         if (nr_likes || subselects.nr) {
     291        5701 :                 if (newMalBlkStmt(mb, mb->ssize) < 0) {
     292           0 :                         GDKfree(vars);
     293           0 :                         goto wrapup;
     294             :                 }
     295             : 
     296        5700 :                 pushInstruction(mb, old[0]);
     297             : 
     298      304351 :                 for (i = 1; mb->errors == NULL && i < limit; i++) {
     299      292955 :                         p = old[i];
     300             : 
     301             :                         /* rewrite batalgebra.like + [theta]select -> likeselect */
     302      292955 :                         if (getModuleId(p) == algebraRef && p->retc == 1
     303       15110 :                                 && (getFunctionId(p) == selectRef
     304       14216 :                                         || getFunctionId(p) == thetaselectRef)) {
     305        7380 :                                 int var = getArg(p, 1);
     306        7380 :                                 InstrPtr q = mb->stmt[vars[var]];    /* BEWARE: the optimizer may not add or remove statements ! */
     307             : 
     308        7380 :                                 if (isLikeOp(q) && !isaBatType(getArgType(mb, q, 2)) && isVarConstant(mb, getArg(q, 2)) &&      /* pattern is a value */
     309           9 :                                         isVarConstant(mb, getArg(q, 3)) &&      /* escape is a value */
     310           9 :                                         isVarConstant(mb, getArg(q, 4)) &&      /* isensitive flag is a value */
     311           9 :                                         getArg(q, 0) == getArg(p,
     312             :                                                                                    1)
     313             :                                         /* the output variable from batalgebra.like is the input one for [theta]select */
     314             :                                         ) {
     315           9 :                                         int has_cand = (getArgType(mb, p, 2) == newBatType(TYPE_oid)),
     316           9 :                                                 offset = 0, anti = (getFunctionId(q)[0] == 'n');
     317           9 :                                         bit ignore_case = *(bit *) getVarValue(mb, getArg(q, 4)),
     318           9 :                                                 selectok = TRUE;
     319             : 
     320             :                                         /* TODO at the moment we cannot convert if the select statement has NULL semantics
     321             :                                            we can convert it into VAL is NULL or PATTERN is NULL or ESCAPE is NULL
     322             :                                          */
     323           9 :                                         if (getFunctionId(p) == selectRef
     324           2 :                                                 && isVarConstant(mb, getArg(p, 2 + has_cand))
     325           2 :                                                 && isVarConstant(mb, getArg(p, 3 + has_cand))
     326           2 :                                                 && isVarConstant(mb, getArg(p, 4 + has_cand))
     327           2 :                                                 && isVarConstant(mb, getArg(p, 5 + has_cand))
     328           2 :                                                 && isVarConstant(mb, getArg(p, 6 + has_cand))
     329           4 :                                                 && (p->argc < (has_cand ? 9 : 8)
     330           0 :                                                         || isVarConstant(mb, getArg(p, 7 + has_cand)))) {
     331           2 :                                                 bit low = *(bit *) getVarValue(mb,
     332             :                                                                                                            getArg(p, 2 + has_cand)),
     333           2 :                                                         high = *(bit *) getVarValue(mb,
     334             :                                                                                                                 getArg(p, 3 + has_cand));
     335           2 :                                                 bit li = *(bit *) getVarValue(mb,
     336             :                                                                                                           getArg(p, 4 + has_cand)),
     337           2 :                                                         hi = *(bit *) getVarValue(mb,
     338             :                                                                                                           getArg(p, 5 + has_cand));
     339           2 :                                                 bit santi = *(bit *) getVarValue(mb,
     340             :                                                                                                                  getArg(p, 6 + has_cand));
     341           2 :                                                 bit sunknown = (p->argc == (has_cand ? 9 : 8)) ? 0 : *(bit *) getVarValue(mb, getArg(p, 7 + has_cand));
     342             : 
     343             :                                                 /* semantic or not symmetric cases, it cannot be converted */
     344           2 :                                                 if (is_bit_nil(low) || is_bit_nil(li)
     345           0 :                                                         || is_bit_nil(santi) || low != high || li != hi
     346           0 :                                                         || sunknown)
     347           2 :                                                         selectok = FALSE;
     348             : 
     349             :                                                 /* there are no negative candidate lists so on = false situations swap anti flag */
     350           2 :                                                 if (low == 0)
     351           0 :                                                         anti = !anti;
     352           2 :                                                 if (li == 0)
     353           0 :                                                         anti = !anti;
     354           2 :                                                 if (santi)
     355           0 :                                                         anti = !anti;
     356           7 :                                         } else if (getFunctionId(p) == thetaselectRef
     357           7 :                                                            && isVarConstant(mb, getArg(p, 3))
     358           7 :                                                            && isVarConstant(mb, getArg(p, 4))) {
     359           7 :                                                 bit truth_value = *(bit *) getVarValue(mb, getArg(p, 3));
     360           7 :                                                 str comparison = (str) getVarValue(mb, getArg(p, 4));
     361             : 
     362             :                                                 /* there are no negative candidate lists so on = false situations swap anti flag */
     363           7 :                                                 if (truth_value == 0)
     364           2 :                                                         anti = !anti;
     365           5 :                                                 else if (is_bit_nil(truth_value))
     366           0 :                                                         selectok = FALSE;
     367           7 :                                                 if (strcmp(comparison, "<>") == 0)
     368           0 :                                                         anti = !anti;
     369           7 :                                                 else if (strcmp(comparison, "==") != 0)
     370             :                                                         selectok = FALSE;
     371             :                                         } else {
     372             :                                                 selectok = FALSE;
     373             :                                         }
     374             : 
     375           9 :                                         if (selectok) {
     376           7 :                                                 InstrPtr r = newInstruction(mb, algebraRef, likeselectRef);
     377           7 :                                                 if (r == NULL) {
     378           0 :                                                         msg = createException(MAL, "optimizer.pushselect",
     379             :                                                                                                   SQLSTATE(HY013)
     380             :                                                                                                   MAL_MALLOC_FAIL);
     381           0 :                                                         break;
     382             :                                                 }
     383           7 :                                                 getArg(r, 0) = getArg(p, 0);
     384           7 :                                                 r = pushArgument(mb, r, getArg(q, 1));
     385           7 :                                                 if (has_cand) {
     386           6 :                                                         r = pushArgument(mb, r, getArg(p, 2));
     387           6 :                                                         offset = 1;
     388           1 :                                                 } else if (isaBatType(getArgType(mb, q, 1))) {  /* likeselect calls have a candidate parameter */
     389           1 :                                                         r = pushNilBat(mb, r);
     390           1 :                                                         offset = 1;
     391             :                                                 }
     392          28 :                                                 for (int a = 2; a < q->argc; a++)
     393          21 :                                                         r = pushArgument(mb, r, getArg(q, a));
     394           7 :                                                 if (r->argc < (4 + offset))
     395           0 :                                                         r = pushStr(mb, r,
     396           0 :                                                                                 (str) getVarValue(mb, getArg(q, 3)));
     397           7 :                                                 if (r->argc < (5 + offset))
     398           0 :                                                         r = pushBit(mb, r, ignore_case);
     399           7 :                                                 if (r->argc < (6 + offset))
     400           7 :                                                         r = pushBit(mb, r, anti);
     401           7 :                                                 freeInstruction(p);
     402           7 :                                                 p = r;
     403           7 :                                                 actions++;
     404             :                                         }
     405             :                                 }
     406             :                         }
     407             : 
     408             :                         /* inject table ids into subselect
     409             :                          * s = subselect(c, C1..) => subselect(c, t, C1..)
     410             :                          */
     411      292955 :                         pushInstruction(mb, p);
     412             :                 }
     413        5697 :                 for (; i < limit; i++)
     414           0 :                         if (old[i])
     415           0 :                                 pushInstruction(mb, old[i]);
     416     1163003 :                 for (; i < slimit; i++)
     417     1157305 :                         if (old[i])
     418           0 :                                 freeInstruction(old[i]);
     419        5698 :                 GDKfree(old);
     420        5701 :                 if (msg != MAL_SUCCEED || !push_down_delta) {
     421        5680 :                         GDKfree(vars);
     422        5681 :                         goto wrapup;
     423             :                 }
     424             :         }
     425             : 
     426             :         /* now push selects through delta's */
     427      463697 :         limit = mb->stop;
     428      463697 :         slimit = mb->ssize;
     429      463697 :         old = mb->stmt;
     430             : 
     431      463697 :         nvars = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     432      463721 :         slices = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     433      463724 :         rslices = (bool *) GDKzalloc(sizeof(bool) * mb->vtop);
     434      463724 :         oclean = (bool *) GDKzalloc(sizeof(bool) * mb->vtop);
     435      927441 :         if (!nvars || !slices || !rslices || !oclean ||
     436      463714 :                 newMalBlkStmt(mb, mb->stop + (5 * push_down_delta) + (2 * nr_topn)) < 0) {
     437           0 :                 mb->stmt = old;
     438           0 :                 GDKfree(vars);
     439           0 :                 GDKfree(nvars);
     440           0 :                 GDKfree(slices);
     441           0 :                 GDKfree(rslices);
     442           0 :                 GDKfree(oclean);
     443           0 :                 goto wrapup;
     444             :         }
     445      463727 :         pushInstruction(mb, old[0]);
     446             : 
     447    18199817 :         for (i = 1; mb->errors == NULL && i < limit; i++) {
     448    17272428 :                 int lastbat;
     449    17272428 :                 p = old[i];
     450             : 
     451    34351045 :                 for (j = 0; j < p->retc; j++) {
     452    17078617 :                         int res = getArg(p, j);
     453    17078617 :                         vars[res] = i;
     454             :                 }
     455             : 
     456             :                 /* push subslice under projectdelta */
     457    17272428 :                 if (isSlice(p) && p->retc == 1) {
     458       16358 :                         int var = getArg(p, 1);
     459       16358 :                         InstrPtr q = old[vars[var]];
     460       16358 :                         if (q && getModuleId(q) == sqlRef
     461          11 :                                 && getFunctionId(q) == projectdeltaRef) {
     462           0 :                                 InstrPtr r = copyInstruction(p);
     463           0 :                                 InstrPtr s = copyInstruction(q);
     464           0 :                                 if (r == NULL || s == NULL) {
     465           0 :                                         freeInstruction(r);
     466           0 :                                         freeInstruction(s);
     467           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     468             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     469           0 :                                         break;
     470             :                                 }
     471             : 
     472           0 :                                 rslices[getArg(q, 0)] = true;   /* mark projectdelta as rewritten */
     473           0 :                                 rslices[getArg(p, 0)] = true;   /* mark slice as rewritten */
     474             : 
     475             :                                 /* slice the candidates */
     476           0 :                                 setFunctionId(r, sliceRef);
     477           0 :                                 nvars[getArg(p, 0)] = getArg(r, 0) = newTmpVariable(mb, getArgType(mb, r, 0));
     478           0 :                                 slices[getArg(q, 1)] = getArg(p, 0);
     479             : 
     480           0 :                                 setVarCList(mb, getArg(r, 0));
     481           0 :                                 getArg(r, 1) = getArg(s, 1);
     482           0 :                                 pushInstruction(mb, r);
     483             : 
     484           0 :                                 nvars[getArg(q, 0)] = getArg(s, 0) = newTmpVariable(mb, getArgType(mb, s, 0));
     485           0 :                                 getArg(s, 1) = getArg(r, 0);    /* use result of slice */
     486           0 :                                 pushInstruction(mb, s);
     487           0 :                                 oclean[i] = true;
     488           0 :                                 actions++;
     489           0 :                                 continue;
     490             :                         }
     491             :                 }
     492             :                 /* Leftfetchjoins involving rewritten sliced candidates ids need to be flattened
     493             :                  * l = projection(t, c); => l = c;
     494             :                  * and
     495             :                  * l = projection(s, ntids); => l = s;
     496             :                  */
     497    17256622 :                 else if (getModuleId(p) == algebraRef
     498     1233255 :                                  && getFunctionId(p) == projectionRef) {
     499     1066025 :                         int var = getArg(p, 1);
     500     1066025 :                         InstrPtr r = old[vars[var]], q;
     501             : 
     502     1066025 :                         if (r && isSlice(r) && rslices[var] && getArg(r, 0) == getArg(p, 1)) {
     503           0 :                                 int col = getArg(p, 2);
     504             : 
     505           0 :                                 if (!rslices[col]) {    /* was the deltaproject rewritten (sliced) */
     506           0 :                                         InstrPtr s = old[vars[col]], u = NULL;
     507             : 
     508           0 :                                         if (s && getModuleId(s) == algebraRef
     509           0 :                                                 && getFunctionId(s) == projectRef) {
     510           0 :                                                 col = getArg(s, 1);
     511           0 :                                                 u = s;
     512           0 :                                                 s = old[vars[col]];
     513             :                                         }
     514           0 :                                         if (s && getModuleId(s) == sqlRef
     515           0 :                                                 && getFunctionId(s) == projectdeltaRef) {
     516           0 :                                                 InstrPtr t = copyInstruction(s);
     517           0 :                                                 if (t == NULL) {
     518           0 :                                                         msg = createException(MAL, "optimizer.pushselect",
     519             :                                                                                                   SQLSTATE(HY013)
     520             :                                                                                                   MAL_MALLOC_FAIL);
     521           0 :                                                         break;
     522             :                                                 }
     523             : 
     524           0 :                                                 getArg(t, 1) = nvars[getArg(r, 0)];     /* use result of slice */
     525           0 :                                                 rslices[col] = true;
     526           0 :                                                 nvars[getArg(s, 0)] = getArg(t, 0) = newTmpVariable(mb, getArgType(mb, t, 0));
     527           0 :                                                 pushInstruction(mb, t);
     528           0 :                                                 if (u) {        /* add again */
     529           0 :                                                         if ((t = copyInstruction(u)) == NULL) {
     530           0 :                                                                 msg = createException(MAL,
     531             :                                                                                                           "optimizer.pushselect",
     532             :                                                                                                           SQLSTATE(HY013)
     533             :                                                                                                           MAL_MALLOC_FAIL);
     534           0 :                                                                 break;
     535             :                                                         }
     536           0 :                                                         getArg(t, 1) = nvars[getArg(t, 1)];
     537           0 :                                                         pushInstruction(mb, t);
     538             :                                                 }
     539             :                                         }
     540             :                                 }
     541           0 :                                 q = newAssignment(mb);
     542           0 :                                 if (q == NULL) {
     543           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     544             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     545           0 :                                         break;
     546             :                                 }
     547           0 :                                 getArg(q, 0) = getArg(p, 0);
     548           0 :                                 q = pushArgument(mb, q, getArg(p, 2));
     549           0 :                                 if (nvars[getArg(p, 2)] > 0)
     550           0 :                                         getArg(q, 1) = nvars[getArg(p, 2)];
     551           0 :                                 oclean[i] = true;
     552           0 :                                 actions++;
     553           0 :                                 pushInstruction(mb, q);
     554           0 :                                 continue;
     555             :                         }
     556    16190597 :                 } else if (p->argc >= 2 && slices[getArg(p, 1)] != 0) {
     557             :                         /* use new slice candidate list */
     558           0 :                         assert(slices[getArg(p, 1)] == nvars[getArg(p, 1)]);
     559           0 :                         getArg(p, 1) = slices[getArg(p, 1)];
     560             :                 }
     561             :                 /* remap */
     562    38088194 :                 for (j = p->retc; j < p->argc; j++) {
     563    20815269 :                         int var = getArg(p, j);
     564    20815269 :                         if (nvars[var] > 0) {
     565           0 :                                 getArg(p, j) = nvars[var];
     566             :                         }
     567             :                 }
     568             : 
     569             :                 /* c = delta(b, uid, uvl)
     570             :                  * s = select(c, C1..)
     571             :                  *
     572             :                  * nc = select(b, C1..)
     573             :                  * nu = select(uvl, C1..)
     574             :                  * s = subdelta(nc, uid, nu);
     575             :                  *
     576             :                  * doesn't handle Xselect(x, .. z, C1.. cases) ie multicolumn selects
     577             :                  *
     578             :                  * also handle (if no_mito)
     579             :                  * c = pack(b, ins)
     580             :                  * s = select(c, C1..)
     581             :                  */
     582    17272925 :                 lastbat = lastbat_arg(mb, p);
     583    17272925 :                 if (isSelect(p) && p->retc == 1 && lastbat == 2) {
     584       71239 :                         int var = getArg(p, 1);
     585       71239 :                         InstrPtr q = old[vars[var]];
     586             : 
     587       71239 :                         if (q && q->token == ASSIGNsymbol) {
     588       32084 :                                 var = getArg(q, 1);
     589       32084 :                                 q = old[vars[var]];
     590             :                         }
     591       71239 :                         if (no_mito && q && getModuleId(q) == matRef
     592           0 :                                 && getFunctionId(q) == packRef && q->argc == (q->retc + 2)) {
     593           0 :                                 InstrPtr r = copyInstruction(p);
     594           0 :                                 InstrPtr t = copyInstruction(p);
     595             : 
     596           0 :                                 if (r == NULL || t == NULL) {
     597           0 :                                         freeInstruction(r);
     598           0 :                                         freeInstruction(t);
     599           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     600             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     601           0 :                                         break;
     602             :                                 }
     603           0 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     604           0 :                                 setVarCList(mb, getArg(r, 0));
     605           0 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     606           0 :                                 r->typeresolved = false;
     607           0 :                                 pushInstruction(mb, r);
     608           0 :                                 getArg(t, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     609           0 :                                 setVarCList(mb, getArg(t, 0));
     610           0 :                                 getArg(t, 1) = getArg(q, 2);    /* inserts */
     611           0 :                                 pushInstruction(mb, t);
     612             : 
     613           0 :                                 InstrPtr u = copyInstruction(q);        /* pack result */
     614           0 :                                 if (u == NULL) {
     615           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     616             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     617           0 :                                         break;
     618             :                                 }
     619           0 :                                 getArg(u, 0) = getArg(p, 0);
     620           0 :                                 getArg(u, 1) = getArg(r, 0);
     621           0 :                                 getArg(u, 2) = getArg(t, 0);
     622           0 :                                 u->typeresolved = false;
     623           0 :                                 pushInstruction(mb, u);
     624           0 :                                 oclean[i] = true;
     625           0 :                                 continue;
     626       71239 :                         } else if (q && getModuleId(q) == sqlRef
     627       64106 :                                            && getFunctionId(q) == deltaRef) {
     628       31253 :                                 InstrPtr r = copyInstruction(p);
     629       31253 :                                 InstrPtr s = copyInstruction(p);
     630       31253 :                                 InstrPtr u = copyInstruction(q);
     631             : 
     632       31253 :                                 if (r == NULL || s == NULL || u == NULL) {
     633           0 :                                         freeInstruction(r);
     634           0 :                                         freeInstruction(s);
     635           0 :                                         freeInstruction(u);
     636           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     637             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     638           0 :                                         break;
     639             :                                 }
     640       31253 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     641       31253 :                                 setVarCList(mb, getArg(r, 0));
     642       31253 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     643       31253 :                                 r->typeresolved = false;
     644       31253 :                                 pushInstruction(mb, r);
     645       31253 :                                 getArg(s, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     646       31253 :                                 setVarCList(mb, getArg(s, 0));
     647       31253 :                                 getArg(s, 1) = getArg(q, 3);    /* updates */
     648       31253 :                                 s = ReplaceWithNil(mb, s, 2);   /* no candidate list */
     649       31253 :                                 setArgType(mb, s, 2, newBatType(TYPE_oid));
     650             :                                 /* make sure to resolve again */
     651       31253 :                                 s->token = ASSIGNsymbol;
     652       31253 :                                 s->typeresolved = false;
     653       31253 :                                 s->fcn = NULL;
     654       31253 :                                 s->blk = NULL;
     655       31253 :                                 pushInstruction(mb, s);
     656             : 
     657       31253 :                                 setFunctionId(u, subdeltaRef);
     658       31253 :                                 getArg(u, 0) = getArg(p, 0);
     659       31253 :                                 getArg(u, 1) = getArg(r, 0);
     660       31253 :                                 getArg(u, 2) = getArg(p, 2);    /* pre-cands */
     661       31253 :                                 getArg(u, 3) = getArg(q, 2);    /* update ids */
     662       31253 :                                 u = pushArgument(mb, u, getArg(s, 0));  /* selected updated values ids */
     663       31253 :                                 u->token = ASSIGNsymbol;
     664       31253 :                                 u->typeresolved = false;
     665       31253 :                                 u->fcn = NULL;
     666       31253 :                                 u->blk = NULL;
     667       31253 :                                 pushInstruction(mb, u);
     668       31253 :                                 oclean[i] = true;
     669       31253 :                                 continue;
     670             :                         }
     671    17201069 :                 } else if (getModuleId(p) == algebraRef
     672     1178431 :                                    && getFunctionId(p) == projectionRef) {
     673     1066044 :                         int id = getArg(p, 1);
     674     1066044 :                         InstrPtr s = old[vars[id]];
     675     1066044 :                         int var = getArg(p, 2);
     676     1066044 :                         InstrPtr q = old[vars[var]];
     677             : 
     678     1066044 :                         if (no_mito && getModuleId(q) == matRef
     679           2 :                                 && getFunctionId(q) == packRef && q->argc == 3
     680           0 :                                 && getModuleId(s) == matRef && getFunctionId(s) == packRef
     681           0 :                                 && s->argc == 3) {
     682           0 :                                 InstrPtr r = copyInstruction(p);
     683           0 :                                 InstrPtr t = copyInstruction(p);
     684             : 
     685           0 :                                 if (r == NULL || t == NULL) {
     686           0 :                                         freeInstruction(r);
     687           0 :                                         freeInstruction(t);
     688           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     689             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     690           0 :                                         break;
     691             :                                 }
     692           0 :                                 getArg(r, 0) = newTmpVariable(mb, getArgType(mb, p, 0));
     693           0 :                                 setVarCList(mb, getArg(r, 0));
     694           0 :                                 getArg(r, 1) = getArg(s, 1);
     695           0 :                                 getArg(r, 2) = getArg(q, 1);    /* column */
     696           0 :                                 r->typeresolved = false;
     697           0 :                                 pushInstruction(mb, r);
     698           0 :                                 getArg(t, 0) = newTmpVariable(mb, getArgType(mb, p, 0));
     699           0 :                                 setVarCList(mb, getArg(t, 0));
     700           0 :                                 getArg(t, 1) = getArg(s, 2);
     701           0 :                                 getArg(t, 2) = getArg(q, 2);    /* inserts */
     702           0 :                                 pushInstruction(mb, t);
     703             : 
     704           0 :                                 InstrPtr u = copyInstruction(q);        /* pack result */
     705           0 :                                 if (u == NULL) {
     706           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     707             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     708           0 :                                         break;
     709             :                                 }
     710           0 :                                 getArg(u, 0) = getArg(p, 0);
     711           0 :                                 getArg(u, 1) = getArg(r, 0);
     712           0 :                                 getArg(u, 2) = getArg(t, 0);
     713           0 :                                 u->typeresolved = false;
     714           0 :                                 pushInstruction(mb, u);
     715           0 :                                 oclean[i] = true;
     716           0 :                                 continue;
     717     1066044 :                         } else if (getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef
     718       81519 :                                            && q->argc == 4) {
     719       81519 :                                 q = copyInstruction(q);
     720       81519 :                                 if (q == NULL) {
     721           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     722             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     723           0 :                                         break;
     724             :                                 }
     725       81519 :                                 setFunctionId(q, projectdeltaRef);
     726       81519 :                                 getArg(q, 0) = getArg(p, 0);
     727       81519 :                                 q = PushArgument(mb, q, getArg(p, 1), 1);
     728       81519 :                                 p = q;
     729       81519 :                                 oclean[i] = true;
     730       81519 :                                 actions++;
     731             :                         }
     732    16135025 :                 } else if (isIntersect(p) && p->retc == 1 && lastbat == 4) {
     733             :                         /* l = delta(b, uid, uvl)
     734             :                          * s = intersect(l, r, li, ..)
     735             :                          *
     736             :                          * nc = intersect(b, r, li..)
     737             :                          * nu = intersect(uvl, r, ..)
     738             :                          * s = subdelta(nc, li, uid, nu);
     739             :                          */
     740           8 :                         int var = getArg(p, 1);
     741           8 :                         InstrPtr q = old[vars[var]];
     742             : 
     743           8 :                         if (q && q->token == ASSIGNsymbol) {
     744           0 :                                 var = getArg(q, 1);
     745           0 :                                 q = old[vars[var]];
     746             :                         }
     747           8 :                         if (q && getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef) {
     748           0 :                                 InstrPtr r = copyInstruction(p);
     749           0 :                                 InstrPtr s = copyInstruction(p);
     750           0 :                                 InstrPtr u = copyInstruction(q);
     751             : 
     752           0 :                                 if (r == NULL || s == NULL || u == NULL) {
     753           0 :                                         freeInstruction(r);
     754           0 :                                         freeInstruction(s);
     755           0 :                                         freeInstruction(u);
     756           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     757             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     758           0 :                                         break;
     759             :                                 }
     760           0 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     761           0 :                                 setVarCList(mb, getArg(r, 0));
     762           0 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     763           0 :                                 r->typeresolved = false;
     764           0 :                                 pushInstruction(mb, r);
     765           0 :                                 getArg(s, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     766           0 :                                 setVarCList(mb, getArg(s, 0));
     767           0 :                                 getArg(s, 1) = getArg(q, 3);    /* updates */
     768           0 :                                 s = ReplaceWithNil(mb, s, 3);   /* no candidate list */
     769           0 :                                 setArgType(mb, s, 3, newBatType(TYPE_oid));
     770             :                                 /* make sure to resolve again */
     771           0 :                                 s->token = ASSIGNsymbol;
     772           0 :                                 s->typeresolved = false;
     773           0 :                                 s->fcn = NULL;
     774           0 :                                 s->blk = NULL;
     775           0 :                                 pushInstruction(mb, s);
     776             : 
     777           0 :                                 setFunctionId(u, subdeltaRef);
     778           0 :                                 getArg(u, 0) = getArg(p, 0);
     779           0 :                                 getArg(u, 1) = getArg(r, 0);
     780           0 :                                 getArg(u, 2) = getArg(p, 3);    /* pre-cands */
     781           0 :                                 getArg(u, 3) = getArg(q, 2);    /* update ids */
     782             :                                 //getArg(u, 4) = getArg(s,0);
     783           0 :                                 p = pushArgument(mb, u, getArg(s, 0));  /* push at end */
     784             :                                 /* make sure to resolve again */
     785           0 :                                 u->token = ASSIGNsymbol;
     786           0 :                                 u->typeresolved = false;
     787           0 :                                 u->fcn = NULL;
     788           0 :                                 u->blk = NULL;
     789           0 :                                 pushInstruction(mb, u);
     790           0 :                                 oclean[i] = true;
     791           0 :                                 continue;
     792             :                         }
     793             :                 }
     794    17241055 :                 assert(p == old[i] || oclean[i]);
     795    17241055 :                 pushInstruction(mb, p);
     796             :         }
     797    17734305 :         for (j = 1; j < i; j++)
     798    17270584 :                 if (old[j] && oclean[j])
     799      112772 :                         freeInstruction(old[j]);
     800   103853168 :         for (; i < slimit; i++)
     801   103389449 :                 if (old[i])
     802           0 :                         pushInstruction(mb, old[i]);
     803      463719 :         GDKfree(vars);
     804      463730 :         GDKfree(nvars);
     805      463725 :         GDKfree(slices);
     806      463728 :         GDKfree(rslices);
     807      463729 :         GDKfree(oclean);
     808      463729 :         GDKfree(old);
     809             : 
     810             :         /* Defense line against incorrect plans */
     811      463718 :         if (msg == MAL_SUCCEED && actions > 0) {
     812       21272 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     813       21272 :                 if (msg == MAL_SUCCEED)
     814       21272 :                         msg = chkFlow(mb);
     815       21272 :                 if (msg == MAL_SUCCEED)
     816       21272 :                         msg = chkDeclarations(mb);
     817             :         }
     818      442446 :   wrapup:
     819             :         /* keep actions taken as a fake argument */
     820      483579 :         (void) pushInt(mb, pci, actions);
     821      483579 :         return msg;
     822             : }

Generated by: LCOV version 1.14