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-11-12 19:36:54 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      483523 : OPTprojectionpathImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      22             :                                                                 InstrPtr pci)
      23             : {
      24      483523 :         int i, j, k, actions = 0, maxprefixlength = 0;
      25      483523 :         int *pc = NULL;
      26      483523 :         InstrPtr p, q, r;
      27      483523 :         InstrPtr *old = 0;
      28      483523 :         int *varcnt = NULL;                     /* use count */
      29      483523 :         int limit, slimit;
      30      483523 :         str msg = MAL_SUCCEED;
      31             : 
      32      483523 :         (void) cntxt;
      33      483523 :         (void) stk;
      34      483523 :         if (mb->inlineProp)
      35           0 :                 goto wrapupall;
      36             : 
      37    18622768 :         for (i = 0; i < mb->stop; i++) {
      38    18202318 :                 p = getInstrPtr(mb, i);
      39    18202318 :                 if (getModuleId(p) == algebraRef
      40      460926 :                         && ((getFunctionId(p) == projectionRef && p->argc == 3)
      41      397853 :                                 || getFunctionId(p) == projectionpathRef)) {
      42             :                         break;
      43             :                 }
      44             :         }
      45      483523 :         if (i == mb->stop) {
      46      420447 :                 goto wrapupall;
      47             :         }
      48             : 
      49       63076 :         limit = mb->stop;
      50       63076 :         slimit = mb->ssize;
      51       63076 :         old = mb->stmt;
      52       63076 :         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       63093 :         pc = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);  /* to find last assignment */
      57       63093 :         varcnt = (int *) GDKzalloc(sizeof(int) * mb->vtop * 2);
      58       63093 :         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    16449898 :         for (i = 0; i < limit; i++) {
      71    16386805 :                 p = old[i];
      72    67687237 :                 for (j = p->retc; j < p->argc; j++)
      73    51300432 :                         if (!(getModuleId(p) == languageRef && getFunctionId(p) == passRef))
      74    51300432 :                                 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    16456665 :         for (i = 0; i < limit; i++) {
      82    16393573 :                 p = old[i];
      83    16393573 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef
      84     7395857 :                         && p->argc == 3) {
      85             :                         /*
      86             :                          * Try to expand its argument list with what we have found so far.
      87             :                          */
      88     7395857 :                         int args = p->retc;
      89    22187408 :                         for (j = p->retc; j < p->argc; j++) {
      90    14791551 :                                 if (pc[getArg(p, j)]
      91     6371552 :                                         && (r = getInstrPtr(mb, pc[getArg(p, j)])) != NULL
      92     6371552 :                                         && varcnt[getArg(p, j)] <= 1 && getModuleId(r) == algebraRef
      93     4805511 :                                         && (getFunctionId(r) == projectionRef
      94     4170191 :                                                 || getFunctionId(r) == projectionpathRef))
      95     4805511 :                                         args += r->argc - r->retc;
      96             :                                 else
      97     9986040 :                                         args++;
      98             :                         }
      99     7395857 :                         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     7395873 :                         q->argc = p->retc;
     106    22187546 :                         for (j = p->retc; j < p->argc; j++) {
     107    14791663 :                                 if (pc[getArg(p, j)])
     108     6371615 :                                         r = getInstrPtr(mb, pc[getArg(p, j)]);
     109             :                                 else
     110             :                                         r = 0;
     111     6371615 :                                 if (r && varcnt[getArg(p, j)] > 1)
     112     9986158 :                                         r = 0;
     113             : 
     114             :                                 /* inject the complete sub-path */
     115             : 
     116    14791663 :                                 if (getFunctionId(p) == projectionRef) {
     117    14791667 :                                         if (r && getModuleId(r) == algebraRef
     118     4805505 :                                                 && (getFunctionId(r) == projectionRef
     119     4170191 :                                                         || getFunctionId(r) == projectionpathRef)) {
     120    80090388 :                                                 for (k = r->retc; k < r->argc; k++)
     121    75284878 :                                                         q = pushArgument(mb, q, getArg(r, k));
     122             :                                         } else
     123     9986159 :                                                 q = pushArgument(mb, q, getArg(p, j));
     124             :                                 }
     125             :                         }
     126     7395883 :                         if (q->argc <= p->argc) {
     127             :                                 /* no change */
     128     2607604 :                                 freeInstruction(q);
     129     2607629 :                                 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    80055863 :                         for (j = 1; j < q->argc - 1; j++)
     136    75267584 :                                 if (getBatType(getArgType(mb, q, j)) != TYPE_oid
     137    75267584 :                                         && 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     4788279 :                         setVarType(mb, getArg(q, 0),
     145             :                                            newBatType(getBatType(getArgType(mb, q, q->argc - 1))));
     146     4788279 :                         if (getFunctionId(q) == projectionRef)
     147     4788273 :                                 setFunctionId(q, projectionpathRef);
     148     4788287 :                         q->typeresolved = false;
     149             : 
     150     4788287 :                         freeInstruction(p);
     151     4788280 :                         p = q;
     152             :                         /* keep track of the longest projection path */
     153     4788280 :                         if (p->argc > maxprefixlength)
     154             :                                 maxprefixlength = p->argc;
     155     4788280 :                         actions++;
     156             :                 }
     157     8997716 :   wrapup:
     158    16393625 :                 pushInstruction(mb, p);
     159    50430007 :                 for (j = 0; j < p->retc; j++)
     160    17642810 :                         if (getModuleId(p) == algebraRef
     161     9588065 :                                 && (getFunctionId(p) == projectionRef
     162     6980508 :                                         || getFunctionId(p) == projectionpathRef)) {
     163     7395839 :                                 pc[getArg(p, j)] = mb->stop - 1;
     164             :                         }
     165             :         }
     166             : 
     167    11035397 :         for (; i < slimit; i++)
     168    10972303 :                 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       63094 :         if (actions > 0) {
     177       34807 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     178       34801 :                 if (!msg)
     179       34802 :                         msg = chkFlow(mb);
     180       34805 :                 if (!msg)
     181       34805 :                         msg = chkDeclarations(mb);
     182             :         }
     183       28287 :   wrapupall:
     184             :         /* keep actions taken as a fake argument */
     185      483536 :         (void) pushInt(mb, pci, actions);
     186             : 
     187      483565 :         if (pc)
     188       63081 :                 GDKfree(pc);
     189      483579 :         if (varcnt)
     190       63092 :                 GDKfree(varcnt);
     191      483577 :         if (old)
     192       63091 :                 GDKfree(old);
     193             : 
     194             :         return msg;
     195             : }

Generated by: LCOV version 1.14