Skip to content

Sink a filter that holds a projection into NdFilterExec (#397) - #401

Open
robinskil wants to merge 1 commit into
mainfrom
features/nd-pushdown-projection-filter
Open

robinskil wants to merge 1 commit into
mainfrom
features/nd-pushdown-projection-filter

Conversation

@robinskil

Copy link
Copy Markdown
Collaborator

What changes does this PR make?

NdFilterPushdown now sinks a FilterExec that holds a projection. The conjuncts go
into NdFilterExec. The projection becomes an NdProjectionExec below the broadcast.

Why do you make these changes?

Closes #397. DataFusion adds a projection when the select list is narrower than the
predicate. count(*) gets an empty projection. The rule refused such a filter, so the
plan broadcast every column onto the full grid first.

How do you make these changes?

A residual conjunct reads the columns that the projection drops. So the projection stays
with the residual filter above the broadcast. The rule also keeps a filter that holds a
fetch, because the nd filter has no cap.

Release run on gridded-example.nc, 2.32 M cells, 714.1 K rows survive:

query broadcast before broadcast after
SELECT lat … ST_Within(…) 8.30 ms, 2.32 M rows 2.08 ms, 714.1 K rows
count(*) … ST_Within(…) 5.33 ms, 2.32 M rows 10.08 µs, 0 columns

Does this PR change a public interface or a configuration?

No.

How do you test these changes?

Four unit tests in nd/mod.rs: a narrow projection, an empty projection, a residual
conjunct, and the fetch guard. Each test compares the rewritten plan against the rows
of the original plan.

cargo clippy -p beacon-datafusion-ext --lib --tests
cargo test -p beacon-datafusion-ext --lib

I also checked the queries against a runtime with the nd pipeline off. The rows, the
count(*) and the sum() agree.

Checklist

  • The title of the PR describes the change, and it ends with the issue number if one exists.
  • The code follows the style of the project, and cargo fmt --all --check passes.
  • cargo clippy --workspace --lib --bins --tests reports no new warnings.
  • cargo test --workspace --lib --bins --tests passes.
  • The new code has tests, or the PR explains why it does not.
  • The documentation, the README, and the CHANGELOG show the change.
  • The PR contains no unrelated changes.

Notes on the two open boxes:

  • cargo fmt --all --check does not pass on main today. The new code follows the
    style of the file.
  • The CHANGELOG bullet on N-dimensional execution already states this behaviour, and
    the feature is unreleased.
  • PR Apply the whole pushed-down projection in the ODV and BBF scans (#382) #398 adds beacon-core/tests/nd_pipeline_filters.rs. Its test
    a_narrowing_select_list_keeps_the_filter_above_the_broadcast records the old
    behaviour, so it needs an update there.

Was this patch authored or co-authored using generative AI tooling?

Assisted-by: Claude:claude-opus-5

NdFilterPushdown refuses a FilterExec that holds a projection. DataFusion adds a
projection when the select list is narrower than the predicate. count(*) gets an
empty projection. So the most common spatial query filters after the broadcast.

Split the filter. The conjuncts go into NdFilterExec. The projection becomes an
NdProjectionExec above it, below the broadcast. A residual conjunct reads the
columns that the projection drops, so the projection stays with the residual
filter above the broadcast.

Keep a filter that holds a fetch. The nd filter has no cap. The old rule dropped
the whole node, and the cap with it.

Add four unit tests in nd/mod.rs. Each test compares the rewritten plan against
the rows of the original plan.

Assisted-by: Claude:claude-opus-5
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.46%. Comparing base (2f8f748) to head (6ff9a07).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #401      +/-   ##
==========================================
+ Coverage   82.42%   82.46%   +0.04%     
==========================================
  Files         363      363              
  Lines       59366    59520     +154     
==========================================
+ Hits        48931    49086     +155     
+ Misses      10435    10434       -1     
Files with missing lines Coverage Δ
beacon-db/beacon-datafusion-ext/src/nd/mod.rs 98.15% <100.00%> (+0.44%) ⬆️
...eacon-db/beacon-datafusion-ext/src/nd/optimizer.rs 89.09% <100.00%> (+1.97%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@robinskil robinskil mentioned this pull request Aug 19, 2026
41 tasks
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.

Sink a filter that carries a projection into NdFilterExec

1 participant