You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #173 (geospatial statistics + bbox-only intersects pushdown).
Context
The intersects(column, xmin, ymin, xmax, ymax) predicate added in #173
performs bbox-only pushdown at the row group and page level, then returns
every surviving row to the caller. The reader does not decode the per-row
WKB payload, so:
Rows whose individual geometry falls outside the query bbox are still
emitted (false positives at the row level).
FilterPredicate.not(intersects(...)) is rejected at resolve time —
correct per-row evaluation would require decoding every WKB.
This is a deliberate trade-off: it keeps the runtime dependency-free
(arithmetic on the doubles already in the footer / column index).
Proposal
Add opt-in row-level evaluation that decodes the per-row WKB only when
a geometry library is on the classpath, mirroring how the existing optional
compression codecs (snappy-java, zstd-jni, lz4-java, brotli4j) are wired in core/pom.xml (<optional>true</optional>).
Likely shape:
A small GeometryDecoder SPI inside dev.hardwood.internal.geo with a
default no-op implementation. The implementation is selected via ServiceLoader (or a classpath probe) at reader construction time.
A JTS-backed implementation shipped as a separate optional artifact
(hardwood-geo-jts or core with org.locationtech.jts:jts-core as <optional>true</optional>), so users who don't need exact filtering pay
nothing.
RecordFilterEvaluator / RecordFilterCompiler: when the decoder is
available, replace the unconditional true for GeospatialPredicate
with a real WKB-decode + envelope/intersection test against the query
bbox.
Resolver: drop the UnsupportedOperationException for not(intersects(...)) once row-level evaluation is wired up. The
chunk-level dual (containment instead of overlap) can then be added in RowGroupFilterEvaluator / PageFilterEvaluator for completeness, but
is independent of this change.
Out of scope
Adding new spatial predicates (within, contains, distance).
3D / Z-M filtering — initial predicate stays 2D.
Custom CRS reprojection — query and column CRS are assumed to match.
Acceptance criteria
With jts-core on the test classpath, an intersects query returns
only rows whose decoded geometry actually intersects the query bbox
(verified by an end-to-end test that builds row groups straddling the
query box).
Follow-up to #173 (geospatial statistics + bbox-only
intersectspushdown).Context
The
intersects(column, xmin, ymin, xmax, ymax)predicate added in #173performs bbox-only pushdown at the row group and page level, then returns
every surviving row to the caller. The reader does not decode the per-row
WKB payload, so:
emitted (false positives at the row level).
FilterPredicate.not(intersects(...))is rejected at resolve time —correct per-row evaluation would require decoding every WKB.
This is a deliberate trade-off: it keeps the runtime dependency-free
(arithmetic on the doubles already in the footer / column index).
Proposal
Add opt-in row-level evaluation that decodes the per-row WKB only when
a geometry library is on the classpath, mirroring how the existing optional
compression codecs (snappy-java, zstd-jni, lz4-java, brotli4j) are wired in
core/pom.xml(<optional>true</optional>).Likely shape:
GeometryDecoderSPI insidedev.hardwood.internal.geowith adefault no-op implementation. The implementation is selected via
ServiceLoader(or a classpath probe) at reader construction time.(
hardwood-geo-jtsorcorewithorg.locationtech.jts:jts-coreas<optional>true</optional>), so users who don't need exact filtering paynothing.
RecordFilterEvaluator/RecordFilterCompiler: when the decoder isavailable, replace the unconditional
trueforGeospatialPredicatewith a real WKB-decode + envelope/intersection test against the query
bbox.
UnsupportedOperationExceptionfornot(intersects(...))once row-level evaluation is wired up. Thechunk-level dual (containment instead of overlap) can then be added in
RowGroupFilterEvaluator/PageFilterEvaluatorfor completeness, butis independent of this change.
Out of scope
within,contains, distance).Acceptance criteria
jts-coreon the test classpath, anintersectsquery returnsonly rows whose decoded geometry actually intersects the query bbox
(verified by an end-to-end test that builds row groups straddling the
query box).
from Support geospatial statistics and bounding box metadata #173 (bbox-only pushdown, every surviving row returned, negation
still rejected).
core.docs/content/usage.md) updated to describe the opt-in.References
_designs/GEOSPATIAL_SUPPORT.md(status: implemented for thebbox-only layer in Support geospatial statistics and bounding box metadata #173)
core/pom.xmlsnappy/zstd/lz4/brotli4jblocks