LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_pushselect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 287 526 54.6 %
Date: 2024-04-25 20:03:45 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       81512 : PushArgument(MalBlkPtr mb, InstrPtr p, int arg, int pos)
      19             : {
      20       81512 :         int i;
      21             : 
      22       81512 :         p = pushArgument(mb, p, arg);   /* push at end */
      23       81512 :         if (mb->errors == NULL) {
      24      326048 :                 for (i = p->argc - 1; i > pos; i--)
      25      244536 :                         getArg(p, i) = getArg(p, i - 1);
      26       81512 :                 getArg(p, pos) = arg;
      27             :         }
      28       81512 :         return p;
      29             : }
      30             : 
      31             : static InstrPtr
      32       29994 : ReplaceWithNil(MalBlkPtr mb, InstrPtr p, int pos, int tpe)
      33             : {
      34       29994 :         p = pushNil(mb, p, tpe);        /* push at end */
      35       29994 :         getArg(p, pos) = getArg(p, p->argc - 1);
      36       29994 :         p->argc--;
      37       29994 :         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        6192 : subselect_add(subselect_t *subselects, int tid, int subselect)
      51             : {
      52        6192 :         int i;
      53             : 
      54        6429 :         for (i = 0; i < subselects->nr; i++) {
      55         579 :                 if (subselects->tid[i] == tid) {
      56         342 :                         if (subselects->subselect[i] == subselect)
      57             :                                 return i;
      58             :                         else
      59         342 :                                 return -1;
      60             :                 }
      61             :         }
      62        5850 :         if (i >= MAX_TABLES)
      63             :                 return -1;
      64        5850 :         subselects->nr++;
      65        5850 :         subselects->tid[i] = tid;
      66        5850 :         subselects->subselect[i] = subselect;
      67        5850 :         return i;
      68             : }
      69             : 
      70             : static int
      71    34503587 : lastbat_arg(MalBlkPtr mb, InstrPtr p)
      72             : {
      73    34503587 :         int i = 0;
      74    42617301 :         for (i = p->retc; i < p->argc; i++) {
      75    19587780 :                 int type = getArgType(mb, p, i);
      76    19587780 :                 if (!isaBatType(type) && type != TYPE_bat)
      77             :                         break;
      78             :         }
      79    34503587 :         if (i < p->argc)
      80    11474060 :                 return i - 1;
      81             :         return 0;
      82             : }
      83             : 
      84             : /* check for updates inbetween 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      467667 : OPTpushselectImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
     102             :                                                         InstrPtr pci)
     103             : {
     104      467667 :         int i, j, limit, slimit, actions = 0, *vars, *nvars = NULL,
     105      467667 :                 *slices = NULL, push_down_delta = 0, nr_topn = 0, nr_likes = 0,
     106      467667 :                 no_mito = 0;
     107      467667 :         bool *rslices = NULL, *oclean = NULL;
     108      467667 :         InstrPtr p, *old = NULL;
     109      467667 :         subselect_t subselects;
     110      467667 :         str msg = MAL_SUCCEED;
     111             : 
     112      467667 :         subselects = (subselect_t) { 0 };
     113      467667 :         if (mb->errors)
     114           0 :                 throw(MAL, "optimizer.pushselect", "%s", mb->errors);
     115             : 
     116      467667 :         no_mito = !isOptimizerEnabled(mb, mitosisRef);
     117      467666 :         (void) stk;
     118      467666 :         vars = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     119      467667 :         if (vars == NULL)
     120           0 :                 throw(MAL, "optimizer.pushselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     121             : 
     122      467667 :         limit = mb->stop;
     123      467667 :         slimit = mb->ssize;
     124      467667 :         old = mb->stmt;
     125             : 
     126             :         /* check for bailout conditions */
     127    18115621 :         for (i = 1; mb->errors == NULL && i < limit; i++) {
     128    17660674 :                 int lastbat;
     129    17660674 :                 p = old[i];
     130             : 
     131    35217344 :                 for (j = 0; j < p->retc; j++) {
     132    17556670 :                         int res = getArg(p, j);
     133    17556670 :                         vars[res] = i;
     134             :                 }
     135             : 
     136    17660674 :                 if (getModuleId(p) == algebraRef
     137     1444876 :                         && ((!no_mito && getFunctionId(p) == intersectRef)
     138     1443416 :                                 || getFunctionId(p) == differenceRef)) {
     139       12361 :                         GDKfree(vars);
     140       12361 :                         goto wrapup;
     141             :                 }
     142             : 
     143    17648313 :                 if (isSlice(p))
     144       16619 :                         nr_topn++;
     145             : 
     146    17648343 :                 if (isLikeOp(p))
     147         126 :                         nr_likes++;
     148             : 
     149    17648227 :                 if (no_mito && isIntersect(p))
     150           5 :                         push_down_delta++;
     151             : 
     152    17648227 :                 if ((getModuleId(p) == sqlRef && getFunctionId(p) == deltaRef)
     153    17511553 :                         || (no_mito && getModuleId(p) == matRef
     154           0 :                                 && getFunctionId(p) == packRef && p->argc == (p->retc + 2)))
     155      136674 :                         push_down_delta++;
     156             : 
     157    17648227 :                 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    17648227 :                 lastbat = lastbat_arg(mb, p);
     182    17648227 :                 if (isSelect(p) && p->retc == 1 &&
     183      568663 :                         /* no cand list */ getArgType(mb, p,
     184             :                                                                                   lastbat) != newBatType(TYPE_oid)) {
     185      460522 :                         int i1 = getArg(p, 1), tid = 0;
     186      460522 :                         InstrPtr q = old[vars[i1]];
     187             : 
     188             :                         /* find the table ids */
     189      460522 :                         while (!tid) {
     190      481668 :                                 if (getModuleId(q) == algebraRef
     191       21179 :                                         && getFunctionId(q) == projectionRef) {
     192       19079 :                                         int i1 = getArg(q, 1);
     193       19079 :                                         InstrPtr s = old[vars[i1]];
     194             : 
     195       19079 :                                         if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef)
     196       19079 :                                                 tid = getArg(q, 1);
     197       19079 :                                         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      460525 :                                                         tid = getArg(q, 1);
     203             :                                         }
     204             :                                         break;
     205      462589 :                                 } else if (isMapOp(q) && q->retc == 1 && q->argc >= 2
     206       21180 :                                                    && isaBatType(getArgType(mb, q, 1))) {
     207       21056 :                                         int i1 = getArg(q, 1);
     208       21056 :                                         q = old[vars[i1]];
     209      441534 :                                 } else if (isMapOp(q) && q->retc == 1 && q->argc >= 3
     210         124 :                                                    && isaBatType(getArgType(mb, q, 2))) {
     211          90 :                                         int i2 = getArg(q, 2);
     212          90 :                                         q = old[vars[i2]];
     213             :                                 } else {
     214             :                                         break;
     215             :                                 }
     216             :                         }
     217      460525 :                         if (tid && subselect_add(&subselects, tid, getArg(p, 0)) < 0) {
     218         342 :                                 GDKfree(vars);
     219         342 :                                 goto wrapup;
     220             :                         }
     221             :                 }
     222             :                 /* left hand side */
     223    17647954 :                 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    17647954 :                 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      454947 :         if (nr_likes || subselects.nr) {
     291        4962 :                 if (newMalBlkStmt(mb, mb->ssize) < 0) {
     292           0 :                         GDKfree(vars);
     293           0 :                         goto wrapup;
     294             :                 }
     295             : 
     296        4962 :                 pushInstruction(mb, old[0]);
     297             : 
     298      269992 :                 for (i = 1; mb->errors == NULL && i < limit; i++) {
     299      260068 :                         p = old[i];
     300             : 
     301             :                         /* rewrite batalgebra.like + [theta]select -> likeselect */
     302      260068 :                         if (getModuleId(p) == algebraRef && p->retc == 1
     303       14471 :                                 && (getFunctionId(p) == selectRef
     304       13643 :                                         || getFunctionId(p) == thetaselectRef)) {
     305        6813 :                                 int var = getArg(p, 1);
     306        6813 :                                 InstrPtr q = mb->stmt[vars[var]];    /* BEWARE: the optimizer may not add or remove statements ! */
     307             : 
     308        6813 :                                 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           6 :                                                            && isVarConstant(mb, getArg(p, 4))) {
     359           6 :                                                 bit truth_value = *(bit *) getVarValue(mb, getArg(p, 3));
     360           6 :                                                 str comparison = (str) getVarValue(mb, getArg(p, 4));
     361             : 
     362             :                                                 /* there are no negative candidate lists so on = false situations swap anti flag */
     363           6 :                                                 if (truth_value == 0)
     364           2 :                                                         anti = !anti;
     365           4 :                                                 else if (is_bit_nil(truth_value))
     366           0 :                                                         selectok = FALSE;
     367           6 :                                                 if (strcmp(comparison, "<>") == 0)
     368           0 :                                                         anti = !anti;
     369           6 :                                                 else if (strcmp(comparison, "==") != 0)
     370             :                                                         selectok = FALSE;
     371             :                                         } else {
     372             :                                                 selectok = FALSE;
     373             :                                         }
     374             : 
     375           8 :                                         if (selectok) {
     376           6 :                                                 InstrPtr r = newInstruction(mb, algebraRef, likeselectRef);
     377           6 :                                                 if (r == NULL) {
     378           0 :                                                         msg = createException(MAL, "optimizer.pushselect",
     379             :                                                                                                   SQLSTATE(HY013)
     380             :                                                                                                   MAL_MALLOC_FAIL);
     381           0 :                                                         break;
     382             :                                                 }
     383           6 :                                                 getArg(r, 0) = getArg(p, 0);
     384           6 :                                                 r = pushArgument(mb, r, getArg(q, 1));
     385           6 :                                                 if (has_cand) {
     386           5 :                                                         r = pushArgument(mb, r, getArg(p, 2));
     387           5 :                                                         offset = 1;
     388           1 :                                                 } else if (isaBatType(getArgType(mb, q, 1))) {  /* likeselect calls have a candidate parameter */
     389           1 :                                                         r = pushNil(mb, r, TYPE_bat);
     390           1 :                                                         offset = 1;
     391             :                                                 }
     392          24 :                                                 for (int a = 2; a < q->argc; a++)
     393          18 :                                                         r = pushArgument(mb, r, getArg(q, a));
     394           6 :                                                 if (r->argc < (4 + offset))
     395           0 :                                                         r = pushStr(mb, r,
     396           0 :                                                                                 (str) getVarValue(mb, getArg(q, 3)));
     397           6 :                                                 if (r->argc < (5 + offset))
     398           0 :                                                         r = pushBit(mb, r, ignore_case);
     399           6 :                                                 if (r->argc < (6 + offset))
     400           6 :                                                         r = pushBit(mb, r, anti);
     401           6 :                                                 freeInstruction(p);
     402           6 :                                                 p = r;
     403           6 :                                                 actions++;
     404             :                                         }
     405             :                                 }
     406             :                         }
     407             : 
     408             :                         /* inject table ids into subselect
     409             :                          * s = subselect(c, C1..) => subselect(c, t, C1..)
     410             :                          */
     411      260068 :                         pushInstruction(mb, p);
     412             :                 }
     413        4962 :                 for (; i < limit; i++)
     414           0 :                         if (old[i])
     415           0 :                                 pushInstruction(mb, old[i]);
     416     1019038 :                 for (; i < slimit; i++)
     417     1014076 :                         if (old[i])
     418           0 :                                 freeInstruction(old[i]);
     419        4962 :                 GDKfree(old);
     420        4962 :                 if (msg != MAL_SUCCEED || !push_down_delta) {
     421        4895 :                         GDKfree(vars);
     422        4895 :                         goto wrapup;
     423             :                 }
     424             :         }
     425             : 
     426             :         /* now push selects through delta's */
     427      450052 :         limit = mb->stop;
     428      450052 :         slimit = mb->ssize;
     429      450052 :         old = mb->stmt;
     430             : 
     431      450052 :         nvars = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     432      450069 :         slices = (int *) GDKzalloc(sizeof(int) * mb->vtop);
     433      450066 :         rslices = (bool *) GDKzalloc(sizeof(bool) * mb->vtop);
     434      450069 :         oclean = (bool *) GDKzalloc(sizeof(bool) * mb->vtop);
     435      450068 :         if (!nvars || !slices || !rslices || !oclean
     436      450067 :                 || newMalBlkStmt(mb,
     437      450068 :                                                  mb->stop + (5 * push_down_delta) + (2 * nr_topn)) <
     438             :                 0) {
     439           0 :                 mb->stmt = old;
     440           0 :                 GDKfree(vars);
     441           0 :                 GDKfree(nvars);
     442           0 :                 GDKfree(slices);
     443           0 :                 GDKfree(rslices);
     444           0 :                 GDKfree(oclean);
     445           0 :                 goto wrapup;
     446             :         }
     447      450067 :         pushInstruction(mb, old[0]);
     448             : 
     449    17757547 :         for (i = 1; mb->errors == NULL && i < limit; i++) {
     450    16857425 :                 int lastbat;
     451    16857425 :                 p = old[i];
     452             : 
     453    33534986 :                 for (j = 0; j < p->retc; j++) {
     454    16677561 :                         int res = getArg(p, j);
     455    16677561 :                         vars[res] = i;
     456             :                 }
     457             : 
     458             :                 /* push subslice under projectdelta */
     459    16857425 :                 if (isSlice(p) && p->retc == 1) {
     460       16493 :                         int var = getArg(p, 1);
     461       16493 :                         InstrPtr q = old[vars[var]];
     462       16493 :                         if (q && getModuleId(q) == sqlRef
     463          12 :                                 && getFunctionId(q) == projectdeltaRef) {
     464           0 :                                 InstrPtr r = copyInstruction(p);
     465           0 :                                 InstrPtr s = copyInstruction(q);
     466           0 :                                 if (r == NULL || s == NULL) {
     467           0 :                                         freeInstruction(r);
     468           0 :                                         freeInstruction(s);
     469           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     470             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     471           0 :                                         break;
     472             :                                 }
     473             : 
     474           0 :                                 rslices[getArg(q, 0)] = true;   /* mark projectdelta as rewriten */
     475           0 :                                 rslices[getArg(p, 0)] = true;   /* mark slice as rewriten */
     476             : 
     477             :                                 /* slice the candidates */
     478           0 :                                 setFunctionId(r, sliceRef);
     479           0 :                                 nvars[getArg(p, 0)] = getArg(r, 0) = newTmpVariable(mb, getArgType(mb, r, 0));
     480           0 :                                 slices[getArg(q, 1)] = getArg(p, 0);
     481             : 
     482           0 :                                 setVarCList(mb, getArg(r, 0));
     483           0 :                                 getArg(r, 1) = getArg(s, 1);
     484           0 :                                 pushInstruction(mb, r);
     485             : 
     486           0 :                                 nvars[getArg(q, 0)] = getArg(s, 0) = newTmpVariable(mb, getArgType(mb, s, 0));
     487           0 :                                 getArg(s, 1) = getArg(r, 0);    /* use result of slice */
     488           0 :                                 pushInstruction(mb, s);
     489           0 :                                 oclean[i] = true;
     490           0 :                                 actions++;
     491           0 :                                 continue;
     492             :                         }
     493             :                 }
     494             :                 /* Leftfetchjoins involving rewriten sliced candidates ids need to be flattend
     495             :                  * l = projection(t, c); => l = c;
     496             :                  * and
     497             :                  * l = projection(s, ntids); => l = s;
     498             :                  */
     499    16841889 :                 else if (getModuleId(p) == algebraRef
     500     1211185 :                                  && getFunctionId(p) == projectionRef) {
     501     1053453 :                         int var = getArg(p, 1);
     502     1053453 :                         InstrPtr r = old[vars[var]], q;
     503             : 
     504     1053453 :                         if (r && isSlice(r) && rslices[var] && getArg(r, 0) == getArg(p, 1)) {
     505           0 :                                 int col = getArg(p, 2);
     506             : 
     507           0 :                                 if (!rslices[col]) {    /* was the deltaproject rewriten (sliced) */
     508           0 :                                         InstrPtr s = old[vars[col]], u = NULL;
     509             : 
     510           0 :                                         if (s && getModuleId(s) == algebraRef
     511           0 :                                                 && getFunctionId(s) == projectRef) {
     512           0 :                                                 col = getArg(s, 1);
     513           0 :                                                 u = s;
     514           0 :                                                 s = old[vars[col]];
     515             :                                         }
     516           0 :                                         if (s && getModuleId(s) == sqlRef
     517           0 :                                                 && getFunctionId(s) == projectdeltaRef) {
     518           0 :                                                 InstrPtr t = copyInstruction(s);
     519           0 :                                                 if (t == NULL) {
     520           0 :                                                         msg = createException(MAL, "optimizer.pushselect",
     521             :                                                                                                   SQLSTATE(HY013)
     522             :                                                                                                   MAL_MALLOC_FAIL);
     523           0 :                                                         break;
     524             :                                                 }
     525             : 
     526           0 :                                                 getArg(t, 1) = nvars[getArg(r, 0)];     /* use result of slice */
     527           0 :                                                 rslices[col] = true;
     528           0 :                                                 nvars[getArg(s, 0)] = getArg(t, 0) = newTmpVariable(mb, getArgType(mb, t, 0));
     529           0 :                                                 pushInstruction(mb, t);
     530           0 :                                                 if (u) {        /* add again */
     531           0 :                                                         if ((t = copyInstruction(u)) == NULL) {
     532           0 :                                                                 msg = createException(MAL,
     533             :                                                                                                           "optimizer.pushselect",
     534             :                                                                                                           SQLSTATE(HY013)
     535             :                                                                                                           MAL_MALLOC_FAIL);
     536           0 :                                                                 break;
     537             :                                                         }
     538           0 :                                                         getArg(t, 1) = nvars[getArg(t, 1)];
     539           0 :                                                         pushInstruction(mb, t);
     540             :                                                 }
     541             :                                         }
     542             :                                 }
     543           0 :                                 q = newAssignment(mb);
     544           0 :                                 if (q == NULL) {
     545           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     546             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     547           0 :                                         break;
     548             :                                 }
     549           0 :                                 getArg(q, 0) = getArg(p, 0);
     550           0 :                                 q = pushArgument(mb, q, getArg(p, 2));
     551           0 :                                 if (nvars[getArg(p, 2)] > 0)
     552           0 :                                         getArg(q, 1) = nvars[getArg(p, 2)];
     553           0 :                                 oclean[i] = true;
     554           0 :                                 actions++;
     555           0 :                                 pushInstruction(mb, q);
     556           0 :                                 continue;
     557             :                         }
     558    15788436 :                 } else if (p->argc >= 2 && slices[getArg(p, 1)] != 0) {
     559             :                         /* use new slice candidate list */
     560           0 :                         assert(slices[getArg(p, 1)] == nvars[getArg(p, 1)]);
     561           0 :                         getArg(p, 1) = slices[getArg(p, 1)];
     562             :                 }
     563             :                 /* remap */
     564    37588370 :                 for (j = p->retc; j < p->argc; j++) {
     565    20729965 :                         int var = getArg(p, j);
     566    20729965 :                         if (nvars[var] > 0) {
     567           0 :                                 getArg(p, j) = nvars[var];
     568             :                         }
     569             :                 }
     570             : 
     571             :                 /* c = delta(b, uid, uvl)
     572             :                  * s = select(c, C1..)
     573             :                  *
     574             :                  * nc = select(b, C1..)
     575             :                  * nu = select(uvl, C1..)
     576             :                  * s = subdelta(nc, uid, nu);
     577             :                  *
     578             :                  * doesn't handle Xselect(x, .. z, C1.. cases) ie multicolumn selects
     579             :                  *
     580             :                  * also handle (if no_mito)
     581             :                  * c = pack(b, ins)
     582             :                  * s = select(c, C1..)
     583             :                  */
     584    16858405 :                 lastbat = lastbat_arg(mb, p);
     585    16858405 :                 if (isSelect(p) && p->retc == 1 && lastbat == 2) {
     586       68947 :                         int var = getArg(p, 1);
     587       68947 :                         InstrPtr q = old[vars[var]];
     588             : 
     589       68947 :                         if (q && q->token == ASSIGNsymbol) {
     590       32353 :                                 var = getArg(q, 1);
     591       32353 :                                 q = old[vars[var]];
     592             :                         }
     593       68947 :                         if (no_mito && q && getModuleId(q) == matRef
     594           0 :                                 && getFunctionId(q) == packRef && q->argc == (q->retc + 2)) {
     595           0 :                                 InstrPtr r = copyInstruction(p);
     596           0 :                                 InstrPtr t = copyInstruction(p);
     597             : 
     598           0 :                                 if (r == NULL || t == NULL) {
     599           0 :                                         freeInstruction(r);
     600           0 :                                         freeInstruction(t);
     601           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     602             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     603           0 :                                         break;
     604             :                                 }
     605           0 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     606           0 :                                 setVarCList(mb, getArg(r, 0));
     607           0 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     608           0 :                                 r->typechk = TYPE_UNKNOWN;
     609           0 :                                 pushInstruction(mb, r);
     610           0 :                                 getArg(t, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     611           0 :                                 setVarCList(mb, getArg(t, 0));
     612           0 :                                 getArg(t, 1) = getArg(q, 2);    /* inserts */
     613           0 :                                 pushInstruction(mb, t);
     614             : 
     615           0 :                                 InstrPtr u = copyInstruction(q);        /* pack result */
     616           0 :                                 if (u == NULL) {
     617           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     618             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     619           0 :                                         break;
     620             :                                 }
     621           0 :                                 getArg(u, 0) = getArg(p, 0);
     622           0 :                                 getArg(u, 1) = getArg(r, 0);
     623           0 :                                 getArg(u, 2) = getArg(t, 0);
     624           0 :                                 u->typechk = TYPE_UNKNOWN;
     625           0 :                                 pushInstruction(mb, u);
     626           0 :                                 oclean[i] = true;
     627           0 :                                 continue;
     628       68947 :                         } else if (q && getModuleId(q) == sqlRef
     629       63265 :                                            && getFunctionId(q) == deltaRef) {
     630       29994 :                                 InstrPtr r = copyInstruction(p);
     631       29994 :                                 InstrPtr s = copyInstruction(p);
     632       29994 :                                 InstrPtr u = copyInstruction(q);
     633             : 
     634       29994 :                                 if (r == NULL || s == NULL || u == NULL) {
     635           0 :                                         freeInstruction(r);
     636           0 :                                         freeInstruction(s);
     637           0 :                                         freeInstruction(u);
     638           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     639             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     640           0 :                                         break;
     641             :                                 }
     642       29994 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     643       29994 :                                 setVarCList(mb, getArg(r, 0));
     644       29994 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     645       29994 :                                 r->typechk = TYPE_UNKNOWN;
     646       29994 :                                 pushInstruction(mb, r);
     647       29994 :                                 getArg(s, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     648       29994 :                                 setVarCList(mb, getArg(s, 0));
     649       29994 :                                 getArg(s, 1) = getArg(q, 3);    /* updates */
     650       29994 :                                 s = ReplaceWithNil(mb, s, 2, TYPE_bat); /* no candidate list */
     651       29994 :                                 setArgType(mb, s, 2, newBatType(TYPE_oid));
     652             :                                 /* make sure to resolve again */
     653       29994 :                                 s->token = ASSIGNsymbol;
     654       29994 :                                 s->typechk = TYPE_UNKNOWN;
     655       29994 :                                 s->fcn = NULL;
     656       29994 :                                 s->blk = NULL;
     657       29994 :                                 pushInstruction(mb, s);
     658             : 
     659       29994 :                                 setFunctionId(u, subdeltaRef);
     660       29994 :                                 getArg(u, 0) = getArg(p, 0);
     661       29994 :                                 getArg(u, 1) = getArg(r, 0);
     662       29994 :                                 getArg(u, 2) = getArg(p, 2);    /* pre-cands */
     663       29994 :                                 getArg(u, 3) = getArg(q, 2);    /* update ids */
     664       29994 :                                 u = pushArgument(mb, u, getArg(s, 0));  /* selected updated values ids */
     665       29994 :                                 u->token = ASSIGNsymbol;
     666       29994 :                                 u->typechk = TYPE_UNKNOWN;
     667       29994 :                                 u->fcn = NULL;
     668       29994 :                                 u->blk = NULL;
     669       29994 :                                 pushInstruction(mb, u);
     670       29994 :                                 oclean[i] = true;
     671       29994 :                                 continue;
     672             :                         }
     673    16788675 :                 } else if (getModuleId(p) == algebraRef
     674     1158725 :                                    && getFunctionId(p) == projectionRef) {
     675     1053456 :                         int id = getArg(p, 1);
     676     1053456 :                         InstrPtr s = old[vars[id]];
     677     1053456 :                         int var = getArg(p, 2);
     678     1053456 :                         InstrPtr q = old[vars[var]];
     679             : 
     680     1053456 :                         if (no_mito && getModuleId(q) == matRef
     681           0 :                                 && getFunctionId(q) == packRef && q->argc == 3
     682           0 :                                 && getModuleId(s) == matRef && getFunctionId(s) == packRef
     683           0 :                                 && s->argc == 3) {
     684           0 :                                 InstrPtr r = copyInstruction(p);
     685           0 :                                 InstrPtr t = copyInstruction(p);
     686             : 
     687           0 :                                 if (r == NULL || t == NULL) {
     688           0 :                                         freeInstruction(r);
     689           0 :                                         freeInstruction(t);
     690           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     691             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     692           0 :                                         break;
     693             :                                 }
     694           0 :                                 getArg(r, 0) = newTmpVariable(mb, getArgType(mb, p, 0));
     695           0 :                                 setVarCList(mb, getArg(r, 0));
     696           0 :                                 getArg(r, 1) = getArg(s, 1);
     697           0 :                                 getArg(r, 2) = getArg(q, 1);    /* column */
     698           0 :                                 r->typechk = TYPE_UNKNOWN;
     699           0 :                                 pushInstruction(mb, r);
     700           0 :                                 getArg(t, 0) = newTmpVariable(mb, getArgType(mb, p, 0));
     701           0 :                                 setVarCList(mb, getArg(t, 0));
     702           0 :                                 getArg(t, 1) = getArg(s, 2);
     703           0 :                                 getArg(t, 2) = getArg(q, 2);    /* inserts */
     704           0 :                                 pushInstruction(mb, t);
     705             : 
     706           0 :                                 InstrPtr u = copyInstruction(q);        /* pack result */
     707           0 :                                 if (u == NULL) {
     708           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     709             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     710           0 :                                         break;
     711             :                                 }
     712           0 :                                 getArg(u, 0) = getArg(p, 0);
     713           0 :                                 getArg(u, 1) = getArg(r, 0);
     714           0 :                                 getArg(u, 2) = getArg(t, 0);
     715           0 :                                 u->typechk = TYPE_UNKNOWN;
     716           0 :                                 pushInstruction(mb, u);
     717           0 :                                 oclean[i] = true;
     718           0 :                                 continue;
     719     1053456 :                         } else if (getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef
     720       81512 :                                            && q->argc == 4) {
     721       81512 :                                 q = copyInstruction(q);
     722       81512 :                                 if (q == NULL) {
     723           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     724             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     725           0 :                                         break;
     726             :                                 }
     727       81512 :                                 setFunctionId(q, projectdeltaRef);
     728       81512 :                                 getArg(q, 0) = getArg(p, 0);
     729       81512 :                                 q = PushArgument(mb, q, getArg(p, 1), 1);
     730       81512 :                                 p = q;
     731       81512 :                                 oclean[i] = true;
     732       81512 :                                 actions++;
     733             :                         }
     734    15735219 :                 } else if (isIntersect(p) && p->retc == 1 && lastbat == 4) {
     735             :                         /* l = delta(b, uid, uvl)
     736             :                          * s = intersect(l, r, li, ..)
     737             :                          *
     738             :                          * nc = intersect(b, r, li..)
     739             :                          * nu = intersect(uvl, r, ..)
     740             :                          * s = subdelta(nc, li, uid, nu);
     741             :                          */
     742           5 :                         int var = getArg(p, 1);
     743           5 :                         InstrPtr q = old[vars[var]];
     744             : 
     745           5 :                         if (q && q->token == ASSIGNsymbol) {
     746           0 :                                 var = getArg(q, 1);
     747           0 :                                 q = old[vars[var]];
     748             :                         }
     749           5 :                         if (q && getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef) {
     750           0 :                                 InstrPtr r = copyInstruction(p);
     751           0 :                                 InstrPtr s = copyInstruction(p);
     752           0 :                                 InstrPtr u = copyInstruction(q);
     753             : 
     754           0 :                                 if (r == NULL || s == NULL || u == NULL) {
     755           0 :                                         freeInstruction(r);
     756           0 :                                         freeInstruction(s);
     757           0 :                                         freeInstruction(u);
     758           0 :                                         msg = createException(MAL, "optimizer.pushselect",
     759             :                                                                                   SQLSTATE(HY013) MAL_MALLOC_FAIL);
     760           0 :                                         break;
     761             :                                 }
     762           0 :                                 getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     763           0 :                                 setVarCList(mb, getArg(r, 0));
     764           0 :                                 getArg(r, 1) = getArg(q, 1);    /* column */
     765           0 :                                 r->typechk = TYPE_UNKNOWN;
     766           0 :                                 pushInstruction(mb, r);
     767           0 :                                 getArg(s, 0) = newTmpVariable(mb, newBatType(TYPE_oid));
     768           0 :                                 setVarCList(mb, getArg(s, 0));
     769           0 :                                 getArg(s, 1) = getArg(q, 3);    /* updates */
     770           0 :                                 s = ReplaceWithNil(mb, s, 3, TYPE_bat); /* no candidate list */
     771           0 :                                 setArgType(mb, s, 3, newBatType(TYPE_oid));
     772             :                                 /* make sure to resolve again */
     773           0 :                                 s->token = ASSIGNsymbol;
     774           0 :                                 s->typechk = TYPE_UNKNOWN;
     775           0 :                                 s->fcn = NULL;
     776           0 :                                 s->blk = NULL;
     777           0 :                                 pushInstruction(mb, s);
     778             : 
     779           0 :                                 setFunctionId(u, subdeltaRef);
     780           0 :                                 getArg(u, 0) = getArg(p, 0);
     781           0 :                                 getArg(u, 1) = getArg(r, 0);
     782           0 :                                 getArg(u, 2) = getArg(p, 3);    /* pre-cands */
     783           0 :                                 getArg(u, 3) = getArg(q, 2);    /* update ids */
     784             :                                 //getArg(u, 4) = getArg(s,0);
     785           0 :                                 p = pushArgument(mb, u, getArg(s, 0));  /* push at end */
     786             :                                 /* make sure to resolve again */
     787           0 :                                 u->token = ASSIGNsymbol;
     788           0 :                                 u->typechk = TYPE_UNKNOWN;
     789           0 :                                 u->fcn = NULL;
     790           0 :                                 u->blk = NULL;
     791           0 :                                 pushInstruction(mb, u);
     792           0 :                                 oclean[i] = true;
     793           0 :                                 continue;
     794             :                         }
     795             :                 }
     796    16827628 :                 assert(p == old[i] || oclean[i]);
     797    16827628 :                 pushInstruction(mb, p);
     798             :         }
     799    17309778 :         for (j = 1; j < i; j++)
     800    16859710 :                 if (old[j] && oclean[j])
     801      111506 :                         freeInstruction(old[j]);
     802   100818554 :         for (; i < slimit; i++)
     803   100368493 :                 if (old[i])
     804           0 :                         pushInstruction(mb, old[i]);
     805      450061 :         GDKfree(vars);
     806      450069 :         GDKfree(nvars);
     807      450068 :         GDKfree(slices);
     808      450069 :         GDKfree(rslices);
     809      450068 :         GDKfree(oclean);
     810      450068 :         GDKfree(old);
     811             : 
     812             :         /* Defense line against incorrect plans */
     813      450067 :         if (msg == MAL_SUCCEED && actions > 0) {
     814       19989 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     815       19989 :                 if (msg == MAL_SUCCEED)
     816       19989 :                         msg = chkFlow(mb);
     817       19989 :                 if (msg == MAL_SUCCEED)
     818       19989 :                         msg = chkDeclarations(mb);
     819             :         }
     820      430078 :   wrapup:
     821             :         /* keep actions taken as a fake argument */
     822      467665 :         (void) pushInt(mb, pci, actions);
     823      467665 :         return msg;
     824             : }

Generated by: LCOV version 1.14