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

Reply via email to