LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 101 88.1 %
Date: 2024-12-20 21:24:02 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, date 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      470752 : OPTgeneratorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
      93             :                                                    InstrPtr pci)
      94             : {
      95      470752 :         InstrPtr p, q, *old, *series;
      96      470752 :         int i, k, limit, slimit, actions = 0;
      97             :         /* intRef, lngRef and dblRef are globally defined */
      98      470752 :         const char *bteRef = getName("bte");
      99      470769 :         const char *shtRef = getName("sht");
     100             :         //const char *intRef = getName("int");
     101             :         //const char *lngRef = getName("lng");
     102      470769 :         const char *fltRef = getName("flt");
     103             :         //const char *dblRef = getName("dbl");
     104      470760 :         str msg = MAL_SUCCEED;
     105      470760 :         int needed = 0;
     106             : 
     107      470760 :         (void) stk;
     108             : 
     109      470760 :         old = mb->stmt;
     110      470760 :         limit = mb->stop;
     111      470760 :         slimit = mb->ssize;
     112             : 
     113             :         // check applicability first
     114    29469976 :         for (i = 0; i < limit; i++) {
     115    28999687 :                 p = old[i];
     116    28999687 :                 if (getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef)
     117    28999687 :                         needed = 1;
     118             :                 /* avoid error in table-udf-column-descriptor */
     119    28999687 :                 if (p->token == RETURNsymbol || p->barrier == RETURNsymbol) {
     120         471 :                         old = NULL;
     121         471 :                         goto wrapup;
     122             :                 }
     123             :         }
     124      470289 :         if (!needed)
     125      470034 :                 goto wrapup;
     126             : 
     127         255 :         series = (InstrPtr *) GDKzalloc(sizeof(InstrPtr) * mb->vtop);
     128         255 :         if (series == NULL)
     129           0 :                 throw(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     130             : 
     131         255 :         if (newMalBlkStmt(mb, mb->ssize) < 0) {
     132           0 :                 GDKfree(series);
     133           0 :                 throw(MAL, "optimizer.generator", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     134             :         }
     135             : 
     136        6665 :         for (i = 0; mb->errors == NULL && i < limit; i++) {
     137        6665 :                 p = old[i];
     138        6665 :                 if (p->token == ENDsymbol) {
     139             :                         break;
     140             :                 }
     141        6410 :                 if (getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef) {
     142         268 :                         series[getArg(p, 0)] = p;
     143         268 :                         setModuleId(p, generatorRef);
     144         268 :                         setFunctionId(p, parametersRef);
     145         268 :                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     146         268 :                         pushInstruction(mb, p);
     147         268 :                         old[i] = NULL;
     148        6142 :                 } else if (getModuleId(p) == algebraRef && getFunctionId(p) == rangejoinRef
     149           6 :                                    && series[getArg(p, 2)]) {
     150           4 :                         errorCheck(p, i, algebraRef, getArg(p, 2));
     151        6138 :                 } else if (getModuleId(p) == algebraRef && getFunctionId(p) == selectRef
     152          80 :                                    && series[getArg(p, 1)]) {
     153          23 :                         errorCheck(p, i, algebraRef, getArg(p, 1));
     154        6115 :                 } else if (getModuleId(p) == algebraRef
     155        1417 :                                    && getFunctionId(p) == thetaselectRef
     156          77 :                                    && series[getArg(p, 1)]) {
     157          29 :                         errorCheck(p, i, algebraRef, getArg(p, 1));
     158        6086 :                 } else if (getModuleId(p) == algebraRef
     159        1388 :                                    && getFunctionId(p) == projectionRef
     160         856 :                                    && series[getArg(p, 2)]) {
     161         173 :                         errorCheck(p, i, algebraRef, getArg(p, 2));
     162        5913 :                 } else if (getModuleId(p) == sqlRef
     163         795 :                                    && getFunctionId(p) == putName("exportValue")
     164           0 :                                    && isaBatType(getArgType(mb, p, 0))) {
     165             :                         // interface expects scalar type only, not expressible in MAL signature
     166           0 :                         mb->errors = createException(MAL, "generate_series",
     167             :                                                                                  SQLSTATE(42000)
     168             :                                                                                  "internal error, generate_series is a table producing function");
     169        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == bteRef
     170          10 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     171           0 :                         casting(bte);
     172        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == shtRef
     173           2 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     174           0 :                         casting(sht);
     175        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == intRef
     176          41 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     177           0 :                         casting(int);
     178        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == lngRef
     179           6 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     180           0 :                         casting(lng);
     181        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == fltRef
     182           1 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     183           0 :                         casting(flt);
     184        5913 :                 } else if (getModuleId(p) == batcalcRef && getFunctionId(p) == dblRef
     185           3 :                                    && series[getArg(p, 1)] && p->argc == 2) {
     186           0 :                         casting(dbl);
     187        5913 :                 } else if (getModuleId(p) == languageRef && getFunctionId(p) == passRef) {
     188         524 :                         pushInstruction(mb, p);
     189         524 :                         old[i] = NULL;
     190             :                 } else {
     191             :                         // check for use without conversion
     192       17921 :                         for (k = p->retc; k < p->argc; k++) {
     193       12532 :                                 if (series[getArg(p, k)]) {
     194         311 :                                         const char *m = getModuleId(p);
     195         311 :                                         setModuleId(p, generatorRef);
     196         311 :                                         typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     197         311 :                                         if (!p->typeresolved) {
     198         311 :                                                 setModuleId(p, m);
     199         311 :                                                 typeChecker(cntxt->usermodule, mb, p, i, TRUE);
     200         311 :                                                 InstrPtr r = series[getArg(p, k)];
     201         311 :                                                 setModuleId(r, generatorRef);
     202         311 :                                                 setFunctionId(r, seriesRef);
     203         311 :                                                 typeChecker(cntxt->usermodule, mb, r, getPC(mb, r),
     204             :                                                                         TRUE);
     205             :                                         }
     206             :                                 }
     207             :                         }
     208        5389 :                         pushInstruction(mb, p);
     209        5389 :                         old[i] = NULL;
     210             :                 }
     211             :         }
     212        8082 :         for (; i < limit; i++)
     213        7827 :                 pushInstruction(mb, old[i]);
     214         255 :   bailout:
     215       52322 :         for (; i < slimit; i++) {
     216       52067 :                 if (old[i])
     217           0 :                         pushInstruction(mb, old[i]);
     218             :         }
     219         255 :         GDKfree(old);
     220         255 :         GDKfree(series);
     221             : 
     222             :         /* Defense line against incorrect plans */
     223             :         /* all new/modified statements are already checked */
     224             :         // msg = chkTypes(cntxt->usermodule, mb, FALSE);
     225             :         // if (!msg)
     226             :         //      msg = chkFlow(mb);
     227             :         // if (!msg)
     228             :         //      msg = chkDeclarations(mb);
     229             :         /* keep all actions taken as a post block comment */
     230      470760 :   wrapup:
     231             :         /* keep actions taken as a fake argument */
     232      470760 :         (void) pushInt(mb, pci, actions);
     233      470760 :         return msg;
     234             : }

Generated by: LCOV version 1.14