LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_emptybind.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 107 132 81.1 %
Date: 2021-10-13 02:24:04 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /* author M.Kersten
      10             :  * This optimizer hunts for the empty persistent tables accessed and propagates them.
      11             :  *
      12             :  * Patterns to look for:
      13             :  *  X_13 := algebra.projection(X_1,X_4);
      14             :  *  where either argument is empty
      15             :  *
      16             :  */
      17             : #include "monetdb_config.h"
      18             : #include "opt_emptybind.h"
      19             : #include "opt_aliases.h"
      20             : #include "opt_deadcode.h"
      21             : #include "mal_builder.h"
      22             : 
      23             : #define emptyresult(I)                                                                  \
      24             :         do {                                                                                            \
      25             :                 int tpe = getVarType(mb,getArg(p,I));                   \
      26             :                 clrFunction(p);                                                                 \
      27             :                 setModuleId(p,batRef);                                                  \
      28             :                 setFunctionId(p,newRef);                                                \
      29             :                 p->argc = p->retc;                                                                \
      30             :                 p = pushType(mb,p, getBatType(tpe));                    \
      31             :                 if( p) {                                                                                \
      32             :                         setVarType(mb, getArg(p,0), tpe);                       \
      33             :                         setVarFixed(mb, getArg(p,0));                           \
      34             :                         empty[getArg(p,0)]= i;                                          \
      35             :         }  } while (0)
      36             : 
      37             : 
      38             : str
      39      353093 : OPTemptybindImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      40             : {
      41             :         int i,j, actions =0, extras= 0;
      42             :         int *empty = NULL;
      43      353093 :         int limit = mb->stop, slimit = mb->ssize;
      44             :         InstrPtr p, q, *old = NULL, *updated = NULL;
      45             :         str sch,tbl;
      46             :         int etop= 0, esize= 256;
      47             :         str msg = MAL_SUCCEED;
      48             : 
      49             :         (void) stk;
      50             :         (void) cntxt;
      51             : 
      52             :         // use an instruction reference table to keep
      53             : 
      54    20453026 :         for( i=0; i< mb->stop; i++) {
      55    20099933 :                 p = getInstrPtr(mb,i);
      56    20099933 :                 if( getModuleId(p) == sqlRef && (getFunctionId(p) == emptybindRef || getFunctionId(p) == emptybindidxRef))
      57      202126 :                         extras += p->argc;
      58             :         }
      59      353093 :         if (extras == 0){
      60      331154 :                 goto wrapup;
      61             :         }
      62             : 
      63             :         // track of where 'emptybind' results are produced
      64             :         // reserve space for maximal number of emptybat variables created
      65       21939 :         empty = (int *) GDKzalloc((mb->vsize + extras) * sizeof(int));
      66       21939 :         if ( empty == NULL)
      67           0 :                 throw(MAL,"optimizer.emptybind", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      68             : 
      69       21939 :         updated= (InstrPtr *) GDKzalloc(esize * sizeof(InstrPtr));
      70       21939 :         if( updated == 0){
      71           0 :                 GDKfree(empty);
      72           0 :                 throw(MAL,"optimizer.emptybind", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      73             :         }
      74             : 
      75       21939 :         old = mb->stmt;
      76       21939 :         if (newMalBlkStmt(mb, mb->ssize) < 0) {
      77           0 :                 GDKfree(empty);
      78           0 :                 GDKfree(updated);
      79           0 :                 throw(MAL,"optimizer.emptybind", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      80             :         }
      81             : 
      82             :         /* Symbolic evaluation of instructions with empty BAT variables */
      83             :         actions = 0;
      84     3713794 :         for (i = 0; i < limit; i++) {
      85     3713794 :                 p = old[i];
      86             : 
      87     3713794 :                 pushInstruction(mb,p);
      88     3713794 :                 if (p->token == ENDsymbol){
      89      678595 :                         for(i++; i<limit; i++)
      90      656656 :                                 if (old[i])
      91      656656 :                                         pushInstruction(mb,old[i]);
      92             :                         break;
      93             :                 }
      94             : 
      95             :                 /*
      96             :                  * The bulk of the intelligence lies in inspecting calling
      97             :                  * sequences to filter and replace results
      98             :                  */
      99     3691855 :                 if ( getModuleId(p) == batRef && getFunctionId(p) == newRef){
     100       54516 :                         empty[getArg(p,0)] = i;
     101       54516 :                         continue;
     102             :                 }
     103             : 
     104             :                 // any of these instructions leave a non-empty BAT behind
     105     3637339 :                 if(p && getModuleId(p) == sqlRef && isUpdateInstruction(p)){
     106       25989 :                         if ( etop == esize){
     107             :                                 InstrPtr *tmp = updated;
     108           5 :                                 updated = (InstrPtr*) GDKrealloc( updated, (esize += 256) * sizeof(InstrPtr));
     109           5 :                                 if( updated == NULL){
     110           0 :                                         GDKfree(tmp);
     111           0 :                                         GDKfree(empty);
     112           0 :                                         goto wrapup;
     113             :                                 }
     114             :                         }
     115       25989 :                         updated[etop++]= p;
     116             :                 }
     117             : 
     118             :                 /* restore the naming, dropping the runtime property 'empty'
     119             :                  * Keep the bind operation, because it is cheap, rather focus on their re-use
     120             :                  */
     121             : 
     122     3637339 :                 if (getFunctionId(p) == emptybindRef) {
     123      198845 :                         setFunctionId(p,bindRef);
     124      198845 :                         p->typechk= TYPE_UNKNOWN;
     125      198845 :                         empty[getArg(p,0)] = i;
     126      198845 :                         if( p->retc == 2){
     127      180063 :                                 empty[getArg(p,1)] = i;
     128             :                         }
     129             :                         // replace the call into a empty bat creation unless the table was updated already in the same query
     130      198845 :                         sch = getVarConstant(mb,getArg(p,2  + (p->retc==2))).val.sval;
     131      198845 :                         tbl = getVarConstant(mb,getArg(p,3  + (p->retc==2))).val.sval;
     132      198941 :                         for(j= 0; j< etop; j++){
     133         158 :                                 q= updated[j];
     134         158 :                                 if(q && getModuleId(q) == sqlRef && isUpdateInstruction(q)){
     135         158 :                                         int c = getFunctionId(q) == claimRef;  /* claim has 2 results */
     136         158 :                                         if ( strcmp(getVarConstant(mb,getArg(q,2+c)).val.sval, sch) == 0 &&
     137         118 :                                                  strcmp(getVarConstant(mb,getArg(q,3+c)).val.sval, tbl) == 0 ){
     138          62 :                                                 empty[getArg(p,0)] = 0;
     139          62 :                                                 if( p->retc == 2){
     140          53 :                                                         empty[getArg(p,1)] = 0;
     141             :                                                 }
     142             :                                                 break;
     143             :                                         }
     144             :                                 }
     145          96 :                                 if(q && getModuleId(q) == sqlcatalogRef){
     146           0 :                                         if ( strcmp(getVarConstant(mb,getArg(q,2)).val.sval, sch) == 0 ){
     147           0 :                                                 empty[getArg(p,0)] = 0;
     148           0 :                                                 if( p->retc == 2){
     149           0 :                                                         empty[getArg(p,1)] = 0;
     150             :                                                 }
     151             :                                                 break;
     152             :                                         }
     153             :                                 }
     154             :                         }
     155      198845 :                         continue;
     156             :                 }
     157             : 
     158     3438494 :                 if (getFunctionId(p) == emptybindidxRef) {
     159        3281 :                         setFunctionId(p,bindidxRef);
     160        3281 :                         p->typechk= TYPE_UNKNOWN;
     161        3281 :                         empty[getArg(p,0)] = i;
     162        3281 :                         if( p->retc == 2){
     163        2958 :                                 empty[getArg(p,1)] = i;
     164             :                         }
     165             :                         // replace the call into a empty bat creation unless the table was updated already in the same query
     166        3281 :                         sch = getVarConstant(mb,getArg(p,2  + (p->retc==2))).val.sval;
     167        3281 :                         tbl = getVarConstant(mb,getArg(p,3  + (p->retc==2))).val.sval;
     168        3352 :                         for(j= 0; j< etop; j++){
     169          76 :                                 q= updated[j];
     170          76 :                                 if(q && getModuleId(q) == sqlRef && (getFunctionId(q) == appendRef || getFunctionId(q) == updateRef )){
     171          76 :                                         if ( strcmp(getVarConstant(mb,getArg(q,2)).val.sval, sch) == 0 &&
     172          76 :                                                  strcmp(getVarConstant(mb,getArg(q,3)).val.sval, tbl) == 0 ){
     173           5 :                                                 empty[getArg(p,0)] = 0;
     174           5 :                                                 if( p->retc == 2){
     175           2 :                                                         empty[getArg(p,1)] = 0;
     176             :                                                 }
     177             :                                                 break;
     178             :                                         }
     179             :                                 }
     180          71 :                                 if(q && getModuleId(q) == sqlcatalogRef){
     181           0 :                                         if ( strcmp(getVarConstant(mb,getArg(q,2)).val.sval, sch) == 0 ){
     182           0 :                                                 empty[getArg(p,0)] = 0;
     183           0 :                                                 break;
     184             :                                         }
     185             :                                 }
     186             :                         }
     187        3281 :                         continue;
     188             :                 }
     189             : 
     190             :                 // delta operations without updates can be replaced by an assignment
     191     3435213 :                 if (getModuleId(p)== sqlRef && getFunctionId(p) == deltaRef && p->argc == 4){
     192      183996 :                         if (empty[getArg(p,2)] && empty[getArg(p,3)]){
     193      182966 :                                 actions++;
     194      182966 :                                 clrFunction(p);
     195      182966 :                                 p->argc = 2;
     196      182966 :                                 if (empty[getArg(p,1)]){
     197       13852 :                                         empty[getArg(p,0)] = i;
     198             :                                 }
     199             :                         }
     200      183996 :                         continue;
     201             :                 }
     202             : 
     203     3251217 :                 if (getModuleId(p)== sqlRef && getFunctionId(p) == projectdeltaRef) {
     204           0 :                         if( empty[getArg(p,3)] && empty[getArg(p,4)] ){
     205           0 :                                 actions++;
     206           0 :                                 setModuleId(p,algebraRef);
     207           0 :                                 setFunctionId(p,projectionRef);
     208           0 :                                 p->argc = 3;
     209           0 :                                 p->typechk= TYPE_UNKNOWN;
     210             :                         }
     211           0 :                         continue;
     212             :                 }
     213     3251217 :                 if (getModuleId(p)== algebraRef){
     214     2354872 :                         if( getFunctionId(p) == projectionRef) {
     215     2109350 :                                 if( empty[getArg(p,1)] || empty[getArg(p,2)] ){
     216       45504 :                                         actions++;
     217       45504 :                                         emptyresult(0);
     218             :                                 }
     219             :                         }
     220     2354872 :                         if( getFunctionId(p) == thetaselectRef || getFunctionId(p) == selectRef) {
     221      123102 :                                 if( empty[getArg(p,1)] || empty[getArg(p,2)] ){
     222        3137 :                                         actions++;
     223        3137 :                                         emptyresult(0);
     224             :                                 }
     225             :                         }
     226             :                 }
     227     3251217 :                 if( getModuleId(p) == batstrRef){
     228         486 :                         if( empty[getArg(p,1)] || empty[getArg(p,2)] ){
     229         219 :                                 actions++;
     230         219 :                                 emptyresult(0);
     231             :                         }
     232             :                 }
     233     3251217 :                 if (getModuleId(p)== batRef && isUpdateInstruction(p)){
     234      121794 :                         if( empty[getArg(p,1)] && empty[getArg(p,2)]){
     235       11374 :                                 emptyresult(0);
     236      110420 :                         } else if (empty[getArg(p,2)]){
     237         134 :                                 actions++;
     238         134 :                                 clrFunction(p);
     239         134 :                                 p->argc = 2;
     240             :                         }
     241             :                 }
     242             :         }
     243             : 
     244     3834663 :         for(; i<slimit; i++)
     245     3812724 :                 if (old[i])
     246           0 :                         pushInstruction(mb, old[i]);
     247       21939 :         GDKfree(old);
     248       21939 :         GDKfree(empty);
     249       21939 :         GDKfree(updated);
     250             :         /* Defense line against incorrect plans */
     251       21939 :         msg = chkTypes(cntxt->usermodule, mb, FALSE);
     252       21939 :         if (!msg)
     253       21939 :                 msg = chkFlow(mb);
     254       21939 :         if (!msg)
     255       21939 :                 msg = chkDeclarations(mb);
     256             :         /* keep all actions taken as a post block comment */
     257           0 : wrapup:
     258             :         /* keep actions taken as a fake argument*/
     259      353093 :         (void) pushInt(mb, pci, actions);
     260      353093 :         return msg;
     261             : }

Generated by: LCOV version 1.14