Repository navigation
docs(core-spec): Let dataset-scoped metrics reference source columns as source.column - #633
justint-db wants to merge 1 commit into
Conversation
42a0307 to
f403d0c
Compare
|
I welcome the Regarding column references. Are all columns always available? A dataset-scoped metric might be defined in terms of other metrics, and evaluated in a rolled-up context. As an analogy, consider the following SQL query: SELECT job, MAX(sal) - MIN(sal) + deptno AS m
FROM emp
GROUP BY jobThe reference to Would the This latter option I call "cube semantics", based on what comes out of the query SELECT job, deptno, MAX(sal) - MIN(sal) + deptno AS m
FROM emp
GROUP BY CUBE(job, deptno) |
|
Maybe we can talk more about "cube semantics" sometime. Once you're thinking in terms of SQL's |
…as source.column A dataset-scoped metric may now reference a column of its dataset's source, written as source.column. The source qualifier is case insensitive and reaches a column that a field of the same name shadows. Unqualified names must still be declared fields. source is not reserved. If a dataset declares a field named source, the field takes precedence, and the dataset's metrics cannot refer to source columns. The validator accepts source.column and reports its use in a dataset that declares a field named source. Co-authored-by: Isaac <[email protected]>
f403d0c to
92a73f1
Compare
| qualifiers = set() | ||
| undeclared = set() | ||
| uses_source = False | ||
| for col in tree.find_all(exp.Column): |
There was a problem hiding this comment.
validate_metric_scoping rejects a dataset-scoped metric that uses DATEDIFF with a unit, because sqlglot parses the unit as a column. On 92a73f1, DATEDIFF(day, source.opened_at, source.closed_at) fails with "references undeclared field(s) 'day'". So does the form from expression_language.md, DATEDIFF(day, start_date, end_date), with both fields declared.
validate_metric_references and validate_field_shadowing already skip the unit through iter_columns. With it here, on 92a73f1 with sqlglot 30.27.0:
DATEDIFF(day, source.opened_at, source.closed_at)passes.DATEDIFF(day, start_date, end_date)with both fields declared passes.DATEDIFF(MINUTE, opened_at, CURRENT_TIMESTAMP)under OSSIE_SQL_2026 passes.DATEDIFF(day, opened_at, closed_at)withclosed_atundeclared reportsCLOSED_ATinstead ofday.SUM(minute)with no fieldminuteis still reported.validation/tests: 493 passed, the same as without the change.
| for col in tree.find_all(exp.Column): | |
| for col in iter_columns(tree): |
If you'd rather keep this PR's scope, I can send this as a follow-up after it lands, as I offered in #608.
Summary
A dataset-scoped metric can now reference columns of its dataset's
source, written assource.column.Rules (
spec.mdMetric Scoping and Name Resolution,expression_language.mdName Spaces)SUM(net_amount).source:SUM(source.quantity). The qualifier is case insensitive.source.amountrefers to the source column even when the dataset declares a field namedamount.sourceis not reserved. If a dataset declares a field namedsource, the name refers to that field, and the dataset's metrics cannot refer to source columns.Changes from the earlier version of this PR, following JB's review:
source.is required for source columns. Unqualified source-column names are no longer accepted, so a reference can't silently change meaning when a field is added later. This could be relaxed in the future.Validator (
validation/validate.py)source.columnin dataset-scoped metrics.SUM(quantiy)fails.source.columnin a dataset that declares a field namedsource.spec.yaml,ossie-schema.json, and a comment in the Python model are updated to match.Related Issues
Follows #486 and #591.
AGG()reservation: #662 (was previously part of this PR, now moved out to its own PR).Checklist
Specification
core-spec/and follow the existing structureValidation
validation/are updated if the spec changedTests
validation/tests/: 493 passed;python/tests/: 268 passed)