Changeset: b2d69a4e4620 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b2d69a4e4620
Modified Files:
        gdk/gdk_analytic.c
        gdk/gdk_analytic.h
        sql/backends/monet5/sql_rank.c
        sql/backends/monet5/sql_rank.mal
        sql/backends/monet5/sql_rank.mal.sh
        sql/backends/monet5/sql_rank_hge.mal
        sql/backends/monet5/sql_rank_hge.mal.sh
        sql/common/sql_types.c
        sql/server/rel_select.c
Branch: analytics
Log Message:

Extend window bounds type coverage for all countable SQL types.


diffs (truncated from 715 to 300 lines):

diff --git a/gdk/gdk_analytic.c b/gdk/gdk_analytic.c
--- a/gdk/gdk_analytic.c
+++ b/gdk/gdk_analytic.c
@@ -388,7 +388,7 @@ GDKanalyticaldiff(BAT *r, BAT *b, BAT *p
 
 #define ANALYTICAL_WINDOW_BOUNDS_BRANCHES(FRAME, BOUNDF, BOUNDV) \
        do { \
-               switch(tpe) { \
+               switch(tp1) { \
                        case TYPE_bit: \
                                ANALYTICAL_WINDOW_BOUNDS_CALC_FIXED(bit, 
ANALYTICAL_WINDOW_BOUNDS_FIXED##FRAME, BOUNDF) \
                                break; \
@@ -457,46 +457,70 @@ GDKanalyticaldiff(BAT *r, BAT *b, BAT *p
 
 #define NO_BOUNDARIES
 
+#define ANALYTICAL_BOUNDS_BRANCHES(TPE) \
+       do { \
+               if (l) { /* dynamic bounds */ \
+                       TPE *restrict limit = (TPE*) Tloc(l, 0); \
+                       BUN ll = 0; \
+                       if (unit == 0) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ROWS, 
limit[ll++], limit[k]) \
+                       } else if (unit == 1) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_RANGE, 
limit[ll++], limit[k]) \
+                       } else if (unit == 2) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_GROUPS, 
limit[ll++], limit[k]) \
+                       } else { \
+                               assert(0); \
+                       } \
+               } else { /* static bounds */ \
+                       TPE limit = *((TPE*)bound); \
+                       if (limit == GDK_##TPE##_max) { /* UNBOUNDED PRECEDING 
and UNBOUNDED FOLLOWING cases, avoid overflow */  \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_UNBOUNDED, 
limit, limit) \
+                       } else if (unit == 0) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ROWS, limit, 
limit) \
+                       } else if (unit == 1) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_RANGE, 
limit, limit) \
+                       } else if (unit == 2) { \
+                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_GROUPS, 
limit, limit) \
+                       } else { \
+                               assert(0); \
+                       } \
+               } \
+       } while(0);
+
 gdk_return
