Skip to content

fix(schema-compiler): multi_stage leaf measure missing FROM clause#10550

Draft
TheRoot-1 wants to merge 1 commit intocube-js:masterfrom
TheRoot-1:fix/multi-stage-leaf-missing-from-clause
Draft

fix(schema-compiler): multi_stage leaf measure missing FROM clause#10550
TheRoot-1 wants to merge 1 commit intocube-js:masterfrom
TheRoot-1:fix/multi-stage-leaf-missing-from-clause

Conversation

@TheRoot-1
Copy link
Copy Markdown

Summary

  • Fixes a crash in renderWithQuery when a multi_stage measure's sql has no {} measure dependencies (leaf node in the dependency graph)
  • memberFrom is null for leaves, causing fromSubQueryfromSql to be null, which triggers the error check: "Multi stage member '...' lacks FROM clause in sub query"
  • Adds a fallback: when fromSubQuery was never built and the withQuery has measures, build a subquery directly from the cube's own table

Fixes: #10549
Related: #9241

Test plan

  • Added unit tests in base-query.test.ts covering:
    • Leaf sum measure does not throw
    • CTE query is generated (multi_stage path is taken)
    • Filters propagate through the leaf fallback subquery
    • avg type works as well as sum
  • All existing unit tests pass (466 tests, 464 pass, 2 pre-existing failures in error-reporter.test.ts)

When a multi_stage measure's sql references a raw column with no measure
dependencies, fromMeasures is null so fromSubQuery is never built, leaving
fromSql null. The existing error check then throws "lacks FROM clause".

Add a fallback: when fromSql is null but withQuery.measures is non-empty,
build a subquery directly from the cube's own table instead of failing.

Fixes: cube-js#10549
Related: cube-js#9241
@TheRoot-1
Copy link
Copy Markdown
Author

Context on how this surfaces: this edge case came up when auto-generating Cube schemas from another modeling tool. The converter produced multi_stage: true on leaf measures that reference columns directly (sql: amount) rather than other measures via {}.

The intended Cube pattern is a chain where the leaf is a regular measure and multi_stage is on the derived measure. We're aware of that and are fixing the converter separately. This PR handles the case gracefully rather than throwing an unhelpful error.

@TheRoot-1
Copy link
Copy Markdown
Author

Converting to draft — some findings since opening:

Tesseract has the same bug. The Rust planner flags leaf measures via is_without_member_leaf in plan_for_leaf_cte_query() but produces FromSource::Empty (empty string), resulting in invalid SQL with no FROM clause. This PR only fixes the JS planner path.

This may not be an intended use case. Every multi_stage example in the test suite uses {} measure references. A leaf with sql: amount, multi_stage: true and no {} dependency isn't the expected pattern. A schema-level validation error might be more appropriate than a runtime fallback.

Leaving as draft until the team weighs in on the preferred approach — see #10549 for the full discussion.

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.

multi_stage leaf measure throws "lacks FROM clause" when sql references raw column

1 participant