Changeset: 91ffc175a0e6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/91ffc175a0e6
Modified Files:
        gdk/gdk_aggr.c
        gdk/gdk_join.c
        monetdb5/mal/mal_instruction.c
        monetdb5/mal/mal_interpreter.c
        monetdb5/mal/mal_resolve.c
        monetdb5/mal/mal_session.c
        monetdb5/optimizer/opt_macro.c
        monetdb5/optimizer/opt_reorder.c
        sql/backends/monet5/UDF/pyapi3/conversion3.c
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_scenario.c
        sql/storage/sql_storage.h
        sql/storage/store.c
        sql/storage/store_dependency.c
Branch: Sep2022
Log Message:

Do more error checking, most for running in low memory conditions.


diffs (truncated from 639 to 300 lines):

diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -56,6 +56,8 @@
  * This function finds the minimum and maximum group id (and the
  * number of groups) and initializes the variables for candidates
  * selection.
+ *
+ * In case of error, returns an error message.
  */
 const char *
 BATgroupaggrinit(BAT *b, BAT *g, BAT *e, BAT *s,
diff --git a/gdk/gdk_join.c b/gdk/gdk_join.c
--- a/gdk/gdk_join.c
+++ b/gdk/gdk_join.c
@@ -3054,7 +3054,7 @@ hashjoin(BAT **r1p, BAT **r2p, BAT *l, B
 /* Count the number of unique values for the first half and the complete
  * set (the sample s of b) and return the two values in *cnt1 and
  * *cnt2. In case of error, both values are 0. */
-static void
+static gdk_return
 count_unique(BAT *b, BAT *s, BUN *cnt1, BUN *cnt2)
 {
        struct canditer ci;
@@ -3080,7 +3080,7 @@ count_unique(BAT *b, BAT *s, BUN *cnt1, 
                /* trivial: already unique */
                *cnt1 = half;
                *cnt2 = ci.ncand;
-               return;
+               return GDK_SUCCEED;
        }
 
        (void) BATordered(b);
@@ -3091,7 +3091,7 @@ count_unique(BAT *b, BAT *s, BUN *cnt1, 
                /* trivial: all values are the same */
                *cnt1 = *cnt2 = 1;
                bat_iterator_end(&bi);
-               return;
+               return GDK_SUCCEED;
        }
 
        assert(bi.type != TYPE_void);
@@ -3152,7 +3152,7 @@ count_unique(BAT *b, BAT *s, BUN *cnt1, 
                seen = GDKzalloc((65536 / 32) * sizeof(seen[0]));
                if (seen == NULL) {
                        bat_iterator_end(&bi);
-                       return;
+                       return GDK_FAIL;
                }
                for (i = 0; i < ci.ncand; i++) {
                        if (i == half) {
@@ -3193,7 +3193,7 @@ count_unique(BAT *b, BAT *s, BUN *cnt1, 
                        HEAPfree(&hs.heaplink, true);
                        HEAPfree(&hs.heapbckt, true);
                        bat_iterator_end(&bi);
-                       return;
+                       return GDK_FAIL;
                }
                for (i = 0; i < ci.ncand; i++) {
                        if (i == half)
@@ -3226,7 +3226,7 @@ count_unique(BAT *b, BAT *s, BUN *cnt1, 
                  ALGOBATPAR(b), ALGOOPTBATPAR(s),
                  *cnt1, *cnt2, algomsg, GDKusec() - t0);
 
-       return;
+       return GDK_SUCCEED;
 }
 
 static double
@@ -3251,12 +3251,19 @@ guess_uniques(BAT *b, struct canditer *c
                s1 = BATsample_with_seed(b, 1000, (uint64_t) GDKusec() * 
(uint64_t) b->batCacheid);
        } else {
                BAT *s2 = BATsample_with_seed(ci->s, 1000, (uint64_t) GDKusec() 
* (uint64_t) b->batCacheid);
+               if (s2 == NULL)
+                       return -1;
                s1 = BATproject(s2, ci->s);
                BBPreclaim(s2);
        }
+       if (s1 == NULL)
+               return -1;
        BUN n2 = BATcount(s1);
        BUN n1 = n2 / 2;
-       count_unique(b, s1, &cnt1, &cnt2);
+       if (count_unique(b, s1, &cnt1, &cnt2) != GDK_SUCCEED) {
+               BBPreclaim(s1);
+               return -1;
+       }
        BBPreclaim(s1);
 
        double A = (double) (cnt2 - cnt1) / (n2 - n1);
@@ -3337,8 +3344,11 @@ joincost(BAT *r, struct canditer *lci, s
                        MT_lock_set(&r->theaplock);
                        double unique_est = r->tunique_est;
                        MT_lock_unset(&r->theaplock);
-                       if (unique_est == 0)
+                       if (unique_est == 0) {
                                unique_est = guess_uniques(r, &(struct 
canditer){.tpe=cand_dense, .ncand=BATcount(r)});
+                               if (unique_est < 0)
+                                       return -1;
+                       }
                        /* we have an estimate of the number of unique
                         * values, assume some collisions */
                        rcost *= 1.1 * ((double) cnt / unique_est);
@@ -3367,8 +3377,11 @@ joincost(BAT *r, struct canditer *lci, s
                        MT_lock_set(&r->theaplock);
                        double unique_est = r->tunique_est;
                        MT_lock_unset(&r->theaplock);
-                       if (unique_est == 0)
+                       if (unique_est == 0) {
                                unique_est = guess_uniques(r, rci);
+                               if (unique_est < 0)
+                                       return -1;
+                       }
                        /* we have an estimate of the number of unique
                         * values, assume some chains */
                        rccost = 1.1 * ((double) cnt / unique_est);
@@ -3873,6 +3886,10 @@ leftjoin(BAT **r1p, BAT **r2p, BAT *l, B
                }
        }
        rcost = joincost(r, &lci, &rci, &rhash, &prhash, &rcand);
+       if (rcost < 0) {
+               rc = GDK_FAIL;
+               goto doreturn;
+       }
 
        if (!nil_on_miss && !only_misses && !not_in && !max_one && !min_one) {
                /* maybe do a hash join on the swapped operands; if we
@@ -3882,6 +3899,10 @@ leftjoin(BAT **r1p, BAT **r2p, BAT *l, B
                double lcost;
 
                lcost = joincost(l, &rci, &lci, &lhash, &plhash, &lcand);
+               if (lcost < 0) {
+                       rc = GDK_FAIL;
+                       goto doreturn;
+               }
                if (semi)
                        lcost += rci.ncand; /* cost of BATunique(r) */
                /* add cost of sorting; obviously we don't know the
@@ -4196,6 +4217,10 @@ BATjoin(BAT **r1p, BAT **r2p, BAT *l, BA
 
        lcost = joincost(l, &rci, &lci, &lhash, &plhash, &lcand);
        rcost = joincost(r, &lci, &rci, &rhash, &prhash, &rcand);
+       if (lcost < 0 || rcost < 0) {
+               rc = GDK_FAIL;
+               goto doreturn;
+       }
 
        /* if the cost of doing searches on l is lower than the cost
         * of doing searches on r, we swap */
diff --git a/monetdb5/mal/mal_instruction.c b/monetdb5/mal/mal_instruction.c
--- a/monetdb5/mal/mal_instruction.c
+++ b/monetdb5/mal/mal_instruction.c
@@ -114,7 +114,10 @@ newMalBlk(int elements)
 
        /* each MAL instruction implies at least one variable
         * we reserve some extra for constants */
-       elements= (elements + 8) %  MALCHUNK == 0 ? elements + 8: ((elements + 
8)/MALCHUNK + 1) * MALCHUNK;
+       assert(elements >= 0);
+       elements += 8;
+       if (elements % MALCHUNK != 0)
+               elements = (elements / MALCHUNK + 1) * MALCHUNK;
        v = (VarRecord *) GDKzalloc(sizeof(VarRecord) * elements );
        if (v == NULL) {
                GDKfree(mb);
@@ -152,17 +155,13 @@ newMalBlk(int elements)
        return mb;
 }
 
-/* We only grow until the MAL block can be used */
-static int growBlk(int elm)
-{
-       return elm % MALCHUNK ==0 ? elm + MALCHUNK : elm;
-}
-
 int
 resizeMalBlk(MalBlkPtr mb, int elements)
 {
        int i;
-       elements = elements  %  MALCHUNK == 0?  elements: (elements / MALCHUNK 
+1) * MALCHUNK;
+       assert(elements >= 0);
+       if (elements % MALCHUNK != 0)
+               elements = (elements / MALCHUNK + 1) * MALCHUNK;
 
        if( elements > mb->ssize){
                InstrPtr *ostmt = mb->stmt;
@@ -773,8 +772,7 @@ makeVarSpace(MalBlkPtr mb)
 {
        if (mb->vtop >= mb->vsize) {
                VarRecord *new;
-               int s = growBlk(mb->vsize);
-
+               int s = (mb->vtop / MALCHUNK + 1) * MALCHUNK;
                new = (VarRecord*) GDKrealloc(mb->var, s * sizeof(VarRecord));
                if (new == NULL) {
                        // the only place to return an error signal at this 
stage.
@@ -782,7 +780,7 @@ makeVarSpace(MalBlkPtr mb)
                        mb->errors = createMalException(mb,0,TYPE, 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
                        return -1;
                }
-               memset( ((char*) new) + mb->vsize * sizeof(VarRecord), 0, (s- 
mb->vsize) * sizeof(VarRecord));
+               memset(new + mb->vsize, 0, (s - mb->vsize) * sizeof(VarRecord));
                mb->vsize = s;
                mb->var = new;
        }
@@ -828,7 +826,6 @@ newVariable(MalBlkPtr mb, const char *na
                return -1;
        }
        if (makeVarSpace(mb)) {
-               assert(0);
                /* no space for a new variable */
                return -1;
        }
@@ -898,7 +895,8 @@ newTypeVariable(MalBlkPtr mb, malType ty
        if( i < mb->vtop )
                return i;
        n = newTmpVariable(mb, type);
-       setVarTypedef(mb, n);
+       if (n >= 0)
+               setVarTypedef(mb, n);
        return n;
 }
 
@@ -977,6 +975,7 @@ trimMalVariables_(MalBlkPtr mb, MalStkPt
                                getArg(q, j) = alias[getArg(q, j)];
                        }
                }
+               mb->vtop = cnt;
        }
        /* rename the temporary variable */
        mb->vid = 0;
@@ -987,7 +986,6 @@ trimMalVariables_(MalBlkPtr mb, MalStkPt
 */
 
        GDKfree(alias);
-       mb->vtop = cnt;
 }
 
 void
@@ -1411,11 +1409,12 @@ pushInstruction(MalBlkPtr mb, InstrPtr p
 
        extra = mb->vsize - mb->vtop; // the extra variables already known
        if (mb->stop + 1 >= mb->ssize) {
-               if( resizeMalBlk(mb, growBlk(mb->ssize + extra)) ){
+               int s = ((mb->ssize + extra) / MALCHUNK + 1) * MALCHUNK;
+               if( resizeMalBlk(mb, s) < 0 ){
                        /* perhaps we can continue with a smaller increment.
                         * But the block remains marked as faulty.
                         */
-                       if( resizeMalBlk(mb,mb->ssize + 1)){
+                       if( resizeMalBlk(mb,mb->ssize + 1) < 0){
                                /* we are now left with the situation that the 
new instruction is dangling .
                                 * The hack is to take an instruction out of 
the block that is likely not referenced independently
                                 * The last resort is to take the first, which 
should always be there
diff --git a/monetdb5/mal/mal_interpreter.c b/monetdb5/mal/mal_interpreter.c
--- a/monetdb5/mal/mal_interpreter.c
+++ b/monetdb5/mal/mal_interpreter.c
@@ -854,7 +854,8 @@ runMALsequence(Client cntxt, MalBlkPtr m
 
                        stkpc= mb->stop;
                        continue;
-               }       }
+               }
+               }
 
                /* monitoring information should reflect the input arguments,
                   which may be removed by garbage collection  */
diff --git a/monetdb5/mal/mal_resolve.c b/monetdb5/mal/mal_resolve.c
--- a/monetdb5/mal/mal_resolve.c
+++ b/monetdb5/mal/mal_resolve.c
@@ -690,11 +690,16 @@ chkInstruction(Module s, MalBlkPtr mb, I
 str
 chkProgram(Module s, MalBlkPtr mb)
 {
-       str msg = MAL_SUCCEED;
+       str msg;
 /* it is not ready yet, too fragile
                mb->typefixed = mb->stop == chk; ignored END */
 /*     if( mb->flowfixed == 0)*/
 
+       if (mb->errors){
+               msg = mb->errors;
+               mb->errors = NULL;
+               return msg;
+       }
        msg = chkTypes(s, mb, FALSE);
        if( msg == MAL_SUCCEED)
                msg = chkFlow(mb);
diff --git a/monetdb5/mal/mal_session.c b/monetdb5/mal/mal_session.c
--- a/monetdb5/mal/mal_session.c
+++ b/monetdb5/mal/mal_session.c
@@ -106,7 +106,8 @@ MSresetClientPrg(Client cntxt, const cha
        setModuleId(p, mod);
        setFunctionId(p, fcn);
        if( findVariable(mb,fcn) < 0)
-               p->argv[0] = newVariable(mb, fcn, strlen(fcn), TYPE_void);
+               if ((p->argv[0] = newVariable(mb, fcn, strlen(fcn), TYPE_void)) 
< 0)
+                       throw(MAL, "resetClientPrg", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
 
        setVarType(mb, findVariable(mb, fcn), TYPE_void);
        /* remove any MAL history */
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to