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-12-20 21:24:02 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      499097 : OPTprojectionpathImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      22             :                                                                 InstrPtr pci)
      23             : {
      24      499097 :         int i, j, k, actions = 0, maxprefixlength = 0;
      25      499097 :         int *pc = NULL;
      26      499097 :         InstrPtr p, q, r;
      27      499097 :         InstrPtr *old = 0;
      28      499097 :         int *varcnt = NULL;                     /* use count */
      29      499097 :         int limit, slimit;
      30      499097 :         str msg = MAL_SUCCEED;
      31             : 
      32      499097 :         (void) cntxt;
      33      499097 :         (void) stk;
      34      499097 :         if (mb->inlineProp)
      35           0 :                 goto wrapupall;
      36             : 
      37    19339746 :         for (i = 0; i < mb->stop; i++) {
      38    18904366 :                 p = getInstrPtr(mb, i);
      39    18904366 :                 if (getModuleId(p) == algebraRef
      40      469481 :                         && ((getFunctionId(p) == projectionRef && p->argc == 3)
      41      405764 :                                 || getFunctionId(p) == projectionpathRef)) {
      42             :                         break;
      43             :                 }
      44             :         }
      45      499097 :         if (i == mb->stop) {
      46      435377 :                 goto wrapupall;
      47             :         }
      48             : 
      49       63720 :         limit = mb->stop;
      50       63720 :         slimit = mb->ssize;
      51       63720 :         old = mb->stmt;
      52       63720 :         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       63779 :         pc = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);  /* to find last assignment */
      57       63778 :         varcnt = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);
      58       63779 :         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    16575989 :         for (i = 0; i < limit; i++) {
      71    16512210 :                 p = old[i];
      72    68164139 :                 for (j = p->retc; j < p->argc; j++)
      73    51651929 :                         if (!(getModuleId(p) == languageRef && getFunctionId(p) == passRef))
      74    51651929 :                                 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    16586436 :         for (i = 0; i < limit; i++) {
      82    16522660 :                 p = old[i];
      83    16522660 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef
      84     7423851 :                         && p->argc == 3) {
      85             :                         /*
      86             :                          * Try to expand its argument list with what we have found so far.
      87             :                          */
      88     7423851 :                         int args = p->retc;
      89    22271299 :                         for (j = p->retc; j < p->argc; j++) {
      90    14847448 :                                 if (pc[getArg(p, j)]
      91     6392848 :                                         && (r = getInstrPtr(mb, pc[getArg(p, j)])) != NULL
      92     6392848 :                                         && varcnt[getArg(p, j)] <= 1 && getModuleId(r) == algebraRef
      93     4812254 :                                         && (getFunctionId(r) == projectionRef
      94     4171639 :                                                 || getFunctionId(r) == projectionpathRef))
      95     4812254 :                                         args += r->argc - r->retc;
      96             :                                 else
      97    10035194 :                                         args++;
      98             :                         }
      99     7423851 :                         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     7423895 :                         q->argc = p->retc;
     106    22271606 :                         for (j = p->retc; j < p->argc; j++) {
     107    14847712 :                                 if (pc[getArg(p, j)])
     108     6392913 :                                         r = getInstrPtr(mb, pc[getArg(p, j)]);
     109             :                                 else
     110             :                                         r = 0;
     111     6392913 :                                 if (r && varcnt[getArg(p, j)] > 1)
     112    10035468 :                                         r = 0;
     113             : 
     114             :                                 /* inject the complete sub-path */
     115             : 
     116    14847712 :                                 if (getFunctionId(p) == projectionRef) {
     117    14847747 :                                         if (r && getModuleId(r) == algebraRef
     118     4812251 :                                                 && (getFunctionId(r) == projectionRef
     119     4171639 :                                                         || getFunctionId(r) == projectionpathRef)) {
     120    80112050 :                                                 for (k = r->retc; k < r->argc; k++)
     121    75299802 :                                                         q = pushArgument(mb, q, getArg(r, k));
     122             :                                         } else
     123    10035496 :                                                 q = pushArgument(mb, q, getArg(p, j));
     124             :                                 }
     125             :                         }
     126     7423894 :                         if (q->argc <= p->argc) {
     127             :                                 /* no change */
     128     2628886 :                                 freeInstruction(q);
     129     2628921 :                                 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    80077512 :                         for (j = 1; j < q->argc - 1; j++)
     136    75282504 :                                 if (getBatType(getArgType(mb, q, j)) != TYPE_oid
     137    75282504 :                                         && 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     4795008 :                         setVarType(mb, getArg(q, 0),
     145             :                                            newBatType(getBatType(getArgType(mb, q, q->argc - 1))));
     146     4795008 :                         if (getFunctionId(q) == projectionRef)
     147     4795007 :                                 setFunctionId(q, projectionpathRef);
     148     4795012 :                         q->typeresolved = false;
     149             : 
     150     4795012 :                         freeInstruction(p);
     151     4795014 :                         p = q;
     152             :                         /* keep track of the longest projection path */
     153     4795014 :                         if (p->argc > maxprefixlength)
     154             :                                 maxprefixlength = p->argc;
     155     4795014 :                         actions++;
     156             :                 }
     157     9098809 :   wrapup:
     158    16522744 :                 pushInstruction(mb, p);
     159    50828513 :                 for (j = 0; j < p->retc; j++)
     160    17783112 :                         if (getModuleId(p) == algebraRef
     161     9635734 :                                 && (getFunctionId(p) == projectionRef
     162     7006962 :                                         || getFunctionId(p) == projectionpathRef)) {
     163     7423788 :                                 pc[getArg(p, j)] = mb->stop - 1;
     164             :                         }
     165             :         }
     166             : 
     167    11158021 :         for (; i < slimit; i++)
     168    11094243 :                 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       63778 :         if (actions > 0) {
     177       35097 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     178       35094 :                 if (!msg)
     179       35096 :                         msg = chkFlow(mb);
     180       35095 :                 if (!msg)
     181       35095 :                         msg = chkDeclarations(mb);
     182             :         }
     183       28681 :   wrapupall:
     184             :         /* keep actions taken as a fake argument */
     185      499154 :         (void) pushInt(mb, pci, actions);
     186             : 
     187      499139 :         if (pc)
     188       63761 :                 GDKfree(pc);
     189      499157 :         if (varcnt)
     190       63779 :                 GDKfree(varcnt);
     191      499157 :         if (old)
     192       63778 :                 GDKfree(old);
     193             : 
     194             :         return msg;
     195             : }

Generated by: LCOV version 1.14