fix(core-py): drop orphan cubes when their base model is pruned#2362
fix(core-py): drop orphan cubes when their base model is pruned#2362goldmedal wants to merge 1 commit into
Conversation
Manifest extraction prunes models down to those a query reaches, but kept all cubes unconditionally. A cube whose baseObject model got pruned then failed wren-core MDL analysis with "baseObject is not a defined Model or View" — so any query touching only tables unrelated to a cube's base, or a scalar query referencing no model, broke once a cube existed (issue #2360). Filter cubes to those whose baseObject still resolves to a kept model or view. Cube queries emit `SELECT ... FROM <baseObject>`, so a queried cube's base model is always pulled in — dropping orphans is therefore safe. Backport of Canner/wren-engine-saas #892 (+ #895 view-cube coverage). Closes #2360 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WalkthroughManifest extraction now prunes cubes whose ChangesManifest cube pruning
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Problem — fixes #2360
With a cube defined in the manifest, querying any table other than the cube's base model fails:
Root cause
ManifestExtractor(extractor.rs) prunes models down to those a query reaches, but kept all cubes unconditionally (cubes: mdl.manifest.cubes.clone()). When a query touches only tables unrelated to a cube'sbaseObject, that base model gets pruned away while the cube is retained — leaving an orphan cube whosebaseObjectno longer resolves. wren-core's lineage validation (lineage.rs) then rejects the extracted manifest.The full-manifest fallback in
engine._plan()does not rescue this: extraction itself succeeds (the orphan is silent), and the failure surfaces later inget_session_context, where there is no fallback — so the query hard-fails. Even a scalarSELECT 1breaks once a cube exists.Fix
Filter cubes to those whose
baseObjectstill resolves to a kept model or view (extract_cubes). A cube query emitsSELECT ... FROM <baseObject>, so a queried cube's base is always pulled into the extracted manifest — dropping orphans is safe and never removes a cube the query actually needs.Verification
cargo test --no-default-features extractor: 36 passed, incl. 6 newtest_extract_manifest_for_cubescases (model-based, view-based, scalar/no-model, unrelated-model).revenuecube overorders+ a separatepartsmodel;extract_by(["parts"])thenSessionContext.transform_sql("SELECT ... FROM parts"):['revenue'](orphan) →baseObject 'orders' is not a defined Model or View[]→ transform succeedspytest tests/unit/test_cube_cli.py: 16 passed (querying the cube itself still pulls in its base and works).cargo fmt --checkclean,cargo clippy --no-default-features --all-targetsno warnings.Scope
One file:
core/wren-core-py/src/extractor.rs(production change + Rust regression tests). No public API change;Manifest.cubesis unchanged in shape.🤖 Generated with Claude Code