Skip to content

fix(mem-wal): refill scans after shadow filtering#7917

Merged
hamersaw merged 3 commits into
lance-format:mainfrom
u70b3:fix/memwal-scan-limit-underfill
Jul 23, 2026
Merged

fix(mem-wal): refill scans after shadow filtering#7917
hamersaw merged 3 commits into
lance-format:mainfrom
u70b3:fix/memwal-scan-limit-underfill

Conversation

@u70b3

@u70b3 u70b3 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • stop pushing a finite source limit below cross-generation PkBlockFilterExec
  • let the existing post-filter LocalLimitExec pull until it has offset + limit live rows or reaches EOF
  • retain limit pushdown for sources without a block filter
  • add regressions for update/filter predicate crossing, active tombstones, multiple base fragments, and offset/limit semantics

Closes #7916

Why

A stale prefix could consume an on-disk source's finite limit before cross-generation shadow filtering removed it. The scan then returned fewer rows than requested even though later live rows existed. A finite over-fetch factor cannot make that exact.

Block-filtered scans now use the existing execution tree as a streaming refill: LocalLimitExec stays above PkBlockFilterExec, continues pulling until enough rows survive, and cancels the child once the source contribution is full. Sources without a block filter keep the physical limit pushdown.

Testing

  • cargo test -p lance --lib test_lsm_scan_limit_
  • cargo test -p lance --lib dataset::mem_wal::scanner::
  • cargo test -p lance --lib dataset::mem_wal::
  • cargo fmt --all
  • cargo clippy --all --tests --benches -- -D warnings
  • pre-commit hooks: fmt, typos, and Cargo lock sync

Compatibility

No public API, file format, or dependency changes.

Classification

This fixes silently incomplete query results and should be labeled critical-fix. The linked issue uses the required bug: title prefix, but GitHub rejected label mutation for the contributor account.

@github-actions github-actions Bot added the bug Something isn't working label Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

MemWAL scan planning validates overfetch_factor, avoids finite child fetch limits for block-filtered sources, and uses post-filter local limits to refill results. Tests cover update and tombstone shadowing with LIMIT and OFFSET, plus the base-only plan shape.

Changes

MemWAL scan limit refill

Layer / File(s) Summary
Overfetch validation scope
rust/lance/src/dataset/mem_wal/scanner/builder.rs, rust/lance/src/dataset/mem_wal/scanner/planner.rs
Plain scans no longer use overfetch_factor; search planning still validates it, and planner documentation reflects validation-only behavior.
Planner fetch and block-filter handling
rust/lance/src/dataset/mem_wal/scanner/planner.rs
Block-filtered sources use unbounded child scans with k = 0, while eligible sources retain finite fetch pushdown and local limits.
Shadow-filter limit regression coverage
rust/lance/src/dataset/mem_wal/scanner/planner.rs
Integration tests verify refill after update and tombstone shadowing, offset handling across fragments, and the updated base-only limit plan shape.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: hamersaw, touch-of-grey

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main fix: scans refilling after shadow filtering.
Description check ✅ Passed The description matches the change and explains the refill fix, retained pushdown, and added regressions.
Linked Issues check ✅ Passed The code changes address #7916 by refilling block-filtered scans, preserving pushdown elsewhere, and covering the listed shadowing cases.
Out of Scope Changes check ✅ Passed No unrelated changes are indicated; the edits and tests stay focused on the scan-refill fix and related overfetch behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
rust/lance/src/dataset/mem_wal/scanner/planner.rs-107-109 (1)

107-109: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a synchronized usage example for this public builder method.

The documentation links to plan_scan but has no example showing with_overfetch_factor in a builder chain.

