fix(db): keep residual clauses residual when combining WHERE clauses - #1977
Conversation
applyOptimizations combined the remaining WHERE clauses of an outer-join query into one plain AND, dropping the residual marker on predicates that were already pushed into a subquery. The next optimization pass treated them as new predicates and pushed them again, so optimizeQuery only stopped at its iteration limit and left duplicated predicates in the subquery. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe optimizer now retains source-free predicates and separates regular WHERE clauses from residual clauses. Structural tests and live-query checks cover predicate placement across join types and repeated optimization. ChangesOptimizer residual handling
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The change fixes optimizer non-convergence for outer-join queries with multiple WHERE clauses and keeps source-free predicates that were previously dropped. No merge-blocking risk was found. The author reports that the one remaining suite failure also occurs on main. Architecture SummaryArchitecture risk: 🟡 Medium · up to The change affects 2 systems. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
Reliability and maintainability
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 3 files. (3 skipped: 3 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
# Conflicts: # docs/contributing/oracle-coverage.md
More templates
@tanstack/angular-db
@tanstack/browser-db-sqlite-persistence
@tanstack/capacitor-db-sqlite-persistence
@tanstack/cloudflare-durable-objects-db-sqlite-persistence
@tanstack/db
@tanstack/db-ivm
@tanstack/db-sqlite-persistence-core
@tanstack/electric-db-collection
@tanstack/electron-db-sqlite-persistence
@tanstack/expo-db-sqlite-persistence
@tanstack/node-db-sqlite-persistence
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/react-native-db-sqlite-persistence
@tanstack/react-router-with-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/tauri-db-sqlite-persistence
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
Changes
Outer joins could make the optimizer push the same filter into a source on each pass. The source gained repeated filters until the ten-pass limit. This PR keeps pushed predicates in their source once and retains their outer residual marker.
Jaime02 reported the repeated-filter case in #1977 after work on #1976. The original patch fixed the common case. A query with an existing residual clause still left three outer WHERE groups. This follow-up combines regular clauses and residual clauses separately. It also removes the second residual-reassembly step.
The loss audit found another error in the same WHERE grouping path. A filter that touched no source, such as
where(() => new Value(false)), disappeared from a joined query. The live-query Collection then published rows even though the filter was false. The optimizer now keeps every clause without one eligible source in the outer WHERE.Evidence and limits
The optimizer oracle checks predicate values, counts, residual markers, outer clause groups, and the extracted source filters. It checks the first optimizer result and a later pass. Its cases cover LEFT, RIGHT, INNER, and FULL joins, namespace predicates, source-free predicates, later RIGHT/FULL joins, and an ordered QueryRef that declines pushdown.
The source-free case also checks public rows. Before the fix, its first snapshot contained three rows instead of none. An empty-source-filter mutant and a predicate-value-blind recorder both fail at their intended oracle checks. The review record lists the checked boundaries and open paths.
The production diff has nine fewer lines than
origin/main. The fullpackages/db/testssuite passed: 197 files and 7,675 tests. Package type checking, ESLint, Prettier, and the diff check passed. The suite used two Vitest threads and a 120-second test timeout.Checklist
packages/db/testssuite.Release impact
Summary by CodeRabbit