LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_coercion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 54 89 60.7 %
Date: 2024-12-20 20:06:10 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    21833701 : coercionOptimizerCalcStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      36             : {
      37    21833701 :         InstrPtr p = getInstrPtr(mb, i);
      38    21833701 :         int r, a, b, varid;
      39             : 
      40    21833701 :         r = getBatType(getVarType(mb, getArg(p, 0)));
      41             : #ifdef HAVE_HGE
      42    21833701 :         if (r != TYPE_hge)
      43             :                 return;
      44             : #endif
      45        8722 :         if (getModuleId(p) != batcalcRef || getFunctionId(p) == 0)
      46             :                 return;
      47        1128 :         if ((getFunctionId(p) != plusRef && getFunctionId(p) != minusRef
      48         914 :                  && getFunctionId(p) != mulRef && getFunctionId(p) != divRef
      49        1128 :                  && 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    21833702 : coercionOptimizerAggrStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      73             : {
      74    21833702 :         InstrPtr p = getInstrPtr(mb, i);
      75    21833702 :         int r, k;
      76             : 
      77    21833702 :         (void) cntxt;
      78             : 
      79    21833702 :         if (getModuleId(p) != aggrRef || getFunctionId(p) == 0)
      80             :                 return;
      81       57693 :         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      483992 : OPTcoercionImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      96             :                                                   InstrPtr pci)
      97             : {
      98      483992 :         int i, k, t;
      99      483992 :         InstrPtr p;
     100      483992 :         int actions = 0;
     101      483992 :         const char *calcRef = putName("calc");
     102      483992 :         Coercion *coerce = GDKzalloc(sizeof(Coercion) * mb->vtop);
     103      483990 :         str msg = MAL_SUCCEED;
     104             : 
     105      483990 :         if (coerce == NULL)
     106           0 :                 throw(MAL, "optimizer.coercion", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     107             :         (void) cntxt;
     108             :         (void) stk;                                     /* to fool compilers */
     109             : 
     110    25634957 :         for (i = 1; i < mb->stop; i++) {
     111    25150976 :                 p = getInstrPtr(mb, i);
     112    25150976 :                 if (getModuleId(p) == NULL)
     113     3317277 :                         continue;
     114             : /* Downscale the type, avoiding hge storage when lng would be sufficient.
     115             :  */
     116             : #ifdef HAVE_HGE
     117    21833699 :                 if (getModuleId(p) == batcalcRef
     118      164247 :                         && getFunctionId(p) == hgeRef
     119         366 :                         && p->retc == 1 && p->argc == 5 && isVarConstant(mb, getArg(p, 1))
     120         128 :                         && getArgType(mb, p, 1) == TYPE_int
     121           0 :                         && isVarConstant(mb, getArg(p, 3))
     122           0 :                         && getArgType(mb, p, 3) == TYPE_int
     123           0 :                         && isVarConstant(mb, getArg(p, 4))
     124           0 :                         && getArgType(mb, p, 4) == TYPE_int
     125             :                         /* from-scale == to-scale, i.e., no scale change */
     126           0 :                         && *(int *) getVarValue(mb, getArg(p, 1)) == *(int *) getVarValue(mb, getArg (p, 4)))
     127             :                 {
     128           0 :                         k = getArg(p, 0);
     129           0 :                         coerce[k].pc = i;
     130           0 :                         coerce[k].totype = TYPE_hge;
     131           0 :                         coerce[k].src = getArg(p, 2);
     132           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 2));
     133             :                 }
     134             : #endif
     135    21833699 :                 if (getModuleId(p) == batcalcRef
     136      164247 :                         && getFunctionId(p) == dblRef
     137        1338 :                         && p->retc == 1
     138        1338 :                         && (p->argc == 2
     139        1338 :                                 || (p->argc == 3 && isVarConstant(mb, getArg(p, 1))
     140        1276 :                                         && getArgType(mb, p, 1) == TYPE_int
     141             :                                         //to-scale == 0, i.e., no scale change
     142           0 :                                         && *(int *) getVarValue(mb, getArg(p, 1)) == 0))) {
     143           0 :                         k = getArg(p, 0);
     144           0 :                         coerce[k].pc = i;
     145           0 :                         coerce[k].totype = TYPE_dbl;
     146           0 :                         coerce[k].src = getArg(p, 1 + (p->argc == 3));
     147           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 1 + (p->argc == 3)));
     148             :                 }
     149    21833699 :                 coercionOptimizerAggrStep(cntxt, mb, i, coerce);
     150    21833698 :                 coercionOptimizerCalcStep(cntxt, mb, i, coerce);
     151    21833690 :                 if (getModuleId(p) == calcRef && p->argc == 2) {
     152       24660 :                         t = getVarType(mb, getArg(p, 1));
     153       24660 :                         if (getVarType(mb, getArg(p, 0)) == t
     154        4250 :                                 && strcmp(getFunctionId(p), ATOMname(t)) == 0) {
     155             :                                 /* turn it into an assignment */
     156         161 :                                 clrFunction(p);
     157         161 :                                 actions++;
     158             :                         }
     159             :                 }
     160             :         }
     161             :         /*
     162             :          * This optimizer affects the flow, but not the type and declaration
     163             :          * structure. A cheaper optimizer is sufficient.
     164             :          */
     165      483981 :         GDKfree(coerce);
     166             : 
     167             :         /* Defense line against incorrect plans */
     168      483992 :         if (actions > 0) {
     169          70 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     170          70 :                 if (!msg)
     171          70 :                         msg = chkFlow(mb);
     172          70 :                 if (!msg)
     173          70 :                         msg = chkDeclarations(mb);
     174             :         }
     175             :         /* keep actions taken as a fake argument */
     176      483992 :         (void) pushInt(mb, pci, actions);
     177      483992 :         return msg;
     178             : }

Generated by: LCOV version 1.14