Changeset: f7406735f6d8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f7406735f6d8
Added Files:
        sql/backends/monet5/generator/Tests/generator05.test
Modified Files:
        sql/backends/monet5/generator/90_generator.sql
        sql/backends/monet5/generator/Tests/All
        sql/backends/monet5/generator/generator.c
Branch: default
Log Message:

add generate_series for dates, ie steps of 1 or more days or months.


diffs (truncated from 670 to 300 lines):

diff --git a/sql/backends/monet5/generator/90_generator.sql 
b/sql/backends/monet5/generator/90_generator.sql
--- a/sql/backends/monet5/generator/90_generator.sql
+++ b/sql/backends/monet5/generator/90_generator.sql
@@ -54,6 +54,14 @@ create function sys.generate_series(firs
 returns table (value decimal(10,2))
 external name generator.series;
 
+create function sys.generate_series(first date, "limit" date, stepsize 
interval month)
+returns table (value date)
+external name generator.series;
+
+create function sys.generate_series(first date, "limit" date, stepsize 
interval day)
+returns table (value date)
+external name generator.series;
+
 create function sys.generate_series(first timestamp, "limit" timestamp, 
stepsize interval second)
 returns table (value timestamp)
 external name generator.series;
diff --git a/sql/backends/monet5/generator/Tests/All 
b/sql/backends/monet5/generator/Tests/All
--- a/sql/backends/monet5/generator/Tests/All
+++ b/sql/backends/monet5/generator/Tests/All
@@ -3,6 +3,7 @@ generator01
 generator02
 generator03
 generator04
+generator05
 
 rangejoin
 
diff --git a/sql/backends/monet5/generator/Tests/generator05.test 
b/sql/backends/monet5/generator/Tests/generator05.test
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/generator/Tests/generator05.test
@@ -0,0 +1,24 @@
+query T nosort
+select * from generate_series(date '2023-01-01',date '2024-01-01', interval 
'1' month) where value < date '2023-06-06'
+----
+2023-01-01
+2023-02-01
+2023-03-01
+2023-04-01
+2023-05-01
+
+query T nosort
+select * from generate_series(date '2023-01-01',date '2024-01-01', interval 
'15' day) where value < date '2023-06-06'
+----
+2023-01-01
+2023-01-16
+2023-01-31
+2023-02-15
+2023-03-02
+2023-03-17
+2023-04-01
+2023-04-16
+2023-05-01
+2023-05-16
+2023-05-31
+
diff --git a/sql/backends/monet5/generator/generator.c 
b/sql/backends/monet5/generator/generator.c
--- a/sql/backends/monet5/generator/generator.c
+++ b/sql/backends/monet5/generator/generator.c
@@ -12,7 +12,7 @@
 
 /*
  * (c) Martin Kersten, Sjoerd Mullender
- * Series generating module for integer, decimal, real, double and timestamps.
+ * Series generating module for integer, decimal, real, double, date and 
timestamps.
  */
 
 #include "monetdb_config.h"
@@ -51,11 +51,21 @@ VLTgenerator_noop(Client cntxt, MalBlkPt
        case TYPE_flt: VLTnoop(flt); break;
        case TYPE_dbl: VLTnoop(dbl); break;
        default:
-               if (tpe == TYPE_timestamp){
+               if (tpe == TYPE_date) {
+                       /* with date, step is of SQL type "interval month or 
day",
+                        * i.e., MAL / C type "int" or "lng" */
+                       int steptpe = pci->argc==4 ? getArgType(mb,pci,3) : 0;
+                       if (steptpe == TYPE_int)
+                               VLTnoop(int);
+                       else /* default interval days */
+                               VLTnoop(lng);
+               } else if (tpe == TYPE_timestamp) {
                        /* with timestamp, step is of SQL type "interval 
seconds",
                         * i.e., MAL / C type "lng" */
                         VLTnoop(lng);
-               } else throw(MAL,"generator.noop", SQLSTATE(42000) "unknown 
data type %d", getArgType(mb,pci,1));
+               } else {
+                       throw(MAL,"generator.noop", SQLSTATE(42000) "unknown 
data type %d", getArgType(mb,pci,1));
+               }
        }
        if( zeroerror)
                throw(MAL,"generator.noop", SQLSTATE(42000) "Zero step size not 
allowed");
@@ -204,7 +214,77 @@ VLTgenerator_table_(BAT **result, Client
                VLTmaterialize_flt(dbl);
                break;
        default:
-               if (tpe == TYPE_timestamp) {
+               if (tpe == TYPE_date && pci->argc == 3)
+                       throw(MAL,"generator.table", SQLSTATE(42000) "Date step 
missing");
+               if (tpe == TYPE_date && getArgType(mb, pci, 3) == TYPE_int) { 
/* months */
+                       date *v,f,l;
+                       int s;
+                       ValRecord ret;
+                       if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
+                                      &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
+                               throw(MAL, "generator.table",
+                                     SQLSTATE(42000) "Illegal generator 
expression range");
+                       f = *getArgReference_TYPE(stk, pci, 1, date);
+                       l = *getArgReference_TYPE(stk, pci, 2, date);
+                       s = *getArgReference_int(stk, pci, 3);
+                       if (s == 0 ||
+                           (s > 0 && ret.val.btval > 0) ||
+                           (s < 0 && ret.val.btval < 0) ||
+                               is_date_nil(f) || is_date_nil(l))
+                               throw(MAL, "generator.table",
+                                     SQLSTATE(42000) "Illegal generator 
range");
+                       n = (BUN) (date_diff(l, f) / (s *28)); /* n maybe too 
large now */
+                       bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
+                       if (bn == NULL)
+                               throw(MAL, "generator.table", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       v = (date *) Tloc(bn, 0);
+                       for (c = 0; c < n && f < l; c++) {
+                               *v++ = f;
+                               f = date_add_month(f, s);
+                               if (is_date_nil(f)) {
+                                       BBPreclaim(bn);
+                                       throw(MAL, "generator.table", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+                       n = c;
+                       bn->tsorted = s > 0 || n <= 1;
+                       bn->trevsorted = s < 0 || n <= 1;
+               } else if (tpe == TYPE_date) { /* days */
+                       date *v,f,l;
+                       lng s;
+                       ValRecord ret;
+                       if (VARcalccmp(&ret, &stk->stk[pci->argv[1]],
+                                      &stk->stk[pci->argv[2]]) != GDK_SUCCEED)
+                               throw(MAL, "generator.table",
+                                     SQLSTATE(42000) "Illegal generator 
expression range");
+                       f = *getArgReference_TYPE(stk, pci, 1, date);
+                       l = *getArgReference_TYPE(stk, pci, 2, date);
+                       s = *getArgReference_lng(stk, pci, 3);
+                       if (s == 0 ||
+                           (s > 0 && ret.val.btval > 0) ||
+                           (s < 0 && ret.val.btval < 0) ||
+                               is_date_nil(f) || is_date_nil(l))
+                               throw(MAL, "generator.table",
+                                     SQLSTATE(42000) "Illegal generator 
range");
+                       s /= 24*60*60*1000;
+                       /* check if s is really in nr of days or usecs */
+                       n = (BUN) (date_diff(l, f) / s) + 1; /* n maybe too 
large now */
+                       bn = COLnew(0, TYPE_date, n + 1, TRANSIENT);
+                       if (bn == NULL)
+                               throw(MAL, "generator.table", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       v = (date *) Tloc(bn, 0);
+                       for (c = 0; c < n && f < l; c++) {
+                               *v++ = f;
+                               f = date_add_day(f, s);
+                               if (is_date_nil(f)) {
+                                       BBPreclaim(bn);
+                                       throw(MAL, "generator.table", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+                       n = c;
+                       bn->tsorted = s > 0 || n <= 1;
+                       bn->trevsorted = s < 0 || n <= 1;
+               } else if (tpe == TYPE_timestamp) {
                        timestamp *v,f,l;
                        lng s;
                        ValRecord ret;
@@ -421,7 +501,158 @@ VLTgenerator_subselect(Client cntxt, Mal
        case TYPE_flt: calculate_range(flt, dbl); break;
        case TYPE_dbl: calculate_range(dbl, dbl); break;
        default:
-               if(  tpe == TYPE_timestamp){
+               if (p->argc == 3) {
+                       BBPreclaim(cand);
+                       throw(MAL,"generator.table", SQLSTATE(42000) "Date step 
missing");
+               }
+               if (tpe == TYPE_date && getArgType(mb, p, 3) == TYPE_int) { /* 
months */
+                       date tsf,tsl;
+                       date tlow,thgh;
+                       int tss;
+                       oid *ol;
+
+                       tsf = *getArgReference_TYPE(stk, p, 1, date);
+                       tsl = *getArgReference_TYPE(stk, p, 2, date);
+                       tss = *getArgReference_int(stk, p, 3);
+                       if ( tss == 0 ||
+                               is_date_nil(tsf) || is_date_nil(tsl) ||
+                                (tss > 0 && tsf > tsl ) ||
+                                (tss < 0 && tsf < tsl )
+                               ) {
+                               BBPreclaim(cand);
+                               throw(MAL, "generator.select",  SQLSTATE(42000) 
"Illegal generator range");
+                       }
+
+                       tlow = *getArgReference_TYPE(stk,pci,i, date);
+                       thgh = *getArgReference_TYPE(stk,pci,i+1, date);
+
+                       if (!is_date_nil(tlow) && tlow == thgh)
+                               hi = li;
+                       if( hi && !is_date_nil(thgh)) {
+                               thgh = date_add_month(thgh, 1);
+                               if (is_date_nil(thgh)) {
+                                       BBPreclaim(cand);
+                                       throw(MAL, "generator.select", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+                       if( !li && !is_date_nil(tlow)) {
+                               tlow = date_add_month(tlow, 1);
+                               if (is_date_nil(tlow)) {
+                                       BBPreclaim(cand);
+                                       throw(MAL, "generator.select", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+
+                       o2 = (BUN) (date_diff(tsl, tsf) / (tss*28));
+                       bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
+                       if (bn == NULL) {
+                               BBPreclaim(cand);
+                               throw(MAL, "generator.select", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       }
+
+                       // simply enumerate the sequence and filter it by 
predicate and candidate list
+                       ol = (oid *) Tloc(bn, 0);
+                       for (o1=0; o1 <= o2; o1++) {
+                               if(((is_date_nil(tlow) || tsf >= tlow) &&
+                                   (is_date_nil(thgh) || tsf < thgh)) != anti 
){
+                                       /* could be improved when no candidate 
list is available into a void/void BAT */
+                                       if( cand == NULL || 
canditer_contains(&ci, o1)) {
+                                               *ol++ = o1;
+                                               n++;
+                                       }
+                               }
+                               tsf = date_add_month(tsf, tss);
+                               if (is_date_nil(tsf)) {
+                                       BBPreclaim(cand);
+                                       BBPreclaim(bn);
+                                       throw(MAL, "generator.select", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+                       BBPreclaim(cand);
+                       BATsetcount(bn, n);
+                       bn->tsorted = true;
+                       bn->trevsorted = BATcount(bn) <= 1;
+                       bn->tkey = true;
+                       bn->tnil = false;
+                       bn->tnonil = true;
+                       * getArgReference_bat(stk, pci, 0) = bn->batCacheid;
+                       BBPkeepref(bn);
+                       return MAL_SUCCEED;
+               } else if (tpe == TYPE_date) { /* days */
+                       date tsf,tsl;
+                       date tlow,thgh;
+                       lng tss;
+                       oid *ol;
+
+                       tsf = *getArgReference_TYPE(stk, p, 1, date);
+                       tsl = *getArgReference_TYPE(stk, p, 2, date);
+                       tss = *getArgReference_lng(stk, p, 3);
+                       if ( tss == 0 ||
+                               is_date_nil(tsf) || is_date_nil(tsl) ||
+                                (tss > 0 && tsf > tsl ) ||
+                                (tss < 0 && tsf < tsl )
+                               ) {
+                               BBPreclaim(cand);
+                               throw(MAL, "generator.select",  SQLSTATE(42000) 
"Illegal generator range");
+                       }
+                       tss /= 24*60*60*1000;
+
+                       tlow = *getArgReference_TYPE(stk,pci,i, date);
+                       thgh = *getArgReference_TYPE(stk,pci,i+1, date);
+
+                       if (!is_date_nil(tlow) && tlow == thgh)
+                               hi = li;
+                       if( hi && !is_date_nil(thgh)) {
+                               thgh = date_add_month(thgh, 1);
+                               if (is_date_nil(thgh)) {
+                                       BBPreclaim(cand);
+                                       throw(MAL, "generator.select", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+                       if( !li && !is_date_nil(tlow)) {
+                               tlow = date_add_month(tlow, 1);
+                               if (is_date_nil(tlow)) {
+                                       BBPreclaim(cand);
+                                       throw(MAL, "generator.select", 
SQLSTATE(22003) "overflow in calculation");
+                               }
+                       }
+
+                       o2 = (BUN) (date_diff(tsl, tsf) / tss) + 1;
+                       bn = COLnew(0, TYPE_oid, o2 + 1, TRANSIENT);
+                       if (bn == NULL) {
+                               BBPreclaim(cand);
+                               throw(MAL, "generator.select", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       }
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to