TableScanBuilder::with_case_sensitive(false) is ignored when binding scan filters

Open Beginner friendly
#2,490 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
rust
Domain
databases

Research direction

Start in crates/iceberg/src/scan/mod.rs, especially the builder flag near line 93 and build() near line 278; trace the bound predicate into process_data_manifest_entry near line 529. Verify how scan filters are bound and how the no-snapshot early return behaves. Done means case-insensitive scans resolve Reference("ID") against a field named id, while normal scans retain case-sensitive behavior.

Written by the indexing model from the issue text.

Description

TableScanBuilder::with_case_sensitive(false) does not appear to be honored when the scan filter is bound.

What I found

  • TableScanBuilder::with_case_sensitive stores the flag on the builder in crates/iceberg/src/scan/mod.rs
  • build() later binds the scan predicate with true instead of the configured flag
  • that bound predicate is then used for file metrics pruning in process_data_manifest_entry

Relevant code

  • crates/iceberg/src/scan/mod.rs:93
  • crates/iceberg/src/scan/mod.rs:278
  • crates/iceberg/src/scan/mod.rs:529

Why this looks wrong
A scan configured with with_case_sensitive(false) should allow case-insensitive field resolution consistently across planning. Right now, filters are effectively bound case-sensitively during scan construction.

Expected behavior
A filter like Reference("ID") == ... should bind successfully against a schema field named id when the scan was configured with with_case_sensitive(false).

Actual behavior
The filter is bound as if case sensitivity were still enabled, because build() hardcodes true during binding:

let snapshot_bound_predicate = if let Some(ref predicates) = self.filter {
    Some(predicates.bind(schema.clone(), true)?)
} else {
    None
};

There is also a smaller related gap in the same method: when the table has no current snapshot, build() returns early before binding the filter at all, so malformed filters can be skipped on empty tables. But the main issue here is the incorrect case-sensitivity handling on normal scans.

I did not find an obvious existing issue for this in a quick tracker search.

Dominant language
Rust
Stars
1.4k
Forks
574
Avg merge
1d 18h
Merged PRs (30d)
84

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from apache/iceberg-rust

All issues in apache/iceberg-rust

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.