-GDKanalyticalwindowbounds(BAT *r, BAT *b, BAT *p, BAT *l, lng bound, int tpe, 
int unit, bool start)
+GDKanalyticalwindowbounds(BAT *r, BAT *b, BAT *p, BAT *l, const void* restrict 
bound, int tp1, int tp2, int unit, bool start)
 {
        BUN i = 0, k = 0, ncnt, cnt = BATcount(b);
        lng *restrict rb = (lng*) Tloc(r, 0);
        bit *np = p ? (bit*) Tloc(p, 0) : NULL, *pnp = np, *nend = np;
        BATiter bpi = bat_iterator(b);
-       int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe);
+       int (*atomcmp)(const void *, const void *) = ATOMcompare(tp1);
 
        if (unit == 3) { //special case, there are no boundaries
                ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ALL, NO_BOUNDARIES, 
NO_BOUNDARIES)
        } else {
-               assert((!l && bound >= 0) || (l && bound == 0));
-               if (l) { //dynamic bounds
-                       lng *restrict limit = (lng*) Tloc(l, 0);
-                       BUN ll = 0;
-
-                       if (unit == 0) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ROWS, 
limit[ll++], limit[k])
-                       } else if (unit == 1) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_RANGE, 
limit[ll++], limit[k])
-                       } else if (unit == 2) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_GROUPS, 
limit[ll++], limit[k])
-                       } else {
-                               assert(0);
-                       }
-               } else { //fixed bounds
-                       lng limit = bound;
-
-                       if (bound == GDK_lng_max) { //UNBOUNDED PRECEDING and 
UNBOUNDED FOLLOWING cases, avoid overflow.
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_UNBOUNDED, 
limit, limit)
-                       } else if (unit == 0) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ROWS, limit, 
limit)
-                       } else if (unit == 1) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_RANGE, 
limit, limit)
-                       } else if (unit == 2) {
-                               ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_GROUPS, 
limit, limit)
-                       } else {
-                               assert(0);
-                       }
+               assert((!l && bound) || (l && !bound));
+               switch(tp2) {
+                       case TYPE_bte:
+                               ANALYTICAL_BOUNDS_BRANCHES(bte)
+                               break;
+                       case TYPE_sht:
+                               ANALYTICAL_BOUNDS_BRANCHES(sht)
+                               break;
+                       case TYPE_int:
+                               ANALYTICAL_BOUNDS_BRANCHES(int)
+                               break;
+                       case TYPE_lng:
+                               ANALYTICAL_BOUNDS_BRANCHES(lng)
+                               break;
+#ifdef HAVE_HGE
+                       case TYPE_hge:
+                               ANALYTICAL_BOUNDS_BRANCHES(hge)
+                               break;
+#endif
+                       default:
+                               GDKerror("analytical bounds: type %s not 
supported.\n", ATOMname(tp2));
+                               return GDK_FAIL;
                }
        }
        BATsetcount(r, cnt);
