Changeset: 50fa819b01c1 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=50fa819b01c1 Modified Files: monetdb5/optimizer/opt_prelude.c monetdb5/optimizer/opt_prelude.h monetdb5/optimizer/opt_support.c sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_rank.c sql/backends/monet5/sql_rank.h 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/include/sql_catalog.h sql/server/rel_select.c sql/test/analytics/Tests/analytics07.sql sql/test/analytics/Tests/analytics07.stable.out Branch: analytics Log Message:
Cleaned code generation for window bounds, because the range bound with CURRENT ROW has a different meaning, and the current implementation was incompatible for temporal types. Now instead of having separate MAL calls for FOLLOWING and PRECEDING bounds, join both together. diffs (truncated from 1393 to 300 lines): diff --git a/monetdb5/optimizer/opt_prelude.c b/monetdb5/optimizer/opt_prelude.c --- a/monetdb5/optimizer/opt_prelude.c +++ b/monetdb5/optimizer/opt_prelude.c @@ -310,8 +310,7 @@ str unpinRef; str updateRef; str userRef; str vectorRef; -str window_following_boundRef; -str window_preceding_boundRef; +str window_boundRef; str wlcRef; str wlrRef; str zero_or_oneRef; @@ -617,8 +616,7 @@ void optimizerInit(void) updateRef = putName("update"); userRef = putName("user"); vectorRef = putName("vector"); - window_following_boundRef = putName("window_following_bound"); - window_preceding_boundRef = putName("window_preceding_bound"); + window_boundRef = putName("window_bound"); wlcRef = putName("wlc"); wlrRef = putName("wlr"); zero_or_oneRef = putName("zero_or_one"); diff --git a/monetdb5/optimizer/opt_prelude.h b/monetdb5/optimizer/opt_prelude.h --- a/monetdb5/optimizer/opt_prelude.h +++ b/monetdb5/optimizer/opt_prelude.h @@ -310,8 +310,7 @@ mal_export str unpinRef; mal_export str updateRef; mal_export str userRef; mal_export str vectorRef; -mal_export str window_following_boundRef; -mal_export str window_preceding_boundRef; +mal_export str window_boundRef; mal_export str wlcRef; mal_export str wlrRef; mal_export str zero_or_oneRef; diff --git a/monetdb5/optimizer/opt_support.c b/monetdb5/optimizer/opt_support.c --- a/monetdb5/optimizer/opt_support.c +++ b/monetdb5/optimizer/opt_support.c @@ -521,8 +521,7 @@ isOrderDepenent(InstrPtr p) if( getModuleId(p) != batsqlRef) return 0; if ( getFunctionId(p) == differenceRef || - getFunctionId(p) == window_following_boundRef || - getFunctionId(p) == window_preceding_boundRef || + getFunctionId(p) == window_boundRef || getFunctionId(p) == row_numberRef || getFunctionId(p) == rankRef || getFunctionId(p) == dense_rankRef || diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -499,7 +499,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l else if(f->func->type == F_ANALYTIC && es->nrcols == 0) { if(en == exps->h) es = stmt_const(be, bin_first_column(be, left), es); /* ensure the first argument is a column */ - if((!strcmp(f->func->base.name, "window_preceding_bound") || !strcmp(f->func->base.name, "window_following_bound")) + if((!strcmp(f->func->base.name, "window_bound")) && exps->h->next && list_length(f->func->ops) == 6 && en == exps->h->next) es = stmt_const(be, bin_first_column(be, left), es); } 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 @@ -73,47 +73,56 @@ SQLdiff(Client cntxt, MalBlkPtr mb, MalS is_negative = vlimit->val.MEMBER < 0; \ limit = &vlimit->val.MEMBER; \ -static str -doSQLwindowbound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bool preceding, const str mod) +str +SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { - bool has_partitions = (pci->argc > 6); - lng first_half = *getArgReference_lng(stk, pci, has_partitions ? 5 : 4); str msg = MAL_SUCCEED; + bool preceding; + lng first_half; + int unit, bound, excl, part_offset = (pci->argc > 6); + + if ((pci->argc != 6 && pci->argc != 7) || getArgType(mb, pci, part_offset + 2) != TYPE_int || + getArgType(mb, pci, part_offset + 3) != TYPE_int || getArgType(mb, pci, part_offset + 4) != TYPE_int) { + throw(SQL, "sql.window_bound", SQLSTATE(42000) "Invalid arguments"); + } + + unit = *getArgReference_int(stk, pci, part_offset + 2); + bound = *getArgReference_int(stk, pci, part_offset + 3); + excl = *getArgReference_int(stk, pci, part_offset + 4); + + assert(unit >= 0 && unit <= 3); + assert(bound >= 0 && bound <= 5); + assert(excl >= 0 && excl <= 2); + preceding = (bound % 2 == 0); + first_half = (bound < 2 || bound == 4); (void)cntxt; 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), - excl = *getArgReference_int(stk, pci, has_partitions ? 4 : 3), - limit_pos = has_partitions ? 6 : 5, - tp1 = getBatType(getArgType(mb, pci, has_partitions ? 2 : 1)), - tp2 = getArgType(mb, pci, limit_pos); + BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 1)), *p = NULL, *r, *l = NULL; + int tp1 = getBatType(getArgType(mb, pci, part_offset + 1)), tp2 = getArgType(mb, pci, part_offset + 5); void* limit = NULL; bool is_negative = false, is_null = false, is_a_bat; gdk_return gdk_code; - assert(unit >= 0 && unit <= 3); - assert(excl >= 0 && excl <= 2); - if (!b) - throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor"); + throw(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor"); if (excl != 0) { BBPunfix(b->batCacheid); - throw(SQL, mod, SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented"); + throw(SQL, "sql.window_bound", SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented"); } is_a_bat = isaBatType(tp2); if(is_a_bat) tp2 = getBatType(tp2); - voidresultBAT(r, TYPE_lng, BATcount(b), b, mod); - if(is_a_bat) { - l = BATdescriptor(*getArgReference_bat(stk, pci, limit_pos)); + voidresultBAT(r, TYPE_lng, BATcount(b), b, "sql.window_bound"); + if(is_a_bat) { //SQL_CURRENT_ROW shall never fall in limit validation + l = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 5)); if (!l) { BBPunfix(b->batCacheid); - throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor"); + throw(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor"); } switch (tp2) { case TYPE_bte: @@ -142,18 +151,18 @@ doSQLwindowbound(Client cntxt, MalBlkPtr default: { BBPunfix(b->batCacheid); BBPunfix(l->batCacheid); - throw(SQL, mod, SQLSTATE(42000) "%s limit not available for %s", mod, ATOMname(tp2)); + throw(SQL, "sql.window_bound", SQLSTATE(42000) "%s limit not available for %s", "sql.window_bound", ATOMname(tp2)); } } if(is_null || is_negative) { BBPunfix(b->batCacheid); BBPunfix(l->batCacheid); if(is_null) - throw(SQL, mod, SQLSTATE(HY005) "All values on %s boundary must be non-null", preceding ? "PRECEDING" : "FOLLOWING"); - throw(SQL, mod, SQLSTATE(HY005) "All values on %s boundary must be non-negative", preceding ? "PRECEDING" : "FOLLOWING"); + throw(SQL, "sql.window_bound", SQLSTATE(HY005) "All values on %s boundary must be non-null", preceding ? "PRECEDING" : "FOLLOWING"); + throw(SQL, "sql.window_bound", SQLSTATE(HY005) "All values on %s boundary must be non-negative", preceding ? "PRECEDING" : "FOLLOWING"); } } else { - ValRecord *vlimit = &(stk)->stk[(pci)->argv[limit_pos]]; + ValRecord *vlimit = &(stk)->stk[(pci)->argv[part_offset + 5]]; switch (tp2) { case TYPE_bte: @@ -181,24 +190,25 @@ doSQLwindowbound(Client cntxt, MalBlkPtr #endif default: { BBPunfix(b->batCacheid); - throw(SQL, mod, SQLSTATE(42000) "%s limit is not available for %s", mod, ATOMname(tp2)); + throw(SQL, "sql.window_bound", SQLSTATE(42000) "%s limit is not available for %s", "sql.window_bound", ATOMname(tp2)); } } if(is_null) - throw(SQL, mod, SQLSTATE(42000) "The %s boundary must be non-null", preceding ? "PRECEDING" : "FOLLOWING"); + throw(SQL, "sql.window_bound", SQLSTATE(42000) "The %s boundary must be non-null", preceding ? "PRECEDING" : "FOLLOWING"); if(is_negative) - throw(SQL, mod, SQLSTATE(42000) "The %s boundary must be non-negative", preceding ? "PRECEDING" : "FOLLOWING"); + throw(SQL, "sql.window_bound", SQLSTATE(42000) "The %s boundary must be non-negative", preceding ? "PRECEDING" : "FOLLOWING"); } - if (has_partitions) { + if (part_offset) { p = BATdescriptor(*getArgReference_bat(stk, pci, 1)); if (!p) { if(l) BBPunfix(l->batCacheid); BBPunfix(b->batCacheid); - throw(SQL, mod, SQLSTATE(HY005) "Cannot access column descriptor"); + throw(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor"); } } - if((tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) && unit == 1) { //only for RANGE frame + //On RANGE frame, when "CURRENT ROW" is not specified, the ranges are calculated with SQL intervals in mind + if((tp1 == TYPE_daytime || tp1 == TYPE_date || tp1 == TYPE_timestamp) && unit == 1 && bound < 4) { msg = MTIMEanalyticalrangebounds(r, b, p, l, limit, tp1, tp2, preceding, first_half); if(msg == MAL_SUCCEED) BBPkeepref(*res = r->batCacheid); @@ -207,7 +217,7 @@ doSQLwindowbound(Client cntxt, MalBlkPtr if(gdk_code == GDK_SUCCEED) BBPkeepref(*res = r->batCacheid); else - msg = createException(SQL, mod, GDK_EXCEPTION); + msg = createException(SQL, "sql.window_bound", GDK_EXCEPTION); } if(l) BBPunfix(l->batCacheid); if(p) BBPunfix(p->batCacheid); @@ -220,18 +230,6 @@ doSQLwindowbound(Client cntxt, MalBlkPtr return msg; } -str -SQLwindow_preceding_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) -{ - return doSQLwindowbound(cntxt, mb, stk, pci, true, "sql.window_preceding_bound"); -} - -str -SQLwindow_following_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) -{ - return doSQLwindowbound(cntxt, mb, stk, pci, false, "sql.window_following_bound"); -} - str SQLrow_number(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { diff --git a/sql/backends/monet5/sql_rank.h b/sql/backends/monet5/sql_rank.h --- a/sql/backends/monet5/sql_rank.h +++ b/sql/backends/monet5/sql_rank.h @@ -12,8 +12,7 @@ #include "sql.h" sql5_export str SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); -sql5_export str SQLwindow_preceding_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); -sql5_export str SQLwindow_following_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +sql5_export str SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); sql5_export str SQLrow_number(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); sql5_export str SQLrank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); sql5_export str SQLdense_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); 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,299 +24,155 @@ pattern batsql.diff(p:bat[:bit], b:bat[: address SQLdiff comment "return true if cur != prev row"; -pattern sql.window_preceding_bound(b:any_1, unit:int, excl:int, fh:lng, start:bte) :lng -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern sql.window_bound(b:any_1, unit:int, bound:int, excl:int, limit:bte) :lng +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern batsql.window_preceding_bound(b:bat[:any_1], unit:int, excl:int, fh:lng, start:bte) :bat[:lng] -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern batsql.window_bound(b:bat[:any_1], unit:int, bound:int, excl:int, limit:bte) :bat[:lng] +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern sql.window_preceding_bound(p:bit, b:any_1, unit:int, excl:int, fh:lng, start:bte) :lng -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern sql.window_bound(p:bit, b:any_1, unit:int, bound:int, excl:int, limit:bte) :lng +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern batsql.window_preceding_bound(p:bat[:bit], b:bat[:any_1], unit:int, excl:int, fh:lng, start:bte) :bat[:lng] -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern batsql.window_bound(p:bat[:bit], b:bat[:any_1], unit:int, bound:int, excl:int, limit:bte) :bat[:lng] +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern batsql.window_preceding_bound(b:bat[:any_1], unit:int, excl:int, fh:lng, start:bat[:bte]) :bat[:lng] -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern batsql.window_bound(b:bat[:any_1], unit:int, bound:int, excl:int, limit:bat[:bte]) :bat[:lng] +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern batsql.window_preceding_bound(p:bat[:bit], b:bat[:any_1], unit:int, excl:int, fh:lng, start:bat[:bte]) :bat[:lng] -address SQLwindow_preceding_bound -comment "computes the start ranges for each row"; +pattern batsql.window_bound(p:bat[:bit], b:bat[:any_1], unit:int, bound:int, excl:int, limit:bat[:bte]) :bat[:lng] +address SQLwindow_bound +comment "computes window ranges for each row"; -pattern sql.window_following_bound(b:any_1, unit:int, excl:int, fh:lng, end:bte) :lng -address SQLwindow_following_bound -comment "computes the end ranges for each row"; - -pattern batsql.window_following_bound(b:bat[:any_1], unit:int, excl:int, fh:lng, end:bte) :bat[:lng] -address SQLwindow_following_bound -comment "computes the end ranges for each row"; - -pattern sql.window_following_bound(p:bit, b:any_1, unit:int, excl:int, fh:lng, end:bte) :lng -address SQLwindow_following_bound -comment "computes the end ranges for each row"; +pattern sql.window_bound(b:any_1, unit:int, bound:int, excl:int, limit:sht) :lng +address SQLwindow_bound +comment "computes window ranges for each row"; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list