Changeset: e7f20b0bc1d8 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/e7f20b0bc1d8 Modified Files: geom/monetdb5/geom.c geom/monetdb5/geom.h geom/monetdb5/geomBulk.c geom/sql/40_geom.sql monetdb5/optimizer/opt_mitosis.c Branch: geo-update-dev Log Message:
DWithin with RTree index implementation, add distance parameter to rtree/no_index C functions diffs (248 lines): diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c --- a/geom/monetdb5/geom.c +++ b/geom/monetdb5/geom.c @@ -5517,14 +5517,16 @@ static mel_func geom_init_funcs[] = { command("rtree", "Intersectsselect", wkbIntersectsSelectRTree, false, "TODO", args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("anti",bit))), command("rtree", "Intersectsjoin", wkbIntersectsJoinRTree, false, "TODO", args(2, 8, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))), - //command("rtree", "DWithin", wkbIntersects, false, "Returns true if these Geometries 'spatially intersect in 2D'", args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))), - //command("rtree", "DWithinselect", wkbIntersectsSelectRTree, false, "TODO", args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("anti",bit))), - //command("rtree", "DWithinjoin", wkbIntersectsJoinRTree, false, "TODO", args(2, 8, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))), + command("rtree", "DWithin", wkbDWithin, false, "Returns true if these Geometries 'spatially intersect in 2D'", args(1,4, arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))), + command("rtree", "DWithinselect", wkbDWithinSelectRTree, false, "TODO", args(1, 6, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("dst",dbl), arg("anti",bit))), + command("rtree", "DWithinjoin", wkbDWithinJoinRTree, false, "TODO", args(2, 9, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("sl",oid),batarg("sr",oid), arg("dst",dbl),arg("nil_matches",bit),arg("estimate",lng))), command("geom", "Intersects_noindex", wkbIntersects, false, "Returns true if these Geometries 'spatially intersect in 2D'", args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))), command("geom", "Intersects_noindexselect", wkbIntersectsSelectNoIndex, false, "TODO", args(1, 5, batarg("", oid), batarg("b", wkb), batarg("s", oid), arg("c", wkb), arg("anti",bit))), command("geom", "Intersects_noindexjoin", wkbIntersectsJoinNoIndex, false, "TODO", args(2, 8, batarg("lr",oid),batarg("rr",oid), batarg("a", wkb), batarg("b", wkb), batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))), + command("geom", "DWithin", wkbDWithin, false, "Returns true if the two geometries are within the specifies distance from each other", args(1,4, arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))), + command("geom", "IntersectsMBR", mbrIntersects, false, "TODO", args(1,3, arg("",bit),arg("a",mbr),arg("b",mbr))), command("aggr", "Collect", wkbCollectAggr, false, "TODO", args(1, 2, arg("", wkb), batarg("val", wkb))), @@ -5586,7 +5588,6 @@ static mel_func geom_init_funcs[] = { command("geom", "Within", wkbWithin, false, "Returns TRUE if the geometry A is completely inside geometry B", args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))), command("geom", "Covers", wkbCovers, false, "Returns TRUE if no point of geometry B is outside geometry A", args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))), command("geom", "CoveredBy", wkbCoveredBy, false, "Returns TRUE if no point of geometry A is outside geometry B", args(1,3, arg("",bit),arg("a",wkb),arg("b",wkb))), - command("geom", "DWithin", wkbDWithin, false, "Returns true if the two geometries are within the specifies distance from each other", args(1,4, arg("",bit),arg("a",wkb),arg("b",wkb),arg("dst",dbl))), command("geom", "DWithin2", wkbDWithinMbr, false, "" /* <<< desc TODO */, args(1,6, arg("",bit),arg("a",wkb),arg("b",wkb),arg("a_mbr",mbr),arg("b_mbr",mbr),arg("dst",dbl))), command("geom", "GeometryN", wkbGeometryN, false, "Returns the 1-based Nth geometry if the geometry is a GEOMETRYCOLLECTION, (MULTI)POINT, (MULTI)LINESTRING, MULTICURVE or (MULTI)POLYGON. Otherwise, return NULL", args(1,3, arg("",wkb),arg("g",wkb),arg("n",int))), command("geom", "NumGeometries", wkbNumGeometries, false, "Returns the number of geometries", args(1,2, arg("",int),arg("g",wkb))), diff --git a/geom/monetdb5/geom.h b/geom/monetdb5/geom.h --- a/geom/monetdb5/geom.h +++ b/geom/monetdb5/geom.h @@ -219,6 +219,11 @@ geom_export str geom_sql_upgrade(int); geom_export str wkbIntersectsJoinNoIndex(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate); geom_export str wkbIntersectsSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti); + geom_export str wkbIntersectsJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate); geom_export str wkbIntersectsSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti); + +geom_export str wkbDWithinJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, double *distance, bit *nil_matches, lng *estimate); +geom_export str wkbDWithinSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, double *distance, bit *anti); + geom_export str mbrIntersects(bit* out, mbr** mbr1, mbr** mbr2); diff --git a/geom/monetdb5/geomBulk.c b/geom/monetdb5/geomBulk.c --- a/geom/monetdb5/geomBulk.c +++ b/geom/monetdb5/geomBulk.c @@ -14,23 +14,16 @@ #include "geod.h" #include "geom_atoms.h" +//TODO Is GEOSDistanceWithin(g1,g2,0) the same (performance) as GEOSIntersects(g1,g2)? + /********** Geo Update Start **********/ static str -filterSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry *), const char *name) +filterSelectRTree(bat* outid, const bat *bid , const bat *sid, GEOSGeom const_geom, mbr *const_mbr, double distance, bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry *, double), const char *name) { BAT *out = NULL, *b = NULL, *s = NULL; BATiter b_iter; struct canditer ci; - GEOSGeom col_geom, const_geom; - - //WKB constant is NULL - if ((const_geom = wkb2geos(wkb_const)) == NULL) { - if ((out = BATdense(0, 0, 0)) == NULL) - throw(MAL, name, GDK_EXCEPTION); - *outid = out->batCacheid; - BBPkeepref(out); - return MAL_SUCCEED; - } + GEOSGeom col_geom; //Get BAT, BATiter and candidate list if ((b = BATdescriptor(*bid)) == NULL) @@ -50,19 +43,13 @@ filterSelectRTree(bat* outid, const bat throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); } - //Calculate the MBR for the constant geometry - mbr *const_mbr = NULL; - wkbMBR(&const_mbr,&wkb_const); - //Get a candidate list from searching on the rtree with the constant mbr - //Note: the candidates returned from RTREEsearch are BUNs not OIDs BUN* results_rtree = RTREEsearch(b,(mbr_t*)const_mbr, b->batCount); + //TODO Change literal value of BUN_NONE to BUN_NONE in loop condition //Cycle through rtree candidates //If there is a original candidate list, make sure the rtree cand is in there //Then do the actual calculation for the predicate using the GEOS function - - //TODO Change literal value of BUN_NONE to BUN_NONE in loop condition for (int i = 0; results_rtree[i] != 18446744073709551615U && i < (int) b->batCount; i++) { oid cand = results_rtree[i]; @@ -87,7 +74,7 @@ filterSelectRTree(bat* outid, const bat throw(MAL, name, SQLSTATE(38000) "Geometries of different SRID"); } //GEOS function returns 1 on true, 0 on false and 2 on exception - bit cond = ((*func)(col_geom, const_geom) == 1); + bit cond = ((*func)(col_geom, const_geom, distance) == 1); if (cond != anti) { if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) { GEOSGeom_destroy(col_geom); @@ -113,12 +100,12 @@ filterSelectRTree(bat* outid, const bat } static str -filterSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry *), const char *name) +filterSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, double distance, bit anti, char (*func) (const GEOSGeometry *, const GEOSGeometry *, double), const char *name) { BAT *out = NULL, *b = NULL, *s = NULL; BATiter b_iter; struct canditer ci; - GEOSGeom const_geom, col_geom; + GEOSGeom col_geom, const_geom; //WKB constant is NULL if ((const_geom = wkb2geos(wkb_const)) == NULL) { @@ -163,7 +150,7 @@ filterSelectNoIndex(bat* outid, const ba throw(MAL, name, SQLSTATE(38000) "Geometries of different SRID"); } //GEOS function returns 1 on true, 0 on false and 2 on exception - bit cond = ((*func)(col_geom, const_geom) == 1); + bit cond = ((*func)(col_geom, const_geom, distance) == 1); if (cond != anti) { if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) { if (col_geom) @@ -194,15 +181,62 @@ filterSelectNoIndex(bat* outid, const ba str wkbIntersectsSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti) { //If there is an RTree on memory or on file, use the RTree method. Otherwise, use the no index version. - if (RTREEexists_bid((bat*)bid)) - return filterSelectRTree(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectRTree"); + if (RTREEexists_bid((bat*)bid)) { + //Calculate MBR of constant geometry first + GEOSGeom const_geom; + if ((const_geom = wkb2geos(*wkb_const)) == NULL) { + BAT *out = NULL; + if ((out = BATdense(0, 0, 0)) == NULL) + throw(MAL, "geom.wkbIntersectsSelectRTree", GDK_EXCEPTION); + *outid = out->batCacheid; + BBPkeepref(out); + return MAL_SUCCEED; + } + //Calculate the MBR for the constant geometry + mbr *const_mbr = NULL; + wkbMBR(&const_mbr,wkb_const); + + return filterSelectRTree(outid,bid,sid,const_geom,const_mbr,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectRTree"); + } else - return filterSelectNoIndex(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectNoIndex"); + return filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectNoIndex"); +} + +str +wkbDWithinSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, double* distance, bit *anti) { + //If there is an RTree on memory or on file, use the RTree method. Otherwise, use the no index version. + if (RTREEexists_bid((bat*)bid)) { + //Calculate MBR of constant geometry first + GEOSGeom const_geom; + if ((const_geom = wkb2geos(*wkb_const)) == NULL) { + BAT *out = NULL; + if ((out = BATdense(0, 0, 0)) == NULL) + throw(MAL, "geom.wkbDWithinSelectRTree", GDK_EXCEPTION); + *outid = out->batCacheid; + BBPkeepref(out); + return MAL_SUCCEED; + } + //Calculate the MBR for the constant geometry + mbr *const_mbr = NULL; + wkbMBR(&const_mbr,wkb_const); + + //We expand the bounding box to cover the "distance within" area + //And use GEOSIntersects with the expanded bounding box + //TODO This expansion is too much + const_mbr->xmin -=(*distance); + const_mbr->ymin -=(*distance); + const_mbr->xmax +=(*distance); + const_mbr->ymax +=(*distance); + + return filterSelectRTree(outid,bid,sid,const_geom,const_mbr,*distance,*anti,GEOSDistanceWithin,"geom.wkbDWithinSelectRTree"); + } + else + return filterSelectNoIndex(outid,bid,sid,*wkb_const,*distance,*anti,GEOSDistanceWithin,"geom.wkbDWithinSelectNoIndex"); } str wkbIntersectsSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti) { - return filterSelectNoIndex(outid,bid,sid,*wkb_const,*anti,GEOSIntersects,"geom.wkbIntersectsSelectNoIndex"); + return filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin,"geom.wkbIntersectsSelectNoIndex"); } static str @@ -377,6 +411,12 @@ wkbIntersectsJoinRTree(bat *lres_id, bat } str +wkbDWithinJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, double *distance, bit *nil_matches, lng *estimate) { + (void) distance; + return filterJoinRTree(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,GEOSIntersects,"geom.wkbDWithinJoinRTree"); +} + +str wkbIntersectsJoinNoIndex(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate) { return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,estimate,GEOSIntersects,"geom.wkbIntersectsJoinNoIndex"); } diff --git a/geom/sql/40_geom.sql b/geom/sql/40_geom.sql --- a/geom/sql/40_geom.sql +++ b/geom/sql/40_geom.sql @@ -22,6 +22,9 @@ CREATE FILTER FUNCTION ST_IntersectsGeog CREATE FUNCTION ST_IntersectsMBR(mbr1 mbr, mbr2 mbr) RETURNS bool EXTERNAL NAME geom."IntersectsMBR"; CREATE FILTER FUNCTION ST_Intersects(geom1 Geometry, geom2 Geometry) EXTERNAL NAME rtree."Intersects"; CREATE FILTER FUNCTION ST_Intersects_NoIndex(geom1 Geometry, geom2 Geometry) EXTERNAL NAME geom."Intersects_noindex"; + +CREATE FILTER FUNCTION ST_DWithin(geom1 Geometry, geom2 Geometry, distance double) EXTERNAL NAME rtree."DWithin"; +CREATE FUNCTION ST_DWithin_NoIndex(geom1 Geometry, geom2 Geometry, distance double) RETURNS boolean EXTERNAL NAME geom."DWithin"; ------------------------------------------------------------------------- ------------------------- Geography functions --------------------------- ------------------------------------------------------------------------- @@ -513,8 +516,6 @@ GRANT EXECUTE ON FUNCTION ST_CoveredBy(G --CREATE FUNCTION ST_LineCrossingDirection RETURNS EXTERNAL NAME --CREATE FUNCTION ST_Distance(geog1 Geometry, geog2 Geometry) RETURNS double EXTERNAL NAME geom."Distance" --CREATE FUNCTION ST_Distance(geog1 Geometry, geog2 Geometry, use_spheroid boolean) RETURNS double EXTERNAL NAME geom."Distance" -CREATE FUNCTION ST_DWithin(geom1 Geometry, geom2 Geometry, dst double) RETURNS boolean EXTERNAL NAME geom."DWithin"; -GRANT EXECUTE ON FUNCTION ST_DWithin(Geometry, Geometry, double) TO PUBLIC; CREATE FUNCTION ST_DWithin2(geom1 Geometry, geom2 Geometry, bbox1 mbr, bbox2 mbr, dst double) RETURNS boolean EXTERNAL NAME geom."DWithin2"; GRANT EXECUTE ON FUNCTION ST_DWithin2(Geometry, Geometry, mbr, mbr, double) TO PUBLIC; --CREATE FUNCTION ST_HausdorffDistance RETURNS EXTERNAL NAME diff --git a/monetdb5/optimizer/opt_mitosis.c b/monetdb5/optimizer/opt_mitosis.c --- a/monetdb5/optimizer/opt_mitosis.c +++ b/monetdb5/optimizer/opt_mitosis.c @@ -70,8 +70,10 @@ OPTmitosisImplementation(Client cntxt, M } /* rtree functions should not be optimized by mitosis (single-threaded execution) */ - if ( getModuleId(p) == rtreeRef) + if ( getModuleId(p) == rtreeRef){ + pieces = 0; goto bailout; + } /* do not split up floating point bat that is being summed */ if (p->retc == 1 && _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org