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-04-26 00:35:57 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      477389 : OPTprojectionpathImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      22             :                                                                 InstrPtr pci)
      23             : {
      24      477389 :         int i, j, k, actions = 0, maxprefixlength = 0;
      25      477389 :         int *pc = NULL;
      26      477389 :         InstrPtr p, q, r;
      27      477389 :         InstrPtr *old = 0;
      28      477389 :         int *varcnt = NULL;                     /* use count */
      29      477389 :         int limit, slimit;
      30      477389 :         str msg = MAL_SUCCEED;
      31             : 
      32      477389 :         (void) cntxt;
      33      477389 :         (void) stk;
      34      477389 :         if (mb->inlineProp)
      35           0 :                 goto wrapupall;
      36             : 
      37    18251318 :         for (i = 0; i < mb->stop; i++) {
      38    17832918 :                 p = getInstrPtr(mb, i);
      39    17832918 :                 if (getModuleId(p) == algebraRef
      40      402753 :                         && ((getFunctionId(p) == projectionRef && p->argc == 3)
      41      343764 :                                 || getFunctionId(p) == projectionpathRef)) {
      42             :                         break;
      43             :                 }
      44             :         }
      45      477389 :         if (i == mb->stop) {
      46      418400 :                 goto wrapupall;
      47             :         }
      48             : 
      49       58989 :         limit = mb->stop;
      50       58989 :         slimit = mb->ssize;
      51       58989 :         old = mb->stmt;
      52       58989 :         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       59013 :         pc = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);  /* to find last assignment */
      57       59012 :         varcnt = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);
      58       59013 :         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 re-use  used as arguments first.
      68             :          * A pass operation is not a real re-use
      69             :          */
      70    14423299 :         for (i = 0; i < limit; i++) {
      71    14364286 :                 p = old[i];
      72    59117469 :                 for (j = p->retc; j < p->argc; j++)
      73    44753183 :                         if (!(getModuleId(p) == languageRef && getFunctionId(p) == passRef))
      74    44753183 :                                 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    14429468 :         for (i = 0; i < limit; i++) {
      82    14370461 :                 p = old[i];
      83    14370461 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef
      84     6715298 :                         && p->argc == 3) {
      85             :                         /*
      86             :                          * Try to expand its argument list with what we have found so far.
      87             :                          */
      88     6715298 :                         int args = p->retc;
      89    20145772 :                         for (j = p->retc; j < p->argc; j++) {
      90    13430474 :                                 if (pc[getArg(p, j)]
      91     5905834 :                                         && (r = getInstrPtr(mb, pc[getArg(p, j)])) != NULL
      92     5905834 :                                         && varcnt[getArg(p, j)] <= 1 && getModuleId(r) == algebraRef
      93     4643253 :                                         && (getFunctionId(r) == projectionRef
      94     4130817 :                                                 || getFunctionId(r) == projectionpathRef))
      95     4643253 :                                         args += r->argc - r->retc;
      96             :                                 else
      97     8787221 :                                         args++;
      98             :                         }
      99     6715298 :                         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     6715314 :                         q->argc = p->retc;
     106    20145883 :                         for (j = p->retc; j < p->argc; j++) {
     107    13430567 :                                 if (pc[getArg(p, j)])
     108     5905887 :                                         r = getInstrPtr(mb, pc[getArg(p, j)]);
     109             :                                 else
     110             :                                         r = 0;
     111     5905887 :                                 if (r && varcnt[getArg(p, j)] > 1)
     112     8787314 :                                         r = 0;
     113             : 
     114             :                                 /* inject the complete sub-path */
     115             : 
     116    13430567 :                                 if (getFunctionId(p) == projectionRef) {
     117    13430574 :                                         if (r && getModuleId(r) == algebraRef
     118     4643253 :                                                 && (getFunctionId(r) == projectionRef
     119     4130817 :                                                         || getFunctionId(r) == projectionpathRef)) {
     120    79484966 :                                                 for (k = r->retc; k < r->argc; k++)
     121    74841714 :                                                         q = pushArgument(mb, q, getArg(r, k));
     122             :                                         } else
     123     8787320 :                                                 q = pushArgument(mb, q, getArg(p, j));
     124             :                                 }
     125             :                         }
     126     6715316 :                         if (q->argc <= p->argc) {
     127             :                                 /* no change */
     128     2088658 :                                 freeInstruction(q);
     129     2088678 :                                 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    79451738 :                         for (j = 1; j < q->argc - 1; j++)
     136    74825080 :                                 if (getBatType(getArgType(mb, q, j)) != TYPE_oid
     137    74825080 :                                         && 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     4626658 :                         setVarType(mb, getArg(q, 0),
     145             :                                            newBatType(getBatType(getArgType(mb, q, q->argc - 1))));
     146     4626658 :                         if (getFunctionId(q) == projectionRef)
     147     4626660 :                                 setFunctionId(q, projectionpathRef);
     148     4626660 :                         q->typeresolved = false;
     149             : 
     150     4626660 :                         freeInstruction(p);
     151     4626662 :                         p = q;
     152             :                         /* keep track of the longest projection path */
     153     4626662 :                         if (p->argc > maxprefixlength)
     154             :                                 maxprefixlength = p->argc;
     155     4626662 :                         actions++;
     156             :                 }
     157     7655163 :   wrapup:
     158    14370503 :                 pushInstruction(mb, p);
     159    44204149 :                 for (j = 0; j < p->retc; j++)
     160    15463191 :                         if (getModuleId(p) == algebraRef
     161     8387925 :                                 && (getFunctionId(p) == projectionRef
     162     6299280 :                                         || getFunctionId(p) == projectionpathRef)) {
     163     6715310 :                                 pc[getArg(p, j)] = mb->stop - 1;
     164             :                         }
     165             :         }
     166             : 
     167     9896622 :         for (; i < slimit; i++)
     168     9837609 :                 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       59013 :         if (actions > 0) {
     177       33164 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     178       33163 :                 if (!msg)
     179       33163 :                         msg = chkFlow(mb);
     180       33160 :                 if (!msg)
     181       33160 :                         msg = chkDeclarations(mb);
     182             :         }
     183       25849 :   wrapupall:
     184             :         /* keep actions taken as a fake argument */
     185      477412 :         (void) pushInt(mb, pci, actions);
     186             : 
     187      477440 :         if (pc)
     188       59002 :                 GDKfree(pc);
     189      477449 :         if (varcnt)
     190       59013 :                 GDKfree(varcnt);
     191      477450 :         if (old)
     192       59012 :                 GDKfree(old);
     193             : 
     194             :         return msg;
     195             : }

Generated by: LCOV version 1.14