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-07 21:21:43 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      493340 : OPTprojectionpathImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      22             :                                                                 InstrPtr pci)
      23             : {
      24      493340 :         int i, j, k, actions = 0, maxprefixlength = 0;
      25      493340 :         int *pc = NULL;
      26      493340 :         InstrPtr p, q, r;
      27      493340 :         InstrPtr *old = 0;
      28      493340 :         int *varcnt = NULL;                     /* use count */
      29      493340 :         int limit, slimit;
      30      493340 :         str msg = MAL_SUCCEED;
      31             : 
      32      493340 :         (void) cntxt;
      33      493340 :         (void) stk;
      34      493340 :         if (mb->inlineProp)
      35           0 :                 goto wrapupall;
      36             : 
      37    18851737 :         for (i = 0; i < mb->stop; i++) {
      38    18420465 :                 p = getInstrPtr(mb, i);
      39    18420465 :                 if (getModuleId(p) == algebraRef
      40      406372 :                         && ((getFunctionId(p) == projectionRef && p->argc == 3)
      41      344304 :                                 || getFunctionId(p) == projectionpathRef)) {
      42             :                         break;
      43             :                 }
      44             :         }
      45      493340 :         if (i == mb->stop) {
      46      431272 :                 goto wrapupall;
      47             :         }
      48             : 
      49       62068 :         limit = mb->stop;
      50       62068 :         slimit = mb->ssize;
      51       62068 :         old = mb->stmt;
      52       62068 :         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       62100 :         pc = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);  /* to find last assignment */
      57       62101 :         varcnt = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);
      58       62101 :         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    15220681 :         for (i = 0; i < limit; i++) {
      71    15158580 :                 p = old[i];
      72    62311718 :                 for (j = p->retc; j < p->argc; j++)
      73    47153138 :                         if (!(getModuleId(p) == languageRef && getFunctionId(p) == passRef))
      74    47153138 :                                 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    15226380 :         for (i = 0; i < limit; i++) {
      82    15164281 :                 p = old[i];
      83    15164281 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef
      84     6966822 :                         && p->argc == 3) {
      85             :                         /*
      86             :                          * Try to expand its argument list with what we have found so far.
      87             :                          */
      88     6966822 :                         int args = p->retc;
      89    20900340 :                         for (j = p->retc; j < p->argc; j++) {
      90    13933518 :                                 if (pc[getArg(p, j)]
      91     6125518 :                                         && (r = getInstrPtr(mb, pc[getArg(p, j)])) != NULL
      92     6125518 :                                         && varcnt[getArg(p, j)] <= 1 && getModuleId(r) == algebraRef
      93     4701304 :                                         && (getFunctionId(r) == projectionRef
      94     4145574 :                                                 || getFunctionId(r) == projectionpathRef))
      95     4701304 :                                         args += r->argc - r->retc;
      96             :                                 else
      97     9232214 :                                         args++;
      98             :                         }
      99     6966822 :                         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     6966825 :                         q->argc = p->retc;
     106    20900424 :                         for (j = p->retc; j < p->argc; j++) {
     107    13933606 :                                 if (pc[getArg(p, j)])
     108     6125552 :                                         r = getInstrPtr(mb, pc[getArg(p, j)]);
     109             :                                 else
     110             :                                         r = 0;
     111     6125552 :                                 if (r && varcnt[getArg(p, j)] > 1)
     112     9232304 :                                         r = 0;
     113             : 
     114             :                                 /* inject the complete sub-path */
     115             : 
     116    13933606 :                                 if (getFunctionId(p) == projectionRef) {
     117    13933616 :                                         if (r && getModuleId(r) == algebraRef
     118     4701302 :                                                 && (getFunctionId(r) == projectionRef
     119     4145574 :                                                         || getFunctionId(r) == projectionpathRef)) {
     120    79739803 :                                                 for (k = r->retc; k < r->argc; k++)
     121    75038505 :                                                         q = pushArgument(mb, q, getArg(r, k));
     122             :                                         } else
     123     9232314 :                                                 q = pushArgument(mb, q, getArg(p, j));
     124             :                                 }
     125             :                         }
     126     6966818 :                         if (q->argc <= p->argc) {
     127             :                                 /* no change */
     128     2282317 :                                 freeInstruction(q);
     129     2282357 :                                 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    79706175 :                         for (j = 1; j < q->argc - 1; j++)
     136    75021674 :                                 if (getBatType(getArgType(mb, q, j)) != TYPE_oid
     137    75021674 :                                         && 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     4684501 :                         setVarType(mb, getArg(q, 0),
     145             :                                            newBatType(getBatType(getArgType(mb, q, q->argc - 1))));
     146     4684501 :                         if (getFunctionId(q) == projectionRef)
     147     4684501 :                                 setFunctionId(q, projectionpathRef);
     148     4684504 :                         q->typeresolved = false;
     149             : 
     150     4684504 :                         freeInstruction(p);
     151     4684504 :                         p = q;
     152             :                         /* keep track of the longest projection path */
     153     4684504 :                         if (p->argc > maxprefixlength)
     154             :                                 maxprefixlength = p->argc;
     155     4684504 :                         actions++;
     156             :                 }
     157     8197459 :   wrapup:
     158    15164320 :                 pushInstruction(mb, p);
     159    46657321 :                 for (j = 0; j < p->retc; j++)
     160    16328722 :                         if (getModuleId(p) == algebraRef
     161     8784649 :                                 && (getFunctionId(p) == projectionRef
     162     6502367 :                                         || getFunctionId(p) == projectionpathRef)) {
     163     6966788 :                                 pc[getArg(p, j)] = mb->stop - 1;
     164             :                         }
     165             :         }
     166             : 
     167    10410452 :         for (; i < slimit; i++)
     168    10348352 :                 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       62100 :         if (actions > 0) {
     177       34497 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     178       34498 :                 if (!msg)
     179       34498 :                         msg = chkFlow(mb);
     180       34493 :                 if (!msg)
     181       34493 :                         msg = chkDeclarations(mb);
     182             :         }
     183       27603 :   wrapupall:
     184             :         /* keep actions taken as a fake argument */
     185      493372 :         (void) pushInt(mb, pci, actions);
     186             : 
     187      493425 :         if (pc)
     188       62093 :                 GDKfree(pc);
     189      493433 :         if (varcnt)
     190       62101 :                 GDKfree(varcnt);
     191      493433 :         if (old)
     192       62100 :                 GDKfree(old);
     193             : 
     194             :         return msg;
     195             : }

Generated by: LCOV version 1.14