Skip to content

fix: WHERE filter pushdown silently corrupts OR/CASE queries#155

Open
jxom wants to merge 1 commit intomainfrom
fix/where-filter-pushdown
Open

fix: WHERE filter pushdown silently corrupts OR/CASE queries#155
jxom wants to merge 1 commit intomainfrom
fix/where-filter-pushdown

Conversation

@jxom
Copy link
Copy Markdown
Member

@jxom jxom commented Mar 31, 2026

Problem

extract_raw_column_predicates used visit_expressions which recursively walks all sub-expressions, including children of OR and CASE nodes. This meant:

WHERE block_num = 1 OR block_num = 2

Would extract both block_num = 1 AND block_num = 2 as separate AND predicates in the CTE, silently changing query semantics from a disjunction to a conjunction — returning fewer rows than expected.

Fix

Replace visit_expressions with a manual walk (collect_and_conjuncts) that only recurses through top-level AND conjuncts. At OR, CASE, or any non-AND expression, we stop recursing. Only simple leaf predicates on raw columns are extracted.

Mixed expressions like a AND (b OR c) correctly push down only a.

Tests

  • test_or_predicates_not_pushed_down — OR predicates are NOT pushed down
  • test_case_predicates_not_pushed_down — CASE predicates are NOT pushed down
  • test_simple_and_predicates_pushed_down — simple AND conjuncts still work
  • test_mixed_and_or_only_pushes_safe_conjuncts — mixed AND/OR only pushes safe parts
  • test_nested_or_inside_and_not_pushed_down — nested OR inside AND correctly skipped
  • All 5 existing pushdown tests continue to pass

The extract_raw_column_predicates function used visit_expressions which
recursively walks into ALL sub-expressions, including children of OR and
CASE nodes. This meant WHERE block_num = 1 OR block_num = 2 would extract
both sides as separate AND predicates in the CTE, silently changing query
semantics from a disjunction to a conjunction.

Fix: Replace visit_expressions with a manual walk that only recurses
through top-level AND conjuncts. At OR, CASE, or any non-AND expression,
we stop recursing — only simple leaf predicates on raw columns are
extracted. Mixed expressions like 'a AND (b OR c)' correctly push down
only 'a'.

Amp-Thread-ID: https://ampcode.com/threads/T-019d458d-01b9-76ca-9fb1-ac75d2653f95
Co-authored-by: Amp <amp@ampcode.com>
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