LCOV - code coverage report
Current view: top level - sql/backends/monet5/generator - generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 393 954 41.2 %
Date: 2024-10-03 20:03:20 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, date 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         254 : VLTgenerator_noop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      39             : {
      40         254 :         int nullerr= 0, zeroerror=0, tpe;
      41         254 :         (void) cntxt;
      42             : 
      43         254 :         switch( tpe = getArgType(mb,pci,1)){
      44         117 :         case TYPE_bte: VLTnoop(bte); break;
      45          26 :         case TYPE_sht: VLTnoop(sht); break;
      46          36 :         case TYPE_int: VLTnoop(int); break;
      47          17 :         case TYPE_lng: VLTnoop(lng); break;
      48             : #ifdef HAVE_HGE
      49           9 :         case TYPE_hge: VLTnoop(hge); break;
      50             : #endif
      51           6 :         case TYPE_flt: VLTnoop(flt); break;
      52          10 :         case TYPE_dbl: VLTnoop(dbl); break;
      53          33 :         default:
      54          33 :                 if (tpe == TYPE_date) {
      55             :                         /* with date, step is of SQL type "interval month or day",
      56             :                          * i.e., MAL / C type "int" or "lng" */
      57           4 :                         int steptpe = pci->argc==4 ? getArgType(mb,pci,3) : 0;
      58           4 :                         if (steptpe == TYPE_int)
      59           2 :                                 VLTnoop(int);
      60             :                         else /* default interval days */
      61           2 :                                 VLTnoop(lng);
      62          29 :                 } else if (tpe == TYPE_timestamp) {
      63             :                         /* with timestamp, step is of SQL type "interval seconds",
      64             :                          * i.e., MAL / C type "lng" */
      65          29 :                          VLTnoop(lng);
      66             :                 } else {
      67           0 :                         throw(MAL,"generator.noop", SQLSTATE(42000) "unknown data type %d", getArgType(mb,pci,1));
      68             :                 }
      69             :         }
      70         254 :         if( zeroerror)
      71           2 :                 throw(MAL,"generator.noop", SQLSTATE(42000) "Zero step size not allowed");
      72         252 :         if( nullerr)
      73           2 :                 throw(MAL,"generator.noop", SQLSTATE(42000) "Null step size not allowed");
      74             :         return MAL_SUCCEED;
      75             : }
      76             : 
      77             : #define check_bte() ((void)0)
      78             : #define check_sht() ((void)0)
      79             : #if SIZEOF_BUN < SIZEOF_LNG
      80             : #define check_int()                                                                                             \
      81             :         do {                                                                                                            \
      82             :                 if (cnt > (unsigned int) BUN_MAX)                                            \
      83             :                         throw(MAL, "generator.table",                                         \
      84             :                                   SQLSTATE(42000) "Illegal generator range"); \
      85             :         } while (0)
      86             : #else
      87             : #define check_int() ((void)0)
      88             : #endif
      89             : #define check_lng()                                                                                             \
      90             :         do {                                                                                                            \
      91             :                 if (cnt > (ulng) BUN_MAX)                                                            \
      92             :                         throw(MAL, "generator.table",                                         \
      93             :                                   SQLSTATE(42000) "Illegal generator range"); \
      94             :         } while (0)
      95             : #ifdef HAVE_HGE
      96             : #define check_hge()                                                                                             \
      97             :         do {                                                                                                            \
      98             :                 if (cnt > (uhge) BUN_MAX)                                                            \
      99             :                         throw(MAL, "generator.table",                                         \
     100             :                                   SQLSTATE(42000) "Illegal generator range"); \
     101             :         } while (0)
     102             : #endif
     103             : 
     104             : #define VLTmaterialize(TPE, uTPE)                                                                               \
     105             :         do {                                                                                                                            \
     106             :                 TPE f, l, s;                                                                                                    \
     107             :                 uTPE cnt;                                                                                                               \
     108             :                                                                                                                                                 \
     109             :                 f = *getArgReference_##TPE(stk, pci, 1);                                                \
     110             :                 l = *getArgReference_##TPE(stk, pci, 2);                                                \
     111             :                 if ( pci->argc == 3)                                                                                 \
     112             :                         s = f <= l ? (TPE) 1 : (TPE) -1;                                                     \
     113             :                 else                                                                                                                    \
     114             :                         s =  *getArgReference_##TPE(stk,pci, 3);                                        \
     115             :                 if (s == 0 || is_##TPE##_nil(f) || is_##TPE##_nil(l) || is_##TPE##_nil(s)) \
     116             :                         throw(MAL, "generator.table",                                                         \
     117             :                               SQLSTATE(42000) "Illegal generator range");                     \
     118             :                 if (f == l) {                                                                                                   \
     119             :                         cnt = 0;                                                                                                        \
     120             :                 } else if (f < l) {                                                                                          \
     121             :                         /* cnt = l - f */                                                                                       \
     122             :                         if (s <= 0)                                                                                                  \
     123             :                                 throw(MAL, "generator.table",                                                 \
     124             :                                           SQLSTATE(42000) "Illegal generator range");         \
     125             :                         if (f >= 0 || l <= 0) {                                                                           \
     126             :                                 /* no chance of any kind of overflow */                                 \
     127             :                                 cnt = l - f;                                                                                    \
     128             :                         } else {                                                                                                        \
     129             :                                 /* f < 0 && l > 0, do calculation is unsigned type */     \
     130             :                                 cnt = (uTPE) l + (uTPE) -f;                                                             \
     131             :                         }                                                                                                                       \
     132             :                         uTPE i = cnt / (uTPE) s;                                                                        \
     133             :                         if (i * (uTPE) s != cnt)                                                                        \
     134             :                                 i++;                                                                                                    \
     135             :                         cnt = i;                                                                                                        \
     136             :                 } else {                                                                                                                \
     137             :                         /* l < f; cnt = f - l */                                                                     \
     138             :                         if (s >= 0)                                                                                                  \
     139             :                                 throw(MAL, "generator.table",                                                 \
     140             :                                           SQLSTATE(42000) "Illegal generator range");         \
     141             :                         if (l >= 0 || f <= 0) {                                                                           \
     142             :                                 /* no chance of any kind of overflow */                                 \
     143             :                                 cnt = f - l;                                                                                    \
     144             :                         } else {                                                                                                        \
     145             :                                 /* f > 0 && l < 0, do calculation is unsigned type */     \
     146             :                                 cnt = (uTPE) f + (uTPE) -l;                                                             \
     147             :                         }                                                                                                                       \
     148             :                         uTPE i = cnt / (uTPE) -s;                                                                       \
     149             :                         if (i * (uTPE) -s != cnt)                                                                       \
     150             :                                 i++;                                                                                                    \
     151             :                         cnt = i;                                                                                                        \
     152             :                 }                                                                                                                               \
     153             :                 check_##TPE();                                                                                                  \
     154             :                 n = (BUN) cnt;                                                                                                  \
     155             :                 bn = COLnew(0, TYPE_##TPE, n, TRANSIENT);                                               \
     156             :                 if (bn == NULL)                                                                                                 \
     157             :                         throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);       \
     158             :                 TPE *v = (TPE *) Tloc(bn, 0);                                                                   \
     159             :                 while (cnt > 0) {                                                                                            \
     160             :                         *v++ = f;                                                                                                       \
     161             :                         f += s;                                                                                                         \
     162             :                         cnt--;                                                                                                          \
     163             :                 }                                                                                                                               \
     164             :                 bn->tsorted = s > 0 || n <= 1;                                                                 \
     165             :                 bn->trevsorted = s < 0 || n <= 1;                                                              \
     166             :         } while (0)
     167             : 
     168             : #define VLTmaterialize_flt(TPE)                                                                                 \
     169             :         do {                                                                                                                            \
     170             :                 TPE *v, f, l, s;                                                                                                \
     171             :                 f = *getArgReference_##TPE(stk, pci, 1);                                                \
     172             :                 l = *getArgReference_##TPE(stk, pci, 2);                                                \
     173             :                 if ( pci->argc == 3)                                                                                 \
     174             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     175             :                 else s =  *getArgReference_##TPE(stk,pci, 3);                                   \
     176             :                 if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) \
     177             :                         throw(MAL, "generator.table",                                                         \
     178             :                               SQLSTATE(42000) "Illegal generator range");                     \
     179             :                 n = (BUN) ((l - f) / s);                                                                                \
     180             :                 if ((TPE) (n * s + f) != l)                                                                             \
     181             :                         n++;                                                                                                            \
     182             :                 bn = COLnew(0, TYPE_##TPE, n, TRANSIENT);                                               \
     183             :                 if (bn == NULL)                                                                                                 \
     184             :                         throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);       \
     185             :                 v = (TPE*) Tloc(bn, 0);                                                                                 \
     186             :                 for (BUN c = 0; c < n; c++)                                                                          \
     187             :                         *v++ = (TPE) (f + c * s);                                                                       \
     188             :                 bn->tsorted = s > 0 || n <= 1;                                                                 \
     189             :                 bn->trevsorted = s < 0 || n <= 1;                                                              \
     190             :         } while (0)
     191             : 
     192             : static str
     193         223 : VLTgenerator_table_(BAT **result, Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     194             : {
     195         223 :         BAT *bn;
     196         223 :         int tpe;
     197         223 :         (void) cntxt;
     198         223 :         BUN n;
     199             : 
     200         223 :         *result = NULL;
     201         223 :         tpe = getArgType(mb, pci, 1);
     202         223 :         switch (tpe) {
     203         102 :         case TYPE_bte:
     204        1848 :                 VLTmaterialize(bte, uint8_t);
     205          87 :                 break;
     206          26 :         case TYPE_sht:
     207       68020 :                 VLTmaterialize(sht, uint16_t);
     208          23 :                 break;
     209          36 :         case TYPE_int:
     210   118986496 :                 VLTmaterialize(int, unsigned);
     211          33 :                 break;
     212          15 :         case TYPE_lng:
     213          60 :                 VLTmaterialize(lng, ulng);
     214          11 :                 break;
     215             : #ifdef HAVE_HGE
     216           9 :         case TYPE_hge:
     217        1384 :                 VLTmaterialize(hge, uhge);
     218           9 :                 break;
     219             : #endif
     220           5 :         case TYPE_flt:
     221          28 :                 VLTmaterialize_flt(flt);
     222           5 :                 break;
     223           8 :         case TYPE_dbl:
     224          53 :                 VLTmaterialize_flt(dbl);
     225           8 :                 break;
     226          22 :         default:
     227          22 :                 if (tpe == TYPE_date && pci->argc == 3)
     228           0 :                         throw(MAL,"generator.table", SQLSTATE(42000) "Date step missing");
     229           2 :                 if (tpe == TYPE_date && getArgType(mb, pci, 3) == TYPE_int) { /* months */
     230           1 :                         date *v,f,l;
     231           1 :                         int s;
     232           1 :                         ValRecord ret;
     233           1 :                         if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
     234           1 :                                        &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
     235           0 :                                 throw(MAL, "generator.table",
     236             :                                       SQLSTATE(42000) "Illegal generator expression range");
     237           1 :                         f = *getArgReference_TYPE(stk, pci, 1, date);
     238           1 :                         l = *getArgReference_TYPE(stk, pci, 2, date);
     239           1 :                         s = *getArgReference_int(stk, pci, 3);
     240           1 :                         if (s == 0 ||
     241           1 :                             (s > 0 && ret.val.btval > 0) ||
     242           0 :                             (s < 0 && ret.val.btval < 0) ||
     243           1 :                                 is_date_nil(f) || is_date_nil(l))
     244           0 :                                 throw(MAL, "generator.table",
     245             :                                       SQLSTATE(42000) "Illegal generator range");
     246           1 :                         n = (BUN) (date_diff(l, f) / (s *28)); /* n maybe too large now */
     247           1 :                         bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
     248           1 :                         if (bn == NULL)
     249           0 :                                 throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     250           1 :                         v = (date *) Tloc(bn, 0);
     251           1 :                         BUN c;
     252           4 :                         for (c = 0; c < n && f < l; c++) {
     253           3 :                                 *v++ = f;
     254           3 :                                 f = date_add_month(f, s);
     255           3 :                                 if (is_date_nil(f)) {
     256           0 :                                         BBPreclaim(bn);
     257           0 :                                         throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
     258             :                                 }
     259             :                         }
     260           1 :                         n = c;
     261           1 :                         bn->tsorted = s > 0 || n <= 1;
     262           1 :                         bn->trevsorted = s < 0 || n <= 1;
     263           1 :                 } else if (tpe == TYPE_date) { /* days */
     264           1 :                         date *v,f,l;
     265           1 :                         lng s;
     266           1 :                         ValRecord ret;
     267           1 :                         if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
     268           1 :                                        &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
     269           0 :                                 throw(MAL, "generator.table",
     270             :                                       SQLSTATE(42000) "Illegal generator expression range");
     271           1 :                         f = *getArgReference_TYPE(stk, pci, 1, date);
     272           1 :                         l = *getArgReference_TYPE(stk, pci, 2, date);
     273           1 :                         s = *getArgReference_lng(stk, pci, 3);
     274           1 :                         if (s == 0 ||
     275           1 :                             (s > 0 && ret.val.btval > 0) ||
     276           0 :                             (s < 0 && ret.val.btval < 0) ||
     277           1 :                                 is_date_nil(f) || is_date_nil(l))
     278           0 :                                 throw(MAL, "generator.table",
     279             :                                       SQLSTATE(42000) "Illegal generator range");
     280           1 :                         s /= 24*60*60*1000;
     281             :                         /* check if s is really in nr of days or usecs */
     282           1 :                         n = (BUN) (date_diff(l, f) / s) + 1; /* n maybe too large now */
     283           1 :                         bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
     284           1 :                         if (bn == NULL)
     285           0 :                                 throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     286           1 :                         v = (date *) Tloc(bn, 0);
     287           1 :                         BUN c;
     288           3 :                         for (c = 0; c < n && f < l; c++) {
     289           2 :                                 *v++ = f;
     290           2 :                                 f = date_add_day(f, (int) s);
     291           2 :                                 if (is_date_nil(f)) {
     292           0 :                                         BBPreclaim(bn);
     293           0 :                                         throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
     294             :                                 }
     295             :                         }
     296           1 :                         n = c;
     297           1 :                         bn->tsorted = s > 0 || n <= 1;
     298           1 :                         bn->trevsorted = s < 0 || n <= 1;
     299          20 :                 } else if (tpe == TYPE_timestamp) {
     300          20 :                         timestamp *v,f,l;
     301          20 :                         lng s;
     302          20 :                         ValRecord ret;
     303          20 :                         if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
     304          20 :                                        &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
     305           0 :                                 throw(MAL, "generator.table",
     306             :                                       SQLSTATE(42000) "Illegal generator expression range");
     307          20 :                         f = *getArgReference_TYPE(stk, pci, 1, timestamp);
     308          20 :                         l = *getArgReference_TYPE(stk, pci, 2, timestamp);
     309          20 :                         if ( pci->argc == 3)
     310           0 :                                         throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     311          20 :                         s = *getArgReference_lng(stk, pci, 3);
     312          20 :                         if (s == 0 ||
     313          20 :                             (s > 0 && ret.val.btval > 0) ||
     314          10 :                             (s < 0 && ret.val.btval < 0) ||
     315          20 :                                 is_timestamp_nil(f) || is_timestamp_nil(l))
     316           0 :                                 throw(MAL, "generator.table",
     317             :                                       SQLSTATE(42000) "Illegal generator range");
     318             :                         /* casting one value to lng causes the whole
     319             :                          * computation to be done as lng, reducing the
     320             :                          * risk of overflow */
     321          20 :                         s *= 1000; /* msec -> usec */
     322          20 :                         n = (BUN) (timestamp_diff(l, f) / s);
     323          20 :                         bn = COLnew(0, TYPE_timestamp, n + 1, TRANSIENT);
     324          20 :                         if (bn == NULL)
     325           0 :                                 throw(MAL, "generator.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     326          20 :                         v = (timestamp *) Tloc(bn, 0);
     327         166 :                         for (BUN c = 0; c < n; c++) {
     328         146 :                                 *v++ = f;
     329         146 :                                 f = timestamp_add_usec(f, s);
     330         146 :                                 if (is_timestamp_nil(f)) {
     331           0 :                                         BBPreclaim(bn);
     332           0 :                                         throw(MAL, "generator.table", SQLSTATE(22003) "overflow in calculation");
     333             :                                 }
     334             :                         }
     335          20 :                         if (f != l) {
     336          11 :                                 *v++ = f;
     337          11 :                                 n++;
     338             :                         }
     339          20 :                         bn->tsorted = s > 0 || n <= 1;
     340          20 :                         bn->trevsorted = s < 0 || n <= 1;
     341             :                 } else {
     342           0 :                         throw(MAL, "generator.table", SQLSTATE(42000) "Unsupported type");
     343             :                 }
     344             :                 break;
     345             :         }
     346         198 :         BATsetcount(bn, n);
     347         198 :         bn->tkey = true;
     348         198 :         bn->tnil = false;
     349         198 :         bn->tnonil = true;
     350         198 :         *result = bn;
     351         198 :         return MAL_SUCCEED;
     352             : }
     353             : 
     354             : str
     355         227 : VLTgenerator_table(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     356             : {
     357         227 :         str msg;
     358         227 :         BAT *bn = NULL;
     359             : 
     360         227 :         if ((msg = VLTgenerator_noop(cntxt, mb, stk, pci)) != MAL_SUCCEED)
     361             :                 return msg;
     362             : 
     363         223 :         msg =  VLTgenerator_table_(&bn, cntxt, mb, stk, pci);
     364         223 :         if( msg == MAL_SUCCEED){
     365         198 :                 *getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     366         198 :                 BBPkeepref(bn);
     367             :         }
     368             :         return msg;
     369             : }
     370             : 
     371             : /*
     372             :  * Selection over the generator table does not require a materialization of the table
     373             :  * An optimizer can replace the subselect directly into a generator specific one.
     374             :  * The target to look for is generator.series(A1,A2,A3)
     375             :  * We need the generator parameters, which are injected to replace the target column
     376             :  */
     377             : static InstrPtr
     378         165 : findGeneratorDefinition(MalBlkPtr mb, InstrPtr pci, int target)
     379             : {
     380         165 :         InstrPtr q, p = NULL;
     381         165 :         int i;
     382             : 
     383        2393 :         for (i = 1; i < mb->stop; i++) {
     384        2393 :                 q = getInstrPtr(mb, i);
     385        2393 :                 if (q->argv[0] == target && getModuleId(q) == generatorRef && (getFunctionId(q) == parametersRef || getFunctionId(q) == seriesRef))
     386        2393 :                         p = q;
     387        2393 :                 if (q == pci)
     388         165 :                         return p;
     389             :         }
     390             :         return p;
     391             : }
     392             : 
     393             : #define calculate_range(TPE, TPE2)                                                                              \
     394             :         do {                                                                                                                            \
     395             :                 TPE f, l, s, low, hgh;                                                                                  \
     396             :                                                                                                                                                 \
     397             :                 f = * getArgReference_##TPE(stk, p, 1);                                                 \
     398             :                 l = * getArgReference_##TPE(stk, p, 2);                                                 \
     399             :                 if ( p->argc == 3)                                                                                           \
     400             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     401             :                 else s = * getArgReference_##TPE(stk, p, 3);                                    \
     402             :                 if (s == 0 || (s > 0 && f > l) || (s < 0 && f < l) || is_##TPE##_nil(f) || is_##TPE##_nil(l)) { \
     403             :                         BBPreclaim(cand);                                                                                       \
     404             :                         throw(MAL, "generator.select",                                                                \
     405             :                               SQLSTATE(42000) "Illegal generator range");                     \
     406             :                 }                                                                                                                               \
     407             :                 n = (BUN) (((TPE2) l - (TPE2) f) / (TPE2) s);                                   \
     408             :                 if ((TPE)(n * s + f) != l)                                                                              \
     409             :                         n++;                                                                                                            \
     410             :                                                                                                                                                 \
     411             :                 low = * getArgReference_##TPE(stk, pci, i);                                             \
     412             :                 hgh = * getArgReference_##TPE(stk, pci, i + 1);                                 \
     413             :                                                                                                                                                 \
     414             :                 if (!is_##TPE##_nil(low) && low == hgh)                                                 \
     415             :                         hi = li;                                                                                                        \
     416             :                 if (is_##TPE##_nil(low) && is_##TPE##_nil(hgh)) {                               \
     417             :                         if (li && hi && !anti) {                                                                        \
     418             :                                 /* match NILs (of which there aren't */                                 \
     419             :                                 /* any) */                                                                                              \
     420             :                                 o1 = o2 = 0;                                                                                    \
     421             :                         } else {                                                                                                        \
     422             :                                 /* match all non-NIL values, */                                                 \
     423             :                                 /* i.e. everything */                                                                   \
     424             :                                 o1 = 0;                                                                                                 \
     425             :                                 o2 = (oid) n;                                                                                   \
     426             :                         }                                                                                                                       \
     427             :                 } else if (s > 0) {                                                                                          \
     428             :                         if (is_##TPE##_nil(low) || low < f)                                                  \
     429             :                                 o1 = 0;                                                                                                 \
     430             :                         else {                                                                                                          \
     431             :                                 o1 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s);                \
     432             :                                 if ((TPE) (f + o1 * s) < low ||                                                      \
     433             :                                     (!li && (TPE) (f + o1 * s) == low))                                 \
     434             :                                         o1++;                                                                                           \
     435             :                         }                                                                                                                       \
     436             :                         if (is_##TPE##_nil(hgh))                                                                        \
     437             :                                 o2 = (oid) n;                                                                                   \
     438             :                         else if (hgh < f)                                                                                    \
     439             :                                 o2 = 0;                                                                                                 \
     440             :                         else {                                                                                                          \
     441             :                                 o2 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s);                \
     442             :                                 if ((hi && (TPE) (f + o2 * s) == hgh) ||                                \
     443             :                                     (TPE) (f + o2 * s) < hgh)                                                        \
     444             :                                         o2++;                                                                                           \
     445             :                         }                                                                                                                       \
     446             :                 } else {                                                                                                                \
     447             :                         if (is_##TPE##_nil(low))                                                                        \
     448             :                                 o2 = (oid) n;                                                                                   \
     449             :                         else if (low > f)                                                                                    \
     450             :                                 o2 = 0;                                                                                                 \
     451             :                         else {                                                                                                          \
     452             :                                 o2 = (oid) (((TPE2) low - (TPE2) f) / (TPE2) s);                \
     453             :                                 if ((li && (TPE) (f + o2 * s) == low) ||                                \
     454             :                                     (TPE) (f + o2 * s) > low)                                                        \
     455             :                                         o2++;                                                                                           \
     456             :                         }                                                                                                                       \
     457             :                         if (is_##TPE##_nil(hgh) || hgh > f)                                                  \
     458             :                                 o1 = 0;                                                                                                 \
     459             :                         else {                                                                                                          \
     460             :                                 o1 = (oid) (((TPE2) hgh - (TPE2) f) / (TPE2) s);                \
     461             :                                 if ((!hi && (TPE) (f + o1 * s) == hgh) ||                               \
     462             :                                     (TPE) (f + o1 * s) > hgh)                                                        \
     463             :                                         o1++;                                                                                           \
     464             :                         }                                                                                                                       \
     465             :                 }                                                                                                                               \
     466             :         } while (0)
     467             : 
     468             : str
     469           0 : VLTgenerator_subselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     470             : {
     471           0 :         bit li, hi, anti;
     472           0 :         int i;
     473           0 :         oid o1, o2;
     474           0 :         BUN n = 0;
     475           0 :         BAT *bn, *cand = NULL;
     476           0 :         struct canditer ci = (struct canditer) {.tpe = cand_dense};
     477           0 :         InstrPtr p;
     478           0 :         int tpe;
     479             : 
     480           0 :         (void) cntxt;
     481           0 :         p = findGeneratorDefinition(mb, pci, pci->argv[1]);
     482           0 :         if (p == NULL)
     483           0 :                 throw(MAL, "generator.select",
     484             :                       SQLSTATE(42000) "Could not locate definition for object");
     485             : 
     486           0 :         if (pci->argc == 8) {        /* candidate list included */
     487           0 :                 bat candid = *getArgReference_bat(stk, pci, 2);
     488           0 :                 if (candid) {
     489           0 :                         cand = BATdescriptor(candid);
     490           0 :                         if (cand == NULL)
     491           0 :                                 throw(MAL, "generator.select",
     492             :                                       SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     493           0 :                         canditer_init(&ci, NULL, cand);
     494             :                 }
     495             :                 i = 3;
     496             :         } else
     497             :                 i = 2;
     498             : 
     499           0 :         li = * getArgReference_bit(stk, pci, i + 2);
     500           0 :         hi = * getArgReference_bit(stk, pci, i + 3);
     501           0 :         anti = * getArgReference_bit(stk, pci, i + 4);
     502             : 
     503           0 :         switch ( tpe = getArgType(mb, pci, i)) {
     504           0 :         case TYPE_bte: calculate_range(bte, sht); break;
     505           0 :         case TYPE_sht: calculate_range(sht, int); break;
     506           0 :         case TYPE_int: calculate_range(int, lng); break;
     507             : #ifndef HAVE_HGE
     508             :         case TYPE_lng: calculate_range(lng, lng); break;
     509             : #else
     510           0 :         case TYPE_lng: calculate_range(lng, hge); break;
     511           0 :         case TYPE_hge: calculate_range(hge, hge); break;
     512             : #endif
     513           0 :         case TYPE_flt: calculate_range(flt, dbl); break;
     514           0 :         case TYPE_dbl: calculate_range(dbl, dbl); break;
     515           0 :         default:
     516           0 :                 if (p->argc == 3) {
     517           0 :                         BBPreclaim(cand);
     518           0 :                         throw(MAL,"generator.table", SQLSTATE(42000) "Date step missing");
     519             :                 }
     520           0 :                 if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
     521           0 :                         date tsf,tsl;
     522           0 :                         date tlow,thgh;
     523           0 :                         int tss;
     524           0 :                         oid *ol;
     525             : 
     526           0 :                         tsf = *getArgReference_TYPE(stk, p, 1, date);
     527           0 :                         tsl = *getArgReference_TYPE(stk, p, 2, date);
     528           0 :                         tss = *getArgReference_int(stk, p, 3);
     529           0 :                         if ( tss == 0 ||
     530           0 :                                 is_date_nil(tsf) || is_date_nil(tsl) ||
     531           0 :                                  (tss > 0 && tsf > tsl ) ||
     532           0 :                                  (tss < 0 && tsf < tsl )
     533             :                                 ) {
     534           0 :                                 BBPreclaim(cand);
     535           0 :                                 throw(MAL, "generator.select",  SQLSTATE(42000) "Illegal generator range");
     536             :                         }
     537             : 
     538           0 :                         tlow = *getArgReference_TYPE(stk,pci,i, date);
     539           0 :                         thgh = *getArgReference_TYPE(stk,pci,i+1, date);
     540             : 
     541           0 :                         if (!is_date_nil(tlow) && tlow == thgh)
     542           0 :                                 hi = li;
     543           0 :                         if( hi && !is_date_nil(thgh)) {
     544           0 :                                 thgh = date_add_month(thgh, 1);
     545           0 :                                 if (is_date_nil(thgh)) {
     546           0 :                                         BBPreclaim(cand);
     547           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     548             :                                 }
     549             :                         }
     550           0 :                         if( !li && !is_date_nil(tlow)) {
     551           0 :                                 tlow = date_add_month(tlow, 1);
     552           0 :                                 if (is_date_nil(tlow)) {
     553           0 :                                         BBPreclaim(cand);
     554           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     555             :                                 }
     556             :                         }
     557             : 
     558           0 :                         o2 = (BUN) (date_diff(tsl, tsf) / (tss*28));
     559           0 :                         bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
     560           0 :                         if (bn == NULL) {
     561           0 :                                 BBPreclaim(cand);
     562           0 :                                 throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     563             :                         }
     564             : 
     565             :                         // simply enumerate the sequence and filter it by predicate and candidate list
     566           0 :                         ol = (oid *) Tloc(bn, 0);
     567           0 :                         for (o1=0; o1 <= o2; o1++) {
     568           0 :                                 if(((is_date_nil(tlow) || tsf >= tlow) &&
     569           0 :                                     (is_date_nil(thgh) || tsf < thgh)) != anti ){
     570             :                                         /* could be improved when no candidate list is available into a void/void BAT */
     571           0 :                                         if( cand == NULL || canditer_contains(&ci, o1)) {
     572           0 :                                                 *ol++ = o1;
     573           0 :                                                 n++;
     574             :                                         }
     575             :                                 }
     576           0 :                                 tsf = date_add_month(tsf, tss);
     577           0 :                                 if (is_date_nil(tsf)) {
     578           0 :                                         BBPreclaim(cand);
     579           0 :                                         BBPreclaim(bn);
     580           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     581             :                                 }
     582             :                         }
     583           0 :                         BBPreclaim(cand);
     584           0 :                         BATsetcount(bn, n);
     585           0 :                         bn->tsorted = true;
     586           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     587           0 :                         bn->tkey = true;
     588           0 :                         bn->tnil = false;
     589           0 :                         bn->tnonil = true;
     590           0 :                         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     591           0 :                         BBPkeepref(bn);
     592           0 :                         return MAL_SUCCEED;
     593           0 :                 } else if (tpe == TYPE_date) { /* days */
     594           0 :                         date tsf,tsl;
     595           0 :                         date tlow,thgh;
     596           0 :                         lng tss;
     597           0 :                         oid *ol;
     598             : 
     599           0 :                         tsf = *getArgReference_TYPE(stk, p, 1, date);
     600           0 :                         tsl = *getArgReference_TYPE(stk, p, 2, date);
     601           0 :                         tss = *getArgReference_lng(stk, p, 3);
     602           0 :                         if ( tss == 0 ||
     603           0 :                                 is_date_nil(tsf) || is_date_nil(tsl) ||
     604           0 :                                  (tss > 0 && tsf > tsl ) ||
     605           0 :                                  (tss < 0 && tsf < tsl )
     606             :                                 ) {
     607           0 :                                 BBPreclaim(cand);
     608           0 :                                 throw(MAL, "generator.select",  SQLSTATE(42000) "Illegal generator range");
     609             :                         }
     610           0 :                         tss /= 24*60*60*1000;
     611             : 
     612           0 :                         tlow = *getArgReference_TYPE(stk,pci,i, date);
     613           0 :                         thgh = *getArgReference_TYPE(stk,pci,i+1, date);
     614             : 
     615           0 :                         if (!is_date_nil(tlow) && tlow == thgh)
     616           0 :                                 hi = li;
     617           0 :                         if( hi && !is_date_nil(thgh)) {
     618           0 :                                 thgh = date_add_month(thgh, 1);
     619           0 :                                 if (is_date_nil(thgh)) {
     620           0 :                                         BBPreclaim(cand);
     621           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     622             :                                 }
     623             :                         }
     624           0 :                         if( !li && !is_date_nil(tlow)) {
     625           0 :                                 tlow = date_add_month(tlow, 1);
     626           0 :                                 if (is_date_nil(tlow)) {
     627           0 :                                         BBPreclaim(cand);
     628           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     629             :                                 }
     630             :                         }
     631             : 
     632           0 :                         o2 = (BUN) (date_diff(tsl, tsf) / tss) + 1;
     633           0 :                         bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
     634           0 :                         if (bn == NULL) {
     635           0 :                                 BBPreclaim(cand);
     636           0 :                                 throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     637             :                         }
     638             : 
     639             :                         // simply enumerate the sequence and filter it by predicate and candidate list
     640           0 :                         ol = (oid *) Tloc(bn, 0);
     641           0 :                         for (o1=0; o1 <= o2; o1++) {
     642           0 :                                 if(((is_date_nil(tlow) || tsf >= tlow) &&
     643           0 :                                     (is_date_nil(thgh) || tsf < thgh)) != anti ){
     644             :                                         /* could be improved when no candidate list is available into a void/void BAT */
     645           0 :                                         if( cand == NULL || canditer_contains(&ci, o1)) {
     646           0 :                                                 *ol++ = o1;
     647           0 :                                                 n++;
     648             :                                         }
     649             :                                 }
     650           0 :                                 tsf = date_add_day(tsf, (int) tss);
     651           0 :                                 if (is_date_nil(tsf)) {
     652           0 :                                         BBPreclaim(cand);
     653           0 :                                         BBPreclaim(bn);
     654           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     655             :                                 }
     656             :                         }
     657           0 :                         BBPreclaim(cand);
     658           0 :                         BATsetcount(bn, n);
     659           0 :                         bn->tsorted = true;
     660           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     661           0 :                         bn->tkey = true;
     662           0 :                         bn->tnil = false;
     663           0 :                         bn->tnonil = true;
     664           0 :                         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     665           0 :                         BBPkeepref(bn);
     666           0 :                         return MAL_SUCCEED;
     667           0 :                 } else if (tpe == TYPE_timestamp) {
     668           0 :                         timestamp tsf,tsl;
     669           0 :                         timestamp tlow,thgh;
     670           0 :                         lng tss;
     671           0 :                         oid *ol;
     672             : 
     673           0 :                         tsf = *getArgReference_TYPE(stk, p, 1, timestamp);
     674           0 :                         tsl = *getArgReference_TYPE(stk, p, 2, timestamp);
     675           0 :                         if (p->argc == 3) {
     676           0 :                                 BBPreclaim(cand);
     677           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     678             :                         }
     679           0 :                         tss = *getArgReference_lng(stk, p, 3);
     680           0 :                         if ( tss == 0 ||
     681           0 :                                 is_timestamp_nil(tsf) || is_timestamp_nil(tsl) ||
     682           0 :                                  (tss > 0 && tsf > tsl ) ||
     683           0 :                                  (tss < 0 && tsf < tsl )
     684             :                                 ) {
     685           0 :                                 BBPreclaim(cand);
     686           0 :                                 throw(MAL, "generator.select",  SQLSTATE(42000) "Illegal generator range");
     687             :                         }
     688             : 
     689           0 :                         tlow = *getArgReference_TYPE(stk,pci,i, timestamp);
     690           0 :                         thgh = *getArgReference_TYPE(stk,pci,i+1, timestamp);
     691             : 
     692           0 :                         if (!is_timestamp_nil(tlow) && tlow == thgh)
     693           0 :                                 hi = li;
     694           0 :                         if( hi && !is_timestamp_nil(thgh)) {
     695           0 :                                 thgh = timestamp_add_usec(thgh, 1);
     696           0 :                                 if (is_timestamp_nil(thgh)) {
     697           0 :                                         BBPreclaim(cand);
     698           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     699             :                                 }
     700             :                         }
     701           0 :                         if( !li && !is_timestamp_nil(tlow)) {
     702           0 :                                 tlow = timestamp_add_usec(tlow, 1);
     703           0 :                                 if (is_timestamp_nil(tlow)) {
     704           0 :                                         BBPreclaim(cand);
     705           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     706             :                                 }
     707             :                         }
     708             : 
     709             :                         /* casting one value to lng causes the whole
     710             :                          * computation to be done as lng, reducing the
     711             :                          * risk of overflow */
     712           0 :                         tss *= 1000; /* msec -> usec */
     713           0 :                         o2 = (BUN) (timestamp_diff(tsl, tsf) / tss);
     714           0 :                         bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
     715           0 :                         if (bn == NULL) {
     716           0 :                                 BBPreclaim(cand);
     717           0 :                                 throw(MAL, "generator.select", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     718             :                         }
     719             : 
     720             :                         // simply enumerate the sequence and filter it by predicate and candidate list
     721           0 :                         ol = (oid *) Tloc(bn, 0);
     722           0 :                         for (o1=0; o1 <= o2; o1++) {
     723           0 :                                 if(((is_timestamp_nil(tlow) || tsf >= tlow) &&
     724           0 :                                     (is_timestamp_nil(thgh) || tsf < thgh)) != anti ){
     725             :                                         /* could be improved when no candidate list is available into a void/void BAT */
     726           0 :                                         if( cand == NULL || canditer_contains(&ci, o1)) {
     727           0 :                                                 *ol++ = o1;
     728           0 :                                                 n++;
     729             :                                         }
     730             :                                 }
     731           0 :                                 tsf = timestamp_add_usec(tsf, tss);
     732           0 :                                 if (is_timestamp_nil(tsf)) {
     733           0 :                                         BBPreclaim(cand);
     734           0 :                                         BBPreclaim(bn);
     735           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     736             :                                 }
     737             :                         }
     738           0 :                         BBPreclaim(cand);
     739           0 :                         BATsetcount(bn, n);
     740           0 :                         bn->tsorted = true;
     741           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     742           0 :                         bn->tkey = true;
     743           0 :                         bn->tnil = false;
     744           0 :                         bn->tnonil = true;
     745           0 :                         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     746           0 :                         BBPkeepref(bn);
     747           0 :                         return MAL_SUCCEED;
     748             :                 } else {
     749           0 :                         BBPreclaim(cand);
     750           0 :                         throw(MAL, "generator.select", SQLSTATE(42000) "Unsupported type in select");
     751             :                 }
     752             :         }
     753           0 :         if (o1 > (oid) n)
     754             :                 o1 = (oid) n;
     755           0 :         if (o2 > (oid) n)
     756             :                 o2 = (oid) n;
     757           0 :         assert(o1 <= o2);
     758           0 :         assert(o2 - o1 <= (oid) n);
     759           0 :         if (anti && o1 == o2) {
     760           0 :                 o1 = 0;
     761           0 :                 o2 = (oid) n;
     762           0 :                 anti = 0;
     763             :         }
     764           0 :         if (cand) {
     765           0 :                 if (anti) {
     766           0 :                         bn = canditer_slice2val(&ci, oid_nil, o1, o2, oid_nil);
     767             :                 } else {
     768           0 :                         bn = canditer_sliceval(&ci, o1, o2);
     769             :                 }
     770           0 :                 BBPunfix(cand->batCacheid);
     771           0 :                 if (bn == NULL)
     772           0 :                         throw(MAL, "generator.select",
     773             :                               SQLSTATE(HY013) MAL_MALLOC_FAIL);
     774             :         } else {
     775           0 :                 if (anti) {
     776           0 :                         oid o;
     777           0 :                         oid *op;
     778             : 
     779           0 :                         bn = COLnew(0, TYPE_oid, n - (o2 - o1), TRANSIENT);
     780           0 :                         if (bn == NULL)
     781           0 :                                 throw(MAL, "generator.select",
     782             :                                       SQLSTATE(HY013) MAL_MALLOC_FAIL);
     783           0 :                         BATsetcount(bn, n - (o2 - o1));
     784           0 :                         op = (oid *) Tloc(bn, 0);
     785           0 :                         for (o = 0; o < o1; o++)
     786           0 :                                 *op++ = o;
     787           0 :                         for (o = o2; o < (oid) n; o++)
     788           0 :                                 *op++ = o;
     789           0 :                         bn->tnil = false;
     790           0 :                         bn->tnonil = true;
     791           0 :                         bn->tsorted = true;
     792           0 :                         bn->trevsorted = BATcount(bn) <= 1;
     793           0 :                         bn->tkey = true;
     794             :                 } else {
     795           0 :                         bn = BATdense(0, o1, (BUN) (o2 - o1));
     796           0 :                         if (bn == NULL)
     797           0 :                                 throw(MAL, "generator.select",
     798             :                                       SQLSTATE(HY013) MAL_MALLOC_FAIL);
     799             :                 }
     800             :         }
     801           0 :         * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
     802           0 :         BBPkeepref(bn);
     803           0 :         return MAL_SUCCEED;
     804             : }
     805             : 
     806             : #define PREVVALUEbte(x) ((x) - 1)
     807             : #define PREVVALUEsht(x) ((x) - 1)
     808             : #define PREVVALUEint(x) ((x) - 1)
     809             : #define PREVVALUElng(x) ((x) - 1)
     810             : #ifdef HAVE_HGE
     811             : #define PREVVALUEhge(x) ((x) - 1)
     812             : #endif
     813             : #define PREVVALUEoid(x) ((x) - 1)
     814             : #define PREVVALUEflt(x) nextafterf((x), -GDK_flt_max)
     815             : #define PREVVALUEdbl(x) nextafter((x), -GDK_dbl_max)
     816             : 
     817             : #define NEXTVALUEbte(x) ((x) + 1)
     818             : #define NEXTVALUEsht(x) ((x) + 1)
     819             : #define NEXTVALUEint(x) ((x) + 1)
     820             : #define NEXTVALUElng(x) ((x) + 1)
     821             : #ifdef HAVE_HGE
     822             : #define NEXTVALUEhge(x) ((x) + 1)
     823             : #endif
     824             : #define NEXTVALUEoid(x) ((x) + 1)
     825             : #define NEXTVALUEflt(x) nextafterf((x), GDK_flt_max)
     826             : #define NEXTVALUEdbl(x) nextafter((x), GDK_dbl_max)
     827             : 
     828             : #define HGE_ABS(a) (((a) < 0) ? -(a) : (a))
     829             : 
     830             : #define VLTthetasubselect(TPE,ABS)                                                                              \
     831             :         do {                                                                                                                            \
     832             :                 TPE f,l,s, low, hgh;                                                                                    \
     833             :                 BUN j; oid *v;                                                                                                  \
     834             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
     835             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
     836             :                 if ( p->argc == 3)                                                                                           \
     837             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
     838             :                 else s =  *getArgReference_##TPE(stk,p, 3);                                             \
     839             :                 if( s == 0 || (f<l && s < 0) || (f>l && s> 0))      {                               \
     840             :                         BBPreclaim(cand);                                                                                       \
     841             :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal range"); \
     842             :                 }                                                                                                                               \
     843             :                 cap = (BUN)(ABS(l-f)/ABS(s));                                                                   \
     844             :                 bn = COLnew(0, TYPE_oid, cap, TRANSIENT);                                               \
     845             :                 if( bn == NULL) {                                                                                               \
     846             :                         BBPreclaim(cand);                                                                                       \
     847             :                         throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     848             :                 }                                                                                                                               \
     849             :                 low= hgh = TPE##_nil;                                                                                   \
     850             :                 v = (oid*) Tloc(bn,0);                                                                                  \
     851             :                 if ( strcmp(oper,"<") == 0){                                                                       \
     852             :                         hgh= *getArgReference_##TPE(stk,pci,3);                                         \
     853             :                         hgh = PREVVALUE##TPE(hgh);                                                                      \
     854             :                 } else if ( strcmp(oper,"<=") == 0){                                                       \
     855             :                         hgh= *getArgReference_##TPE(stk,pci,3);                                         \
     856             :                 } else if ( strcmp(oper,">") == 0){                                                                \
     857             :                         low= *getArgReference_##TPE(stk,pci,3);                                         \
     858             :                         low = NEXTVALUE##TPE(low);                                                                      \
     859             :                 } else if ( strcmp(oper,">=") == 0){                                                       \
     860             :                         low= *getArgReference_##TPE(stk,pci,3);                                         \
     861             :                 } else if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){ \
     862             :                         hgh= low= *getArgReference_##TPE(stk,pci,3);                            \
     863             :                         anti = 1;                                                                                                       \
     864             :                 } else if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){      \
     865             :                         hgh= low= *getArgReference_##TPE(stk,pci,3);                            \
     866             :                 } else {                                                                                                                \
     867             :                         BBPreclaim(cand);                                                                                       \
     868             :                         BBPreclaim(bn);                                                                                         \
     869             :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");     \
     870             :                 }                                                                                                                               \
     871             :                 for(j=0;j<cap;j++, f+=s, o++)                                                                        \
     872             :                         if( ((is_##TPE##_nil(low) || f >= low) && (is_##TPE##_nil(hgh) || f <= hgh)) != anti){ \
     873             :                                 if(cand == NULL || canditer_contains(&ci, o)) {                     \
     874             :                                         *v++ = o;                                                                                       \
     875             :                                         c++;                                                                                            \
     876             :                                 }                                                                                                               \
     877             :                         }                                                                                                                       \
     878             :         } while (0)
     879             : 
     880             : 
     881          29 : str VLTgenerator_thetasubselect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     882             : {
     883          29 :         int anti =0,tpe;
     884          29 :         bat cndid =0;
     885          29 :         BAT *cand = 0, *bn = NULL;
     886          29 :         struct canditer ci = (struct canditer) {.tpe = cand_dense};
     887          29 :         BUN cap,j, c = 0;
     888          29 :         oid o = 0;
     889          29 :         InstrPtr p;
     890          29 :         str oper;
     891             : 
     892          29 :         (void) cntxt;
     893          29 :         p = findGeneratorDefinition(mb,pci,pci->argv[1]);
     894          29 :         if( p == NULL)
     895           0 :                 throw(MAL,"generator.thetaselect",SQLSTATE(42000) "Could not locate definition for object");
     896             : 
     897          29 :         assert(pci->argc == 5); // candidate list included
     898          29 :         cndid = *getArgReference_bat(stk,pci, 2);
     899          29 :         if( !is_bat_nil(cndid)){
     900           2 :                 cand = BATdescriptor(cndid);
     901           2 :                 if( cand == NULL)
     902           0 :                         throw(MAL,"generator.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     903           2 :                 canditer_init(&ci, NULL, cand);
     904             :         }
     905          29 :         oper= *getArgReference_str(stk,pci,4);
     906             : 
     907             :         // check the step direction
     908             : 
     909          29 :         switch( tpe =getArgType(mb,pci,3)){
     910         119 :         case TYPE_bte: VLTthetasubselect(bte,abs);break;
     911           0 :         case TYPE_sht: VLTthetasubselect(sht,abs);break;
     912           0 :         case TYPE_int: VLTthetasubselect(int,abs);break;
     913          16 :         case TYPE_lng: VLTthetasubselect(lng,llabs);break;
     914             : #ifdef HAVE_HGE
     915           0 :         case TYPE_hge: VLTthetasubselect(hge,HGE_ABS);break;
     916             : #endif
     917           8 :         case TYPE_flt: VLTthetasubselect(flt,fabsf);break;
     918          25 :         case TYPE_dbl: VLTthetasubselect(dbl,fabs);break;
     919          11 :         default:
     920          11 :                 if (tpe == TYPE_date && p->argc == 3) {
     921           0 :                         BBPreclaim(cand);
     922           0 :                         throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
     923             :                 }
     924           2 :                 if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
     925           1 :                         date f,l, val, low, hgh;
     926           1 :                         int  s;
     927           1 :                         oid *v;
     928             : 
     929           1 :                         f = *getArgReference_TYPE(stk,p, 1, date);
     930           1 :                         l = *getArgReference_TYPE(stk,p, 2, date);
     931           1 :                         s = *getArgReference_int(stk,p, 3);
     932           1 :                         if ( s == 0 ||
     933           1 :                                  (s > 0 && f > l) ||
     934           1 :                                  (s < 0 && f < l)
     935             :                                 ) {
     936           0 :                                 BBPreclaim(cand);
     937           0 :                                 throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
     938             :                         }
     939             : 
     940           1 :                         hgh = low = date_nil;
     941           1 :                         if ( strcmp(oper,"<") == 0){
     942           1 :                                 hgh= *getArgReference_TYPE(stk,pci,3, date);
     943           1 :                                 hgh = date_add_month(hgh, -1);
     944           1 :                                 if (is_date_nil(hgh)) {
     945           0 :                                         BBPreclaim(cand);
     946           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     947             :                                 }
     948             :                         } else
     949           0 :                         if ( strcmp(oper,"<=") == 0){
     950           0 :                                 hgh= *getArgReference_TYPE(stk,pci,3, date) ;
     951             :                         } else
     952           0 :                         if ( strcmp(oper,">") == 0){
     953           0 :                                 low= *getArgReference_TYPE(stk,pci,3, date);
     954           0 :                                 low = date_add_month(low, 1);
     955           0 :                                 if (is_date_nil(low)) {
     956           0 :                                         BBPreclaim(cand);
     957           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
     958             :                                 }
     959             :                         } else
     960           0 :                         if ( strcmp(oper,">=") == 0){
     961           0 :                                 low= *getArgReference_TYPE(stk,pci,3, date);
     962             :                         } else
     963           0 :                         if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
     964           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, date);
     965           0 :                                 anti = 1;
     966             :                         } else
     967           0 :                         if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
     968           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, date);
     969             :                         } else {
     970           0 :                                 BBPreclaim(cand);
     971           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
     972             :                         }
     973             : 
     974           1 :                         cap = (BUN) (date_diff(l, f) / (s*28));
     975           1 :                         bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
     976           1 :                         if( bn == NULL) {
     977           0 :                                 BBPreclaim(cand);
     978           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     979             :                         }
     980           1 :                         v = (oid*) Tloc(bn,0);
     981             : 
     982           1 :                         val = f;
     983          14 :                         for(j = 0; j< cap; j++,  o++){
     984          26 :                                 if (((is_date_nil(low) || val >= low) &&
     985          13 :                                      (is_date_nil(hgh) || val <= hgh)) != anti){
     986           5 :                                         if(cand == NULL || canditer_contains(&ci, o)){
     987           5 :                                                 *v++ = o;
     988           5 :                                                 c++;
     989             :                                         }
     990             :                                 }
     991          13 :                                 val = date_add_month(val, s);
     992          13 :                                 if (is_date_nil(val)) {
     993           0 :                                         BBPreclaim(cand);
     994           0 :                                         BBPreclaim(bn);
     995           0 :                                         throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
     996             :                                 }
     997             :                         }
     998           1 :                 } else if (tpe == TYPE_date) { /* days */
     999           1 :                         date f,l, val, low, hgh;
    1000           1 :                         lng  s;
    1001           1 :                         oid *v;
    1002             : 
    1003           1 :                         f = *getArgReference_TYPE(stk,p, 1, date);
    1004           1 :                         l = *getArgReference_TYPE(stk,p, 2, date);
    1005           1 :                         s = *getArgReference_lng(stk,p, 3);
    1006           1 :                         if ( s == 0 ||
    1007           1 :                                  (s > 0 && f > l) ||
    1008           1 :                                  (s < 0 && f < l)
    1009             :                                 ) {
    1010           0 :                                 BBPreclaim(cand);
    1011           0 :                                 throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
    1012             :                         }
    1013           1 :                         s /= 24*60*60*1000;
    1014             : 
    1015           1 :                         hgh = low = date_nil;
    1016           1 :                         if ( strcmp(oper,"<") == 0){
    1017           1 :                                 hgh= *getArgReference_TYPE(stk,pci,3, date);
    1018           1 :                                 hgh = date_add_day(hgh, -1);
    1019           1 :                                 if (is_date_nil(hgh)) {
    1020           0 :                                         BBPreclaim(cand);
    1021           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
    1022             :                                 }
    1023             :                         } else
    1024           0 :                         if ( strcmp(oper,"<=") == 0){
    1025           0 :                                 hgh= *getArgReference_TYPE(stk,pci,3, date) ;
    1026             :                         } else
    1027           0 :                         if ( strcmp(oper,">") == 0){
    1028           0 :                                 low= *getArgReference_TYPE(stk,pci,3, date);
    1029           0 :                                 low = date_add_month(low, 1);
    1030           0 :                                 if (is_date_nil(low)) {
    1031           0 :                                         BBPreclaim(cand);
    1032           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
    1033             :                                 }
    1034             :                         } else
    1035           0 :                         if ( strcmp(oper,">=") == 0){
    1036           0 :                                 low= *getArgReference_TYPE(stk,pci,3, date);
    1037             :                         } else
    1038           0 :                         if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
    1039           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, date);
    1040           0 :                                 anti = 1;
    1041             :                         } else
    1042           0 :                         if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
    1043           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, date);
    1044             :                         } else {
    1045           0 :                                 BBPreclaim(cand);
    1046           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
    1047             :                         }
    1048             : 
    1049           1 :                         cap = (BUN) (date_diff(l, f) / s) + 1;
    1050           1 :                         bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
    1051           1 :                         if( bn == NULL) {
    1052           0 :                                 BBPreclaim(cand);
    1053           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1054             :                         }
    1055           1 :                         v = (oid*) Tloc(bn,0);
    1056             : 
    1057           1 :                         val = f;
    1058          26 :                         for(j = 0; j< cap; j++,  o++){
    1059          50 :                                 if (((is_date_nil(low) || val >= low) &&
    1060          25 :                                      (is_date_nil(hgh) || val <= hgh)) != anti){
    1061          11 :                                         if(cand == NULL || canditer_contains(&ci, o)){
    1062          11 :                                                 *v++ = o;
    1063          11 :                                                 c++;
    1064             :                                         }
    1065             :                                 }
    1066          25 :                                 val = date_add_day(val, (int) s);
    1067          25 :                                 if (is_date_nil(val)) {
    1068           0 :                                         BBPreclaim(cand);
    1069           0 :                                         BBPreclaim(bn);
    1070           0 :                                         throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
    1071             :                                 }
    1072             :                         }
    1073           9 :                 } else if ( tpe == TYPE_timestamp){
    1074           9 :                         timestamp f,l, val, low, hgh;
    1075           9 :                         lng  s;
    1076           9 :                         oid *v;
    1077             : 
    1078           9 :                         f = *getArgReference_TYPE(stk,p, 1, timestamp);
    1079           9 :                         l = *getArgReference_TYPE(stk,p, 2, timestamp);
    1080           9 :                         if ( p->argc == 3) {
    1081           0 :                                 BBPreclaim(cand);
    1082           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
    1083             :                         }
    1084           9 :                         s = *getArgReference_lng(stk,p, 3);
    1085           9 :                         if ( s == 0 ||
    1086           9 :                                  (s > 0 && f > l) ||
    1087           9 :                                  (s < 0 && f < l)
    1088             :                                 ) {
    1089           0 :                                 BBPreclaim(cand);
    1090           0 :                                 throw(MAL, "generator.select", SQLSTATE(42000) "Illegal generator range");
    1091             :                         }
    1092             : 
    1093           9 :                         hgh = low = timestamp_nil;
    1094           9 :                         if ( strcmp(oper,"<") == 0){
    1095           5 :                                 hgh= *getArgReference_TYPE(stk,pci,3, timestamp);
    1096           5 :                                 hgh = timestamp_add_usec(hgh, -1);
    1097           5 :                                 if (is_timestamp_nil(hgh)) {
    1098           0 :                                         BBPreclaim(cand);
    1099           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
    1100             :                                 }
    1101             :                         } else
    1102           4 :                         if ( strcmp(oper,"<=") == 0){
    1103           0 :                                 hgh= *getArgReference_TYPE(stk,pci,3, timestamp) ;
    1104             :                         } else
    1105           4 :                         if ( strcmp(oper,">") == 0){
    1106           3 :                                 low= *getArgReference_TYPE(stk,pci,3, timestamp);
    1107           3 :                                 low = timestamp_add_usec(low, 1);
    1108           3 :                                 if (is_timestamp_nil(low)) {
    1109           0 :                                         BBPreclaim(cand);
    1110           0 :                                         throw(MAL, "generator.select", SQLSTATE(22003) "overflow in calculation");
    1111             :                                 }
    1112             :                         } else
    1113           1 :                         if ( strcmp(oper,">=") == 0){
    1114           0 :                                 low= *getArgReference_TYPE(stk,pci,3, timestamp);
    1115             :                         } else
    1116           1 :                         if ( strcmp(oper,"!=") == 0 || strcmp(oper, "<>") == 0){
    1117           0 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
    1118           0 :                                 anti = 1;
    1119             :                         } else
    1120           1 :                         if ( strcmp(oper,"==") == 0 || strcmp(oper, "=") == 0){
    1121           1 :                                 hgh= low= *getArgReference_TYPE(stk,pci,3, timestamp);
    1122             :                         } else {
    1123           0 :                                 BBPreclaim(cand);
    1124           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Unknown operator");
    1125             :                         }
    1126             : 
    1127           9 :                         s *= 1000; /* msec -> usec */
    1128           9 :                         cap = (BUN) (timestamp_diff(l, f) / s);
    1129           9 :                         bn = COLnew(0, TYPE_oid, cap, TRANSIENT);
    1130           9 :                         if( bn == NULL) {
    1131           0 :                                 BBPreclaim(cand);
    1132           0 :                                 throw(MAL,"generator.thetaselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1133             :                         }
    1134           9 :                         v = (oid*) Tloc(bn,0);
    1135             : 
    1136           9 :                         val = f;
    1137          85 :                         for(j = 0; j< cap; j++,  o++){
    1138         148 :                                 if (((is_timestamp_nil(low) || val >= low) &&
    1139          50 :                                      (is_timestamp_nil(hgh) || val <= hgh)) != anti){
    1140          34 :                                         if(cand == NULL || canditer_contains(&ci, o)){
    1141          31 :                                                 *v++ = o;
    1142          31 :                                                 c++;
    1143             :                                         }
    1144             :                                 }
    1145          76 :                                 val = timestamp_add_usec(val, s);
    1146          76 :                                 if (is_timestamp_nil(val)) {
    1147           0 :                                         BBPreclaim(cand);
    1148           0 :                                         BBPreclaim(bn);
    1149           0 :                                         throw(MAL, "generator.thetaselect", SQLSTATE(22003) "overflow in calculation");
    1150             :                                 }
    1151             :                         }
    1152             :                 } else {
    1153           0 :                         BBPreclaim(cand);
    1154           0 :                         throw(MAL,"generator.thetaselect", SQLSTATE(42000) "Illegal generator arguments");
    1155             :                 }
    1156             :         }
    1157             : 
    1158          29 :         if( cndid)
    1159          29 :                 BBPunfix(cndid);
    1160          29 :         BATsetcount(bn,c);
    1161          29 :         bn->tsorted = true;
    1162          29 :         bn->trevsorted = false;
    1163          29 :         bn->tkey = true;
    1164          29 :         bn->tnil = false;
    1165          29 :         bn->tnonil = true;
    1166          29 :         *getArgReference_bat(stk,pci,0) = bn->batCacheid;
    1167          29 :         BBPkeepref(bn);
    1168          29 :         return MAL_SUCCEED;
    1169             : }
    1170             : 
    1171             : #define VLTprojection(TPE)                                                                                              \
    1172             :         do {                                                                                                                            \
    1173             :                 TPE f,l,s, val;                                                                                                 \
    1174             :                 TPE *v;                                                                                                                 \
    1175             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
    1176             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
    1177             :                 if ( p->argc == 3)                                                                                           \
    1178             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
    1179             :                 else                                                                                                                    \
    1180             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
    1181             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
    1182             :                         BBPunfix(b->batCacheid);                                                                     \
    1183             :                         throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range"); \
    1184             :                 }                                                                                                                               \
    1185             :                 bn = COLnew(0, TYPE_##TPE, cnt, TRANSIENT);                                             \
    1186             :                 if( bn == NULL){                                                                                                \
    1187             :                         BBPunfix(b->batCacheid);                                                                     \
    1188             :                         throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);   \
    1189             :                 }                                                                                                                               \
    1190             :                 v = (TPE*) Tloc(bn,0);                                                                                  \
    1191             :                 for(; cnt-- > 0; o++){                                                                                       \
    1192             :                         val = f + ((TPE) (ol == NULL  ? o : ol[o])) * s;                        \
    1193             :                         if ( (s > 0 &&  (val < f || val >= l)) || (s < 0 && (val <= l || val > f))) \
    1194             :                                 continue;                                                                                               \
    1195             :                         *v++ = val;                                                                                                     \
    1196             :                         c++;                                                                                                            \
    1197             :                 }                                                                                                                               \
    1198             :         } while (0)
    1199             : 
    1200         136 : str VLTgenerator_projection(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1201             : {
    1202         136 :         int tpe;
    1203         136 :         bat *ret;
    1204         136 :         BAT *b, *bn = NULL;
    1205         136 :         BUN cnt, c = 0;
    1206         136 :         oid *ol = NULL, o= 0;
    1207         136 :         InstrPtr p;
    1208             : 
    1209         136 :         (void) cntxt;
    1210         136 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
    1211             : 
    1212         136 :         ret = getArgReference_bat(stk,pci,0);
    1213         136 :         b = BATdescriptor(*getArgReference_bat(stk,pci,1));
    1214         136 :         if( b == NULL)
    1215           0 :                 throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1216             : 
    1217             :         // if it does not exist we should fall back to the ordinary projection to try
    1218             :         // it might have been materialized already
    1219         136 :         if( p == NULL){
    1220           0 :                 bn = BATdescriptor( *getArgReference_bat(stk,pci,2));
    1221           0 :                 if( bn == NULL) {
    1222           0 :                         BBPunfix(b->batCacheid);
    1223           0 :                         throw(MAL,"generator.projection", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1224             :                 }
    1225           0 :                 BAT *bp = BATproject(b, bn);
    1226           0 :                 BBPunfix(b->batCacheid);
    1227           0 :                 BBPunfix(bn->batCacheid);
    1228           0 :                 if (bp == NULL)
    1229           0 :                         throw(MAL, "generator.projection", GDK_EXCEPTION);
    1230           0 :                 *ret = bp->batCacheid;
    1231           0 :                 BBPkeepref(bp);
    1232           0 :                 return MAL_SUCCEED;
    1233             :         }
    1234             : 
    1235         136 :         cnt = BATcount(b);
    1236         136 :         if ( b->ttype == TYPE_void)
    1237          52 :                 o = b->tseqbase;
    1238             :         else
    1239          84 :                 ol = (oid*) Tloc(b,0);
    1240             : 
    1241             :         /* the actual code to perform a projection over generators */
    1242         136 :         switch( tpe = getArgType(mb,p,1)){
    1243         431 :         case TYPE_bte:  VLTprojection(bte); break;
    1244      999008 :         case TYPE_sht:  VLTprojection(sht); break;
    1245     1149348 :         case TYPE_int:  VLTprojection(int); break;
    1246          14 :         case TYPE_lng:  VLTprojection(lng); break;
    1247             : #ifdef HAVE_HGE
    1248           0 :         case TYPE_hge:  VLTprojection(hge); break;
    1249             : #endif
    1250           7 :         case TYPE_flt:  VLTprojection(flt); break;
    1251          17 :         case TYPE_dbl:  VLTprojection(dbl); break;
    1252          37 :         default:
    1253          37 :                 if (tpe == TYPE_date && p->argc == 3) {
    1254           0 :                         BBPunfix(b->batCacheid);
    1255           0 :                         throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
    1256             :                 }
    1257           2 :                 if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* months */
    1258           1 :                         date f,l, val;
    1259           1 :                         int s,t;
    1260           1 :                         date *v;
    1261           1 :                         f = *getArgReference_TYPE(stk,p, 1, date);
    1262           1 :                         l = *getArgReference_TYPE(stk,p, 2, date);
    1263           1 :                         s =  *getArgReference_int(stk,p, 3);
    1264           1 :                         if ( s == 0 ||
    1265           1 :                              (s< 0 && f < l) ||
    1266           1 :                              (s> 0 && l < f) ) {
    1267           0 :                                 BBPunfix(b->batCacheid);
    1268           0 :                                 throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
    1269             :                         }
    1270             : 
    1271           1 :                         bn = COLnew(0, TYPE_date, cnt, TRANSIENT);
    1272           1 :                         if( bn == NULL){
    1273           0 :                                 BBPunfix(b->batCacheid);
    1274           0 :                                 throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1275             :                         }
    1276             : 
    1277           1 :                         v = (date*) Tloc(bn,0);
    1278             : 
    1279           6 :                         for(; cnt-- > 0; o++){
    1280           5 :                                 t = ((int) (ol == NULL ? o : ol[o])) * s;
    1281           5 :                                 val = date_add_month(f, t);
    1282           5 :                                 if (is_date_nil(val)) {
    1283           0 :                                         BBPunfix(b->batCacheid);
    1284           0 :                                         BBPreclaim(bn);
    1285           0 :                                         throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
    1286             :                                 }
    1287             : 
    1288           5 :                                 if ( is_date_nil(val))
    1289             :                                         continue;
    1290           5 :                                 if (s > 0 && (val < f || val >= l) )
    1291           0 :                                         continue;
    1292           5 :                                 if (s < 0 && (val <= l || val > f) )
    1293           0 :                                         continue;
    1294           5 :                                 *v++ = val;
    1295           5 :                                 c++;
    1296             :                         }
    1297           1 :                 } else if (tpe == TYPE_date) { /* days */
    1298           1 :                         date f,l, val;
    1299           1 :                         lng s,t;
    1300           1 :                         date *v;
    1301           1 :                         f = *getArgReference_TYPE(stk,p, 1, date);
    1302           1 :                         l = *getArgReference_TYPE(stk,p, 2, date);
    1303           1 :                         s =  *getArgReference_lng(stk,p, 3);
    1304           1 :                         if ( s == 0 ||
    1305           1 :                              (s< 0 && f < l) ||
    1306           1 :                              (s> 0 && l < f) ) {
    1307           0 :                                 BBPunfix(b->batCacheid);
    1308           0 :                                 throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
    1309             :                         }
    1310           1 :                         s /= 24*60*60*1000;
    1311             : 
    1312           1 :                         bn = COLnew(0, TYPE_date, cnt, TRANSIENT);
    1313           1 :                         if( bn == NULL){
    1314           0 :                                 BBPunfix(b->batCacheid);
    1315           0 :                                 throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1316             :                         }
    1317             : 
    1318           1 :                         v = (date*) Tloc(bn,0);
    1319             : 
    1320          12 :                         for(; cnt-- > 0; o++){
    1321          11 :                                 t = ((int) (ol == NULL ? o : ol[o])) * s;
    1322          11 :                                 val = date_add_day(f, (int) t);
    1323          11 :                                 if (is_date_nil(val)) {
    1324           0 :                                         BBPunfix(b->batCacheid);
    1325           0 :                                         BBPreclaim(bn);
    1326           0 :                                         throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
    1327             :                                 }
    1328             : 
    1329          11 :                                 if ( is_date_nil(val))
    1330             :                                         continue;
    1331          11 :                                 if (s > 0 && (val < f || val >= l) )
    1332           0 :                                         continue;
    1333          11 :                                 if (s < 0 && (val <= l || val > f) )
    1334           0 :                                         continue;
    1335          11 :                                 *v++ = val;
    1336          11 :                                 c++;
    1337             :                         }
    1338          35 :                 } else if ( tpe == TYPE_timestamp){
    1339          35 :                         timestamp f,l, val;
    1340          35 :                         lng s,t;
    1341          35 :                         timestamp *v;
    1342          35 :                         f = *getArgReference_TYPE(stk,p, 1, timestamp);
    1343          35 :                         l = *getArgReference_TYPE(stk,p, 2, timestamp);
    1344          35 :                         if ( p->argc == 3) {
    1345           0 :                                 BBPunfix(b->batCacheid);
    1346           0 :                                 throw(MAL,"generator.table", SQLSTATE(42000) "Timestamp step missing");
    1347             :                         }
    1348          35 :                         s =  *getArgReference_lng(stk,p, 3);
    1349          35 :                         if ( s == 0 ||
    1350          35 :                              (s< 0 && f < l) ||
    1351          35 :                              (s> 0 && l < f) ) {
    1352           0 :                                 BBPunfix(b->batCacheid);
    1353           0 :                                 throw(MAL,"generator.projection", SQLSTATE(42000) "Illegal range");
    1354             :                         }
    1355             : 
    1356          35 :                         s *= 1000; /* msec -> usec */
    1357          35 :                         bn = COLnew(0, TYPE_timestamp, cnt, TRANSIENT);
    1358          35 :                         if( bn == NULL){
    1359           0 :                                 BBPunfix(b->batCacheid);
    1360           0 :                                 throw(MAL,"generator.projection", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1361             :                         }
    1362             : 
    1363          35 :                         v = (timestamp*) Tloc(bn,0);
    1364             : 
    1365          89 :                         for(; cnt-- > 0; o++){
    1366          54 :                                 t = ((lng) (ol == NULL ? o : ol[o])) * s;
    1367          54 :                                 val = timestamp_add_usec(f, t);
    1368          54 :                                 if (is_timestamp_nil(val)) {
    1369           0 :                                         BBPunfix(b->batCacheid);
    1370           0 :                                         BBPreclaim(bn);
    1371           0 :                                         throw(MAL, "generator.projection", SQLSTATE(22003) "overflow in calculation");
    1372             :                                 }
    1373             : 
    1374          54 :                                 if ( is_timestamp_nil(val))
    1375             :                                         continue;
    1376          54 :                                 if (s > 0 && (val < f || val >= l) )
    1377           0 :                                         continue;
    1378          54 :                                 if (s < 0 && (val <= l || val > f) )
    1379           0 :                                         continue;
    1380          54 :                                 *v++ = val;
    1381          54 :                                 c++;
    1382             :                         }
    1383             :                 }
    1384             :         }
    1385             : 
    1386             :         /* administrative wrapup of the projection */
    1387         136 :         BBPunfix(b->batCacheid);
    1388         136 :         if( bn){
    1389         136 :                 BATsetcount(bn,c);
    1390         136 :                 bn->tsorted = bn->trevsorted = false;
    1391         136 :                 bn->tkey = false;
    1392         136 :                 bn->tnil = false;
    1393         136 :                 bn->tnonil = false;
    1394         136 :                 *getArgReference_bat(stk,pci,0) = bn->batCacheid;
    1395         136 :                 BBPkeepref(bn);
    1396             :         }
    1397             :         return MAL_SUCCEED;
    1398             : }
    1399             : 
    1400             : /* The operands of a join operation can either be defined on a generator */
    1401             : #define VLTjoin(TPE, ABS)                                                                                               \
    1402             :         do {                                                                                                                            \
    1403             :                 TPE f,l,s; TPE *v; BUN w;                                                                               \
    1404             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
    1405             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
    1406             :                 if ( p->argc == 3)                                                                                           \
    1407             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
    1408             :                 else                                                                                                                    \
    1409             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
    1410             :                 incr = s > 0;                                                                                                        \
    1411             :                 v = (TPE*) Tloc(b,0);                                                                                   \
    1412             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
    1413             :                         BBPunfix(bln->batCacheid);                                                                   \
    1414             :                         BBPunfix(brn->batCacheid);                                                                   \
    1415             :                         BBPreclaim(bl);                                                                                         \
    1416             :                         BBPreclaim(br);                                                                                         \
    1417             :                         throw(MAL,"generator.join", SQLSTATE(42000) "Illegal range"); \
    1418             :                 }                                                                                                                               \
    1419             :                 for( ; cnt >0; cnt--,o++,v++){                                                                       \
    1420             :                         w = (BUN) (ABS(*v -f)/ABS(s));                                                          \
    1421             :                         if ( f + (TPE)(w * s) == *v ){                                                          \
    1422             :                                 *ol++ = (oid) w;                                                                                \
    1423             :                                 *or++ = o;                                                                                              \
    1424             :                                 c++;                                                                                                    \
    1425             :                         }                                                                                                                       \
    1426             :                 }                                                                                                                               \
    1427             :         } while (0)
    1428             : 
    1429           0 : str VLTgenerator_join(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1430             : {
    1431           0 :         BAT  *b, *bl = NULL, *br = NULL, *bln = NULL, *brn= NULL;
    1432           0 :         BUN cnt,c =0;
    1433           0 :         oid o= 0, *ol, *or;
    1434           0 :         int tpe, incr=0, materialized = 0;
    1435           0 :         InstrPtr p = NULL, q = NULL;
    1436           0 :         str msg = MAL_SUCCEED;
    1437             : 
    1438           0 :         (void) cntxt;
    1439             :         // we assume at most one of the arguments to refer to the generator
    1440           0 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
    1441           0 :         q = findGeneratorDefinition(mb,pci,pci->argv[3]);
    1442             : 
    1443           0 :         if (p == NULL && q == NULL) {
    1444           0 :                 bl = BATdescriptor(*getArgReference_bat(stk, pci, 2));
    1445           0 :                 br = BATdescriptor(*getArgReference_bat(stk, pci, 3));
    1446           0 :                 if (bl == NULL || br == NULL) {
    1447           0 :                         BBPreclaim(bl);
    1448           0 :                         BBPreclaim(br);
    1449           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1450             :                 }
    1451           0 :                 gdk_return rc = BATjoin(&bln, &brn, bl, br, NULL, NULL, false, BUN_NONE);
    1452           0 :                 BBPunfix(bl->batCacheid);
    1453           0 :                 BBPunfix(br->batCacheid);
    1454           0 :                 if (rc != GDK_SUCCEED)
    1455           0 :                         throw(MAL,"generator.join", GDK_EXCEPTION);
    1456           0 :                 *getArgReference_bat(stk, pci, 0) = bln->batCacheid;
    1457           0 :                 *getArgReference_bat(stk, pci, 1) = brn->batCacheid;
    1458           0 :                 BBPkeepref(bln);
    1459           0 :                 BBPkeepref(brn);
    1460           0 :                 return MAL_SUCCEED;
    1461             :         }
    1462             : 
    1463           0 :         if( p == NULL){
    1464           0 :                 bl = BATdescriptor(*getArgReference_bat(stk,pci,2));
    1465           0 :                 if( bl == NULL)
    1466           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1467             :         }
    1468           0 :         if ( q == NULL){
    1469             :                 /* p != NULL, hence bl == NULL */
    1470           0 :                 br = BATdescriptor(*getArgReference_bat(stk,pci,3));
    1471           0 :                 if( br == NULL)
    1472           0 :                         throw(MAL,"generator.join", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1473             :         }
    1474             : 
    1475             :         // in case of both generators  || getModuleId(q) == generatorRef)materialize the 'smallest' one first
    1476             :         // or implement more knowledge, postponed
    1477           0 :         if (p && q ){
    1478           0 :                 msg =  VLTgenerator_table_(&bl, cntxt, mb, stk, p);
    1479           0 :                 if( msg || bl == NULL )
    1480           0 :                         throw(MAL,"generator.join",SQLSTATE(42000) "Join over generator pairs not supported");
    1481             :                 else
    1482             :                         p = NULL;
    1483             :                 materialized =1;
    1484             :         }
    1485             : 
    1486             :         // switch roles to have a single target bat[:oid,:any] designated
    1487             :         // by b and reference instruction p for the generator
    1488           0 :         b = q? bl : br;
    1489           0 :         p = q? q : p;
    1490           0 :         cnt = BATcount(b);
    1491           0 :         tpe = b->ttype;
    1492           0 :         o= b->hseqbase;
    1493             : 
    1494           0 :         bln = COLnew(0,TYPE_oid, cnt, TRANSIENT);
    1495           0 :         brn = COLnew(0,TYPE_oid, cnt, TRANSIENT);
    1496           0 :         if( bln == NULL || brn == NULL){
    1497           0 :                 BBPreclaim(bln);
    1498           0 :                 BBPreclaim(brn);
    1499           0 :                 BBPreclaim(bl);
    1500           0 :                 BBPreclaim(br);
    1501           0 :                 throw(MAL,"generator.join", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1502             :         }
    1503           0 :         ol = (oid*) Tloc(bln,0);
    1504           0 :         or = (oid*) Tloc(brn,0);
    1505             : 
    1506             :         /* The actual join code for generators be injected here */
    1507           0 :         switch(tpe){
    1508           0 :         case TYPE_bte: VLTjoin(bte,abs); break;
    1509           0 :         case TYPE_sht: VLTjoin(sht,abs); break;
    1510           0 :         case TYPE_int: VLTjoin(int,abs); break;
    1511           0 :         case TYPE_lng: VLTjoin(lng,llabs); break;
    1512             : #ifdef HAVE_HGE
    1513           0 :         case TYPE_hge: VLTjoin(hge,HGE_ABS); break;
    1514             : #endif
    1515           0 :         case TYPE_flt: VLTjoin(flt,fabsf); break;
    1516           0 :         case TYPE_dbl: VLTjoin(dbl,fabs); break;
    1517           0 :         default:
    1518           0 :                 if(tpe == TYPE_date || tpe == TYPE_timestamp){
    1519             :                         // it is easier to produce the date or timestamp series
    1520             :                         // then to estimate the possible index
    1521           0 :                         }
    1522           0 :                 BBPunfix(bln->batCacheid);
    1523           0 :                 BBPunfix(brn->batCacheid);
    1524           0 :                 BBPreclaim(bl);
    1525           0 :                 BBPreclaim(br);
    1526           0 :                 throw(MAL,"generator.join", SQLSTATE(42000) "Illegal type");
    1527             :         }
    1528             : 
    1529           0 :         BATsetcount(bln,c);
    1530           0 :         bln->tsorted = bln->trevsorted = false;
    1531           0 :         bln->tkey = false;
    1532           0 :         bln->tnil = false;
    1533           0 :         bln->tnonil = false;
    1534           0 :         bln->tsorted = incr || c <= 1;
    1535           0 :         bln->trevsorted = !incr || c <= 1;
    1536             : 
    1537           0 :         BATsetcount(brn,c);
    1538           0 :         brn->tsorted = brn->trevsorted = false;
    1539           0 :         brn->tkey = false;
    1540           0 :         brn->tnil = false;
    1541           0 :         brn->tnonil = false;
    1542           0 :         brn->tsorted = incr || c <= 1;
    1543           0 :         brn->trevsorted = !incr || c <= 1;
    1544           0 :         if( q){
    1545           0 :                 *getArgReference_bat(stk,pci,0) = brn->batCacheid;
    1546           0 :                 BBPkeepref(brn);
    1547           0 :                 *getArgReference_bat(stk,pci,1) = bln->batCacheid;
    1548           0 :                 BBPkeepref(bln);
    1549             :         } else {
    1550           0 :                 *getArgReference_bat(stk,pci,0) = bln->batCacheid;
    1551           0 :                 BBPkeepref(bln);
    1552           0 :                 *getArgReference_bat(stk,pci,1) = brn->batCacheid;
    1553           0 :                 BBPkeepref(brn);
    1554             :         }
    1555           0 :         if ( materialized){
    1556           0 :                 BBPreclaim(bl);
    1557           0 :                 bl = 0;
    1558             :         }
    1559           0 :         BBPreclaim(bl);
    1560           0 :         BBPreclaim(br);
    1561             :         return msg;
    1562             : }
    1563             : 
    1564             : #define VLTrangeExpand()                                                                                                \
    1565             :         do {                                                                                                                            \
    1566             :                 limit+= cnt * (limit/(done?done:1)+1);                                                  \
    1567             :                 if (BATextend(bln, limit) != GDK_SUCCEED) {                                             \
    1568             :                         BBPunfix(blow->batCacheid);                                                                  \
    1569             :                         BBPunfix(bhgh->batCacheid);                                                                  \
    1570             :                         BBPunfix(bln->batCacheid);                                                                   \
    1571             :                         BBPunfix(brn->batCacheid);                                                                   \
    1572             :                         throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1573             :                 }                                                                                                                               \
    1574             :                 if (BATextend(brn, limit) != GDK_SUCCEED) {                                             \
    1575             :                         BBPunfix(blow->batCacheid);                                                                  \
    1576             :                         BBPunfix(bhgh->batCacheid);                                                                  \
    1577             :                         BBPunfix(bln->batCacheid);                                                                   \
    1578             :                         BBPunfix(brn->batCacheid);                                                                   \
    1579             :                         throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
    1580             :                 }                                                                                                                               \
    1581             :                 ol = (oid*) Tloc(bln,0) + c;                                                                    \
    1582             :                 or = (oid*) Tloc(brn,0) + c;                                                                    \
    1583             :         } while (0)
    1584             : 
    1585             : /* The operands of a join operation can either be defined on a generator */
    1586             : #define VLTrangejoin(TPE, ABS, FLOOR)                                                                   \
    1587             :         do {                                                                                                                            \
    1588             :                 TPE f,f1,l,s; TPE *vlow,*vhgh; BUN w;                                                   \
    1589             :                 f = *getArgReference_##TPE(stk,p, 1);                                                   \
    1590             :                 l = *getArgReference_##TPE(stk,p, 2);                                                   \
    1591             :                 if ( p->argc == 3)                                                                                           \
    1592             :                         s = f<l? (TPE) 1: (TPE)-1;                                                                   \
    1593             :                 else                                                                                                                    \
    1594             :                         s = * getArgReference_##TPE(stk, p, 3);                                         \
    1595             :                 incr = s > 0;                                                                                                        \
    1596             :                 if ( s == 0 || (f> l && s>0) || (f<l && s < 0))     {                               \
    1597             :                         BBPreclaim(bln);                                                                                        \
    1598             :                         BBPreclaim(brn);                                                                                        \
    1599             :                         BBPreclaim(blow);                                                                                       \
    1600             :                         BBPreclaim(bhgh);                                                                                       \
    1601             :                         throw(MAL,"generator.rangejoin", SQLSTATE(42000) "Illegal range"); \
    1602             :                 }                                                                                                                               \
    1603             :                 vlow = (TPE*) Tloc(blow,0);                                                                             \
    1604             :                 vhgh = (TPE*) Tloc(bhgh,0);                                                                             \
    1605             :                 for( ; cnt >0; cnt--, done++, o++,vlow++,vhgh++){                            \
    1606             :                         f1 = f + FLOOR(ABS(*vlow-f)/ABS(s)) * s;                                        \
    1607             :                         if ( f1 < *vlow )                                                                                    \
    1608             :                                 f1+= s;                                                                                                 \
    1609             :                         w = (BUN) FLOOR(ABS(f1-f)/ABS(s));                                                      \
    1610             :                         for( ; (f1 > *vlow || (li && f1 == *vlow)) && (f1 < *vhgh || (ri && f1 == *vhgh)); f1 += s, w++){ \
    1611             :                                 if(c == limit)                                                                                  \
    1612             :                                         VLTrangeExpand();                                                                       \
    1613             :                                 *ol++ = (oid) w;                                                                                \
    1614             :                                 *or++ = o;                                                                                              \
    1615             :                                 c++;                                                                                                    \
    1616             :                         }                                                                                                                       \
    1617             :                 }                                                                                                                               \
    1618             :         } while (0)
    1619             : 
    1620           0 : str VLTgenerator_rangejoin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
    1621             : {
    1622           0 :         BAT  *blow = NULL, *bhgh = NULL, *bln = NULL, *brn= NULL;
    1623           0 :         bit li,ri;
    1624           0 :         BUN limit, cnt, done=0, c =0;
    1625           0 :         oid o= 0, *ol, *or;
    1626           0 :         int tpe, incr=0;
    1627           0 :         InstrPtr p = NULL;
    1628           0 :         str msg = MAL_SUCCEED;
    1629             : 
    1630           0 :         (void) cntxt;
    1631             :         // the left join argument should be a generator
    1632           0 :         p = findGeneratorDefinition(mb,pci,pci->argv[2]);
    1633           0 :         if( p == NULL)
    1634           0 :                 throw(MAL,"generator.rangejoin",SQLSTATE(42000) "Invalid arguments");
    1635             : 
    1636           0 :         blow = BATdescriptor(*getArgReference_bat(stk,pci,3));
    1637           0 :         if( blow == NULL)
    1638           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1639             : 
    1640           0 :         bhgh = BATdescriptor(*getArgReference_bat(stk,pci,4));
    1641           0 :         if( bhgh == NULL){
    1642           0 :                 BBPunfix(blow->batCacheid);
    1643           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1644             :         }
    1645           0 :         li = *getArgReference_bit(stk,pci,5);
    1646           0 :         ri = *getArgReference_bit(stk,pci,6);
    1647             : 
    1648           0 :         cnt = BATcount(blow);
    1649           0 :         limit = 2 * cnt; //top off result before expansion
    1650           0 :         tpe = blow->ttype;
    1651           0 :         o= blow->hseqbase;
    1652             : 
    1653           0 :         bln = COLnew(0,TYPE_oid, limit, TRANSIENT);
    1654           0 :         brn = COLnew(0,TYPE_oid, limit, TRANSIENT);
    1655           0 :         if( bln == NULL || brn == NULL){
    1656           0 :                 BBPreclaim(bln);
    1657           0 :                 BBPreclaim(brn);
    1658           0 :                 BBPreclaim(blow);
    1659           0 :                 BBPreclaim(bhgh);
    1660           0 :                 throw(MAL,"generator.rangejoin", SQLSTATE(HY013) MAL_MALLOC_FAIL);
    1661             :         }
    1662           0 :         ol = (oid*) Tloc(bln,0);
    1663           0 :         or = (oid*) Tloc(brn,0);
    1664             : 
    1665             :         /* The actual join code for generators be injected here */
    1666           0 :         switch(tpe){
    1667           0 :         case TYPE_bte: VLTrangejoin(bte,abs,IDENTITY); break;
    1668           0 :         case TYPE_sht: VLTrangejoin(sht,abs,IDENTITY); break;
    1669           0 :         case TYPE_int: VLTrangejoin(int,abs,IDENTITY); break;
    1670           0 :         case TYPE_lng: VLTrangejoin(lng,llabs,IDENTITY); break;
    1671             : #ifdef HAVE_HGE
    1672           0 :         case TYPE_hge: VLTrangejoin(hge,HGE_ABS,IDENTITY); break;
    1673             : #endif
    1674           0 :         case TYPE_flt: VLTrangejoin(flt,fabsf,floorf); break;
    1675           0 :         case TYPE_dbl: VLTrangejoin(dbl,fabs,floor); break;
    1676           0 :         default:
    1677           0 :                 if( tpe == TYPE_date || tpe == TYPE_timestamp){
    1678             :                         // it is easier to produce the date or timestamp series
    1679             :                         // then to estimate the possible index
    1680           0 :                         }
    1681           0 :                 BBPreclaim(bln);
    1682           0 :                 BBPreclaim(brn);
    1683           0 :                 BBPreclaim(blow);
    1684           0 :                 BBPreclaim(bhgh);
    1685           0 :                 throw(MAL,"generator.rangejoin","Illegal type");
    1686             :         }
    1687             : 
    1688           0 :         BATsetcount(bln,c);
    1689           0 :         bln->tsorted = bln->trevsorted = false;
    1690           0 :         bln->tkey = false;
    1691           0 :         bln->tnil = false;
    1692           0 :         bln->tnonil = false;
    1693           0 :         bln->tsorted = incr || c <= 1;
    1694           0 :         bln->trevsorted = !incr || c <= 1;
    1695             : 
    1696           0 :         BATsetcount(brn,c);
    1697           0 :         brn->tsorted = brn->trevsorted = false;
    1698           0 :         brn->tkey = false;
    1699           0 :         brn->tnil = false;
    1700           0 :         brn->tnonil = false;
    1701           0 :         brn->tsorted = incr || c <= 1;
    1702           0 :         brn->trevsorted = !incr || c <= 1;
    1703           0 :         *getArgReference_bat(stk,pci,0) = bln->batCacheid;
    1704           0 :         BBPkeepref(bln);
    1705           0 :         *getArgReference_bat(stk,pci,1) = brn->batCacheid;
    1706           0 :         BBPkeepref(brn);
    1707           0 :         BBPreclaim(blow);
    1708           0 :         BBPreclaim(bhgh);
    1709           0 :         return msg;
    1710             : }
    1711             : 
    1712             : #include "mel.h"
    1713             : static mel_func generator_init_funcs[] = {
    1714             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
    1715             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
    1716             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
    1717             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
    1718             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
    1719             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
    1720             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
    1721             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
    1722             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
    1723             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
    1724             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
    1725             :  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))),
    1726             :  pattern("generator", "series", VLTgenerator_table, false, "date generator with step size in months", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",int))),
    1727             :  pattern("generator", "series", VLTgenerator_table, false, "date generator with step size in days", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",lng))),
    1728             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,4, batarg("",timestamp),arg("first",timestamp),arg("limit",timestamp),arg("step",lng))),
    1729             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",bte),arg("first",bte),arg("limit",bte),arg("step",bte))),
    1730             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",sht),arg("first",sht),arg("limit",sht),arg("step",sht))),
    1731             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",int),arg("first",int),arg("limit",int),arg("step",int))),
    1732             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",lng),arg("first",lng),arg("limit",lng),arg("step",lng))),
    1733             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",flt),arg("first",flt),arg("limit",flt),arg("step",flt))),
    1734             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,4, batarg("",dbl),arg("first",dbl),arg("limit",dbl),arg("step",dbl))),
    1735             :  pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize (months)", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",int))),
    1736             :  pattern("generator", "parameters", VLTgenerator_noop, false, "Retain the table definition, but don't materialize (days)", args(1,4, batarg("",date),arg("first",date),arg("limit",date),arg("step",lng))),
    1737             :  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))),
    1738             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",bte),arg("first",bte),arg("limit",bte))),
    1739             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",sht),arg("first",sht),arg("limit",sht))),
    1740             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",int),arg("first",int),arg("limit",int))),
    1741             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",lng),arg("first",lng),arg("limit",lng))),
    1742             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",flt),arg("first",flt),arg("limit",flt))),
    1743             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",dbl),arg("first",dbl),arg("limit",dbl))),
    1744             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",bte),batarg("cnd",oid),arg("low",bte),arg("oper",str))),
    1745             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",sht),batarg("cnd",oid),arg("low",sht),arg("oper",str))),
    1746             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",int),batarg("cnd",oid),arg("low",int),arg("oper",str))),
    1747             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",lng),batarg("cnd",oid),arg("low",lng),arg("oper",str))),
    1748             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",flt),batarg("cnd",oid),arg("low",flt),arg("oper",str))),
    1749             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "", args(1,5, batarg("",oid),batarg("b",dbl),batarg("cnd",oid),arg("low",dbl),arg("oper",str))),
    1750             :  pattern("generator", "thetaselect", VLTgenerator_thetasubselect, false, "Overloaded selection routine", args(1,5, batarg("",oid),batarg("b",date),batarg("cnd",oid),arg("low",date),arg("oper",str))),
    1751             :  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))),
    1752             :  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))),
    1753             :  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))),
    1754             :  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))),
    1755             :  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))),
    1756             :  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))),
    1757             :  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))),
    1758             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,7, batarg("",oid),batarg("b",date),arg("low",date),arg("high",date),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1759             :  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))),
    1760             :  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))),
    1761             :  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))),
    1762             :  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))),
    1763             :  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))),
    1764             :  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))),
    1765             :  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))),
    1766             :  pattern("generator", "select", VLTgenerator_subselect, false, "", args(1,8, batarg("",oid),batarg("b",date),batarg("cand",oid),arg("low",date),arg("high",date),arg("li",bit),arg("hi",bit),arg("anti",bit))),
    1767             :  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))),
    1768             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",bte),batarg("b",oid),batarg("cand",bte))),
    1769             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",sht),batarg("b",oid),batarg("cand",sht))),
    1770             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",int),batarg("b",oid),batarg("cand",int))),
    1771             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",lng),batarg("b",oid),batarg("cand",lng))),
    1772             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",flt),batarg("b",oid),batarg("cand",flt))),
    1773             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",dbl),batarg("b",oid),batarg("cand",dbl))),
    1774             :  pattern("generator", "projection", VLTgenerator_projection, false, "", args(1,3, batarg("",date),batarg("b",oid),batarg("cand",date))),
    1775             :  pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",timestamp),batarg("b",oid),batarg("cand",timestamp))),
    1776             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",bte),batarg("gen",bte))),
    1777             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",sht),batarg("gen",sht))),
    1778             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",int),batarg("gen",int))),
    1779             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",lng),batarg("gen",lng))),
    1780             :  pattern("generator", "join", VLTgenerator_join, false, "", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",flt),batarg("gen",flt))),
    1781             :  pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",dbl),batarg("gen",dbl))),
    1782             :  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))),
    1783             :  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))),
    1784             :  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))),
    1785             :  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))),
    1786             :  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))),
    1787             :  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))),
    1788             : #ifdef HAVE_HGE
    1789             :  pattern("generator", "series", VLTgenerator_table, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
    1790             :  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))),
    1791             :  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))),
    1792             :  pattern("generator", "parameters", VLTgenerator_noop, false, "", args(1,3, batarg("",hge),arg("first",hge),arg("limit",hge))),
    1793             :  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))),
    1794             :  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))),
    1795             :  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))),
    1796             :  pattern("generator", "projection", VLTgenerator_projection, false, "Overloaded projection operation", args(1,3, batarg("",hge),batarg("b",oid),batarg("cand",hge))),
    1797             :  pattern("generator", "join", VLTgenerator_join, false, "Overloaded join operation", args(2,4, batarg("l",oid),batarg("r",oid),batarg("b",hge),batarg("gen",hge))),
    1798             : #endif
    1799             :  { .imp=NULL }
    1800             : };
    1801             : #include "mal_import.h"
    1802             : #ifdef _MSC_VER
    1803             : #undef read
    1804             : #pragma section(".CRT$XCU",read)
    1805             : #endif
    1806         315 : LIB_STARTUP_FUNC(init_generator_mal)
    1807         315 : { mal_module("generator", NULL, generator_init_funcs); }

Generated by: LCOV version 1.14