LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_projectionpath.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 94 106 88.7 %
Date: 2024-10-03 20:03:20 Functions: 1 1 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             : /* author: M Kersten
      14             :  * Post-optimization of projection lists.
      15             :  */
      16             : #include "monetdb_config.h"
      17             : #include "opt_deadcode.h"
      18             : #include "opt_projectionpath.h"
      19             : 
      20             : str
      21      483207 : OPTprojectionpathImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      22             :                                                                 InstrPtr pci)
      23             : {
      24      483207 :         int i, j, k, actions = 0, maxprefixlength = 0;
      25      483207 :         int *pc = NULL;
      26      483207 :         InstrPtr p, q, r;
      27      483207 :         InstrPtr *old = 0;
      28      483207 :         int *varcnt = NULL;                     /* use count */
      29      483207 :         int limit, slimit;
      30      483207 :         str msg = MAL_SUCCEED;
      31             : 
      32      483207 :         (void) cntxt;
      33      483207 :         (void) stk;
      34      483207 :         if (mb->inlineProp)
      35           0 :                 goto wrapupall;
      36             : 
      37    17096462 :         for (i = 0; i < mb->stop; i++) {
      38    16675816 :                 p = getInstrPtr(mb, i);
      39    16675816 :                 if (getModuleId(p) == algebraRef
      40      301845 :                         && ((getFunctionId(p) == projectionRef && p->argc == 3)
      41      239284 :                                 || getFunctionId(p) == projectionpathRef)) {
      42             :                         break;
      43             :                 }
      44             :         }
      45      483207 :         if (i == mb->stop) {
      46      420646 :                 goto wrapupall;
      47             :         }
      48             : 
      49       62561 :         limit = mb->stop;
      50       62561 :         slimit = mb->ssize;
      51       62561 :         old = mb->stmt;
      52       62561 :         if (newMalBlkStmt(mb, 2 * mb->stop) < 0)
      53           0 :                 throw(MAL, "optimizer.projectionpath", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      54             : 
      55             :         /* beware, new variables and instructions are introduced */
      56       62561 :         pc = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);  /* to find last assignment */
      57       62561 :         varcnt = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);
      58       62561 :         if (pc == NULL || varcnt == NULL) {
      59           0 :                 if (pc)
      60           0 :                         GDKfree(pc);
      61           0 :                 if (varcnt)
      62           0 :                         GDKfree(varcnt);
      63           0 :                 throw(MAL, "optimizer.projectionpath", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      64             :         }
      65             : 
      66             :         /*
      67             :          * Count the variable reuse  used as arguments first.
      68             :          * A pass operation is not a real reuse
      69             :          */
      70     9902127 :         for (i = 0; i < limit; i++) {
      71     9839566 :                 p = old[i];
      72    38632851 :                 for (j = p->retc; j < p->argc; j++)
      73    28793285 :                         if (!(getModuleId(p) == languageRef && getFunctionId(p) == passRef))
      74    28793285 :                                 varcnt[getArg(p, j)]++;
      75             :         }
      76             : 
      77             :         /* assume a single pass over the plan, and only consider projection sequences
      78             :          * beware, we are only able to deal with projections without candidate lists. (argc=3)
      79             :          * We also should not change the type of the outcome, i.e. leaving the last argument untouched.
      80             :          */
      81     9904074 :         for (i = 0; i < limit; i++) {
      82     9841515 :                 p = old[i];
      83     9841515 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef
      84     3821440 :                         && p->argc == 3) {
      85             :                         /*
      86             :                          * Try to expand its argument list with what we have found so far.
      87             :                          */
      88     3821440 :                         int args = p->retc;
      89    11464194 :                         for (j = p->retc; j < p->argc; j++) {
      90     7642754 :                                 if (pc[getArg(p, j)]
      91     3194448 :                                         && (r = getInstrPtr(mb, pc[getArg(p, j)])) != NULL
      92     3194448 :                                         && varcnt[getArg(p, j)] <= 1 && getModuleId(r) == algebraRef
      93     2421037 :                                         && (getFunctionId(r) == projectionRef
      94     2083910 :                                                 || getFunctionId(r) == projectionpathRef))
      95     2421037 :                                         args += r->argc - r->retc;
      96             :                                 else
      97     5221717 :                                         args++;
      98             :                         }
      99     3821440 :                         if ((q = copyInstructionArgs(p, args)) == NULL) {
     100           0 :                                 msg = createException(MAL, "optimizer.projectionpath",
     101             :                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     102           0 :                                 goto wrapupall;
     103             :                         }
     104             : 
     105     3821446 :                         q->argc = p->retc;
     106    11464294 :                         for (j = p->retc; j < p->argc; j++) {
     107     7642853 :                                 if (pc[getArg(p, j)])
     108     3194483 :                                         r = getInstrPtr(mb, pc[getArg(p, j)]);
     109             :                                 else
     110             :                                         r = 0;
     111     3194483 :                                 if (r && varcnt[getArg(p, j)] > 1)
     112     5221816 :                                         r = 0;
     113             : 
     114             :                                 /* inject the complete sub-path */
     115             : 
     116     7642853 :                                 if (getFunctionId(p) == projectionRef) {
     117     7642851 :                                         if (r && getModuleId(r) == algebraRef
     118     2421037 :                                                 && (getFunctionId(r) == projectionRef
     119     2083910 :                                                         || getFunctionId(r) == projectionpathRef)) {
     120    40097265 :                                                 for (k = r->retc; k < r->argc; k++)
     121    37676228 :                                                         q = pushArgument(mb, q, getArg(r, k));
     122             :                                         } else
     123     5221814 :                                                 q = pushArgument(mb, q, getArg(p, j));
     124             :                                 }
     125             :                         }
     126     3821441 :                         if (q->argc <= p->argc) {
     127             :                                 /* no change */
     128     1409188 :                                 freeInstruction(q);
     129     1409194 :                                 goto wrapup;
     130             :                         }
     131             :                         /*
     132             :                          * Final type check and hardwire the result type, because that  can not be inferred directly from the signature
     133             :                          * We already know that all heads are void. Only the last element may have a non-oid type.
     134             :                          */
     135    40079699 :                         for (j = 1; j < q->argc - 1; j++)
     136    37667446 :                                 if (getBatType(getArgType(mb, q, j)) != TYPE_oid
     137    37667446 :                                         && getBatType(getArgType(mb, q, j)) != TYPE_void) {
     138             :                                         /* don't use the candidate list */
     139           0 :                                         freeInstruction(q);
     140           0 :                                         goto wrapup;
     141             :                                 }
     142             : 
     143             :                         /* fix the type */
     144     2412253 :                         setVarType(mb, getArg(q, 0),
     145             :                                            newBatType(getBatType(getArgType(mb, q, q->argc - 1))));
     146     2412253 :                         if (getFunctionId(q) == projectionRef)
     147     2412252 :                                 setFunctionId(q, projectionpathRef);
     148     2412254 :                         q->typeresolved = false;
     149             : 
     150     2412254 :                         freeInstruction(p);
     151     2412253 :                         p = q;
     152             :                         /* keep track of the longest projection path */
     153     2412253 :                         if (p->argc > maxprefixlength)
     154             :                                 maxprefixlength = p->argc;
     155     2412253 :                         actions++;
     156             :                 }
     157     6020075 :   wrapup:
     158     9841522 :                 pushInstruction(mb, p);
     159    30194753 :                 for (j = 0; j < p->retc; j++)
     160    10511718 :                         if (getModuleId(p) == algebraRef
     161     4933915 :                                 && (getFunctionId(p) == projectionRef
     162     3524777 :                                         || getFunctionId(p) == projectionpathRef)) {
     163     3821391 :                                 pc[getArg(p, j)] = mb->stop - 1;
     164             :                         }
     165             :         }
     166             : 
     167    11001287 :         for (; i < slimit; i++)
     168    10938726 :                 if (old[i])
     169           0 :                         pushInstruction(mb, old[i]);
     170             : 
     171             :         /* At this location there used to be commented out experimental code
     172             :          * to reuse common prefixes, but this was counter productive.  This
     173             :          * comment is all that is left. */
     174             : 
     175             :         /* Defense line against incorrect plans */
     176       62561 :         if (actions > 0) {
     177       34682 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     178       34681 :                 if (!msg)
     179       34681 :                         msg = chkFlow(mb);
     180       34682 :                 if (!msg)
     181       34682 :                         msg = chkDeclarations(mb);
     182             :         }
     183       27879 :   wrapupall:
     184             :         /* keep actions taken as a fake argument */
     185      483207 :         (void) pushInt(mb, pci, actions);
     186             : 
     187      483204 :         if (pc)
     188       62560 :                 GDKfree(pc);
     189      483205 :         if (varcnt)
     190       62561 :                 GDKfree(varcnt);
     191      483204 :         if (old)
     192       62560 :                 GDKfree(old);
     193             : 
     194             :         return msg;
     195             : }

Generated by: LCOV version 1.14