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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list