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]