Skip to content

fix(scan): keep the predicate when a partition set cannot express it - #886

Open
jackylee-ch wants to merge 1 commit into
apache:mainfrom
jackylee-ch:fix/partition-set-keeps-unexpressible-conjuncts
Open

jackylee-ch wants to merge 1 commit into
apache:mainfrom
jackylee-ch:fix/partition-set-keeps-unexpressible-conjuncts

Conversation

@jackylee-ch

Copy link
Copy Markdown
Contributor

Defect. from_predicate recognised only And plus Eq/In/IsNull leaves; everything else fell through _ => {}, discarded. With every field covered it built a PartitionSet, and matches_entry is then pure HashSet membership — the predicate is never read again. A partition-only filter is Exact, so DataFusion drops its residual: WHERE dt='2024-01-01' AND dt>='2024-01-02' returned 1 row, not 0.

Fix. collect_eq_candidates reports whether it consumed the whole tree; from_predicate keeps the predicate when it did not. A second conjunct on an already-pinned field also bails: the old code overwrote it, keeping whichever came last — possibly the wider one.

Cost. The fallback pays from_serialized_bytes + eval_row per entry instead of a hash lookup, and an In leaf loses its min/max bound (stats_filter.rs:73). Only on shapes answered wrongly before.

collect_eq_candidates recognised only And plus Eq/In/IsNull leaves; every
other node fell through `_ => {}` and was discarded. Once every partition
field had a candidate, from_predicate built a PartitionSet, and
matches_entry is then pure HashSet membership -- the predicate is never
consulted again. A partition-only filter is Exact, so DataFusion drops
its residual and the discarded conjuncts are never enforced.

collect_eq_candidates now reports whether it consumed the whole tree, and
from_predicate keeps the predicate when it did not. A second conjunct on
an already-pinned field also bails: the assignment used to overwrite the
first, so the set kept whichever came last, which can be the wider one.

This is a regression rather than original behaviour. 513942e (apache#224) added
is_exact_filter_pushdown_for_schema while every manifest entry was still
tested with eval_row against the whole partition predicate; 391349d
(apache#269) replaced that with PartitionFilter::matches_entry two days later.

bucket_filter's copy of this walk is left alone on purpose. Its result is
consumed as a pre-filter -- table_scan.rs:364-369 and its three siblings
drop a bucket only when it is absent from the target set -- so discarding
a conjunct there can only widen the candidate set, never drop a matching
file.
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