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

Generated by: LCOV version 1.14