LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_coercion.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 52 92 56.5 %
Date: 2024-04-25 20:03:45 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             :  * Superflous coercion statements will be garbagecollected later on in the pipeline
      33             :  */
      34             : static void
      35    21096773 : coercionOptimizerCalcStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      36             : {
      37    21096773 :         InstrPtr p = getInstrPtr(mb, i);
      38    21096773 :         int r, a, b, varid;
      39             : 
      40    21096773 :         r = getBatType(getVarType(mb, getArg(p, 0)));
      41             : #ifdef HAVE_HGE
      42    21096773 :         if (r != TYPE_hge)
      43             :                 return;
      44             : #endif
      45       40978 :         if (getModuleId(p) != batcalcRef || getFunctionId(p) == 0)
      46             :                 return;
      47       28046 :         if ((getFunctionId(p) != plusRef && getFunctionId(p) != minusRef
      48       17877 :                  && getFunctionId(p) != mulRef && getFunctionId(p) != divRef
      49       28046 :                  && 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)
      59           0 :                         || p->typechk == TYPE_UNKNOWN)
      60           0 :                         getArg(p, 1) = varid;
      61             :         }
      62           0 :         varid = getArg(p, 2);
      63           0 :         if (b == r && coerce[varid].src && coerce[varid].fromtype < r) {
      64             :                 // Remove upcast on second argument
      65           0 :                 getArg(p, 2) = coerce[varid].src;
      66           0 :                 if (chkInstruction(cntxt->usermodule, mb, p)
      67           0 :                         || p->typechk == TYPE_UNKNOWN)
      68           0 :                         getArg(p, 2) = varid;
      69             :         }
      70             :         return;
      71             : }
      72             : 
      73             : static void
      74    21096783 : coercionOptimizerAggrStep(Client cntxt, MalBlkPtr mb, int i, Coercion *coerce)
      75             : {
      76    21096783 :         InstrPtr p = getInstrPtr(mb, i);
      77    21096783 :         int r, k;
      78             : 
      79    21096783 :         (void) cntxt;
      80             : 
      81    21096783 :         if (getModuleId(p) != aggrRef || getFunctionId(p) == 0)
      82             :                 return;
      83       55593 :         if (!(getFunctionId(p) == subavgRef) || p->argc != 6)
      84             :                 return;
      85             : 
      86           0 :         r = getBatType(getVarType(mb, getArg(p, 0)));
      87           0 :         k = getArg(p, 1);
      88           0 :         if (r == TYPE_dbl && coerce[k].src) {
      89           0 :                 getArg(p, 1) = coerce[k].src;
      90           0 :                 if (chkInstruction(cntxt->usermodule, mb, p)
      91           0 :                         || p->typechk == TYPE_UNKNOWN)
      92           0 :                         getArg(p, 1) = k;
      93             :         }
      94             :         return;
      95             : }
      96             : 
      97             : str
      98      467670 : OPTcoercionImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      99             :                                                   InstrPtr pci)
     100             : {
     101      467670 :         int i, k, t;
     102      467670 :         InstrPtr p;
     103      467670 :         int actions = 0;
     104      467670 :         const char *calcRef = putName("calc");
     105      467672 :         Coercion *coerce = GDKzalloc(sizeof(Coercion) * mb->vtop);
     106      467672 :         str msg = MAL_SUCCEED;
     107             : 
     108      467672 :         if (coerce == NULL)
     109           0 :                 throw(MAL, "optimizer.coercion", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     110             :         (void) cntxt;
     111             :         (void) stk;                                     /* to fool compilers */
     112             : 
     113    24783656 :         for (i = 1; i < mb->stop; i++) {
     114    24315996 :                 p = getInstrPtr(mb, i);
     115    24315996 :                 if (getModuleId(p) == NULL)
     116     3219218 :                         continue;
     117             : /* Downscale the type, avoiding hge storage when lng would be sufficient.
     118             :  */
     119             : #ifdef HAVE_HGE
     120    21096778 :                 if (getModuleId(p) == batcalcRef
     121      216849 :                         && getFunctionId(p) == hgeRef
     122       16219 :                         && p->retc == 1 && p->argc == 5 && isVarConstant(mb, getArg(p, 1))
     123           0 :                         && getArgType(mb, p, 1) == TYPE_int
     124           0 :                         && isVarConstant(mb, getArg(p, 3))
     125           0 :                         && getArgType(mb, p, 3) == TYPE_int
     126           0 :                         && isVarConstant(mb, getArg(p, 4))
     127           0 :                         && getArgType(mb, p, 4) == TYPE_int
     128             :                         /* from-scale == to-scale, i.e., no scale change */
     129           0 :                         && *(int *) getVarValue(mb, getArg(p, 1)) == *(int *) getVarValue(mb, getArg (p, 4)))
     130             :                 {
     131           0 :                         k = getArg(p, 0);
     132           0 :                         coerce[k].pc = i;
     133           0 :                         coerce[k].totype = TYPE_hge;
     134           0 :                         coerce[k].src = getArg(p, 2);
     135           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 2));
     136             :                 }
     137             : #endif
     138    21096778 :                 if (getModuleId(p) == batcalcRef
     139      216849 :                         && getFunctionId(p) == dblRef
     140        1281 :                         && p->retc == 1
     141        1281 :                         && (p->argc == 2
     142        1281 :                                 || (p->argc == 3 && isVarConstant(mb, getArg(p, 1))
     143           0 :                                         && getArgType(mb, p, 1) == TYPE_int
     144             :                                         //to-scale == 0, i.e., no scale change
     145           0 :                                         && *(int *) getVarValue(mb, getArg(p, 1)) == 0))) {
     146           0 :                         k = getArg(p, 0);
     147           0 :                         coerce[k].pc = i;
     148           0 :                         coerce[k].totype = TYPE_dbl;
     149           0 :                         coerce[k].src = getArg(p, 1 + (p->argc == 3));
     150           0 :                         coerce[k].fromtype = getBatType(getArgType(mb, p, 1 + (p->argc == 3)));
     151             :                 }
     152    21096778 :                 coercionOptimizerAggrStep(cntxt, mb, i, coerce);
     153    21096770 :                 coercionOptimizerCalcStep(cntxt, mb, i, coerce);
     154    21096766 :                 if (getModuleId(p) == calcRef && p->argc == 2) {
     155       24745 :                         t = getVarType(mb, getArg(p, 1));
     156       24745 :                         if (getVarType(mb, getArg(p, 0)) == t
     157        4192 :                                 && strcmp(getFunctionId(p), ATOMname(t)) == 0) {
     158             :                                 /* turn it into an assignment */
     159         163 :                                 clrFunction(p);
     160         163 :                                 actions++;
     161             :                         }
     162             :                 }
     163             :         }
     164             :         /*
     165             :          * This optimizer affects the flow, but not the type and declaration
     166             :          * structure. A cheaper optimizer is sufficient.
     167             :          */
     168      467660 :         GDKfree(coerce);
     169             : 
     170             :         /* Defense line against incorrect plans */
     171      467671 :         if (actions > 0) {
     172          71 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     173          71 :                 if (!msg)
     174          71 :                         msg = chkFlow(mb);
     175          71 :                 if (!msg)
     176          71 :                         msg = chkDeclarations(mb);
     177             :         }
     178             :         /* keep actions taken as a fake argument */
     179      467671 :         (void) pushInt(mb, pci, actions);
     180      467671 :         return msg;
     181             : }

Generated by: LCOV version 1.14