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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list