LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_postfix.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 116 126 92.1 %
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             : /* The SQL code generator can not always look ahead to avoid
      14             :  * generation of intermediates.
      15             :  * Some of these patterns are captured in a postfix optimalisation.
      16             :  */
      17             : #include "monetdb_config.h"
      18             : #include "mal_instruction.h"
      19             : #include "opt_postfix.h"
      20             : 
      21             : #define isCandidateList(M,P,I) ((M)->var[getArg(P,I)].id[0]== 'C')
      22             : str
      23      493358 : OPTpostfixImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      24             :                                                  InstrPtr pci)
      25             : {
      26      493358 :         int i, slimit, actions = 0;
      27      493358 :         str msg = MAL_SUCCEED;
      28      493358 :         InstrPtr p;
      29             : 
      30      493358 :         (void) cntxt;
      31      493358 :         (void) stk;
      32             : 
      33      493358 :         slimit = mb->stop;
      34      493358 :         setVariableScope(mb);
      35             :         /* Remove the result from any join/group instruction when it is not used later on */
      36    29746949 :         for (i = 0; i < slimit; i++) {
      37             : /* POSTFIX ACTION FOR THE JOIN CASE  */
      38    28760179 :                 p = getInstrPtr(mb, i);
      39    28760179 :                 if (getModuleId(p) == algebraRef && p->retc == 2) {
      40      455642 :                         if (getFunctionId(p) == leftjoinRef ||  /*getFunctionId(p) == outerjoinRef || */
      41      454994 :                                 getFunctionId(p) == bandjoinRef
      42      454994 :                                 || getFunctionId(p) == rangejoinRef
      43      454844 :                                 || getFunctionId(p) == likejoinRef) {
      44         859 :                                 if (getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
      45          47 :                                         delArgument(p, p->retc - 1);
      46          47 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
      47          47 :                                         actions++;
      48          47 :                                         continue;
      49             :                                 }
      50      454783 :                         } else if (getFunctionId(p) == semijoinRef
      51      454573 :                                            || getFunctionId(p) == joinRef
      52      101610 :                                            || getFunctionId(p) == thetajoinRef
      53       50702 :                                            || /*getFunctionId(p) == outerjoinRef || */
      54       50702 :                                            getFunctionId(p) == crossRef) {
      55      449222 :                                 int is_first_ret_not_used = getVarEolife(mb, getArg(p, p->retc - 2)) == i;
      56      449222 :                                 int is_second_ret_not_used = getVarEolife(mb, getArg(p, p->retc - 1)) == i;
      57             : 
      58      449222 :                                 if (getFunctionId(p) == semijoinRef
      59         210 :                                         &&
      60             :                                         ((is_first_ret_not_used
      61          35 :                                           && getVarConstant(mb, getArg(p, 7)).val.btval != 1 /*not single */ )
      62         210 :                                          || is_second_ret_not_used)) {
      63             :                                         /* Can't swap arguments on single semijoins */
      64          88 :                                         if (is_first_ret_not_used) {
      65             :                                                 /* semijoin with just the right output is a join */
      66           0 :                                                 getArg(p, 2) ^= getArg(p, 3);   /* swap join inputs */
      67           0 :                                                 getArg(p, 3) ^= getArg(p, 2);
      68           0 :                                                 getArg(p, 2) ^= getArg(p, 3);
      69             : 
      70           0 :                                                 getArg(p, 4) ^= getArg(p, 5);   /* swap candidate lists */
      71           0 :                                                 getArg(p, 5) ^= getArg(p, 4);
      72           0 :                                                 getArg(p, 4) ^= getArg(p, 5);
      73           0 :                                                 setFunctionId(p, joinRef);
      74           0 :                                                 delArgument(p, 7);      /* delete 'max_one' argument */
      75             :                                         } else {
      76             :                                                 /* semijoin with just the left output is an intersection */
      77          88 :                                                 setFunctionId(p, intersectRef);
      78             :                                         }
      79             : 
      80         176 :                                         delArgument(p,
      81          88 :                                                                 is_second_ret_not_used ? p->retc - 1 : p->retc -
      82             :                                                                 2);
      83          88 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
      84          88 :                                         actions++;
      85          88 :                                         continue;
      86      449134 :                                 } else if (is_second_ret_not_used) {
      87       54710 :                                         delArgument(p, p->retc - 1);
      88       54710 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
      89       54710 :                                         actions++;
      90       54710 :                                         continue;
      91      394424 :                                 } else if (is_first_ret_not_used &&
      92       26431 :                                                    (getFunctionId(p) == joinRef
      93       13702 :                                                         || (getFunctionId(p) == thetajoinRef
      94       13343 :                                                                 && isVarConstant(mb, getArg(p, 6)))
      95         359 :                                                         || (getFunctionId(p) == crossRef
      96         324 :                                                                 && getVarConstant(mb, getArg(p, 4)).val.btval != 1 /*not single */ ))) {
      97             :                                         /* Can't swap arguments on single cross products */
      98             :                                         /* swap join inputs */
      99       26391 :                                         getArg(p, 2) ^= getArg(p, 3);
     100       26391 :                                         getArg(p, 3) ^= getArg(p, 2);
     101       26391 :                                         getArg(p, 2) ^= getArg(p, 3);
     102             : 
     103       26391 :                                         if (getFunctionId(p) != crossRef) {     /* swap candidate lists */
     104       26072 :                                                 getArg(p, 4) ^= getArg(p, 5);
     105       26072 :                                                 getArg(p, 5) ^= getArg(p, 4);
     106       26072 :                                                 getArg(p, 4) ^= getArg(p, 5);
     107       26072 :                                                 if (getFunctionId(p) == thetajoinRef) { /* swap the comparison */
     108       13343 :                                                         ValRecord *x = &getVarConstant(mb, getArg(p, 6)),
     109       13343 :                                                                 cst = {
     110             :                                                                         .vtype = TYPE_int
     111             :                                                                 };
     112       13343 :                                                         switch (x->val.ival) {
     113       13293 :                                                         case JOIN_LT:
     114       13293 :                                                                 cst.val.ival = JOIN_GT;
     115       13293 :                                                                 break;
     116          17 :                                                         case JOIN_LE:
     117          17 :                                                                 cst.val.ival = JOIN_GE;
     118          17 :                                                                 break;
     119          25 :                                                         case JOIN_GT:
     120          25 :                                                                 cst.val.ival = JOIN_LT;
     121          25 :                                                                 break;
     122           8 :                                                         case JOIN_GE:
     123           8 :                                                                 cst.val.ival = JOIN_LE;
     124           8 :                                                                 break;
     125           0 :                                                         default:
     126           0 :                                                                 cst.val.ival = x->val.ival;
     127             :                                                         }
     128       13343 :                                                         setArg(p, 6, defConstant(mb, TYPE_int, &cst));
     129             :                                                 }
     130             :                                         }
     131       26391 :                                         delArgument(p, p->retc - 2);
     132       26391 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     133       26391 :                                         actions++;
     134       26391 :                                         continue;
     135             :                                 }
     136             :                         }
     137             :                 }
     138             : /* POSTFIX ACTION FOR THE EXTENT CASE  */
     139    28678943 :                 if (getModuleId(p) == groupRef && getFunctionId(p) == groupRef
     140       20326 :                         && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     141       20284 :                         delArgument(p, p->retc - 1);
     142       20284 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     143       20284 :                         actions++;
     144       20284 :                         continue;
     145             :                 }
     146    28658659 :                 if (getModuleId(p) == groupRef && getFunctionId(p) == subgroupRef
     147        4366 :                         && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     148        4366 :                         delArgument(p, p->retc - 1);
     149        4366 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     150        4366 :                         actions++;
     151        4366 :                         continue;
     152             :                 }
     153    28654293 :                 if (getModuleId(p) == groupRef && getFunctionId(p) == subgroupdoneRef
     154       20499 :                         && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     155       20207 :                         delArgument(p, p->retc - 1);
     156       20207 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     157       20207 :                         actions++;
     158       20207 :                         continue;
     159             :                 }
     160    28634086 :                 if (getModuleId(p) == groupRef && getFunctionId(p) == groupdoneRef
     161       41189 :                         && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     162       31751 :                         delArgument(p, p->retc - 1);
     163       31751 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     164       31751 :                         actions++;
     165       31751 :                         continue;
     166             :                 }
     167             : /* POSTFIX ACTION FOR SORT, could be dropping the last two */
     168    28602335 :                 if (getModuleId(p) == algebraRef && getFunctionId(p) == sortRef
     169       23348 :                         && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     170        9896 :                         delArgument(p, p->retc - 1);
     171        9896 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     172        9896 :                         actions++;
     173        9896 :                         if (getModuleId(p) == algebraRef && getFunctionId(p) == sortRef
     174        9896 :                                 && getVarEolife(mb, getArg(p, p->retc - 1)) == i) {
     175        3369 :                                 delArgument(p, p->retc - 1);
     176        3369 :                                 typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     177        3369 :                                 actions++;
     178             :                         }
     179        9896 :                         continue;
     180             :                 }
     181             :         }
     182             :         /* Defense line against incorrect plans */
     183      493412 :         if (actions) {
     184             :                 // msg = chkTypes(cntxt->usermodule, mb, FALSE);
     185             :                 // if (!msg)
     186             :                 //      msg = chkFlow(mb);
     187             :                 // if (!msg)
     188             :                 //      msg = chkDeclarations(mb);
     189      493412 :         }
     190             :         /* keep actions taken as a fake argument */
     191      493412 :         (void) pushInt(mb, pci, actions);
     192      493421 :         return msg;
     193             : }

Generated by: LCOV version 1.14