Changeset: 23ce54d1749b for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=23ce54d1749b
Modified Files:
gdk/gdk_arrays.h
monetdb5/modules/kernel/arrays.c
sql/backends/monet5/rel_bin.c
Branch: arrays
Log Message:
fixed bug when pushing selections on dimensions
fixed a bug when having empty results
organised the code better
diffs (truncated from 342 to 300 lines):
diff --git a/gdk/gdk_arrays.h b/gdk/gdk_arrays.h
--- a/gdk/gdk_arrays.h
+++ b/gdk/gdk_arrays.h
@@ -143,6 +143,70 @@ gdk_cells* cells_replace_dimension(gdk_c
idx; \
})
+#define lowerIdx(dim, value, eq) \
+({\
+ BUN idx = 0; \
+ switch(dim->type) { \
+ case TYPE_bte: \
+ idx = dimensionFndLowerValuePos(*(bte*)value,
*(bte*)dim->min, *(bte*)dim->step, eq); \
+ break; \
+ case TYPE_sht: \
+ idx = dimensionFndLowerValuePos(*(sht*)value,
*(sht*)dim->min, *(sht*)dim->step, eq); \
+ break; \
+ case TYPE_int:\
+ idx = dimensionFndLowerValuePos(*(int*)value,
*(int*)dim->min, *(int*)dim->step, eq); \
+ break; \
+ case TYPE_flt:\
+ idx = dimensionFndLowerValuePos(*(flt*)value,
*(flt*)dim->min, *(flt*)dim->step, eq); \
+ break; \
+ case TYPE_dbl:\
+ idx = dimensionFndLowerValuePos(*(dbl*)value,
*(dbl*)dim->min, *(dbl*)dim->step, eq); \
+ break; \
+ case TYPE_lng:\
+ idx = dimensionFndLowerValuePos(*(lng*)value,
*(lng*)dim->min, *(lng*)dim->step, eq); \
+ break; \
+ case TYPE_hge:\
+ idx = dimensionFndLowerValuePos(*(hge*)value,
*(hge*)dim->min, *(hge*)dim->step, eq); \
+ break; \
+ case TYPE_oid:\
+ idx = dimensionFndLowerValuePos(*(oid*)value,
*(oid*)dim->min, *(oid*)dim->step, eq); \
+ break; \
+ } \
+ idx; \
+})
+
+#define greaterIdx(dim, value, eq) \
+({\
+ BUN idx = 0; \
+ switch(dim->type) { \
+ case TYPE_bte: \
+ idx = dimensionFndGreaterValuePos(*(bte*)value,
*(bte*)dim->min, *(bte*)dim->step, eq); \
+ break; \
+ case TYPE_sht: \
+ idx = dimensionFndGreaterValuePos(*(sht*)value,
*(sht*)dim->min, *(sht*)dim->step, eq); \
+ break; \
+ case TYPE_int:\
+ idx = dimensionFndGreaterValuePos(*(int*)value,
*(int*)dim->min, *(int*)dim->step, eq); \
+ break; \
+ case TYPE_flt:\
+ idx = dimensionFndGreaterValuePos(*(flt*)value,
*(flt*)dim->min, *(flt*)dim->step, eq); \
+ break; \
+ case TYPE_dbl:\
+ idx = dimensionFndGreaterValuePos(*(dbl*)value,
*(dbl*)dim->min, *(dbl*)dim->step, eq); \
+ break; \
+ case TYPE_lng:\
+ idx = dimensionFndGreaterValuePos(*(lng*)value,
*(lng*)dim->min, *(lng*)dim->step, eq); \
+ break; \
+ case TYPE_hge:\
+ idx = dimensionFndGreaterValuePos(*(hge*)value,
*(hge*)dim->min, *(hge*)dim->step, eq); \
+ break; \
+ case TYPE_oid:\
+ idx = dimensionFndGreaterValuePos(*(oid*)value,
*(oid*)dim->min, *(oid*)dim->step, eq); \
+ break; \
+ } \
+ idx; \
+})
+
diff --git a/monetdb5/modules/kernel/arrays.c b/monetdb5/modules/kernel/arrays.c
--- a/monetdb5/modules/kernel/arrays.c
+++ b/monetdb5/modules/kernel/arrays.c
@@ -24,13 +24,19 @@ static gdk_cells* sizesToDimensions(gdk_
return resDims;
}
+static bool compatibleRanges(gdk_dimension *dim1, gdk_dimension *dim2) {
+ if(*(oid*)dim1->max < *(oid*)dim2->min || *(oid*)dim2->max <
*(oid*)dim1->min) {
+ //disjoint ranges. empty result
+ return 0;
+ }
+ return 1;
+}
+
static gdk_dimension* merge2CandidateDimensions(gdk_dimension *dim1,
gdk_dimension *dim2) {
oid min, max, step;
- if(*(oid*)dim1->max < *(oid*)dim2->min || *(oid*)dim2->max <
*(oid*)dim1->min) {
- //disjoint ranges. cannot merge
- return NULL;
- }
+ //check whether the merge creates a dimension or not
+ //In case it does not return NULL and then a BAT should be created
/*the biggest of the mins and the smallest of the maximums */
min = *(oid*)dim1->min > *(oid*)dim2->min ? *(oid*)dim1->min :
*(oid*)dim2->min;
@@ -41,20 +47,8 @@ static gdk_dimension* merge2CandidateDim
//they also have the same number of initial elements because the came
from the same dimension
return createDimension_oid(dim1->dimNum, dim1->initialElementsNum, min,
max, step); }
-static gdk_cells* mergeCandidateDimensions(gdk_cells *dims, gdk_dimension
*dim) {
- gdk_dimension *candDim = getDimension(dims, dim->dimNum);
- gdk_dimension *mergedDim = merge2CandidateDimensions(candDim, dim);
-
-
- //check the limits of the two dimensions
- if(!mergedDim) {
- fprintf(stderr, "Disjoint ranges. Create a BAT");
- //remove the dimension from the candidates
- return cells_remove_dimension(dims, candDim->dimNum);
- }
-
- //create a new dimension that is the combined result of the candidates
and the dim
- return cells_replace_dimension(dims, mergedDim);
+static gdk_dimension* mergeCandidateDimensions(gdk_dimension *dim1,
gdk_dimension *dim2) {
+ return merge2CandidateDimensions(dim1, dim2);
}
static BUN oidToIdx(oid oidVal, int dimNum, int currentDimNum, BUN skipCells,
gdk_array *dims) {
@@ -187,49 +181,59 @@ str ALGdimensionLeftfetchjoin(bat *resul
}
-#if 0
-static str
-ALGbinary(bat *result, const bat *lid, const bat *rid, BAT* (*func)(BAT *, BAT
*), const char *name)
-{
- BAT *left, *right,*bn= NULL;
+static str emptyCandidateResults(ptr *candsRes_dims, bat* candsRes_bid) {
+ BAT *candidatesBAT = NULL;
- if ((left = BATdescriptor(*lid)) == NULL) {
- throw(MAL, name, RUNTIME_OBJECT_MISSING);
- }
- if ((right = BATdescriptor(*rid)) == NULL) {
- BBPunfix(left->batCacheid);
- throw(MAL, name, RUNTIME_OBJECT_MISSING);
- }
- bn = (*func)(left, right);
- BBPunfix(left->batCacheid);
- BBPunfix(right->batCacheid);
- if (bn == NULL)
- throw(MAL, name, GDK_EXCEPTION);
- if (!(bn->batDirty&2))
- BATsetaccess(bn, BAT_READ);
- *result = bn->batCacheid;
- BBPkeepref(*result);
- return MAL_SUCCEED;
+ if((candidatesBAT = BATnew(TYPE_void, TYPE_oid, 0, TRANSIENT)) == NULL)
+ throw(MAL, "algebra.dimensionSubselect", GDK_EXCEPTION);
+ BATsetcount(candidatesBAT, 0);
+ BATseqbase(candidatesBAT, 0);
+ BATderiveProps(candidatesBAT, FALSE);
+
+ BBPkeepref(*candsRes_bid = candidatesBAT->batCacheid);
+ *candsRes_dims = NULL;
+
+ return MAL_SUCCEED;
}
-str ALGdimensionLeftfetchjoin(bat *result, const bat *lid, const bat *rid) {
- return ALGbinary(result, lid, rid, dimensionBATproject_wrap,
"algebra.dimension_leftfetchjoin");
+static bool updateCandidateResults(gdk_cells** dimensionsCandidates_out, BAT**
candidatesBAT_out,
+
gdk_cells *dimensionsCandidates_in, BAT* candidatesBAT_in,
+ int
dimNum, BUN elsNum, oid min, oid max) {
+ //the dimension comes from the original the elements and initial
elements num is the same
+ gdk_dimension *dimensionCand_out = createDimension_oid(dimNum, elsNum,
min, max, 1); //step cannot be 0 or infinite loop
+ gdk_dimension *dimensionCand_in = getDimension(dimensionsCandidates_in,
dimNum);
+
+ //if the existing results for the dimension and the new computed
results can be combined in a new dimension
+ if(compatibleRanges(dimensionCand_in, dimensionCand_out)) {
+ //merge the dimension in the candidates with the result of this
operation
+ dimensionCand_out = mergeCandidateDimensions(dimensionCand_in,
dimensionCand_out);
+ if(!dimensionCand_out) {
+ //the dimensions cannot be merged to a new dimension.
Create a BAT
+ *dimensionsCandidates_out =
cells_remove_dimension(dimensionsCandidates_in, dimNum);
+ } else {
+ *dimensionsCandidates_out =
cells_replace_dimension(dimensionsCandidates_in, dimensionCand_out);
+ //the candidatesBAT does not change
+ *candidatesBAT_out = candidatesBAT_in;
+ }
+ } else //cannot produce candidates. Empty result
+ return 0;
+
+ return 1;
}
-#endif
str ALGdimensionSubselect2(ptr *dimsRes, bat* oidsRes, const ptr *dims, const
ptr* dim, const ptr *dimsCand, const bat* oidsCand,
const void *low, const
void *high, const bit *li, const bit *hi, const bit *anti) {
gdk_array *array = (gdk_array*)*dims; //the sizes of all the dimensions
(I treat them as indices and I do not care about the exact values)
gdk_dimension *dimension = (gdk_dimension*)*dim;
- gdk_cells *dimensionsCandidates = NULL;
+ gdk_cells *dimensionsCandidates_in = NULL, *dimensionsCandidates_out =
NULL;
BAT *candidatesBAT_in = NULL, *candidatesBAT_out = NULL;
- gdk_cells *dimensionsResult = cells_new();
+
+ gdk_dimension *dimensionCand_in = NULL, *dimensionCand_out = NULL;
int type;
const void *nil;
- (void)(bit*)li;
(void)(bit*)hi;
(void)(bit*)anti;
@@ -240,11 +244,11 @@ str ALGdimensionSubselect2(ptr *dimsRes,
}
if(dimsCand)
- dimensionsCandidates = (gdk_cells*)*dimsCand;
+ dimensionsCandidates_in = (gdk_cells*)*dimsCand;
//if there are no candidates then everything is a candidate
if(!dimsCand && !oidsCand) {
- dimensionsCandidates = sizesToDimensions(array);
+ dimensionsCandidates_in = sizesToDimensions(array);
//create an empy candidates BAT
if((candidatesBAT_in = BATnew(TYPE_void, TYPE_oid, 0,
TRANSIENT)) == NULL)
throw(MAL, "algebra.dimensionSubselect", GDK_EXCEPTION);
@@ -253,20 +257,8 @@ str ALGdimensionSubselect2(ptr *dimsRes,
BATderiveProps(candidatesBAT_in, FALSE);
}
- if(!dimensionsCandidates) { //empty results
- //create an empy candidates BAT
- if((candidatesBAT_out = BATnew(TYPE_void, TYPE_oid, 0,
TRANSIENT)) == NULL)
- throw(MAL, "algebra.dimensionSubselect", GDK_EXCEPTION);
- BATsetcount(candidatesBAT_out, 0);
- BATseqbase(candidatesBAT_out, 0);
- BATderiveProps(candidatesBAT_out, FALSE);
-
- *dimsRes = dimensionsResult;
- BBPkeepref(*oidsRes = candidatesBAT_out->batCacheid);
-
- return MAL_SUCCEED;
- }
-
+ if(!dimensionsCandidates_in) //empty results
+ return emptyCandidateResults(dimsRes, oidsRes);
type = dimension->type;
nil = ATOMnilptr(type);
@@ -274,40 +266,55 @@ str ALGdimensionSubselect2(ptr *dimsRes,
if(ATOMcmp(type, low, high) == 0) { //point selection
//find the idx of the value
- gdk_dimension *resDimension = NULL;
- oid qualifyingOID = equalIdx(dimension, low);
- if(qualifyingOID >= dimension->initialElementsNum) {
- //no results. create empty candidates BAT
- if((candidatesBAT_out = BATnew(TYPE_void, TYPE_oid, 0,
TRANSIENT)) == NULL)
- throw(MAL, "algebra.dimensionSubselect", GDK_EXCEPTION);
- BATsetcount(candidatesBAT_out, 0);
- BATseqbase(candidatesBAT_out, 0);
- BATderiveProps(candidatesBAT_in, FALSE);
+ oid qualifyingIdx = equalIdx(dimension, low);
+ if(qualifyingIdx >= dimension->initialElementsNum) {
+ //remove all the dimensions, there will be no results
in the output
+ freeCells(dimensionsCandidates_in);
+ return emptyCandidateResults(dimsRes, oidsRes);
+ } else {
+ if(!updateCandidateResults(&dimensionsCandidates_out,
&candidatesBAT_out, dimensionsCandidates_in, candidatesBAT_in,
dimension->dimNum, dimension->initialElementsNum, qualifyingIdx,
qualifyingIdx)) {
+ //remove all the dimensions, there will be no
results in the output
+ freeCells(dimensionsCandidates_in);
+ return emptyCandidateResults(dimsRes, oidsRes);
+ }
+ }
+ } else if(ATOMcmp(type, low, nil) == 0 && ATOMcmp(type, high, nil) ==
0) {
+ oid qualifyingIdx_min = lowerIdx(dimension, low, *li);
+ oid qualifyingIdx_max = greaterIdx(dimension, high, *hi);
- //remove all the dimensions, there will be no results
in the output
- dimensionsResult = NULL;
- freeCells(dimensionsCandidates);
- } else {
- //the dimension comes from the original this the
elemenst and initial elements num is the same
- resDimension = createDimension_oid(dimension->dimNum,
dimension->initialElementsNum, qualifyingOID, qualifyingOID, 1); //step cannot
be 0 or infinite loop
+ if(qualifyingIdx_max >= dimension->initialElementsNum ||
qualifyingIdx_min >= dimension->initialElementsNum) {
+ freeCells(dimensionsCandidates_in);
+ return emptyCandidateResults(dimsRes, oidsRes);
+ } else {
+ dimensionCand_out =
createDimension_oid(dimension->dimNum, dimension->initialElementsNum,
qualifyingIdx_min, qualifyingIdx_max, 1);
+ dimensionCand_in =
getDimension(dimensionsCandidates_in, dimension->dimNum);
+
+ //if the existing results for the dimension and the new
computed results can be combined in a new dimension
+ if(compatibleRanges(dimensionCand_in,
dimensionCand_out)) {
+ //merge the dimension in the candidates with
the result of this operation
+ dimensionCand_out =
mergeCandidateDimensions(dimensionCand_in, dimensionCand_out);
+ if(!dimensionCand_out) {
+ //the dimensions cannot be merged to a
new dimension. Create a BAT
+ dimensionsCandidates_out =
cells_remove_dimension(dimensionsCandidates_in, dimensionCand_in->dimNum);
+ } else
+ dimensionsCandidates_out =
cells_replace_dimension(dimensionsCandidates_in, dimensionCand_out);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list