Changeset: 291ecf019da8 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/291ecf019da8 Modified Files: geom/monetdb5/geom.c geom/monetdb5/geomBulk.c Branch: geo-update Log Message:
GEOS type conversion is only done once in join filter; More signatures; Some small cleanups diffs (truncated from 455 to 300 lines): diff --git a/geom/monetdb5/geom.c b/geom/monetdb5/geom.c --- a/geom/monetdb5/geom.c +++ b/geom/monetdb5/geom.c @@ -909,8 +909,15 @@ wkbCoversGeographic(bit *out, wkb **a, w /** * FILTER FUNCTIONS **/ + +static inline bit +geosDistanceWithin (GEOSGeom geom1, GEOSGeom geom2, dbl distance_within) { + dbl distance = geoDistanceInternal(geom1, geom2); + return distance <= distance_within; +} + static str -filter_select(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, dbl distance_within, bit anti) +filterSelectGeomGeomDoubleToBit(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, dbl double_flag, bit anti, bit (*func) (GEOSGeom, GEOSGeom, dbl), const char *name) { BAT *out = NULL, *b = NULL, *s = NULL; BATiter b_iter; @@ -920,18 +927,18 @@ filter_select(bat* outid, const bat *bid //Check if the geometry is null and convert to GEOS if ((const_geom = wkb2geos(wkb_const)) == NULL) { if ((out = BATdense(0, 0, 0)) == NULL) - throw(MAL, "geom.wkbDWithinGeographicSelect", GDK_EXCEPTION); + throw(MAL, name, GDK_EXCEPTION); *outid = out->batCacheid; BBPkeepref(*outid); return MAL_SUCCEED; } //get the BATs if ((b = BATdescriptor(*bid)) == NULL) - throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); //get the candidate lists if (sid && !is_bat_nil(*sid) && !(s = BATdescriptor(*sid))) { BBPunfix(b->batCacheid); - throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } canditer_init(&ci, b, s); //create a new BAT for the output @@ -939,17 +946,28 @@ filter_select(bat* outid, const bat *bid BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); - throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY013) MAL_MALLOC_FAIL); + throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); } b_iter = bat_iterator(b); //Loop through column and compare with constant for (BUN i = 0; i < ci.ncand; i++) { oid c_oid = canditer_next(&ci); const wkb *col_wkb = BUNtvar(b_iter, c_oid - b->hseqbase); - if (is_wkb_nil(col_wkb) || (col_geom = wkb2geos(col_wkb)) == NULL) + if ((col_geom = wkb2geos(col_wkb)) == NULL) continue; - double distance = geoDistanceInternal(col_geom, const_geom); - if ((distance <= distance_within && !anti) || (distance > distance_within && anti) ) { + if (GEOSGetSRID(col_geom) != GEOSGetSRID(const_geom)) { + GEOSGeom_destroy(col_geom); + GEOSGeom_destroy(const_geom); + bat_iterator_end(&b_iter); + BBPunfix(b->batCacheid); + if (s) + BBPunfix(s->batCacheid); + BBPreclaim(out); + throw(MAL, name, SQLSTATE(38000) "Geometries of different SRID"); + } + //Apply the (Geom, Geom, double) -> bit function + bit cond = (*func)(col_geom, const_geom, double_flag); + if (cond != anti) { if (BUNappend(out, &c_oid, false) != GDK_SUCCEED) { if (col_geom) GEOSGeom_destroy(col_geom); @@ -960,7 +978,7 @@ filter_select(bat* outid, const bat *bid if (s) BBPunfix(s->batCacheid); BBPreclaim(out); - throw(MAL, "geom.wkbDWithinGeographicSelect", SQLSTATE(HY013) MAL_MALLOC_FAIL); + throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); } } GEOSGeom_destroy(col_geom); @@ -970,34 +988,31 @@ filter_select(bat* outid, const bat *bid BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); - *outid = out->batCacheid; - BBPkeepref(*outid); + BBPkeepref(*outid = out->batCacheid); return MAL_SUCCEED; } static str -filter_join(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, double distance_within, const bat *ls_id, const bat *rs_id, bit nil_matches, lng *estimate, bit anti) -{ - //TODO Use nil_matches? - (void) nil_matches; +filterJoinGeomGeomDoubleToBit(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, double double_flag, const bat *ls_id, const bat *rs_id, bit nil_matches, lng *estimate, bit anti, bit (*func) (GEOSGeom, GEOSGeom, dbl), const char *name) +{ BAT *lres = NULL, *rres = NULL, *l = NULL, *r = NULL, *ls = NULL, *rs = NULL; BATiter l_iter, r_iter; str msg = MAL_SUCCEED; struct canditer l_ci, r_ci; GEOSGeom l_geom, r_geom; + GEOSGeom *l_geoms = NULL, *r_geoms = NULL; //get the input BATs if ((l = BATdescriptor(*l_id)) == NULL || (r = BATdescriptor(*r_id)) == NULL) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - goto free; + if (l) + BBPunfix(l->batCacheid); + if (r) + BBPunfix(r->batCacheid); + throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } //get the candidate lists - if (ls_id && !is_bat_nil(*ls_id) && !(ls = BATdescriptor(*ls_id))) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); - goto free; - } - if (rs_id && !is_bat_nil(*rs_id) && !(rs = BATdescriptor(*rs_id))) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + if (ls_id && !is_bat_nil(*ls_id) && !(ls = BATdescriptor(*ls_id)) && rs_id && !is_bat_nil(*rs_id) && !(rs = BATdescriptor(*rs_id))) { + msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); goto free; } canditer_init(&l_ci, l, ls); @@ -1006,43 +1021,85 @@ filter_join(bat *lres_id, bat *rres_id, if (is_lng_nil(*estimate) || *estimate == 0) *estimate = l_ci.ncand; if ((lres = COLnew(0, ATOMindex("oid"), *estimate, TRANSIENT)) == NULL) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); goto free; } if ((rres = COLnew(0, ATOMindex("oid"), *estimate, TRANSIENT)) == NULL) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); + goto free; + } + + //Allocate arrays for reutilizing GEOS type conversion + if ((l_geoms = GDKmalloc(l_ci.ncand * sizeof(GEOSGeometry *))) == NULL || (r_geoms = GDKmalloc(r_ci.ncand * sizeof(GEOSGeometry *))) == NULL) { + msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); goto free; } l_iter = bat_iterator(l); r_iter = bat_iterator(r); + + //Convert wkb to GEOS only once for (BUN i = 0; i < l_ci.ncand; i++) { oid l_oid = canditer_next(&l_ci); - const wkb *l_wkb = BUNtvar(l_iter, l_oid - l->hseqbase); - if (is_wkb_nil(l_wkb) || (l_geom = wkb2geos(l_wkb)) == NULL) + l_geoms[i] = wkb2geos((const wkb*) BUNtvar(l_iter, l_oid - l->hseqbase)); + } + for (BUN j = 0; j < r_ci.ncand; j++) { + oid r_oid = canditer_next(&r_ci); + r_geoms[j] = wkb2geos((const wkb*)BUNtvar(r_iter, r_oid - r->hseqbase)); + } + + canditer_reset(&l_ci); + for (BUN i = 0; i < l_ci.ncand; i++) { + oid l_oid = canditer_next(&l_ci); + l_geom = l_geoms[i]; + if (!nil_matches && l_geom == NULL) continue; canditer_reset(&r_ci); for (BUN j = 0; j < r_ci.ncand; j++) { oid r_oid = canditer_next(&r_ci); - const wkb *r_wkb = BUNtvar(r_iter, r_oid - r->hseqbase); - if (is_wkb_nil(r_wkb) || (r_geom = wkb2geos(r_wkb)) == NULL) - continue; + r_geom = r_geoms[j]; + //Null handling + if (r_geom == NULL) { + if (nil_matches && l_geom == NULL) { + if (BUNappend(lres, &l_oid, false) != GDK_SUCCEED || BUNappend(rres, &r_oid, false) != GDK_SUCCEED) { + msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); + bat_iterator_end(&l_iter); + bat_iterator_end(&r_iter); + goto free; + } + } + else + continue; + } if (GEOSGetSRID(l_geom) != GEOSGetSRID(r_geom)) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(38000) "Geometries of different SRID"); - GEOSGeom_destroy(r_geom); - GEOSGeom_destroy(l_geom); + msg = createException(MAL, name, SQLSTATE(38000) "Geometries of different SRID"); + bat_iterator_end(&l_iter); + bat_iterator_end(&r_iter); goto free; } - double distance = geoDistanceInternal(l_geom, r_geom); - if ((distance <= distance_within && !anti) || (distance > distance_within && anti) ) { + //Apply the (Geom, Geom) -> bit function + bit cond = (*func)(l_geom, r_geom, double_flag); + if (cond != anti) { if (BUNappend(lres, &l_oid, false) != GDK_SUCCEED || BUNappend(rres, &r_oid, false) != GDK_SUCCEED) { - msg = createException(MAL, "geom.wkbDWithinGeographicJoin", SQLSTATE(HY013) MAL_MALLOC_FAIL); + msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL); + bat_iterator_end(&l_iter); + bat_iterator_end(&r_iter); goto free; } } - GEOSGeom_destroy(r_geom); + } + } + if (l_geoms) { + for (BUN i = 0; i < l_ci.ncand; i++) { + GEOSGeom_destroy(l_geoms[i]); } - GEOSGeom_destroy(l_geom); + GDKfree(l_geoms); + } + if (r_geoms) { + for (BUN i = 0; i < r_ci.ncand; i++) { + GEOSGeom_destroy(r_geoms[i]); + } + GDKfree(r_geoms); } bat_iterator_end(&l_iter); bat_iterator_end(&r_iter); @@ -1052,19 +1109,24 @@ filter_join(bat *lres_id, bat *rres_id, BBPunfix(ls->batCacheid); if (rs) BBPunfix(rs->batCacheid); - *lres_id = lres->batCacheid; - *rres_id = rres->batCacheid; - BBPkeepref(*lres_id); - BBPkeepref(*rres_id); + BBPkeepref(*lres_id = lres->batCacheid); + BBPkeepref(*rres_id = rres->batCacheid); return MAL_SUCCEED; free: - //TODO: Test this - bat_iterator_end(&l_iter); - bat_iterator_end(&r_iter); - if (l) - BBPunfix(l->batCacheid); - if (r) - BBPunfix(r->batCacheid); + if (l_geoms) { + for (BUN i = 0; i < l_ci.ncand; i++) { + GEOSGeom_destroy(l_geoms[i]); + } + GDKfree(l_geoms); + } + if (r_geoms) { + for (BUN i = 0; i < r_ci.ncand; i++) { + GEOSGeom_destroy(r_geoms[i]); + } + GDKfree(r_geoms); + } + BBPunfix(l->batCacheid); + BBPunfix(r->batCacheid); if (ls) BBPunfix(ls->batCacheid); if (rs) @@ -1076,12 +1138,12 @@ free: return msg; } -//select * from brittany_ports as q1 join wpi_ports as q2 on [q1.geom] st_dwithingeographic [q2.geom,5000]; +//select st_distancegeographic(q1.geom,q2.geom) from brittany_ports as q1 join wpi_ports as q2 on [q1.geom] st_dwithingeographic [q2.geom,5000]; str wkbDWithinGeographicJoin(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *d_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate, bit *anti) { double distance_within = 0; BAT *d = NULL; - //Get the distance (const) BAT and get the double value + //Get the distance BAT and get the double value if ((d = BATdescriptor(*d_id)) == NULL) { if (d) BBPunfix(d->batCacheid); @@ -1091,27 +1153,26 @@ wkbDWithinGeographicJoin(bat *lres_id, b distance_within = *((double*) Tloc(d, 0)); } BBPunfix(d->batCacheid); - return filter_join(lres_id,rres_id,l_id,r_id,distance_within,ls_id,rs_id,*nil_matches,estimate,*anti); + return filterJoinGeomGeomDoubleToBit(lres_id,rres_id,l_id,r_id,distance_within,ls_id,rs_id,*nil_matches,estimate,*anti,geosDistanceWithin,"geom.wkbDWithinGeographicJoin"); } //select gml_id,st_distancegeographic(st_setsrid(st_makepoint(-4.50,48.32),4326),q1.geom) from brittany_ports as q1 where [q1.geom] st_dwithingeographic [st_setsrid(st_makepoint(-4.50,48.32),4326),5000]; str wkbDWithinGeographicSelect(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, dbl *distance_within, bit *anti) { - return filter_select(outid,bid,sid,*wkb_const,*distance_within,*anti); -} - -//select * from brittany_ports as q1 join brittany_ports as q2 on [q1.geom] ST_IntersectsGeographic [q2.geom]; + return filterSelectGeomGeomDoubleToBit(outid,bid,sid,*wkb_const,*distance_within,*anti,geosDistanceWithin,"geom.wkbDWithinGeographicSelect"); +} + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list