As per coding guidelines, “Document all public APIs with examples and links to relevant structs and methods; keep examples synchronized with actual signatures.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance/src/dataset/mem_wal/scanner/planner.rs` around lines 107 - 109,
Add a Rust doc-test example to the public builder method with_overfetch_factor,
showing it used in a builder chain with its current signature and a subsequent
plan_scan call. Keep the example synchronized with the actual builder types and
link relevant methods or structs using valid intra-doc links.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Other comments:
In `@rust/lance/src/dataset/mem_wal/scanner/planner.rs`:
- Around line 107-109: Add a Rust doc-test example to the public builder method
with_overfetch_factor, showing it used in a builder chain with its current
signature and a subsequent plan_scan call. Keep the example synchronized with
the actual builder types and link relevant methods or structs using valid
intra-doc links.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: 59c11888-1be0-4184-9dfb-afc3447c4b6b

📥 Commits

Reviewing files that changed from the base of the PR and between 50379ba and e8b9a2d.

📒 Files selected for processing (1)
  • rust/lance/src/dataset/mem_wal/scanner/planner.rs

@u70b3
u70b3 force-pushed the fix/memwal-scan-limit-underfill branch from e8b9a2d to f5cf83a Compare July 22, 2026 13:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
rust/lance/src/dataset/mem_wal/scanner/planner.rs (1)

1001-1002: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the standard in-memory test URI. These tests do not reopen datasets or exercise flushed on-disk generations, so temporary directories add unnecessary filesystem setup.

  • rust/lance/src/dataset/mem_wal/scanner/planner.rs#L1001-L1002: replace the temporary directory-derived base URI with memory://.
  • rust/lance/src/dataset/mem_wal/scanner/planner.rs#L2149-L2150: replace the temporary directory-derived base URI with memory://.

As per coding guidelines, use plain "memory://" URIs in tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/lance/src/dataset/mem_wal/scanner/planner.rs` around lines 1001 - 1002,
Replace the temporary-directory-derived base URI with the plain "memory://" URI
in both affected test setup sites in
rust/lance/src/dataset/mem_wal/scanner/planner.rs (lines 1001-1002 and
2149-2150), removing the unnecessary tempfile setup while preserving the tests’
existing behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rust/lance/src/dataset/mem_wal/scanner/planner.rs`:
- Around line 198-205: Add a plan-level test covering the planner branch in the
scan-building flow where n_needed is Some(n), is_active is false, and
has_block_filter is false, and assert the finite fetch is pushed to the source
scan. Use a limited source without a block filter and inspect the generated plan
rather than only result rows, ensuring the test fails if Some(n) is not passed
to build_source_scan.
- Around line 107-109: Add a synchronized # Examples doctest to the public
builder documented by the comments near Self::plan_scan, showing construction,
setting a valid over-fetch factor, and invoking the builder’s scan-planning API
so it compiles; link referenced types and methods with intra-doc links
consistent with the existing vector and full-text planner documentation.

---

Nitpick comments:
In `@rust/lance/src/dataset/mem_wal/scanner/planner.rs`:
- Around line 1001-1002: Replace the temporary-directory-derived base URI with
the plain "memory://" URI in both affected test setup sites in
rust/lance/src/dataset/mem_wal/scanner/planner.rs (lines 1001-1002 and
2149-2150), removing the unnecessary tempfile setup while preserving the tests’
existing behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Pro Plus

Run ID: abd47088-155e-4259-95d0-7819a2cb25d9

📥 Commits

Reviewing files that changed from the base of the PR and between e8b9a2d and f5cf83a.

📒 Files selected for processing (1)
  • rust/lance/src/dataset/mem_wal/scanner/planner.rs

Comment thread rust/lance/src/dataset/mem_wal/scanner/planner.rs Outdated
Comment thread rust/lance/src/dataset/mem_wal/scanner/planner.rs
@u70b3
u70b3 force-pushed the fix/memwal-scan-limit-underfill branch from dee43d3 to 1c50531 Compare July 23, 2026 02:04

@hamersaw hamersaw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great find! Using LocalLimitExec is a better approach for scan operations. The only change I'm proposing is, if the overfetch_factor configuration on LsmScanPlanner is not used anywhere (besides validation). Lets just go ahead and remove it, along wiht the with_overfetch_factor and stop passing it into the LsmScanBuilder::plan_scan. We still need it on vector + FTS searches, but it's moot on the regular scan path.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.47328% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rust/lance/src/dataset/mem_wal/scanner/builder.rs 93.93% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@u70b3

u70b3 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 0424b95: removed overfetch_factor from LsmScanPlanner and stopped forwarding it on plain scans. It remains wired and validated for vector/FTS searches, with regression coverage for the three paths. cargo fmt --all, targeted tests, and full Rust clippy pass.

@u70b3
u70b3 force-pushed the fix/memwal-scan-limit-underfill branch from 0424b95 to 11de4d9 Compare July 23, 2026 05:00
@u70b3
u70b3 requested a review from hamersaw July 23, 2026 05:00
@u70b3
u70b3 force-pushed the fix/memwal-scan-limit-underfill branch from 11de4d9 to 5729733 Compare July 23, 2026 13:00
@hamersaw

Copy link
Copy Markdown
Contributor

Thanks for the PR!

@hamersaw
hamersaw merged commit 18d1052 into lance-format:main Jul 23, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: MemWAL scans can underfill limits after shadow filtering

2 participants