Changeset: 29e34420a9e9 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=29e34420a9e9
Modified Files:
gdk/gdk_analytic.c
sql/backends/monet5/sql_rank.c
Branch: analytics
Log Message:
Check for overflows while calculating a range boundary. Also check for NULL
boundaries.
diffs (250 lines):
diff --git a/gdk/gdk_analytic.c b/gdk/gdk_analytic.c
--- a/gdk/gdk_analytic.c
+++ b/gdk/gdk_analytic.c
@@ -140,7 +140,9 @@ GDKanalyticaldiff(BAT *r, BAT *b, BAT *p
rlimit = (TPE) BOUNDF; \
v = *pbp; \
for(bs=pbp-1; bs>bl; bs--, curval++) { \
- if (ABSOLUTE(v - *bs) > rlimit) \
+ TPE calc; \
+ SUB_WITH_CHECK(TPE, v, TPE, *bs, TPE, calc,
GDK_##TPE##_max, goto calc_overflow); \
+ if (ABSOLUTE(calc) > rlimit) \
break; \
} \
*rb = curval; \
@@ -155,7 +157,9 @@ GDKanalyticaldiff(BAT *r, BAT *b, BAT *p
rlimit = (TPE) BOUNDF; \
v = *pbp; \
for(bs=pbp+1; bs<bp; bs++, curval++) { \
- if (ABSOLUTE(v - *bs) > rlimit) \
+ TPE calc; \
+ SUB_WITH_CHECK(TPE, v, TPE, *bs, TPE, calc,
GDK_##TPE##_max, goto calc_overflow); \
+ if (ABSOLUTE(calc) > rlimit) \
break; \
} \
*rb = curval; \
@@ -490,11 +494,12 @@ GDKanalyticaldiff(BAT *r, BAT *b, BAT *p
gdk_return
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);
+ BUN i = 0, k = 0, ncnt, cnt = BATcount(b), nils = 0;
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(tp1);
+ int abort_on_error = 1;
if (unit == 3) { //special case, there are no boundaries
ANALYTICAL_WINDOW_BOUNDS_BRANCHES(_ALL, NO_BOUNDARIES,
NO_BOUNDARIES)
@@ -523,9 +528,14 @@ GDKanalyticalwindowbounds(BAT *r, BAT *b
return GDK_FAIL;
}
}
+ goto finish;
+calc_overflow:
+ GDKerror("22003!overflow in calculation.\n");
+ return GDK_FAIL;
+finish:
BATsetcount(r, cnt);
- r->tnonil = true;
- r->tnil = false;
+ r->tnonil = (nils == 0);
+ r->tnil = (nils > 0);
return GDK_SUCCEED;
}
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
@@ -52,7 +52,7 @@ SQLdiff(Client cntxt, MalBlkPtr mb, MalS
if(gdk_code == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- throw(SQL, "sql.diff", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ throw(SQL, "sql.diff", GDK_EXCEPTION);
} else {
bit *res = getArgReference_bit(stk, pci, 0);
@@ -74,7 +74,7 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
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;
+ bool is_negative = false, is_null = false;
gdk_return gdk_code;
assert(unit >= 0 && unit <= 3);
@@ -94,25 +94,35 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
}
switch (tpe) {
case TYPE_bte:
- for(bte *lp = (bte*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_negative; lp++)
+ for(bte *lp = (bte*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_null && !is_negative; lp++) {
+ is_null |= is_bte_nil(*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++)
+ for(sht *lp = (sht*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_null && !is_negative; lp++) {
+ is_null |= is_sht_nil(*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++)
+ for(int *lp = (int*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_null && !is_negative; lp++) {
+ is_null |= is_int_nil(*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++)
+ for(lng *lp = (lng*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_null && !is_negative; lp++) {
+ is_null |= is_lng_nil(*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++)
+ for(hge *lp = (hge*)Tloc(l, 0), *lend =
lp + BATcount(l); lp < lend && !is_null && !is_negative; lp++) {
+ is_null |= is_hge_nil(*lp);
is_negative |= (*lp < 0);
+ }
break;
#endif
default: {
@@ -121,9 +131,11 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
throw(SQL, mod, SQLSTATE(42000) "%s
limit not available for %s", mod, ATOMname(tpe));
}
}
- if(is_negative) {
+ 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", flow ? "PRECEDING" : "FOLLOWING");
throw(SQL, mod, SQLSTATE(HY005) "All values on
%s boundary must be non-negative", flow ? "PRECEDING" : "FOLLOWING");
}
} else {
@@ -131,23 +143,28 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
switch (tpe) {
case TYPE_bte:
+ is_null = is_bte_nil(vlimit->val.btval);
is_negative = vlimit->val.btval < 0;
limit = &vlimit->val.btval;
break;
case TYPE_sht:
+ is_null = is_sht_nil(vlimit->val.shval);
is_negative = vlimit->val.shval < 0;
limit = &vlimit->val.shval;
break;
case TYPE_int:
+ is_null = is_int_nil(vlimit->val.ival);
is_negative = vlimit->val.ival < 0;
limit = &vlimit->val.ival;
break;
case TYPE_lng:
+ is_null = is_lng_nil(vlimit->val.lval);
is_negative = vlimit->val.lval < 0;
limit = &vlimit->val.lval;
break;
#ifdef HAVE_HGE
case TYPE_hge:
+ is_null = is_hge_nil(vlimit->val.hval);
is_negative = vlimit->val.hval < 0;
limit = &vlimit->val.hval;
break;
@@ -157,6 +174,8 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
throw(SQL, mod, SQLSTATE(42000) "%s
limit is not available for %s", mod, ATOMname(tpe));
}
}
+ if(is_null)
+ throw(SQL, mod, SQLSTATE(42000) "The %s
boundary must be non-null", flow ? "PRECEDING" : "FOLLOWING");
if(is_negative)
throw(SQL, mod, SQLSTATE(42000) "The %s
boundary must be non-negative", flow ? "PRECEDING" : "FOLLOWING");
}
@@ -176,7 +195,7 @@ doSQLwindowbound(Client cntxt, MalBlkPtr
if(gdk_code == GDK_SUCCEED) {
BBPkeepref(*res = r->batCacheid);
} else {
- throw(SQL, mod, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ throw(SQL, mod, GDK_EXCEPTION);
}
} else {
lng *res = getArgReference_lng(stk, pci, 0);
@@ -673,7 +692,7 @@ SQLntile(Client cntxt, MalBlkPtr mb, Mal
if(gdk_code == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- throw(SQL, "sql.ntile", SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, "sql.ntile", GDK_EXCEPTION);
} else {
ptr res = getArgReference_ptr(stk, pci, 0);
ptr in = getArgReference_ptr(stk, pci, 1);
@@ -803,7 +822,7 @@ do_limit_value(Client cntxt, MalBlkPtr m
if (gdk_res == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- return createException(SQL, op, SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, op, GDK_EXCEPTION);
} else {
ptr *res = getArgReference(stk, pci, 0);
ptr *in = getArgReference(stk, pci, 1);
@@ -914,7 +933,7 @@ SQLnth_value(Client cntxt, MalBlkPtr mb,
if(gdk_code == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- throw(SQL, "sql.nth_value", SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, "sql.nth_value", GDK_EXCEPTION);
} else {
ValRecord *res = &(stk)->stk[(pci)->argv[0]];
ValRecord *in = &(stk)->stk[(pci)->argv[1]];
@@ -1046,7 +1065,7 @@ do_lead_lag(Client cntxt, MalBlkPtr mb,
if(gdk_code == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- throw(SQL, op, SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ throw(SQL, op, GDK_EXCEPTION);
} else {
ValRecord *res = &(stk)->stk[(pci)->argv[0]];
ValRecord *vin = &(stk)->stk[(pci)->argv[1]];
@@ -1099,7 +1118,7 @@ SQLanalytical_func(Client cntxt, MalBlkP
if (gdk_res == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- return createException(SQL, op, SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, op, GDK_EXCEPTION);
} else {
ptr *res = getArgReference(stk, pci, 0);
ptr *in = getArgReference(stk, pci, 1);
@@ -1176,7 +1195,7 @@ SQLcount(Client cntxt, MalBlkPtr mb, Mal
if (gdk_res == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- return createException(SQL, "sql.count",
SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ throw(SQL, "sql.count", GDK_EXCEPTION);
} else {
lng *res = getArgReference(stk, pci, 0);
ptr *in = getArgReference(stk, pci, 1);
@@ -1261,7 +1280,7 @@ do_analytical_sumprod(Client cntxt, MalB
if (gdk_res == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- return createException(SQL, op, SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, op, GDK_EXCEPTION);
} else {
ptr *res = getArgReference(stk, pci, 0);
ptr *in = getArgReference(stk, pci, 1);
@@ -1354,7 +1373,7 @@ SQLavg(Client cntxt, MalBlkPtr mb, MalSt
if (gdk_res == GDK_SUCCEED)
BBPkeepref(*res = r->batCacheid);
else
- return createException(SQL, "sql.avg", SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ throw(SQL, "sql.avg", GDK_EXCEPTION);
} else {
ptr *res = getArgReference(stk, pci, 0);
ptr *in = getArgReference(stk, pci, 1);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list