LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 87 101 86.1 %
Date: 2024-12-19 20:05:57 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             : #include "monetdb_config.h"
      14             : #include "opt_generator.h"
      15             : #include "mal_builder.h"
      16             : 
      17             : /*
      18             :  * (c) Martin Kersten, Sjoerd Mullender
      19             :  * Series generating module for integer, decimal, real, double and timestamps.
      20             :  */
      21             : 
      22             : #define errorCheck(P,IDX,MOD,I)                                                                         \
      23             :         do {                                                                                                                    \
      24             :                 setModuleId(P, generatorRef);                                                           \
      25             :                 typeChecker(cntxt->usermodule, mb, P, IDX, TRUE);                    \
      26             :                 if (!P->typeresolved) {                                                                              \
      27             :                         setModuleId(P, MOD);                                                                    \
      28             :                         typeChecker(cntxt->usermodule, mb, P, IDX, TRUE);            \
      29             :                         setModuleId(series[I], generatorRef);                                   \
      30             :                         setFunctionId(series[I], seriesRef);                                    \
      31             :                         typeChecker(cntxt->usermodule, mb, series[I], I, TRUE);      \
      32             :                 }                                                                                                                       \
      33             :                 pushInstruction(mb,P);                                                                          \
      34             :         } while (0)
      35             : 
      36             : #define casting(TPE)                                                                                                    \
      37             :         do {                                                                                                                            \
      38             :                 k = getArg(p, 1);                                                                                               \
      39             :                 p->argc = p->retc;                                                                                                \
      40             :                 q = newInstruction(0, calcRef, TPE##Ref);                                               \
      41             :                 if (q == NULL) {                                                                                                \
      42             :                         msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      43             :                         goto bailout;                                                                                           \
      44             :                 }                                                                                                                               \
      45             :                 if (setDestVar(q, newTmpVariable(mb, TYPE_##TPE)) < 0) {             \
      46             :                         freeInstruction(q);                                                                                     \
      47             :                         msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      48             :                         goto bailout;                                                                                           \
      49             :                 }                                                                                                                               \
      50             :                 q = pushArgument(mb, q, getArg(series[k], 1));                                  \
      51             :                 typeChecker(cntxt->usermodule, mb, q, 0, TRUE);                                      \
      52             :                 p = pushArgument(mb, p, getArg(q, 0));                                                  \
      53             :                 pushInstruction(mb, q);                                                                                 \
      54             :                 q = newInstruction(0, calcRef, TPE##Ref);                                               \
      55             :                 if (q == NULL) {                                                                                                \
      56             :                         msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      57             :                         goto bailout;                                                                                           \
      58             :                 }                                                                                                                               \
      59             :                 if (setDestVar(q, newTmpVariable(mb, TYPE_##TPE)) < 0) {             \
      60             :                         freeInstruction(q);                                                                                     \
      61             :                         msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      62             :                         goto bailout;                                                                                           \
      63             :                 }                                                                                                                               \
      64             :                 q = pushArgument(mb, q, getArg(series[k], 2));                                  \
      65             :                 pushInstruction(mb, q);                                                                                 \
      66             :                 typeChecker(cntxt->usermodule,  mb,  q,  0, TRUE);                           \
      67             :                 p = pushArgument(mb, p, getArg(q, 0));                                                  \
      68             :                 if( p->argc == 4){                                                                                           \
      69             :                         q = newInstruction(0, calcRef, TPE##Ref);                                       \
      70             :                         if (q == NULL) {                                                                                        \
      71             :                                 msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      72             :                                 goto bailout;                                                                                   \
      73             :                         }                                                                                                                       \
      74             :                         if (setDestVar(q, newTmpVariable(mb, TYPE_##TPE)) < 0) {     \
      75             :                                 freeInstruction(q);                                                                             \
      76             :                                 msg = createException(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
      77             :                                 goto bailout;                                                                                   \
      78             :                         }                                                                                                                       \
      79             :                         q = pushArgument(mb, q, getArg(series[k], 3));                          \
      80             :                         typeChecker(cntxt->usermodule, mb, q, 0, TRUE);                              \
      81             :                         p = pushArgument(mb, p, getArg(q, 0));                                          \
      82             :                         pushInstruction(mb, q);                                                                         \
      83             :                 }                                                                                                                               \
      84             :                 setModuleId(p, generatorRef);                                                                   \
      85             :                 setFunctionId(p, parametersRef);                                                                \
      86             :                 series[getArg(p, 0)] = p;                                                                               \
      87             :                 pushInstruction(mb, p);                                                                                 \
      88             :                 old[i] = NULL;                                                                                                  \
      89             :         } while (0)
      90             : 
      91             : str
      92      455584 : OPTgeneratorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      93             :                                                    InstrPtr pci)
      94             : {
      95      455584 :         InstrPtr p, q, *old, *series;
      96      455584 :         int i, k, limit, slimit, actions = 0;
      97      455584 :         const char *bteRef = getName("bte");
      98      455584 :         const char *shtRef = getName("sht");
      99      455584 :         const char *intRef = getName("int");
     100      455584 :         const char *lngRef = getName("lng");
     101      455584 :         const char *fltRef = getName("flt");
     102      455584 :         const char *dblRef = getName("dbl");
     103      455584 :         str msg = MAL_SUCCEED;
     104      455584 :         int needed = 0;
     105             : 
     106      455584 :         (void) stk;
     107             : 
     108      455584 :         old = mb->stmt;
     109      455584 :         limit = mb->stop;
     110      455584 :         slimit = mb->ssize;
     111             : 
     112             :         // check applicability first
     113    23929450 :         for (i = 0; i < limit; i++) {
     114    23474337 :                 p = old[i];
     115    23474337 :                 if (getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef)
     116    23474337 :                         needed = 1;
     117             :                 /* avoid error in table-udf-column-descriptor */
     118    23474337 :                 if (p->token == RETURNsymbol || p->barrier == RETURNsymbol) {
     119         471 :                         old = NULL;
     120         471 :                         goto wrapup;
     121             :                 }
     122             :         }
     123      455113 :         if (!needed)
     124      454876 :                 goto wrapup;
     125             : 
     126         237 :         series = (InstrPtr *) GDKzalloc(sizeof(InstrPtr) * mb->vtop);
     127         237 :         if (series == NULL)
     128           0 :                 throw(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     129             : 
     130         237 :         if (newMalBlkStmt(mb, mb->ssize) < 0) {
     131           0 :                 GDKfree(series);
     132           0 :                 throw(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     133             :         }
     134             : 
     135        5462 :         for (i = 0; mb->errors == NULL && i < limit; i++) {
     136        5462 :                 p = old[i];
     137        5462 :                 if (p->token == ENDsymbol) {
     138             :                         break;
     139             :                 }
     140        5225 :                 if (getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef) {
     141         245 :                         series[getArg(p, 0)] = p;
     142         245 :                         setModuleId(p, generatorRef);
     143         245 :                         setFunctionId(p, parametersRef);
     144         245 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     145         245 :                         pushInstruction(mb, p);
     146         245 :                         old[i] = NULL;
     147        4980 :                 } else if (getModuleId(p) == algebraRef && getFunctionId(p) == selectRef
     148          62 :                                    && series[getArg(p, 1)]) {
     149          23 :                         errorCheck(p, i, algebraRef, getArg(p, 1));
     150        4957 :                 } else if (getModuleId(p) == algebraRef
     151         974 :                                    && getFunctionId(p) == thetaselectRef
     152          49 :                                    && series[getArg(p, 1)]) {
     153          29 :                         errorCheck(p, i, algebraRef, getArg(p, 1));
     154        4928 :                 } else if (getModuleId(p) == algebraRef
     155         945 :                                    && getFunctionId(p) == projectionRef
     156         581 :                                    && series[getArg(p, 2)]) {
     157         144 :                         errorCheck(p, i, algebraRef, getArg(p, 2));
     158        4784 :                 } else if (getModuleId(p) == sqlRef
     159         751 :                                    && getFunctionId(p) == putName("exportValue")
     160           0 :                                    && isaBatType(getArgType(mb, p, 0))) {
     161             :                         // interface expects scalar type only, not expressible in MAL signature
     162           0 :                         mb->errors = createException(MAL, "generate_series",
     163             :                                                                                  SQLSTATE(42000)
     164             :                                                                                  "internal error, generate_series is a table producing function");
     165        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == bteRef
     166           0 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     167           0 :                         casting(bte);
     168        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == shtRef
     169           0 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     170           0 :                         casting(sht);
     171        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == intRef
     172          42 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     173           0 :                         casting(int);
     174        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == lngRef
     175           6 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     176           0 :                         casting(lng);
     177        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == fltRef
     178           1 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     179           0 :                         casting(flt);
     180        4784 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == dblRef
     181           2 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     182           0 :                         casting(dbl);
     183        4784 :                 } else if (getModuleId(p) == languageRef && getFunctionId(p) == passRef) {
     184         519 :                         pushInstruction(mb, p);
     185         519 :                         old[i] = NULL;
     186             :                 } else {
     187             :                         // check for use without conversion
     188       14109 :                         for (k = p->retc; k < p->argc; k++) {
     189        9844 :                                 if (series[getArg(p, k)]) {
     190         274 :                                         const char *m = getModuleId(p);
     191         274 :                                         setModuleId(p, generatorRef);
     192         274 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     193         274 :                                         if (!p->typeresolved) {
     194         274 :                                                 setModuleId(p, m);
     195         274 :                                                 typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     196         274 :                                                 InstrPtr r = series[getArg(p, k)];
     197         274 :                                                 setModuleId(r, generatorRef);
     198         274 :                                                 setFunctionId(r, seriesRef);
     199         274 :                                                 typeChecker(cntxt->usermodule, mb, r, getPC(mb, r),
     200             :                                                                         TRUE);
     201             :                                         }
     202             :                                 }
     203             :                         }
     204        4265 :                         pushInstruction(mb, p);
     205        4265 :                         old[i] = NULL;
     206             :                 }
     207             :         }
     208        7576 :         for (; i < limit; i++)
     209        7339 :                 pushInstruction(mb, old[i]);
     210         237 :   bailout:
     211       48345 :         for (; i < slimit; i++) {
     212       48108 :                 if (old[i])
     213           0 :                         pushInstruction(mb, old[i]);
     214             :         }
     215         237 :         GDKfree(old);
     216         237 :         GDKfree(series);
     217             : 
     218             :         /* Defense line against incorrect plans */
     219             :         /* all new/modified statements are already checked */
     220             :         // msg = chkTypes(cntxt->usermodule, mb, FALSE);
     221             :         // if (!msg)
     222             :         //      msg = chkFlow(mb);
     223             :         // if (!msg)
     224             :         //      msg = chkDeclarations(mb);
     225             :         /* keep all actions taken as a post block comment */
     226      455584 :   wrapup:
     227             :         /* keep actions taken as a fake argument */
     228      455584 :         (void) pushInt(mb, pci, actions);
     229      455584 :         return msg;
     230             : }

Generated by: LCOV version 1.14