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

Generated by: LCOV version 1.14