LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_coercion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 53 88 60.2 %
Date: 2024-12-19 23:10:26 Functions: 3 3 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             : /* (c) M. Kersten
      14             :  * Also include down-casting decisions on the SQL code produced
      15             :  */
      16             : 
      17             : #include "monetdb_config.h"
      18             : #include "opt_coercion.h"
      19             : #include "opt_aliases.h"
      20             : 
      21             : typedef struct {
      22             :         int pc;
      23             :         int fromtype;
      24             :         int totype;
      25             :         int src;
      26             : } Coercion;
      27             : 
      28             : /* Check coercions for numeric types towards :hge that can be handled with smaller ones.
      29             :  * For now, limit to +,-,/,*,% hge expressions
      30             :  * Not every combination may be available in the MAL layer, which calls
      31             :  * for a separate type check before fixing it.
      32             :  * Superfluous coercion statements will be garbagecollected later on in the pipeline
      33             :  */
      34             : static void
      35    22461740 : coercionOptimizerCalcStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      36             : {
      37    22461740 :         InstrPtr p = getInstrPtr(mb, i);
      38    22461740 :         int r, a, b, varid;
      39             : 
      40    22461740 :         r = getBatType(getVarType(mb, getArg(p, 0)));
      41             : #ifdef HAVE_HGE
      42    22461740 :         if (r != TYPE_hge)
      43             :                 return;
      44             : #endif
      45        8760 :         if (getModuleId(p) != batcalcRef || getFunctionId(p) == 0)
      46             :                 return;
      47        1136 :         if ((getFunctionId(p) != plusRef && getFunctionId(p) != minusRef
      48         916 :                  && getFunctionId(p) != mulRef && getFunctionId(p) != divRef
      49        1136 :                  && getFunctionId(p) != modRef) || p->argc != 3)
      50             :                 return;
      51             : 
      52           0 :         a = getBatType(getVarType(mb, getArg(p, 1)));
      53           0 :         b = getBatType(getVarType(mb, getArg(p, 2)));
      54           0 :         varid = getArg(p, 1);
      55           0 :         if (a == r && coerce[varid].src && coerce[varid].fromtype < r) {
      56             :                 // Remove upcast on first argument
      57           0 :                 getArg(p, 1) = coerce[varid].src;
      58           0 :                 if (chkInstruction(cntxt->usermodule, mb, p) || !p->typeresolved)
      59           0 :                         getArg(p, 1) = varid;
      60             :         }
      61           0 :         varid = getArg(p, 2);
      62           0 :         if (b == r && coerce[varid].src && coerce[varid].fromtype < r) {
      63             :                 // Remove upcast on second argument
      64           0 :                 getArg(p, 2) = coerce[varid].src;
      65           0 :                 if (chkInstruction(cntxt->usermodule, mb, p) || !p->typeresolved)
      66           0 :                         getArg(p, 2) = varid;
      67             :         }
      68             :         return;
      69             : }
      70             : 
      71             : static void
      72    22461745 : coercionOptimizerAggrStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      73             : {
      74    22461745 :         InstrPtr p = getInstrPtr(mb, i);
      75    22461745 :         int r, k;
      76             : 
      77    22461745 :         (void) cntxt;
      78             : 
      79    22461745 :         if (getModuleId(p) != aggrRef || getFunctionId(p) == 0)
      80             :                 return;
      81       58217 :         if (!(getFunctionId(p) == subavgRef) || p->argc != 6)
      82             :                 return;
      83             : 
      84           0 :         r = getBatType(getVarType(mb, getArg(p, 0)));
      85           0 :         k = getArg(p, 1);
      86           0 :         if (r == TYPE_dbl && coerce[k].src) {
      87           0 :                 getArg(p, 1) = coerce[k].src;
      88           0 :                 if (chkInstruction(cntxt->usermodule, mb, p) || !p->typeresolved)
      89           0 :                         getArg(p, 1) = k;
      90             :         }
      91             :         return;
      92             : }
      93             : 
      94             : str
      95      498125 : OPTcoercionImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      96             :                                                   InstrPtr pci)
      97             : {
      98      498125 :         int i, k, t;
      99      498125 :         InstrPtr p;
     100      498125 :         int actions = 0;
     101      498125 :         Coercion *coerce = GDKzalloc(sizeof(Coercion) * mb->vtop);
     102      498207 :         str msg = MAL_SUCCEED;
     103             : 
     104      498207 :         if (coerce == NULL)
     105           0 :                 throw(MAL, "optimizer.coercion", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     106             :         (void) cntxt;
     107             :         (void) stk;                                     /* to fool compilers */
     108             : 
     109    26428748 :         for (i = 1; i < mb->stop; i++) {
     110    25930554 :                 p = getInstrPtr(mb, i);
     111    25930554 :                 if (getModuleId(p) == NULL)
     112     3469036 :                         continue;
     113             : /* Downscale the type, avoiding hge storage when lng would be sufficient.
     114             :  */
     115             : #ifdef HAVE_HGE
     116    22461518 :                 if (getModuleId(p) == batcalcRef
     117      168229 :                         && getFunctionId(p) == hgeRef
     118         367 :                         && p->retc == 1 && p->argc == 5 && isVarConstant(mb, getArg(p, 1))
     119         128 :                         && getArgType(mb, p, 1) == TYPE_int
     120           0 :                         && isVarConstant(mb, getArg(p, 3))
     121           0 :                         && getArgType(mb, p, 3) == TYPE_int
     122           0 :                         && isVarConstant(mb, getArg(p, 4))
     123           0 :                         && getArgType(mb, p, 4) == TYPE_int
     124             :                         /* from-scale == to-scale, i.e., no scale change */
     125           0 :                         && *(int *) getVarValue(mb, getArg(p, 1)) == *(int *) getVarValue(mb, getArg (p, 4)))
     126             :                 {
     127           0 :                         k = getArg(p, 0);
     128           0 :                         coerce[k].pc = i;
     129           0 :                         coerce[k].totype = TYPE_hge;
     130           0 :                         coerce[k].src = getArg(p, 2);
     131           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 2));
     132             :                 }
     133             : #endif
     134    22461518 :                 if (getModuleId(p) == batcalcRef
     135      168229 :                         && getFunctionId(p) == dblRef
     136        1341 :                         && p->retc == 1
     137        1341 :                         && (p->argc == 2
     138        1341 :                                 || (p->argc == 3 && isVarConstant(mb, getArg(p, 1))
     139        1278 :                                         && getArgType(mb, p, 1) == TYPE_int
     140             :                                         //to-scale == 0, i.e., no scale change
     141           0 :                                         && *(int *) getVarValue(mb, getArg(p, 1)) == 0))) {
     142           0 :                         k = getArg(p, 0);
     143           0 :                         coerce[k].pc = i;
     144           0 :                         coerce[k].totype = TYPE_dbl;
     145           0 :                         coerce[k].src = getArg(p, 1 + (p->argc == 3));
     146           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 1 + (p->argc == 3)));
     147             :                 }
     148    22461518 :                 coercionOptimizerAggrStep(cntxt, mb, i, coerce);
     149    22461715 :                 coercionOptimizerCalcStep(cntxt, mb, i, coerce);
     150    22461505 :                 if (getModuleId(p) == calcRef && p->argc == 2) {
     151       24705 :                         t = getVarType(mb, getArg(p, 1));
     152       24705 :                         if (getVarType(mb, getArg(p, 0)) == t
     153        4275 :                                 && strcmp(getFunctionId(p), ATOMname(t)) == 0) {
     154             :                                 /* turn it into an assignment */
     155         161 :                                 clrFunction(p);
     156         161 :                                 actions++;
     157             :                         }
     158             :                 }
     159             :         }
     160             :         /*
     161             :          * This optimizer affects the flow, but not the type and declaration
     162             :          * structure. A cheaper optimizer is sufficient.
     163             :          */
     164      498194 :         GDKfree(coerce);
     165             : 
     166             :         /* Defense line against incorrect plans */
     167      498213 :         if (actions > 0) {
     168          70 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     169          70 :                 if (!msg)
     170          70 :                         msg = chkFlow(mb);
     171          70 :                 if (!msg)
     172          70 :                         msg = chkDeclarations(mb);
     173             :         }
     174             :         /* keep actions taken as a fake argument */
     175      498213 :         (void) pushInt(mb, pci, actions);
     176      498213 :         return msg;
     177             : }

Generated by: LCOV version 1.14