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