@@ -529,6 +553,7 @@ GDKanalyticalwindowbounds(BAT *r, BAT *b
 #undef ANALYTICAL_WINDOW_BOUNDS_BRANCHES
 #undef ANALYTICAL_WINDOW_BOUNDS_LIMIT
 #undef NO_BOUNDARIES
+#undef ANALYTICAL_BOUNDS_BRANCHES
 
 #define NTILE_CALC(TPE)               \
        do {                              \
diff --git a/gdk/gdk_analytic.h b/gdk/gdk_analytic.h
--- a/gdk/gdk_analytic.h
+++ b/gdk/gdk_analytic.h
@@ -17,7 +17,7 @@
 #include "gdk.h"
 
 gdk_export gdk_return GDKanalyticaldiff(BAT *r, BAT *b, BAT *p, int tpe);
-gdk_export gdk_return GDKanalyticalwindowbounds(BAT *r, BAT *b, BAT *p, BAT 
*l, lng limit, int tpe, int unit, bool start);
+gdk_export gdk_return GDKanalyticalwindowbounds(BAT *r, BAT *b, BAT *p, BAT 
*l, const void* restrict bound, int tp1, int tp2, int unit, bool start);
 
 gdk_export gdk_return GDKanalyticalntile(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe, const void* restrict ntile);
 gdk_export gdk_return GDKanalyticallag(BAT *r, BAT *b, BAT *p, BAT *o, BUN 
lag, const void* restrict default_value, int tpe);
diff --git a/sql/backends/monet5/sql_rank.c b/sql/backends/monet5/sql_rank.c
--- a/sql/backends/monet5/sql_rank.c
+++ b/sql/backends/monet5/sql_rank.c
@@ -70,9 +70,11 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
        if (isaBatType(getArgType(mb, pci, 1))) {
                bat *res = getArgReference_bat(stk, pci, 0);
                BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, 
has_partitions ? 2 : 1)), *p = NULL, *r, *l = NULL;
-               int unit = *getArgReference_int(stk, pci, has_partitions ? 3 : 
2);
-               int excl = *getArgReference_int(stk, pci, has_partitions ? 4 : 
3), limit_pos = has_partitions ? 5 : 4;
-               lng limit = 0;
+               int unit = *getArgReference_int(stk, pci, has_partitions ? 3 : 
2),
+                       excl = *getArgReference_int(stk, pci, has_partitions ? 
4 : 3),
+                       limit_pos = has_partitions ? 5 : 4, tpe = 
getArgType(mb, pci, limit_pos);
+               void* limit = NULL;
+               bool is_negative = false;
                gdk_return gdk_code;
 
                assert(unit >= 0 && unit <= 3);
@@ -83,22 +85,79 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
                if (!b)
                        throw(SQL, mod, SQLSTATE(HY005) "Cannot access column 
descriptor");
                voidresultBAT(r, TYPE_lng, BATcount(b), b, mod);
-               if(isaBatType(getArgType(mb, pci, limit_pos))) {
+               if(isaBatType(tpe)) {
+                       tpe = getBatType(tpe);
                        l = BATdescriptor(*getArgReference_bat(stk, pci, 
limit_pos));
                        if (!l) {
                                BBPunfix(b->batCacheid);
                                throw(SQL, mod, SQLSTATE(HY005) "Cannot access 
column descriptor");
                        }
-                       for(lng *lp = (lng*)Tloc(l, 0), *lend = lp + 
BATcount(l); lp < lend; lp++) {
-                               if(*lp < 0) {
+                       switch (tpe) {
+                               case TYPE_bte:
+                                       for(bte *lp = (bte*)Tloc(l, 0), *lend = 
lp + BATcount(l); lp < lend && !is_negative; lp++)
+                                               is_negative |= (*lp < 0);
+                                       break;
+                               case TYPE_sht:
+                                       for(sht *lp = (sht*)Tloc(l, 0), *lend = 
lp + BATcount(l); lp < lend && !is_negative; lp++)
+                                               is_negative |= (*lp < 0);
+                                       break;
+                               case TYPE_int:
+                                       for(int *lp = (int*)Tloc(l, 0), *lend = 
lp + BATcount(l); lp < lend && !is_negative; lp++)
+                                               is_negative |= (*lp < 0);
+                                       break;
+                               case TYPE_lng:
+                                       for(lng *lp = (lng*)Tloc(l, 0), *lend = 
lp + BATcount(l); lp < lend && !is_negative; lp++)
+                                               is_negative |= (*lp < 0);
+                                       break;
+#ifdef HAVE_HGE
+                               case TYPE_hge:
+                                       for(hge *lp = (hge*)Tloc(l, 0), *lend = 
lp + BATcount(l); lp < lend && !is_negative; lp++)
+                                               is_negative |= (*lp < 0);
+                                       break;
+#endif
+                               default: {
                                        BBPunfix(b->batCacheid);
                                        BBPunfix(l->batCacheid);
-                                       throw(SQL, mod, SQLSTATE(HY005) "All 
values on %s boundary must be non-negative", flow ? "PRECEDING" : "FOLLOWING");
+                                       throw(SQL, mod, SQLSTATE(42000) "%s 
limit not available for %s", mod, ATOMname(tpe));
                                }
                        }
+                       if(is_negative) {
+                               BBPunfix(b->batCacheid);
+                               BBPunfix(l->batCacheid);
+                               throw(SQL, mod, SQLSTATE(HY005) "All values on 
%s boundary must be non-negative", flow ? "PRECEDING" : "FOLLOWING");
+                       }
                } else {
-                       limit = *getArgReference_lng(stk, pci, limit_pos);
-                       if(limit < 0)
+                       ValRecord *vlimit = &(stk)->stk[(pci)->argv[limit_pos]];
+
+                       switch (tpe) {
+                               case TYPE_bte:
+                                       is_negative = vlimit->val.btval < 0;
+                                       limit = &vlimit->val.btval;
+                                       break;
+                               case TYPE_sht:
+                                       is_negative = vlimit->val.shval < 0;
+                                       limit = &vlimit->val.shval;
+                                       break;
+                               case TYPE_int:
+                                       is_negative = vlimit->val.ival < 0;
+                                       limit = &vlimit->val.ival;
+                                       break;
+                               case TYPE_lng:
+                                       is_negative = vlimit->val.lval < 0;
+                                       limit = &vlimit->val.lval;
+                                       break;
+#ifdef HAVE_HGE
+                               case TYPE_hge:
+                                       is_negative = vlimit->val.hval < 0;
+                                       limit = &vlimit->val.hval;
+                                       break;
+#endif
+                               default: {
+                                       BBPunfix(b->batCacheid);
+                                       throw(SQL, mod, SQLSTATE(42000) "%s 
limit is not available for %s", mod, ATOMname(tpe));
+                               }
+                       }
+                       if(is_negative)
                                throw(SQL, mod, SQLSTATE(42000) "The %s 
boundary must be non-negative", flow ? "PRECEDING" : "FOLLOWING");
                }
                if (has_partitions) {
@@ -110,7 +169,7 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
                        }
                }
 
-               gdk_code = GDKanalyticalwindowbounds(r, b, p, l, limit, 
b->ttype, unit, flow);
+               gdk_code = GDKanalyticalwindowbounds(r, b, p, l, limit, 
b->ttype, tpe, unit, flow);
                if(l) BBPunfix(l->batCacheid);
                if(p) BBPunfix(p->batCacheid);
                BBPunfix(b->batCacheid);
diff --git a/sql/backends/monet5/sql_rank.mal b/sql/backends/monet5/sql_rank.mal
--- a/sql/backends/monet5/sql_rank.mal
+++ b/sql/backends/monet5/sql_rank.mal
@@ -24,6 +24,152 @@ pattern batsql.diff(p:bat[:bit], b:bat[:
 address SQLdiff
 comment "return true if cur != prev row";
 
+pattern sql.window_start_bound(b:any_1, unit:int, excl:int, start:bte) :lng
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+pattern batsql.window_start_bound(b:bat[:any_1], unit:int, excl:int, 
start:bte) :bat[:lng]
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+pattern sql.window_start_bound(p:bit, b:any_1, unit:int, excl:int, start:bte) 
:lng
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+pattern batsql.window_start_bound(p:bat[:bit], b:bat[:any_1], unit:int, 
excl:int, start:bte) :bat[:lng]
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+pattern batsql.window_start_bound(b:bat[:any_1], unit:int, excl:int, 
start:bat[:bte]) :bat[:lng]
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+pattern batsql.window_start_bound(p:bat[:bit], b:bat[:any_1], unit:int, 
excl:int, start:bat[:bte]) :bat[:lng]
+address SQLwindowstartbound
+comment "computes the start ranges for each row";
+
+
+pattern sql.window_end_bound(b:any_1, unit:int, excl:int, end:bte) :lng
+address SQLwindowendbound
+comment "computes the end ranges for each row";
+
+pattern batsql.window_end_bound(b:bat[:any_1], unit:int, excl:int, end:bte) 
:bat[:lng]
+address SQLwindowendbound
+comment "computes the end ranges for each row";
+
+pattern sql.window_end_bound(p:bit, b:any_1, unit:int, excl:int, end:bte) :lng
+address SQLwindowendbound
+comment "computes the end ranges for each row";
+
+pattern batsql.window_end_bound(p:bat[:bit], b:bat[:any_1], unit:int, 
excl:int, end:bte) :bat[:lng]
+address SQLwindowendbound
+comment "computes the end ranges for each row";
+
+pattern batsql.window_end_bound(b:bat[:any_1], unit:int, excl:int, 
end:bat[:bte]) :bat[:lng]
+address SQLwindowendbound
+comment "computes the end ranges for each row";
+
+pattern batsql.window_end_bound(p:bat[:bit], b:bat[:any_1], unit:int, 
excl:int, end:bat[:bte]) :bat[:lng]
+address SQLwindowendbound
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to