LCOV - code coverage report
Current view: top level - sql/backends/monet5/generator - generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 231 593 39.0 %
Date: 2024-04-26 00:35:57 Functions: 7 10 70.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             : /*
      14             :  * (c) Martin Kersten, Sjoerd Mullender
      15             :  * Series generating module for integer, decimal, real, double and timestamps.
      16             :  */
      17             : 
      18             : #include "monetdb_config.h"
      19             : #include "opt_prelude.h"
      20             : #include "generator.h"
      21             : #include "gdk_time.h"
      22             : 
      23             : 
      24             : #define IDENTITY(x)     (x)
      25             : 
      26             : /*
      27             :  * The noop simply means that we keep the properties for the generator object.
      28             :  */
      29             : #define VLTnoop(TPE)                                                                                            \
      30             :         do {                                                                                                                    \
      31             :                 TPE s;                                                                                                          \
      32             :                 s = pci->argc == 3 ? 1: *getArgReference_##TPE(stk,pci, 3); \
      33             :                 zeroerror = (s == 0);                                                                           \
      34             :                 nullerr = is_##TPE##_nil(s);                                                            \
      35             :         } while (0)
      36             : 
      37             : str
      38         202 : VLTgenerator_noop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      39             : {
      40         202 :         int nullerr= 0, zeroerror=0, tpe;
      41         202 :         (void) cntxt;
      42             : 
      43         202 :         switch( tpe = getArgType(mb,pci,1)){
      44         105 :         case TYPE_bte: VLTnoop(bte); break;
      45          21 :         case TYPE_sht: VLTnoop(sht); break;
      46          29 :         case TYPE_int: VLTnoop(int); break;
      47          10 :         case TYPE_lng: VLTnoop(lng); break;
      48             : #ifdef HAVE_HGE
      49           0 :         case TYPE_hge: VLTnoop(hge); break;
      50             : #endif
      51           3 :         case TYPE_flt: VLTnoop(flt); break;
      52           7 :         case TYPE_dbl: VLTnoop(dbl); break;
      53          27 :         default:
      54          27 :                 if (tpe == TYPE_timestamp){
      55             :                         /* with timestamp, step is of SQL type "interval seconds",
      56             :                          * i.e., MAL / C type "lng" */
      57          27 :                          VLTnoop(lng);
      58           0 :                 } else throw(MAL,"generator.noop", SQLSTATE(42000) "unknown data type %d", getArgType(mb,pci,1));
      59             :         }
      60         202 :         if( zeroerror)
      61           2 :                 throw(MAL,"generator.noop", SQLSTATE(42000) "Zero step size not allowed");
      62         200 :         if( nullerr)
      63           2 :                 throw(MAL,"generator.noop", SQLSTATE(42000) "Null step size not allowed");
      64             :         return MAL_SUCCEED;
      65             : }
      66             : 
      67             : #define check_bte() (s > 0 ? f > l : f < l)
      68             : #define check_sht() (s > 0 ? f > l : f < l)
      69             : #define check_int() (s > 0 ? f > l : f < l)
      70             : #if SIZEOF_BUN < SIZEOF_LNG
      71             : #define check_lng() (s > 0 ? f > l || s > (lng) BUN_MAX : f < l || s < -(lng) BUN_MAX)
      72             : #else
      73             : #define check_lng() (s > 0 ? f > l : f < l)
      74             : #endif
      75             : #ifdef HAVE_HGE
      76             : #define check_hge() (s > 0 ? f > l || s > (lng) BUN_MAX : f < l || s < -(lng) BUN_MAX)
      77             : #endif
      78             : 
      79             : /*
      80             :  * The base line consists of materializing the generator iterator value
      81             :  */
      82             : #define VLTmaterialize(TPE)                                                                                             \
      83             :         do {                                                                                                                            \
      84             :                 TPE *v, f, l, s;                                                                                                \
      85             :                 f = *getArgReference_##TPE(stk, pci, 1);                                                \
      86             :                 l = *getArgReference_##TPE(stk, pci, 2);                                                \
      87             :                 if ( pci->argc == 3)                                                                                 \
      88             :                         s = f<=l? (TPE) 1: (TPE)-1;                                                                  \
      89             :                 else s =  *getArgReference_##TPE(stk,pci, 3);                                   \
      90             :                 if (s == 0 || is_##TPE##_nil(f) || is_##TPE##_nil(l) || check_##TPE()) \
      91             :                         throw(MAL, "generator.table",                                                         \
      92             :                               SQLSTATE(42000) "Illegal generator range");                     \
      93             :                 if (f == l)                                                                                                             \
      94             :                         n = 0;                                                                                                          \
      95             :                 else if (f > l) {                                                                                            \
      96             :                         /* n = f - l */                                                                                         \
      97             :                         if (l < 1) {                                                                                         \
      98             :                                 if ((lng) BUN_MAX + l < f)                                                           \
      99             :                                         throw(MAL, "generator.table",                                         \
     100             :                                                   SQLSTATE(42000) "Illegal generator range"); \
     101             :                                 else if (GDK_##TPE##_max + l < f)                                            \
     102             :                                         n = (BUN) ((lng) f - l);                                                        \
     103             :                                 else                                                                                                    \
     104             :                                         n = (BUN) (f - l);                                                                      \
     105             :                         } else {                                                                                                        \
     106             :                                 if (-(lng)BUN_MAX + l > f)                                                           \
     107             :                                         throw(MAL, "generator.table",                                         \
     108             :                                                   SQLSTATE(42000) "Illegal generator range"); \
     109             :                                 else if (-GDK_##TPE##_max + l > f)                                           \
     110             :                                         n = (BUN) ((lng) f - l);                                                        \
     111             :                                 else                                                                                                    \
     112             :                                         n = (BUN) (f - l);                                                                      \
     113             :                         }                                                                                                                       \
     114             :                 } else {                                                                                                                \
     115             :                         /* n = l - f */                                                                                         \
     116             :                         if (f < 1) {                                                                                         \
     117             :                                 if ((lng) BUN_MAX + f < l)                                                           \
     118             :                                         throw(MAL, "generator.table",                                         \
     119             :                                                   SQLSTATE(42000) "Illegal generator range"); \
     120             :                                 else if (GDK_##TPE##_max + f < l)                                            \
     121             :                                         n = (BUN) ((lng) l - f);                                                        \
     122             :                                 else                                                                                                    \
     123             :                                         n = (BUN) (l - f);                                                                      \
     124             :                         } else {                                                                                                        \
     125             :                                 if (-(lng)BUN_MAX + f > l)                                                           \
     126             :                                         throw(MAL, "generator.table",                                         \
     127             :                                                   SQLSTATE(42000) "Illegal generator range"); \
     128             :                                 else if (-GDK_##TPE##_max + f > l)                                           \
     129             :                                         n = (BUN) ((lng) l - f);                                                        \
     130             :                                 else                                                                                                    \
     131             :                                         n = (BUN) (l - f);                                                                      \
     132             :                         }                                                                                                                       \
     133             :                 }                                                                                                                               \
     134             :                 step = (BUN) (s < 0 ? -s : s);                                                                       \
     135             :                 n = n/step;                                                                                                             \
     136             :                 if ((TPE) (n * s + f) != l)                                                                             \
     137             :                         n++;                                                                                                            \
     138             :                 bn = COLnew(0, TYPE_##TPE, n, TRANSIENT);                                               \
     139             :                 if (bn == NULL)                                                                                                 \
     140             :                         throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);       \
     141             :                 v = (TPE*) Tloc(bn, 0);                                                                                 \
     142             :                 for (c = 0; c < n; c++)                                                                                      \
     143             :                         *v++ = (TPE) (f + c * s);                                                                       \
     144             :                 bn->tsorted = s > 0 || n <= 1;                                                                 \
     145             :                 bn->trevsorted = s < 0 || n <= 1;                                                              \
     146             :         } while (0)
     147             : 
     148             : #define VLTmaterialize_flt(TPE)                                                                                 \
     149             :         do {                                                                                                                            \
     150             :                 TPE *v, f, l, s;                                                                                                \
     151             :                 f = *getArgReference_##TPE(stk, pci, 1);                                                \
     152             :                 l = *getArgReference_##TPE(stk, pci, 2);                                                \
     153             :                 if ( pci->argc == 3)                                                                                 \
     154             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     155             :                 else s =  *getArgReference_##TPE(stk,pci, 3);                                   \
     156             :                 if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) \
     157             :                         throw(MAL, "generator.table",                                                         \
     158             :                               SQLSTATE(42000) "Illegal generator range");                     \
     159             :                 n = (BUN) ((l - f) / s);                                        \
     160             :                 if ((TPE) (n * s + f) != l)                                                                             \
     161             :                         n++;                                                                                                            \
     162             :                 bn = COLnew(0, TYPE_##TPE, n, TRANSIENT);                                               \
     163             :                 if (bn == NULL)                                                                                                 \
     164             :                         throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);       \
     165             :                 v = (TPE*) Tloc(bn, 0);                                                                                 \
     166             :                 for (c = 0; c < n; c++)                                                                                      \
     167             :                         *v++ = (TPE) (f + c * s);                                                                       \
     168             :                 bn->tsorted = s > 0 || n <= 1;                                                                 \
     169             :                 bn->trevsorted = s < 0 || n <= 1;                                                              \
     170             :         } while (0)
     171             : 
     172             : static str
     173         173 : VLTgenerator_table_(BAT **result, Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     174             : {
     175         173 :         BUN c, n, step;
     176         173 :         BAT *bn;
     177         173 :         int tpe;
     178         173 :         (void) cntxt;
     179             : 
     180         173 :         *result = NULL;
     181         173 :         tpe = getArgType(mb, pci, 1);
     182         173 :         switch (tpe) {
     183          90 :         case TYPE_bte:
     184        1724 :                 VLTmaterialize(bte);
     185          75 :                 break;
     186          21 :         case TYPE_sht:
     187       66011 :                 VLTmaterialize(sht);
     188          18 :                 break;
     189          29 :         case TYPE_int:
     190   118836489 :                 VLTmaterialize(int);
     191          26 :                 break;
     192           8 :         case TYPE_lng:
     193          34 :                 VLTmaterialize(lng);
     194           4 :                 break;
     195             : #ifdef HAVE_HGE
     196           0 :         case TYPE_hge:
     197           0 :                 VLTmaterialize(hge);
     198           0 :                 break;
     199             : #endif
     200           2 :         case TYPE_flt:
     201          17 :                 VLTmaterialize_flt(flt);
     202           2 :                 break;
     203           5 :         case TYPE_dbl:
     204          42 :                 VLTmaterialize_flt(dbl);
     205           5 :                 break;
     206          18 :         default:
     207          18 :                 if (tpe == TYPE_timestamp) {
     208          18 :                         timestamp *v,f,l;
     209          18 :                         lng s;
     210          18 :                         ValRecord ret;
     211          18 :                         if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
     212          18 :                                        &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
     213           0 :                                 throw(MAL, "generator.table",
     214             :                                       SQLSTATE(42000) "Illegal generator expression range");
     215          18 :                         f = *getArgReference_TYPE(stk, pci, 1, timestamp);
     216          18 :                         l = *getArgReference_TYPE(stk, pci, 2, timestamp);
     217          18 :                         if ( pci->argc == 3)
     218           0 :                                         throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     219          18 :                         s = *getArgReference_lng(stk, pci, 3);
     220          18 :                         if (s == 0 ||
     221          18 :                             (s > 0 && ret.val.btval > 0) ||
     222          10 :                             (s < 0 && ret.val.btval < 0) ||
     223          18 :                                 is_timestamp_nil(f) || is_timestamp_nil(l))
     224           0 :                                 throw(MAL, "generator.table",
     225             :                                       SQLSTATE(42000) "Illegal generator range");
     226             :                         /* casting one value to lng causes the whole
     227             :                          * computation to be done as lng, reducing the
     228             :                          * risk of overflow */
     229          18 :                         s *= 1000; /* msec -> usec */
     230          18 :                         n = (BUN) (timestamp_diff(l, f) / s);
     231          18 :                         bn = COLnew(0, TYPE_timestamp, n + 1, TRANSIENT);
     232          18 :                         if (bn == NULL)
     233           0 :                                 throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     234          18 :                         v = (timestamp *) Tloc(bn, 0);
     235         161 :                         for (c = 0; c < n; c++) {
     236         143 :                                 *v++ = f;
     237         143 :                                 f = timestamp_add_usec(f, s);
     238         143 :                                 if (is_timestamp_nil(f)) {
     239           0 :                                         BBPreclaim(bn);
     240           0 :                                         throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
     241             :                                 }
     242             :                         }
     243          18 :                         if (f != l) {
     244           9 :                                 *v++ = f;
     245           9 :                                 n++;
     246             :                         }
     247          18 :                         bn->tsorted = s > 0 || n <= 1;
     248          18 :                         bn->trevsorted = s < 0 || n <= 1;
     249             :                 } else {
     250           0 :                         throw(MAL, "generator.table", SQLSTATE(42000) "Unsupported type");
     251             :                 }
     252          18 :                 break;
     253             :         }
     254         148 :         BATsetcount(bn, c);
     255         148 :         bn->tkey = true;
     256         148 :         bn->tnil = false;
     257         148 :         bn->tnonil = true;
     258         148 :         *result = bn;
     259         148 :         return MAL_SUCCEED;
     260             : }
     261             : 
     262             : str
     263         177 : VLTgenerator_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     264             : {
     265         177 :         str msg;
     266         177 :         BAT *bn = NULL;
     267             : 
     268         177 :         if ((msg = VLTgenerator_noop(cntxt, mb, stk, pci)) != MAL_SUCCEED)
     269             :                 return msg;
     270             : 
     271         173 :         msg =  VLTgenerator_table_(&bn, cntxt, mb, stk, pci);
     272         173 :         if( msg == MAL_SUCCEED){
     273         148 :                 *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     274         148 :                 BBPkeepref(bn);
     275             :         }
     276             :         return msg;
     277             : }
     278             : 
     279             : /*
     280             :  * Selection over the generator table does not require a materialization of the table
     281             :  * An optimizer can replace the subselect directly into a generator specific one.
     282             :  * The target to look for is generator.series(A1,A2,A3)
     283             :  * We need the generator parameters, which are injected to replace the target column
     284             :  */
     285             : static InstrPtr
     286         158 : findGeneratorDefinition(MalBlkPtr mb, InstrPtr pci, int target)
     287             : {
     288         158 :         InstrPtr q, p = NULL;
     289         158 :         int i;
     290             : 
     291        2349 :         for (i = 1; i < mb->stop; i++) {
     292        2350 :                 q = getInstrPtr(mb, i);
     293        2350 :                 if (q->argv[0] == target && getModuleId(q) == generatorRef && (getFunctionId(q) == parametersRef || getFunctionId(q) == seriesRef))
     294        2350 :                         p = q;
     295        2350 :                 if (q == pci)
     296         159 :                         return p;
     297             :         }
     298             :         return p;
     299             : }
     300             : 
     301             : #define calculate_range(TPE, TPE2)                                                                              \
     302             :         do {                                                                                                                            \
     303             :                 TPE f, l, s, low, hgh;                                                                                  \
     304             :                                                                                                                                                 \
     305             :                 f = * getArgReference_##TPE(stk, p, 1);                                                 \
     306             :                 l = * getArgReference_##TPE(stk, p, 2);                                                 \
     307             :                 if ( p->argc == 3)                                                                                           \
     308             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     309             :                 else s = * getArgReference_##TPE(stk, p, 3);                                    \
     310             :                 if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) { \
     311             :                         BBPreclaim(cand);                                                                                       \
     312             :                         throw(MAL, "generator.select",                                                                \
     313             :                               SQLSTATE(42000) "Illegal generator range");                     \
     314             :                 }                                                                                                                               \
     315             :                 n = (BUN) (((TPE2) l - (TPE2) f) / (TPE2) s);                                   \
     316             :                 if ((TPE)(n * s + f) != l)                                                                              \
     317             :                         n++;                                                                                                            \
     318             :                                                                                                                                                 \
     319             :                 low = * getArgReference_##TPE(stk, pci, i);                                             \
     320             :                 hgh = * getArgReference_##TPE(stk, pci, i + 1);                                 \
     321             :                                                                                                                                                 \
     322             :                 if (!is_##TPE##_nil(low) && low == hgh)                                                 \
     323             :                         hi = li;                                                                                                        \
     324             :                 if (is_##TPE##_nil(low) && is_##TPE##_nil(hgh)) {                               \
     325             :                         if (li && hi && !anti) {                                                                        \
     326             :                                 /* match NILs (of which there aren't */                                 \
     327             :                                 /* any) */                                                                                              \
     328             :                                 o1 = o2 = 0;                                                                                    \
     329             :                         } else {                                                                                                        \
     330             :                                 /* match all non-NIL values, */                                                 \
     331             :                                 /* i.e. everything */                                                                   \
     332             :                                 o1 = 0;                                                                                                 \
     333             :                                 o2 = (oid) n;                                                                                   \
     334             :                         }                                                                                                                       \
     335             :                 } else if (s > 0) {                                                                                          \
     336             :                         if (is_##TPE##_nil(low) || low < f)                                                  \
     337             :                                 o1 = 0;                                                                                                 \
     338             :                         else {                                                                                                          \
     339             :                                 o1 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s);                \
     340             :                                 if ((TPE) (f + o1 * s) < low ||                                                      \
     341             :                                     (!li && (TPE) (f + o1 * s) == low))                                 \
     342             :                                         o1++;                                                                                           \
     343             :                         }                                                                                                                       \
     344             :                         if (is_##TPE##_nil(hgh))                                                                        \
     345             :                                 o2 = (oid) n;                                                                                   \
     346             :                         else if (hgh < f)                                                                                    \
     347             :                                 o2 = 0;                                                                                                 \
     348             :                         else {                                                                                                          \
     349             :                                 o2 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s);                \
     350             :                                 if ((hi && (TPE) (f + o2 * s) == hgh) ||                                \
     351             :                                     (TPE) (f + o2 * s) < hgh)                                                        \
     352             :                                         o2++;                                                                                           \
     353             :                         }                                                                                                                       \
     354             :                 } else {                                                                                                                \
     355             :                         if (is_##TPE##_nil(low))                                                                        \
     356             :                                 o2 = (oid) n;                                                                                   \
     357             :                         else if (low > f)                                                                                    \
     358             :                                 o2 = 0;                                                                                                 \
     359             :                         else {                                                                                                          \
     360             :                                 o2 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s);                \
     361             :                                 if ((li && (TPE) (f + o2 * s) == low) ||                                \
     362             :                                     (TPE) (f + o2 * s) > low)                                                        \
     363             :                                         o2++;                                                                                           \
     364             :                         }                                                                                                                       \
     365             :                         if (is_##TPE##_nil(hgh) || hgh > f)                                                  \
     366             :                                 o1 = 0;                                                                                                 \
     367             :                         else {                                                                                                          \
     368             :                                 o1 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s);                \
     369             :                                 if ((!hi && (TPE) (f + o1 * s) == hgh) ||                               \
     370             :                                     (TPE) (f + o1 * s) > hgh)                                                        \
     371             :                                         o1++;                                                                                           \
     372             :                         }                                                                                                                       \
     373             :                 }                                                                                                                               \
     374             :         } while (0)
     375             : 
     376             : str
     377           0 : VLTgenerator_subselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     378             : {
     379           0 :         bit li, hi, anti;
     380           0 :         int i;
     381           0 :         oid o1, o2;
     382           0 :         BUN n = 0;
     383           0 :         BAT *bn, *cand = NULL;
     384           0 :         struct canditer ci = (struct canditer) {.tpe = cand_dense};
     385           0 :         InstrPtr p;
     386           0 :         int tpe;
     387             : 
     388           0 :         (void) cntxt;
     389           0 :         p = findGeneratorDefinition(mb, pci, pci->argv[1]);
     390           0 :         if (p == NULL)
     391           0 :                 throw(MAL, "generator.select",
     392             :                       SQLSTATE(42000) "Could not locate definition for object");
     393             : 
     394           0 :         if (pci->argc == 8) {        /* candidate list included */
     395           0 :                 bat candid = *getArgReference_bat(stk, pci, 2);
     396           0 :                 if (candid) {
     397           0 :                         cand = BATdescriptor(candid);
     398           0 :                         if (cand == NULL)
     399           0 :                                 throw(MAL, "generator.select",
     400             :                                       SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     401           0 :                         canditer_init(&ci, NULL, cand);
     402             :                 }
     403             :                 i = 3;
     404             :         } else
     405             :                 i = 2;
     406             : 
     407           0 :         li = * getArgReference_bit(stk, pci, i + 2);
     408           0 :         hi = * getArgReference_bit(stk, pci, i + 3);
     409           0 :         anti = * getArgReference_bit(stk, pci, i + 4);
     410             : 
     411           0 :         switch ( tpe = getArgType(mb, pci, i)) {
     412           0 :         case TYPE_bte: calculate_range(bte, sht); break;
     413           0 :         case TYPE_sht: calculate_range(sht, int); break;
     414           0 :         case TYPE_int: calculate_range(int, lng); break;
     415             : #ifndef HAVE_HGE
     416             :         case TYPE_lng: calculate_range(lng, lng); break;
     417             : #else
     418           0 :         case TYPE_lng: calculate_range(lng, hge); break;
     419           0 :         case TYPE_hge: calculate_range(hge, hge); break;
     420             : #endif
     421           0 :         case TYPE_flt: calculate_range(flt, dbl); break;
     422           0 :         case TYPE_dbl: calculate_range(dbl, dbl); break;
     423           0 :         default:
     424           0 :                 if(  tpe == TYPE_timestamp){
     425           0 :                         timestamp tsf,tsl;
     426           0 :                         timestamp tlow,thgh;
     427           0 :                         lng tss;
     428           0 :                         oid *ol;
     429             : 
     430           0 :                         tsf = *getArgReference_TYPE(stk, p, 1, timestamp);
     431           0 :                         tsl = *getArgReference_TYPE(stk, p, 2, timestamp);
     432           0 :                         if ( p->argc == 3) {
     433           0 :                                 BBPreclaim(cand);
     434           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     435             :                         }
     436           0 :                         tss = *getArgReference_lng(stk, p, 3);
     437           0 :                         if ( tss == 0 ||
     438           0 :                                 is_timestamp_nil(tsf) || is_timestamp_nil(tsl) ||
     439           0 :                                  (tss > 0 && tsf > tsl ) ||
     440           0 :                                  (tss < 0 && tsf < tsl )
     441             :                                 ) {
     442           0 :                                 BBPreclaim(cand);
     443           0 :                                 throw(MAL, "generator.select",  SQLSTATE(42000) "Illegal generator range");
     444             :                         }
     445             : 
     446           0 :                         tlow = *getArgReference_TYPE(stk,pci,i, timestamp);
     447           0 :                         thgh = *getArgReference_TYPE(stk,pci,i+1, timestamp);
     448             : 
     449           0 :                         if (!is_timestamp_nil(tlow) && tlow == thgh)
     450           0 :                                 hi = li;
     451           0 :                         if( hi && !is_timestamp_nil(thgh)) {
     452           0 :                                 thgh = timestamp_add_usec(thgh, 1);
     453           0 :                                 if (is_timestamp_nil(thgh)) {
     454           0 :                                         BBPreclaim(cand);
     455           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     456             :                                 }
     457             :                         }
     458           0 :                         if( !li && !is_timestamp_nil(tlow)) {
     459           0 :                                 tlow = timestamp_add_usec(tlow, 1);
     460           0 :                                 if (is_timestamp_nil(tlow)) {
     461           0 :                                         BBPreclaim(cand);
     462           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     463             :                                 }
     464             :                         }
     465             : 
     466             :                         /* casting one value to lng causes the whole
     467             :                          * computation to be done as lng, reducing the
     468             :                          * risk of overflow */
     469           0 :                         tss *= 1000; /* msec -> usec */
     470           0 :                         o2 = (BUN) (timestamp_diff(tsl, tsf) / tss);
     471           0 :                         bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
     472           0 :                         if (bn == NULL) {
     473           0 :                                 BBPreclaim(cand);
     474           0 :                                 throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     475             :                         }
     476             : 
     477             :                         // simply enumerate the sequence and filter it by predicate and candidate list
     478           0 :                         ol = (oid *) Tloc(bn, 0);
     479           0 :                         for (o1=0; o1 <= o2; o1++) {
     480           0 :                                 if(((is_timestamp_nil(tlow) || tsf >= tlow) &&
     481           0 :                                     (is_timestamp_nil(thgh) || tsf < thgh)) != anti ){
     482             :                                         /* could be improved when no candidate list is available into a void/void BAT */
     483           0 :                                         if( cand == NULL || canditer_contains(&ci, o1)) {
     484           0 :                                                 *ol++ = o1;
     485           0 :                                                 n++;
     486             :                                         }
     487             :                                 }
     488           0 :                                 tsf = timestamp_add_usec(tsf, tss);
     489           0 :                                 if (is_timestamp_nil(tsf)) {
     490           0 :                                         BBPreclaim(cand);
     491           0 :                                         BBPreclaim(bn);
     492           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     493             :                                 }
     494             :                         }
     495           0 :                         BBPreclaim(cand);
     496           0 :                         BATsetcount(bn, n);
     497           0 :                         bn->tsorted = true;
     498           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     499           0 :                         bn->tkey = true;
     500           0 :                         bn->tnil = false;
     501           0 :                         bn->tnonil = true;
     502           0 :                         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     503           0 :                         BBPkeepref(bn);
     504           0 :                         return MAL_SUCCEED;
     505             :                 } else {
     506           0 :                         BBPreclaim(cand);
     507           0 :                         throw(MAL, "generator.select", SQLSTATE(42000) "Unsupported type in select");
     508             :                 }
     509             :         }
     510           0 :         if (o1 > (oid) n)
     511             :                 o1 = (oid) n;
     512           0 :         if (o2 > (oid) n)
     513             :                 o2 = (oid) n;
     514           0 :         assert(o1 <= o2);
     515           0 :         assert(o2 - o1 <= (oid) n);
     516           0 :         if (anti && o1 == o2) {
     517           0 :                 o1 = 0;
     518           0 :                 o2 = (oid) n;
     519           0 :                 anti = 0;
     520             :         }
     521           0 :         if (cand) {
     522           0 :                 if (anti) {
     523           0 :                         bn = canditer_slice2val(&ci, oid_nil, o1, o2, oid_nil);
     524             :                 } else {
     525           0 :                         bn = canditer_sliceval(&ci, o1, o2);
     526             :                 }
     527           0 :                 BBPunfix(cand->batCacheid);
     528           0 :                 if (bn == NULL)
     529           0 :                         throw(MAL, "generator.select",
     530             :                               SQLSTATE(HY013) MAL_MALLOC_FAIL);
     531             :         } else {
     532           0 :                 if (anti) {
     533           0 :                         oid o;
     534           0 :                         oid *op;
     535             : 
     536           0 :                         bn = COLnew(0, TYPE_oid, n - (o2 - o1), TRANSIENT);
     537           0 :                         if (bn == NULL)
     538           0 :                                 throw(MAL, "generator.select",
     539             :                                       SQLSTATE(HY013) MAL_MALLOC_FAIL);
     540           0 :                         BATsetcount(bn, n - (o2 - o1));
     541           0 :                         op = (oid *) Tloc(bn, 0);
     542           0 :                         for (o = 0; o < o1; o++)
     543           0 :                                 *op++ = o;
     544           0 :                         for (o = o2; o < (oid) n; o++)
     545           0 :                                 *op++ = o;
     546           0 :                         bn->tnil = false;
     547           0 :                         bn->tnonil = true;
     548           0 :                         bn->tsorted = true;
     549           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     550           0 :                         bn->tkey = true;
     551             :                 } else {
     552           0 :                         bn = BATdense(0, o1, (BUN) (o2 - o1));
     553           0 :                         if (bn == NULL)
     554           0 :                                 throw(MAL, "generator.select",
     555             :                                       SQLSTATE(HY013) MAL_MALLOC_FAIL);
     556             :                 }
     557             :         }
     558           0 :         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     559           0 :         BBPkeepref(bn);
     560           0 :         return MAL_SUCCEED;
     561             : }
     562             : 
     563             : #define PREVVALUEbte(x) ((x) - 1)
     564             : #define PREVVALUEsht(x) ((x) - 1)
     565             : #define PREVVALUEint(x) ((x) - 1)
     566             : #define PREVVALUElng(x) ((x) - 1)
     567             : #ifdef HAVE_HGE
     568             : #define PREVVALUEhge(x) ((x) - 1)
     569             : #endif
     570             : #define PREVVALUEoid(x) ((x) - 1)
     571             : #define PREVVALUEflt(x) nextafterf((x), -GDK_flt_max)
     572             : #define PREVVALUEdbl(x) nextafter((x), -GDK_dbl_max)
     573             : 
     574             : #define NEXTVALUEbte(x) ((x) + 1)
     575             : #define NEXTVALUEsht(x) ((x) + 1)
     576             : #define NEXTVALUEint(x) ((x) + 1)
     577             : #define NEXTVALUElng(x) ((x) + 1)
     578             : #ifdef HAVE_HGE
     579             : #define NEXTVALUEhge(x) ((x) + 1)
     580             : #endif
     581             : #define NEXTVALUEoid(x) ((x) + 1)
     582             : #define NEXTVALUEflt(x) nextafterf((x), GDK_flt_max)
     583             : #define NEXTVALUEdbl(x) nextafter((x), GDK_dbl_max)
     584             : 
     585             : #define HGE_ABS(a) (((a) < 0) ? -(a) : (a))
     586             : 
     587             : #define VLTthetasubselect(TPE,ABS)                                                                              \
     588             :         do {                                                                                                                            \
     589             :                 TPE f,l,s, low, hgh;                                                                                    \
     590             :                 BUN j; oid *v;                                                                                                  \
     591             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
     592             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
     593             :                 if ( p->argc == 3)                                                                                           \
     594             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     595             :                 else s =  *getArgReference_##TPE(stk,p, 3);                                             \
     596             :                 if( s == 0 || (f<l && s < 0) || (f>l && s> 0))      {                               \
     597             :                         BBPreclaim(cand);                                                                                       \
     598             :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal range"); \
     599             :                 }                                                                                                                               \
     600             :                 cap = (BUN)(ABS(l-f)/ABS(s));                                                                   \
     601             :                 bn = COLnew(0, TYPE_oid, cap, TRANSIENT);                                               \
     602             :                 if( bn == NULL) {                                                                                               \
     603             :                         BBPreclaim(cand);                                                                                       \
     604             :                         throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     605             :                 }                                                                                                                               \
     606             :                 low= hgh = TPE##_nil;                                                                                   \
     607             :                 v = (oid*) Tloc(bn,0);                                                                                  \
     608             :                 if ( strcmp(oper,"<") == 0){                                                                       \
     609             :                         hgh= *getArgReference_##TPE(stk,pci,3);                                         \
     610             :                         hgh = PREVVALUE##TPE(hgh);                                                                      \
     611             :                 } else if ( strcmp(oper,"<=") == 0){                                                       \
     612             :                         hgh= *getArgReference_##TPE(stk,pci,3);                                         \
     613             :                 } else if ( strcmp(oper,">") == 0){                                                                \
     614             :                         low= *getArgReference_##TPE(stk,pci,3);                                         \
     615             :                         low = NEXTVALUE##TPE(low);                                                                      \
     616             :                 } else if ( strcmp(oper,">=") == 0){                                                       \
     617             :                         low= *getArgReference_##TPE(stk,pci,3);                                         \
     618             :                 } else if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){ \
     619             :                         hgh= low= *getArgReference_##TPE(stk,pci,3);                            \
     620             :                         anti = 1;                                                                                                       \
     621             :                 } else if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){      \
     622             :                         hgh= low= *getArgReference_##TPE(stk,pci,3);                            \
     623             :                 } else {                                                                                                                \
     624             :                         BBPreclaim(cand);                                                                                       \
     625             :                         BBPreclaim(bn);                                                                                         \
     626             :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");     \
     627             :                 }                                                                                                                               \
     628             :                 for(j=0;j<cap;j++, f+=s, o++)                                                                        \
     629             :                         if( ((is_##TPE##_nil(low) || f >= low) && (is_##TPE##_nil(hgh) || f <= hgh)) != anti){ \
     630             :                                 if(cand == NULL || canditer_contains(&ci, o)) {                     \
     631             :                                         *v++ = o;                                                                                       \
     632             :                                         c++;                                                                                            \
     633             :                                 }                                                                                                               \
     634             :                         }                                                                                                                       \
     635             :         } while (0)
     636             : 
     637             : 
     638          27 : str VLTgenerator_thetasubselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     639             : {
     640          27 :         int anti =0,tpe;
     641          27 :         bat cndid =0;
     642          27 :         BAT *cand = 0, *bn = NULL;
     643          27 :         struct canditer ci = (struct canditer) {.tpe = cand_dense};
     644          27 :         BUN cap,j, c = 0;
     645          27 :         oid o = 0;
     646          27 :         InstrPtr p;
     647          27 :         str oper;
     648             : 
     649          27 :         (void) cntxt;
     650          27 :         p = findGeneratorDefinition(mb,pci,pci->argv[1]);
     651          27 :         if( p == NULL)
     652           0 :                 throw(MAL,"generator.thetaselect",SQLSTATE(42000) "Could not locate definition for object");
     653             : 
     654          27 :         assert(pci->argc == 5); // candidate list included
     655          27 :         cndid = *getArgReference_bat(stk,pci, 2);
     656          27 :         if( !is_bat_nil(cndid)){
     657           2 :                 cand = BATdescriptor(cndid);
     658           2 :                 if( cand == NULL)
     659           0 :                         throw(MAL,"generator.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     660           2 :                 canditer_init(&ci, NULL, cand);
     661             :         }
     662          27 :         oper= *getArgReference_str(stk,pci,4);
     663             : 
     664             :         // check the step direction
     665             : 
     666          27 :         switch( tpe =getArgType(mb,pci,3)){
     667         119 :         case TYPE_bte: VLTthetasubselect(bte,abs);break;
     668           0 :         case TYPE_sht: VLTthetasubselect(sht,abs);break;
     669           0 :         case TYPE_int: VLTthetasubselect(int,abs);break;
     670          16 :         case TYPE_lng: VLTthetasubselect(lng,llabs);break;
     671             : #ifdef HAVE_HGE
     672           0 :         case TYPE_hge: VLTthetasubselect(hge,HGE_ABS);break;
     673             : #endif
     674           8 :         case TYPE_flt: VLTthetasubselect(flt,fabsf);break;
     675          25 :         case TYPE_dbl: VLTthetasubselect(dbl,fabs);break;
     676             :         break;
     677           9 :         default:
     678           9 :                 if ( tpe == TYPE_timestamp){
     679           9 :                         timestamp f,l, val, low, hgh;
     680           9 :                         lng  s;
     681           9 :                         oid *v;
     682             : 
     683           9 :                         f = *getArgReference_TYPE(stk,p, 1, timestamp);
     684           9 :                         l = *getArgReference_TYPE(stk,p, 2, timestamp);
     685           9 :                         if ( p->argc == 3) {
     686           0 :                                 BBPreclaim(cand);
     687           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     688             :                         }
     689           9 :                         s = *getArgReference_lng(stk,p, 3);
     690           9 :                         if ( s == 0 ||
     691           9 :                                  (s > 0 && f > l) ||
     692           9 :                                  (s < 0 && f < l)
     693             :                                 ) {
     694           0 :                                 BBPreclaim(cand);
     695           0 :                                 throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
     696             :                         }
     697             : 
     698           9 :                         hgh = low = timestamp_nil;
     699           9 :                         if ( strcmp(oper,"<") == 0){
     700           5 :                                 hgh= *getArgReference_TYPE(stk,pci,3, timestamp);
     701           5 :                                 hgh = timestamp_add_usec(hgh, -1);
     702           5 :                                 if (is_timestamp_nil(hgh)) {
     703           0 :                                         BBPreclaim(cand);
     704           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     705             :                                 }
     706             :                         } else
     707           4 :                         if ( strcmp(oper,"<=") == 0){
     708           0 :                                 hgh= *getArgReference_TYPE(stk,pci,3, timestamp) ;
     709             :                         } else
     710           4 :                         if ( strcmp(oper,">") == 0){
     711           3 :                                 low= *getArgReference_TYPE(stk,pci,3, timestamp);
     712           3 :                                 low = timestamp_add_usec(low, 1);
     713           3 :                                 if (is_timestamp_nil(low)) {
     714           0 :                                         BBPreclaim(cand);
     715           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     716             :                                 }
     717             :                         } else
     718           1 :                         if ( strcmp(oper,">=") == 0){
     719           0 :                                 low= *getArgReference_TYPE(stk,pci,3, timestamp);
     720             :                         } else
     721           1 :                         if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
     722           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
     723           0 :                                 anti = 1;
     724             :                         } else
     725           1 :                         if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
     726           1 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
     727             :                         } else {
     728           0 :                                 BBPreclaim(cand);
     729           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
     730             :                         }
     731             : 
     732           9 :                         s *= 1000; /* msec -> usec */
     733           9 :                         cap = (BUN) (timestamp_diff(l, f) / s);
     734           9 :                         bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
     735           9 :                         if( bn == NULL) {
     736           0 :                                 BBPreclaim(cand);
     737           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     738             :                         }
     739           9 :                         v = (oid*) Tloc(bn,0);
     740             : 
     741           9 :                         val = f;
     742          85 :                         for(j = 0; j< cap; j++,  o++){
     743         148 :                                 if (((is_timestamp_nil(low) || val >= low) &&
     744          50 :                                      (is_timestamp_nil(hgh) || val <= hgh)) != anti){
     745          34 :                                         if(cand == NULL || canditer_contains(&ci, o)){
     746          31 :                                                 *v++ = o;
     747          31 :                                                 c++;
     748             :                                         }
     749             :                                 }
     750          76 :                                 val = timestamp_add_usec(val, s);
     751          76 :                                 if (is_timestamp_nil(val)) {
     752           0 :                                         BBPreclaim(cand);
     753           0 :                                         BBPreclaim(bn);
     754           0 :                                         throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
     755             :                                 }
     756             :                         }
     757             :                 } else {
     758           0 :                         BBPreclaim(cand);
     759           0 :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal generator arguments");
     760             :                 }
     761             :         }
     762             : 
     763          27 :         if( cndid)
     764          27 :                 BBPunfix(cndid);
     765          27 :         BATsetcount(bn,c);
     766          27 :         bn->tsorted = true;
     767          27 :         bn->trevsorted = false;
     768          27 :         bn->tkey = true;
     769          27 :         bn->tnil = false;
     770          27 :         bn->tnonil = true;
     771          27 :         *getArgReference_bat(stk,pci,0) = bn->batCacheid;
     772          27 :         BBPkeepref(bn);
     773          27 :         return MAL_SUCCEED;
     774             : }
     775             : 
     776             : #define VLTprojection(TPE)                                                                                              \
     777             :         do {                                                                                                                            \
     778             :                 TPE f,l,s, val;                                                                                                 \
     779             :                 TPE *v;                                                                                                                 \
     780             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
     781             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
     782             :                 if ( p->argc == 3)                                                                                           \
     783             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     784             :                 else                                                                                                                    \
     785             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
     786             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
     787             :                         BBPunfix(b->batCacheid);                                                                     \
     788             :                         throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range"); \
     789             :                 }                                                                                                                               \
     790             :                 bn = COLnew(0, TYPE_##TPE, cnt, TRANSIENT);                                             \
     791             :                 if( bn == NULL){                                                                                                \
     792             :                         BBPunfix(b->batCacheid);                                                                     \
     793             :                         throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);   \
     794             :                 }                                                                                                                               \
     795             :                 v = (TPE*) Tloc(bn,0);                                                                                  \
     796             :                 for(; cnt-- > 0; o++){                                                                                       \
     797             :                         val = f + ((TPE) (ol == NULL  ? o : ol[o])) * s;                        \
     798             :                         if ( (s > 0 &&  (val < f || val >= l)) || (s < 0 && (val <= l || val > f))) \
     799             :                                 continue;                                                                                               \
     800             :                         *v++ = val;                                                                                                     \
     801             :                         c++;                                                                                                            \
     802             :                 }                                                                                                                               \
     803             :         } while (0)
     804             : 
     805         132 : str VLTgenerator_projection(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     806             : {
     807         132 :         int tpe;
     808         132 :         bat *ret;
     809         132 :         BAT *b, *bn = NULL;
     810         132 :         BUN cnt, c = 0;
     811         132 :         oid *ol = NULL, o= 0;
     812         132 :         InstrPtr p;
     813             : 
     814         132 :         (void) cntxt;
     815         132 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
     816             : 
     817         132 :         ret = getArgReference_bat(stk,pci,0);
     818         132 :         b = BATdescriptor(*getArgReference_bat(stk,pci,1));
     819         132 :         if( b == NULL)
     820           0 :                 throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     821             : 
     822             :         // if it does not exist we should fall back to the ordinary projection to try
     823             :         // it might have been materialized already
     824         132 :         if( p == NULL){
     825           0 :                 bn = BATdescriptor( *getArgReference_bat(stk,pci,2));
     826           0 :                 if( bn == NULL) {
     827           0 :                         BBPunfix(b->batCacheid);
     828           0 :                         throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     829             :                 }
     830           0 :                 BAT *bp = BATproject(b, bn);
     831           0 :                 BBPunfix(b->batCacheid);
     832           0 :                 BBPunfix(bn->batCacheid);
     833           0 :                 if (bp == NULL)
     834           0 :                         throw(MAL, "generator.projection", GDK_EXCEPTION);
     835           0 :                 *ret = bp->batCacheid;
     836           0 :                 BBPkeepref(bp);
     837           0 :                 return MAL_SUCCEED;
     838             :         }
     839             : 
     840         132 :         cnt = BATcount(b);
     841         132 :         if ( b->ttype == TYPE_void)
     842          52 :                 o = b->tseqbase;
     843             :         else
     844          80 :                 ol = (oid*) Tloc(b,0);
     845             : 
     846             :         /* the actual code to perform a projection over generators */
     847         132 :         switch( tpe = getArgType(mb,p,1)){
     848         433 :         case TYPE_bte:  VLTprojection(bte); break;
     849      999008 :         case TYPE_sht:  VLTprojection(sht); break;
     850     1049784 :         case TYPE_int:  VLTprojection(int); break;
     851          14 :         case TYPE_lng:  VLTprojection(lng); break;
     852             : #ifdef HAVE_HGE
     853           0 :         case TYPE_hge:  VLTprojection(hge); break;
     854             : #endif
     855           7 :         case TYPE_flt:  VLTprojection(flt); break;
     856          17 :         case TYPE_dbl:  VLTprojection(dbl); break;
     857          35 :         default:
     858          35 :                 if ( tpe == TYPE_timestamp){
     859          34 :                         timestamp f,l, val;
     860          34 :                         lng s,t;
     861          34 :                         timestamp *v;
     862          34 :                         f = *getArgReference_TYPE(stk,p, 1, timestamp);
     863          33 :                         l = *getArgReference_TYPE(stk,p, 2, timestamp);
     864          34 :                         if ( p->argc == 3) {
     865           0 :                                 BBPunfix(b->batCacheid);
     866           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     867             :                         }
     868          34 :                         s =  *getArgReference_lng(stk,p, 3);
     869          34 :                         if ( s == 0 ||
     870          34 :                              (s< 0 && f < l) ||
     871          34 :                              (s> 0 && l < f) ) {
     872           0 :                                 BBPunfix(b->batCacheid);
     873           0 :                                 throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
     874             :                         }
     875             : 
     876          35 :                         s *= 1000; /* msec -> usec */
     877          35 :                         bn = COLnew(0, TYPE_timestamp, cnt, TRANSIENT);
     878          35 :                         if( bn == NULL){
     879           0 :                                 BBPunfix(b->batCacheid);
     880           0 :                                 throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     881             :                         }
     882             : 
     883          35 :                         v = (timestamp*) Tloc(bn,0);
     884             : 
     885          88 :                         for(; cnt-- > 0; o++){
     886          53 :                                 t = ((lng) (ol == NULL ? o : ol[o])) * s;
     887          53 :                                 val = timestamp_add_usec(f, t);
     888          53 :                                 if (is_timestamp_nil(val)) {
     889           0 :                                         BBPunfix(b->batCacheid);
     890           0 :                                         BBPreclaim(bn);
     891           0 :                                         throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
     892             :                                 }
     893             : 
     894          53 :                                 if ( is_timestamp_nil(val))
     895             :                                         continue;
     896          53 :                                 if (s > 0 && (val < f || val >= l) )
     897           0 :                                         continue;
     898          53 :                                 if (s < 0 && (val <= l || val > f) )
     899           0 :                                         continue;
     900          53 :                                 *v++ = val;
     901          53 :                                 c++;
     902             :                         }
     903             :                 }
     904             :         }
     905             : 
     906             :         /* adminstrative wrapup of the projection */
     907         133 :         BBPunfix(b->batCacheid);
     908         131 :         if( bn){
     909         131 :                 BATsetcount(bn,c);
     910         131 :                 bn->tsorted = bn->trevsorted = false;
     911         131 :                 bn->tkey = false;
     912         131 :                 bn->tnil = false;
     913         131 :                 bn->tnonil = false;
     914         131 :                 *getArgReference_bat(stk,pci,0) = bn->batCacheid;
     915         131 :                 BBPkeepref(bn);
     916             :         }
     917             :         return MAL_SUCCEED;
     918             : }
     919             : 
     920             : /* The operands of a join operation can either be defined on a generator */
     921             : #define VLTjoin(TPE, ABS)                                                                                               \
     922             :         do {                                                                                                                            \
     923             :                 TPE f,l,s; TPE *v; BUN w;                                                                               \
     924             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
     925             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
     926             :                 if ( p->argc == 3)                                                                                           \
     927             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     928             :                 else                                                                                                                    \
     929             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
     930             :                 incr = s > 0;                                                                                                        \
     931             :                 v = (TPE*) Tloc(b,0);                                                                                   \
     932             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
     933             :                         BBPunfix(bln->batCacheid);                                                                   \
     934             :                         BBPunfix(brn->batCacheid);                                                                   \
     935             :                         BBPreclaim(bl);                                                                                         \
     936             :                         BBPreclaim(br);                                                                                         \
     937             :                         throw(MAL,"generator.join", SQLSTATE(42000) "Illegal range"); \
     938             :                 }                                                                                                                               \
     939             :                 for( ; cnt >0; cnt--,o++,v++){                                                                       \
     940             :                         w = (BUN) (ABS(*v -f)/ABS(s));                                                          \
     941             :                         if ( f + (TPE)(w * s) == *v ){                                                          \
     942             :                                 *ol++ = (oid) w;                                                                                \
     943             :                                 *or++ = o;                                                                                              \
     944             :                                 c++;                                                                                                    \
     945             :                         }                                                                                                                       \
     946             :                 }                                                                                                                               \
     947             :         } while (0)
     948             : 
     949           0 : str VLTgenerator_join(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     950             : {
     951           0 :         BAT  *b, *bl = NULL, *br = NULL, *bln = NULL, *brn= NULL;
     952           0 :         BUN cnt,c =0;
     953           0 :         oid o= 0, *ol, *or;
     954           0 :         int tpe, incr=0, materialized = 0;
     955           0 :         InstrPtr p = NULL, q = NULL;
     956           0 :         str msg = MAL_SUCCEED;
     957             : 
     958           0 :         (void) cntxt;
     959             :         // we assume at most one of the arguments to refer to the generator
     960           0 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
     961           0 :         q = findGeneratorDefinition(mb,pci,pci->argv[3]);
     962             : 
     963           0 :         if (p == NULL && q == NULL) {
     964           0 :                 bl = BATdescriptor(*getArgReference_bat(stk, pci, 2));
     965           0 :                 br = BATdescriptor(*getArgReference_bat(stk, pci, 3));
     966           0 :                 if (bl == NULL || br == NULL) {
     967           0 :                         BBPreclaim(bl);
     968           0 :                         BBPreclaim(br);
     969           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     970             :                 }
     971           0 :                 gdk_return rc = BATjoin(&bln, &brn, bl, br, NULL, NULL, false, BUN_NONE);
     972           0 :                 BBPunfix(bl->batCacheid);
     973           0 :                 BBPunfix(br->batCacheid);
     974           0 :                 if (rc != GDK_SUCCEED)
     975           0 :                         throw(MAL,"generator.join", GDK_EXCEPTION);
     976           0 :                 *getArgReference_bat(stk, pci, 0) = bln->batCacheid;
     977           0 :                 *getArgReference_bat(stk, pci, 1) = brn->batCacheid;
     978           0 :                 BBPkeepref(bln);
     979           0 :                 BBPkeepref(brn);
     980           0 :                 return MAL_SUCCEED;
     981             :         }
     982             : 
     983           0 :         if( p == NULL){
     984           0 :                 bl = BATdescriptor(*getArgReference_bat(stk,pci,2));
     985           0 :                 if( bl == NULL)
     986           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     987             :         }
     988           0 :         if ( q == NULL){
     989             :                 /* p != NULL, hence bl == NULL */
     990           0 :                 br = BATdescriptor(*getArgReference_bat(stk,pci,3));
     991           0 :                 if( br == NULL)
     992           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     993             :         }
     994             : 
     995             :         // in case of both generators  || getModuleId(q) == generatorRef)materialize the 'smallest' one first
     996             :         // or implement more knowledge, postponed
     997           0 :         if (p && q ){
     998           0 :                 msg =  VLTgenerator_table_(&bl, cntxt, mb, stk, p);
     999           0 :                 if( msg || bl == NULL )
    1000           0 :                         throw(MAL,"generator.join",SQLSTATE(42000) "Join over generator pairs not supported");
    1001             :                 else
    1002             :                         p = NULL;
    1003             :                 materialized =1;
    1004             :         }
    1005             : 
    1006             :         // switch roles to have a single target bat[:oid,:any] designated
    1007             :         // by b and reference instruction p for the generator
    1008           0 :         b = q? bl : br;
    1009           0 :         p = q? q : p;
    1010           0 :         cnt = BATcount(b);
    1011           0 :         tpe = b->ttype;
    1012           0 :         o= b->hseqbase;
    1013             : 
    1014           0 :         bln = COLnew(0,TYPE_oid, cnt, TRANSIENT);
    1015           0 :         brn = COLnew(0,TYPE_oid, cnt, TRANSIENT);
    1016           0 :         if( bln == NULL || brn == NULL){
    1017           0 :                 BBPreclaim(bln);
    1018           0 :                 BBPreclaim(brn);
    1019           0 :                 BBPreclaim(bl);
    1020           0 :                 BBPreclaim(br);
    1021           0 :                 throw(MAL,"generator.join", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1022             :         }
    1023           0 :         ol = (oid*) Tloc(bln,0);
    1024           0 :         or = (oid*) Tloc(brn,0);
    1025             : 
    1026             :         /* The actual join code for generators be injected here */
    1027           0 :         switch(tpe){
    1028           0 :         case TYPE_bte: VLTjoin(bte,abs); break;
    1029           0 :         case TYPE_sht: VLTjoin(sht,abs); break;
    1030           0 :         case TYPE_int: VLTjoin(int,abs); break;
    1031           0 :         case TYPE_lng: VLTjoin(lng,llabs); break;
    1032             : #ifdef HAVE_HGE
    1033           0 :         case TYPE_hge: VLTjoin(hge,HGE_ABS); break;
    1034             : #endif
    1035           0 :         case TYPE_flt: VLTjoin(flt,fabsf); break;
    1036           0 :         case TYPE_dbl: VLTjoin(dbl,fabs); break;
    1037             :         default:
    1038           0 :                 if( tpe == TYPE_timestamp){
    1039             :                         // it is easier to produce the timestamp series
    1040             :                         // then to estimate the possible index
    1041           0 :                         }
    1042           0 :                 BBPunfix(bln->batCacheid);
    1043           0 :                 BBPunfix(brn->batCacheid);
    1044           0 :                 BBPreclaim(bl);
    1045           0 :                 BBPreclaim(br);
    1046           0 :                 throw(MAL,"generator.join", SQLSTATE(42000) "Illegal type");
    1047             :         }
    1048             : 
    1049           0 :         BATsetcount(bln,c);
    1050           0 :         bln->tsorted = bln->trevsorted = false;
    1051           0 :         bln->tkey = false;
    1052           0 :         bln->tnil = false;
    1053           0 :         bln->tnonil = false;
    1054           0 :         bln->tsorted = incr || c <= 1;
    1055           0 :         bln->trevsorted = !incr || c <= 1;
    1056             : 
    1057           0 :         BATsetcount(brn,c);
    1058           0 :         brn->tsorted = brn->trevsorted = false;
    1059           0 :         brn->tkey = false;
    1060           0 :         brn->tnil = false;
    1061           0 :         brn->tnonil = false;
    1062           0 :         brn->tsorted = incr || c <= 1;
    1063           0 :         brn->trevsorted = !incr || c <= 1;
    1064           0 :         if( q){
    1065           0 :                 *getArgReference_bat(stk,pci,0) = brn->batCacheid;
    1066           0 :                 BBPkeepref(brn);
    1067           0 :                 *getArgReference_bat(stk,pci,1) = bln->batCacheid;
    1068           0 :                 BBPkeepref(bln);
    1069             :         } else {
    1070           0 :                 *getArgReference_bat(stk,pci,0) = bln->batCacheid;
    1071           0 :                 BBPkeepref(bln);
    1072           0 :                 *getArgReference_bat(stk,pci,1) = brn->batCacheid;
    1073           0 :                 BBPkeepref(brn);
    1074             :         }
    1075           0 :         if ( materialized){
    1076           0 :                 BBPreclaim(bl);
    1077           0 :                 bl = 0;
    1078             :         }
    1079           0 :         BBPreclaim(bl);
    1080           0 :         BBPreclaim(br);
    1081             :         return msg;
    1082             : }
    1083             : 
    1084             : #define VLTrangeExpand()                                                                                                \
    1085             :         do {                                                                                                                            \
    1086             :                 limit+= cnt * (limit/(done?done:1)+1);                                                  \
    1087             :                 if (BATextend(bln, limit) != GDK_SUCCEED) {                                             \
    1088             :                         BBPunfix(blow->batCacheid);                                                                  \
    1089             :                         BBPunfix(bhgh->batCacheid);                                                                  \
    1090             :                         BBPunfix(bln->batCacheid);                                                                   \
    1091             :                         BBPunfix(brn->batCacheid);                                                                   \
    1092             :                         throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1093             :                 }                                                                                                                               \
    1094             :                 if (BATextend(brn, limit) != GDK_SUCCEED) {                                             \
    1095             :                         BBPunfix(blow->batCacheid);                                                                  \
    1096             :                         BBPunfix(bhgh->batCacheid);                                                                  \
    1097             :                         BBPunfix(bln->batCacheid);                                                                   \
    1098             :                         BBPunfix(brn->batCacheid);                                                                   \
    1099             :                         throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1100             :                 }                                                                                                                               \
    1101             :                 ol = (oid*) Tloc(bln,0) + c;                                                                    \
    1102             :                 or = (oid*) Tloc(brn,0) + c;                                                                    \
    1103             :         } while (0)
    1104             : 
    1105             : /* The operands of a join operation can either be defined on a generator */
    1106             : #define VLTrangejoin(TPE, ABS, FLOOR)                                                                   \
    1107             :         do {                                                                                                                            \
    1108             :                 TPE f,f1,l,s; TPE *vlow,*vhgh; BUN w;                                                   \
    1109             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
    1110             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
    1111             :                 if ( p->argc == 3)                                                                                           \
    1112             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
    1113             :                 else                                                                                                                    \
    1114             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
    1115             :                 incr = s > 0;                                                                                                        \
    1116             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
    1117             :                         BBPreclaim(bln);                                                                                        \
    1118             :                         BBPreclaim(brn);                                                                                        \
    1119             :                         BBPreclaim(blow);                                                                                       \
    1120             :                         BBPreclaim(bhgh);                                                                                       \
    1121             :                         throw(MAL,"generator.rangejoin", SQLSTATE(42000) "Illegal range"); \
    1122             :                 }                                                                                                                               \
    1123             :                 vlow = (TPE*) Tloc(blow,0);                                                                             \
    1124             :                 vhgh = (TPE*) Tloc(bhgh,0);                                                                             \
    1125             :                 for( ; cnt >0; cnt--, done++, o++,vlow++,vhgh++){                            \
    1126             :                         f1 = f + FLOOR(ABS(*vlow-f)/ABS(s)) * s;                                        \
    1127             :                         if ( f1 < *vlow )                                                                                    \
    1128             :                                 f1+= s;                                                                                                 \
    1129             :                         w = (BUN) FLOOR(ABS(f1-f)/ABS(s));                                                      \
    1130             :                         for( ; (f1 > *vlow || (li && f1 == *vlow)) && (f1 < *vhgh || (ri && f1 == *vhgh)); f1 += s, w++){ \
    1131             :                                 if(c == limit)                                                                                  \
    1132             :                                         VLTrangeExpand();                                                                       \
    1133             :                                 *ol++ = (oid) w;                                                                                \
    1134             :                                 *or++ = o;                                                                                              \
    1135             :                                 c++;                                                                                                    \
    1136             :                         }                                                                                                                       \
    1137             :                 }                                                                                                                               \
    1138             :         } while (0)
    1139             : 
    1140           0 : str VLTgenerator_rangejoin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1141             : {
    1142           0 :         BAT  *blow = NULL, *bhgh = NULL, *bln = NULL, *brn= NULL;
    1143           0 :         bit li,ri;
    1144           0 :         BUN limit, cnt, done=0, c =0;
    1145           0 :         oid o= 0, *ol, *or;
    1146           0 :         int tpe, incr=0;
    1147           0 :         InstrPtr p = NULL;
    1148           0 :         str msg = MAL_SUCCEED;
    1149             : 
    1150           0 :         (void) cntxt;
    1151             :         // the left join argument should be a generator
    1152           0 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
    1153           0 :         if( p == NULL)
    1154           0 :                 throw(MAL,"generator.rangejoin",SQLSTATE(42000) "Invalid arguments");
    1155             : 
    1156           0 :         blow = BATdescriptor(*getArgReference_bat(stk,pci,3));
    1157           0 :         if( blow == NULL)
    1158           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1159             : 
    1160           0 :         bhgh = BATdescriptor(*getArgReference_bat(stk,pci,4));
    1161           0 :         if( bhgh == NULL){
    1162           0 :                 BBPunfix(blow->batCacheid);
    1163           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1164             :         }
    1165           0 :         li = *getArgReference_bit(stk,pci,5);
    1166           0 :         ri = *getArgReference_bit(stk,pci,6);
    1167             : 
    1168           0 :         cnt = BATcount(blow);
    1169           0 :         limit = 2 * cnt; //top off result before expansion
    1170           0 :         tpe = blow->ttype;
    1171           0 :         o= blow->hseqbase;
    1172             : 
    1173           0 :         bln = COLnew(0,TYPE_oid, limit, TRANSIENT);
    1174           0 :         brn = COLnew(0,TYPE_oid, limit, TRANSIENT);
    1175           0 :         if( bln == NULL || brn == NULL){
    1176           0 :                 BBPreclaim(bln);
    1177           0 :                 BBPreclaim(brn);
    1178           0 :                 BBPreclaim(blow);
    1179           0 :                 BBPreclaim(bhgh);
    1180           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1181             :         }
    1182           0 :         ol = (oid*) Tloc(bln,0);
    1183           0 :         or = (oid*) Tloc(brn,0);
    1184             : 
    1185             :         /* The actual join code for generators be injected here */
    1186           0 :         switch(tpe){
    1187           0 :         case TYPE_bte: VLTrangejoin(bte,abs,IDENTITY); break;
    1188           0 :         case TYPE_sht: VLTrangejoin(sht,abs,IDENTITY); break;
    1189           0 :         case TYPE_int: VLTrangejoin(int,abs,IDENTITY); break;
    1190           0 :         case TYPE_lng: VLTrangejoin(lng,llabs,IDENTITY); break;
    1191             : #ifdef HAVE_HGE
    1192           0 :         case TYPE_hge: VLTrangejoin(hge,HGE_ABS,IDENTITY); break;
    1193             : #endif
    1194           0 :         case TYPE_flt: VLTrangejoin(flt,fabsf,floorf); break;
    1195           0 :         case TYPE_dbl: VLTrangejoin(dbl,fabs,floor); break;
    1196             :         default:
    1197           0 :                 if( tpe == TYPE_timestamp){
    1198             :                         // it is easier to produce the timestamp series
    1199             :                         // then to estimate the possible index
    1200           0 :                         }
    1201           0 :                 BBPreclaim(bln);
    1202           0 :                 BBPreclaim(brn);
    1203           0 :                 BBPreclaim(blow);
    1204           0 :                 BBPreclaim(bhgh);
    1205           0 :                 throw(MAL,"generator.rangejoin","Illegal type");
    1206             :         }
    1207             : 
    1208           0 :         BATsetcount(bln,c);
    1209           0 :         bln->tsorted = bln->trevsorted = false;
    1210           0 :         bln->tkey = false;
    1211           0 :         bln->tnil = false;
    1212           0 :         bln->tnonil = false;
    1213           0 :         bln->tsorted = incr || c <= 1;
    1214           0 :         bln->trevsorted = !incr || c <= 1;
    1215             : 
    1216           0 :         BATsetcount(brn,c);
    1217           0 :         brn->tsorted = brn->trevsorted = false;
    1218           0 :         brn->tkey = false;
    1219           0 :         brn->tnil = false;
    1220           0 :         brn->tnonil = false;
    1221           0 :         brn->tsorted = incr || c <= 1;
    1222           0 :         brn->trevsorted = !incr || c <= 1;
    1223           0 :         *getArgReference_bat(stk,pci,0) = bln->batCacheid;
    1224           0 :         BBPkeepref(bln);
    1225           0 :         *getArgReference_bat(stk,pci,1) = brn->batCacheid;
    1226           0 :         BBPkeepref(brn);
    1227           0 :         BBPreclaim(blow);
    1228           0 :         BBPreclaim(bhgh);
    1229           0 :         return msg;
    1230             : }
    1231             : 
    1232             : #include "mel.h"
    1233             : static mel_func generator_init_funcs[] = {
    1234             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
    1235             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
    1236             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
    1237             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
    1238             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
    1239             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
    1240             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
    1241             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
    1242             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
    1243             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
    1244             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
    1245             :  pattern("generator", "series", VLTgenerator_table, false, "Create and materialize a generator table", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
    1246             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
    1247             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
    1248             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
    1249             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
    1250             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
    1251             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
    1252             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
    1253             :  pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
    1254             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
    1255             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
    1256             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
    1257             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
    1258             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
    1259             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
    1260             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",bte),batarg("cnd",oid),arg("low",bte),arg("oper",str))),
    1261             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",sht),batarg("cnd",oid),arg("low",sht),arg("oper",str))),
    1262             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",int),batarg("cnd",oid),arg("low",int),arg("oper",str))),
    1263             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",lng),batarg("cnd",oid),arg("low",lng),arg("oper",str))),
    1264             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",flt),batarg("cnd",oid),arg("low",flt),arg("oper",str))),
    1265             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",dbl),batarg("cnd",oid),arg("low",dbl),arg("oper",str))),
    1266             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",timestamp),batarg("cnd",oid),arg("low",timestamp),arg("oper",str))),
    1267             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",bte),arg("low",bte),arg("high",bte),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1268             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",sht),arg("low",sht),arg("high",sht),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1269             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",int),arg("low",int),arg("high",int),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1270             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",lng),arg("low",lng),arg("high",lng),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1271             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",flt),arg("low",flt),arg("high",flt),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1272             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",dbl),arg("low",dbl),arg("high",dbl),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1273             :  pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,7, batarg("",oid),batarg("b",timestamp),arg("low",timestamp),arg("high",timestamp),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1274             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",bte),batarg("cand",oid),arg("low",bte),arg("high",bte),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1275             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",sht),batarg("cand",oid),arg("low",sht),arg("high",sht),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1276             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",int),batarg("cand",oid),arg("low",int),arg("high",int),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1277             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",lng),batarg("cand",oid),arg("low",lng),arg("high",lng),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1278             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",flt),batarg("cand",oid),arg("low",flt),arg("high",flt),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1279             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",dbl),batarg("cand",oid),arg("low",dbl),arg("high",dbl),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1280             :  pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,8, batarg("",oid),batarg("b",timestamp),batarg("cand",oid),arg("low",timestamp),arg("high",timestamp),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1281             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",bte),batarg("b",oid),batarg("cand",bte))),
    1282             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",sht),batarg("b",oid),batarg("cand",sht))),
    1283             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",int),batarg("b",oid),batarg("cand",int))),
    1284             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",lng),batarg("b",oid),batarg("cand",lng))),
    1285             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",flt),batarg("b",oid),batarg("cand",flt))),
    1286             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",dbl),batarg("b",oid),batarg("cand",dbl))),
    1287             :  pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",timestamp),batarg("b",oid),batarg("cand",timestamp))),
    1288             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",bte),batarg("gen",bte))),
    1289             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",sht),batarg("gen",sht))),
    1290             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",int),batarg("gen",int))),
    1291             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",lng),batarg("gen",lng))),
    1292             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",flt),batarg("gen",flt))),
    1293             :  pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",dbl),batarg("gen",dbl))),
    1294             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",bte),batarg("low",bte),batarg("hgh",bte),arg("li",bit),arg("ri",bit))),
    1295             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",sht),batarg("low",sht),batarg("hgh",sht),arg("li",bit),arg("ri",bit))),
    1296             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",int),batarg("low",int),batarg("hgh",int),arg("li",bit),arg("ri",bit))),
    1297             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",lng),batarg("low",lng),batarg("hgh",lng),arg("li",bit),arg("ri",bit))),
    1298             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",flt),batarg("low",flt),batarg("hgh",flt),arg("li",bit),arg("ri",bit))),
    1299             :  pattern("generator", "join", VLTgenerator_rangejoin, false, "Overloaded range join operation", args(2,7, batarg("l",oid),batarg("r",oid),batarg("gen",dbl),batarg("low",dbl),batarg("hgh",dbl),arg("li",bit),arg("ri",bit))),
    1300             : #ifdef HAVE_HGE
    1301             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
    1302             :  pattern("generator", "series", VLTgenerator_table, false, "Create and materialize a generator table", args(1,4, batarg("",hge),arg("first",hge),arg("limit",hge),arg("step",hge))),
    1303             :  pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize", args(1,4, batarg("",hge),arg("first",hge),arg("limit",hge),arg("step",hge))),
    1304             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
    1305             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",hge),batarg("cnd",oid),arg("low",hge),arg("oper",str))),
    1306             :  pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,7, batarg("",oid),batarg("b",hge),arg("low",hge),arg("high",hge),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1307             :  pattern("generator", "select", VLTgenerator_subselect, false, "Overloaded selection routine", args(1,8, batarg("",oid),batarg("b",hge),batarg("cand",oid),arg("low",hge),arg("high",hge),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1308             :  pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",hge),batarg("b",oid),batarg("cand",hge))),
    1309             :  pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",hge),batarg("gen",hge))),
    1310             : #endif
    1311             :  { .imp=NULL }
    1312             : };
    1313             : #include "mal_import.h"
    1314             : #ifdef _MSC_VER
    1315             : #undef read
    1316             : #pragma section(".CRT$XCU",read)
    1317             : #endif
    1318         329 : LIB_STARTUP_FUNC(init_generator_mal)
    1319         329 : { mal_module("generator", NULL, generator_init_funcs); }

Generated by: LCOV version 1.14