Skip to content

Route constant-geometry spatial-relationship predicates to the TRTREE index#144

Open
estebanzimanyi wants to merge 1 commit into
feat/trtree-mest-multientryfrom
feat/trtree-spatialrel-pushdown
Open

Route constant-geometry spatial-relationship predicates to the TRTREE index#144
estebanzimanyi wants to merge 1 commit into
feat/trtree-mest-multientryfrom
feat/trtree-spatialrel-pushdown

Conversation

@estebanzimanyi
Copy link
Copy Markdown
Member

eIntersects, eContains, eDisjoint and eTouches against a constant geometry are recognised by the TRTREE scan optimizer, which synthesizes the bounding-box && prefilter from the constant and probes the index (single-box or MEST). The bbox is a lossy superset, so the index scan reports supports_pushdown_type = false and DuckDB keeps the original predicate as an exact recheck filter above the scan, mirroring the lossy-index-always-rechecks contract of PostGIS GiST and MobilityDB's tspatial_supportfn. A parity block proves that a row whose bounding box overlaps the query polygon but does not actually intersect it is dropped, identically with and without the index and under MEST multi-entry. Stacked on #143; its commits show in the diff until it merges.

@estebanzimanyi
Copy link
Copy Markdown
Member Author

Reviewer's quickstart — ~6 minutes

What this PR does in one sentence: when a spatial-rel predicate has a constant geometry on one side (e.g. eIntersects(tgeompoint, 'POLYGON(...)'::GEOMETRY)), routes the lookup through the TRTREE multi-entry index instead of scanning every row — proper index pushdown for the most common geofence query shape.

Files (4):

  • src/index/rtree_optimize_scan.cpp — the scan-optimisation pass that recognises the constant-geometry pattern and rewrites the plan node.
  • src/index/rtree_index_scan.cpp — the new constant-geometry-aware scan entry point.
  • src/include/index/rtree_module.hpp — public declarations for the optimiser hook.
  • test/sql/index/ — assertions that the EXPLAIN plan uses the index for the new pattern.

Verification:

CREATE INDEX rt ON trips USING TRTREE (traj);
EXPLAIN SELECT count(*) FROM trips WHERE eIntersects(traj, 'POLYGON(...)'::GEOMETRY);
-- Before this PR: SEQ_SCAN.  After: TRTREE_INDEX_SCAN.

Cross-link: stacked on #143 (MEST multi-entry indexing), which is in turn the foundation for this optimisation. Both will rebuild cleanly once #161 lands (Linux arm64 build).

Why it's safe to merge: the pre-existing scan path remains available for non-constant-geometry cases; this only adds a new index-aware branch.

@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from 037aa12 to e300988 Compare May 29, 2026 21:36
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from 9fa7aa0 to 60b0dbb Compare May 29, 2026 21:36
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from e300988 to 9ec3e35 Compare May 29, 2026 21:38
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from 60b0dbb to f44e09c Compare May 29, 2026 21:38
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from 9ec3e35 to d25c8ef Compare May 30, 2026 05:15
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from f44e09c to d6a3082 Compare May 30, 2026 05:15
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from d25c8ef to 83eea9d Compare June 5, 2026 17:08
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from d6a3082 to b418281 Compare June 5, 2026 17:08
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from 83eea9d to 27cd7ad Compare June 5, 2026 17:15
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from b418281 to 5ef40cd Compare June 5, 2026 17:15
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from 27cd7ad to dfa653a Compare June 5, 2026 18:42
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch 4 times, most recently from c07d41c to b444787 Compare June 6, 2026 06:35
… index

eIntersects/eContains/eDisjoint/eTouches against a constant geometry are
now recognised by the TRTREE scan optimizer, which synthesizes the
bounding-box && prefilter from the constant and probes the index
(single-box or MEST). The bbox is a lossy superset, so the index scan
reports supports_pushdown_type = false and DuckDB keeps the original
predicate as an exact recheck filter above the scan, mirroring the
lossy-index-always-rechecks contract of PostGIS GiST and MobilityDB's
tspatial_supportfn. A parity block proves that a row whose bbox overlaps
the query polygon but does not actually intersect it is dropped,
identically with and without the index and under MEST multi-entry.
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-spatialrel-pushdown branch from b444787 to 90ed740 Compare June 6, 2026 07:15
@estebanzimanyi estebanzimanyi force-pushed the feat/trtree-mest-multientry branch from 5d2bfb9 to 7477875 Compare June 6, 2026 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant