Skip to content

fix(duckdb): Push down IS [NOT] DISTINCT FROM filters - #11398

Open
AYUSHNSUT wants to merge 1 commit into
vortex-data:developfrom
AYUSHNSUT:ayush/duckdb-distinct-from-pushdown
Open

AYUSHNSUT wants to merge 1 commit into
vortex-data:developfrom
AYUSHNSUT:ayush/duckdb-distinct-from-pushdown

Conversation

@AYUSHNSUT

@AYUSHNSUT AYUSHNSUT commented Nov 11, 2026 •

Copy link
Copy Markdown

Summary

IS [NOT] DISTINCT FROM filters fail against a Vortex scan in DuckDB with Binder Error: cannot convert DUCKDB_VX_EXPR_TYPE_COMPARE_DISTINCT_FROM. So do IS [NOT] TRUE and IS [NOT] FALSE, which DuckDB rewrites to them. can_push_expression accepts every BoundComparison, but the converter only handles the six operators in Operator.

This lowers the two operators in the converter so the filter is evaluated by the scan.

Changes

  • vortex-duckdb/src/convert/expr.rs: lower IS NOT DISTINCT FROM as (l IS NULL AND r IS NULL) OR (l IS NOT NULL AND r IS NOT NULL AND l = r), and IS DISTINCT FROM as its negation. Unlike =, the result is never NULL, so it is correct under NOT and OR.
  • vortex-sqllogictest/slt/is_distinct_from.slt: covers a constant, NULL, column against column, NOT (...) and IS [NOT] TRUE. On DuckDB it also asserts through EXPLAIN that no FILTER node remains.

Tests

  • The slt fails on develop with the error above and passes with this change. It also fails if the lowering uses plain = or drops the not-null guards.
  • cargo test -p vortex-duckdb --lib and cargo test -p vortex-sqllogictest --test sqllogictests pass; clippy -D warnings and fmt on the pinned nightly are clean.

Notes

IS DISTINCT FROM lowers to a NOT(...), which has no zone-map falsification rule, so it is not pruned by zone maps. This is from reading the stats rewrite rules, not from a measurement.

AI assistance

Developed with Claude Code (Claude Sonnet 5.5); I reviewed the diff and the test results and stand behind the change.

🤖 Generated with Claude Code

DuckDB filters `x IS [NOT] DISTINCT FROM <value>`, and the `IS [NOT] TRUE/FALSE`
forms it rewrites to them, failed to bind against a Vortex scan with "cannot
convert DUCKDB_VX_EXPR_TYPE_COMPARE_DISTINCT_FROM". `can_push_expression`
accepted every comparison, but the converter only knew the operators in
`Operator`.

Lower them in the converter as
`(l IS NULL AND r IS NULL) OR (l IS NOT NULL AND r IS NOT NULL AND l = r)` and
its negation. Unlike `=`, this is never NULL, so it stays correct under NOT
and OR.

Add a sqllogictest that runs on DuckDB and DataFusion and, on DuckDB, asserts
that the filter is pushed into the scan.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Ayush Mishra <ayushm1906@gmail.com>
@codspeed

codspeed Bot commented Nov 12, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 16.19%

2 warnings

⚠️ Walltime results may be unreliable

Some benchmarks used the Walltime instrument outside CodSpeed Macro Runners, which can make the results inconsistent.

Learn more about Macro Runners

See affected benchmarks

⚠️ 3 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚡ 3 improved benchmarks
✅ 1918 untouched benchmarks
⏩ 50 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
⚡ CPU Simulation bench_compare_varbin[(50000, 2)] 162.9 µs 134.2 µs +21.4%
⚡ CPU Simulation bench_compare_sliced_dict_varbinview[(1000, 10000)] 92.3 µs 80.9 µs +14.1%
⚡ CPU Simulation bench_compare_sliced_dict_varbinview[(9999, 10000)] 234 µs 206.6 µs +13.26%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing AYUSHNSUT:ayush/duckdb-distinct-from-pushdown (736254c) with develop (bc3d422)

Open in CodSpeed

Footnotes

  1. 50 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

This branch has not been deployed

No deployments
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