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

Generated by: LCOV version 1.14