LCOV - code coverage report
Current view: top level - sql/backends/monet5/generator - generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 193 528 36.6 %
Date: 2021-09-14 22:17:06 Functions: 7 10 70.0 %

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

Generated by: LCOV version 1.14