LCOV - code coverage report
Current view: top level - sql/backends/monet5/generator - generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 235 593 39.6 %
Date: 2024-04-25 20:03:45 Functions: 7 10 70.0 %

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

Generated by: LCOV version 1.14