diff --git a/_site/staticwebapp.config.json b/_site/staticwebapp.config.json
deleted file mode 100644
index 56b596620..000000000
--- a/_site/staticwebapp.config.json
+++ /dev/null
@@ -1 +0,0 @@
-{"routes":[{"route":"/","redirect":"/en/","statusCode":301},{"route":"/index.html","redirect":"/en/","statusCode":301},{"route":"/en/references/release-notes","redirect":"/en/references/release-notes/3_26_0.html","statusCode":302},{"route":"/en/te3/other/release-notes","redirect":"/en/references/release-notes/3_26_0.html","statusCode":302},{"route":"/es/references/release-notes","redirect":"/es/references/release-notes/3_26_0.html","statusCode":302},{"route":"/es/te3/other/release-notes","redirect":"/es/references/release-notes/3_26_0.html","statusCode":302},{"route":"/zh/references/release-notes","redirect":"/zh/references/release-notes/3_26_0.html","statusCode":302},{"route":"/zh/te3/other/release-notes","redirect":"/zh/references/release-notes/3_26_0.html","statusCode":302},{"route":"/references/release-notes","redirect":"/en/references/release-notes/3_26_0.html","statusCode":302},{"route":"/Advanced-Scripting.html","redirect":"/en/how-tos/Advanced-Scripting.html","statusCode":301},{"route":"/Best-Practice-Analyzer.html","redirect":"/en/features/Best-Practice-Analyzer.html","statusCode":301},{"route":"/Command-line-Options.html","redirect":"/en/features/Command-line-Options.html","statusCode":301},{"route":"/Custom-Actions.html","redirect":"/en/tutorials/creating-macros.html","statusCode":301},{"route":"/FormatDax.html","redirect":"/en/references/FormatDax.html","statusCode":301},{"route":"/Importing-Tables.html","redirect":"/en/how-tos/Importing-Tables.html","statusCode":301},{"route":"/Power-BI-Desktop-Integration.html","redirect":"/en/getting-started/Power-BI-Desktop-Integration.html","statusCode":301},{"route":"/Useful-script-snippets.html","redirect":"/en/features/Useful-script-snippets.html","statusCode":301},{"route":"/Workspace-Database.html","redirect":"/en/tutorials/workspace-mode.html","statusCode":301},{"route":"/common/Datasets/direct-lake-dataset.html","redirect":"/en/features/Semantic-Model/direct-lake-sql-model.html","statusCode":301},{"route":"/eula","redirect":"/en/security/te3-eula.html","statusCode":301},{"route":"/onboarding/general-introduction.html","redirect":"/en/getting-started/general-introduction.html","statusCode":301},{"route":"/onboarding/index.html","redirect":"/en/getting-started/index.html","statusCode":301},{"route":"/onboarding/installation.html","redirect":"/en/getting-started/installation.html","statusCode":301},{"route":"/other/downloads.html","redirect":"/en/references/downloads.html","statusCode":301},{"route":"/privacy-policy.html","redirect":"/en/security/privacy-policy.html","statusCode":301},{"route":"/projects/te3","redirect":"/en/","statusCode":301},{"route":"/projects/te3/en/latest","redirect":"/en/","statusCode":301},{"route":"/projects/te3/en/latest/downloads.html","redirect":"/en/references/downloads.html","statusCode":301},{"route":"/projects/te3/en/latest/editions.html","redirect":"/en/getting-started/editions.html","statusCode":301},{"route":"/projects/te3/en/latest/getting-started.html","redirect":"/en/getting-started/getting-started.html","statusCode":301},{"route":"/projects/te3/en/latest/security-privacy.html","redirect":"/en/security/security-privacy.html","statusCode":301},{"route":"/roslyn","redirect":"/en/how-tos/Advanced-Scripting.html#compiling-with-roslyn","statusCode":301},{"route":"/te2/Advanced-Scripting.html","redirect":"/en/how-tos/Advanced-Scripting.html","statusCode":301},{"route":"/te2/Best-Practice-Analyzer.html","redirect":"/en/features/Best-Practice-Analyzer.html","statusCode":301},{"route":"/te2/Getting-Started.html","redirect":"/en/getting-started/Getting-Started-te2.html","statusCode":301},{"route":"/te2/Importing-Tables.html","redirect":"/en/how-tos/Importing-Tables.html","statusCode":301},{"route":"/te2/Power-BI-Desktop-Integration.html","redirect":"/en/getting-started/Power-BI-Desktop-Integration.html","statusCode":301},{"route":"/te2/Useful-script-snippets.html","redirect":"/en/features/Useful-script-snippets.html","statusCode":301},{"route":"/te3/downloads.html","redirect":"/en/references/downloads.html","statusCode":301},{"route":"/te3/editions.html","redirect":"/en/getting-started/editions.html","statusCode":301},{"route":"/te3/features/csharp-scripts.html","redirect":"/en/features/csharp-scripts.html","statusCode":301},{"route":"/te3/features/dax-debugger.html","redirect":"/en/features/dax-debugger.html","statusCode":301},{"route":"/te3/features/dax-editor.html","redirect":"/en/features/dax-editor.html","statusCode":301},{"route":"/te3/features/dax-scripts.html","redirect":"/en/features/dax-scripts.html","statusCode":301},{"route":"/te3/features/tmdl.html","redirect":"/en/features/tmdl.html","statusCode":301},{"route":"/te3/getting-started.html","redirect":"/en/getting-started/getting-started.html","statusCode":301},{"route":"/te3/index.html","redirect":"/en/troubleshooting/licensing-activation.html","statusCode":301},{"route":"/te3/logo.svg","redirect":"/en/logo.svg","statusCode":301},{"route":"/te3/other/downloads.html","redirect":"/en/references/downloads.html","statusCode":301},{"route":"/te3/other/release-history.html","redirect":"/en/references/release-history.html","statusCode":301},{"route":"/te3/tutorials/workspace-mode.html","redirect":"/en/tutorials/workspace-mode.html","statusCode":301},{"route":"/tmdl","redirect":"/en/features/tmdl.html","statusCode":301},{"route":"/tmuo","redirect":"/en/references/user-options.html","statusCode":301},{"route":"/user-options.html","redirect":"/en/references/user-options.html","statusCode":301},{"route":"/workspace","redirect":"/en/tutorials/workspace-mode.html","statusCode":301}],"responseOverrides":{"404":{"rewrite":"/404.html"}}}
\ No newline at end of file
diff --git a/configuration/filterConfig.yml b/configuration/filterConfig.yml
index a7f328cb6..e5a14ebba 100644
--- a/configuration/filterConfig.yml
+++ b/configuration/filterConfig.yml
@@ -32,6 +32,10 @@ apiRules:
- exclude:
uidRegex: ^TabularEditor\.SemanticBridge\.Platforms\.Databricks\.Mapping
type: Namespace
+# ANTLR-generated SQL lexer/parser/visitor types (public by generation, not public API)
+- exclude:
+ uidRegex: ^TabularEditor\.SemanticBridge\.Platforms\.Databricks\.Sql
+ type: Namespace
- exclude:
uidRegex: ^TabularEditor\.SemanticBridge\.Platforms\.Databricks\.MetricView\.Extensions
type: Namespace
diff --git a/content/_apiSource/SemanticBridge.dll b/content/_apiSource/SemanticBridge.dll
index bc51edf82..96e84400a 100644
Binary files a/content/_apiSource/SemanticBridge.dll and b/content/_apiSource/SemanticBridge.dll differ
diff --git a/content/_apiSource/SemanticBridge.xml b/content/_apiSource/SemanticBridge.xml
index b62ada949..51251a0b2 100644
--- a/content/_apiSource/SemanticBridge.xml
+++ b/content/_apiSource/SemanticBridge.xml
@@ -4,272 +4,419 @@
SemanticBridge
-
+
- Base record for model objects with common properties
+ Structural surface for a body. Lives
+ alongside the platform-keyed Expressions dict on
+ : the AAST is the structural shape;
+ the dict carries the per-platform source text that the AAST does not
+ yet model. wraps any shape the AAST
+ doesn't yet model structurally.
-
+
- Base record for model objects with common properties
+ Double-dispatch hook. Each concrete subtype calls
+ visitor.Visit(this), routing to the visitor overload that
+ accepts that specific type.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- These are defined such that the success case is the lowest integral value.
-
-
-
+
- Key of the field fragment that represents the primary key for this dimension.
- If not set, no field will be marked as a key.
+ A reference to another measure. is the
+ resolved ; the cross-reference is opaque
+ for equivalency (consistent with model-wide convention that
+ NodeIds are not [EquivalencyComponent]). Two
+ nodes are therefore always structurally
+ equivalent regardless of which measure they target — the
+ differentiator across two such measures is the
+ platform-keyed Expressions dict on
+ .
-
+
- Ensure FactKey, DimensionKey, and RelationshipKey are all set, and that
- the relationships are valid according to cardinality constraints:
- fact to dim is N:1 and left-to-right. Additionally ensure that the
- referenced fact knows about this dimension reference.
+ A reference to another measure. is the
+ resolved ; the cross-reference is opaque
+ for equivalency (consistent with model-wide convention that
+ NodeIds are not [EquivalencyComponent]). Two
+ nodes are therefore always structurally
+ equivalent regardless of which measure they target — the
+ differentiator across two such measures is the
+ platform-keyed Expressions dict on
+ .
-
-
-
- Used as a placeholder source for dummy fact
-
+
+
-
+
- Used as a placeholder for dimension references during construction.
- Since Fact is a record, this creates a minimal instance rather than inheriting.
+ Catch-all for expression shapes the AAST does not yet model
+ structurally. is structural — two
+ nodes are equivalent iff their
+ payload matches.
-
+
- Used as a placeholder for fields during construction of an ITableLike
+ Catch-all for expression shapes the AAST does not yet model
+ structurally. is structural — two
+ nodes are equivalent iff their
+ payload matches.
-
-
- Always call after resolving fields
-
-
+
+
-
+
- Platform-specific expression for derived fields.
- When set, the fragment builds to a DerivedField instead of a Field.
+ Constant-valued expression. The intermediate is abstract; the
+ concrete leaves carry their typed payload. Each platform emitter
+ renders per its target language's literal syntax (DAX uses
+ "..." for strings, BLANK() for null, etc.).
-
-
- Gets the keys of all fields in this table-like fragment.
-
+
+ A string literal payload.
-
-
- Ensure fragment is a valid part of a model.
-
- A collection of build errors found during resolution.
-
- Intended to be used as part of the model build process.
- If errors are returned, then the model cannot have a fully successful
- build; partial success is possible
-
+
+ A string literal payload.
-
-
- Resolve left and right fields, check that cardinalities, kind, and
- direction are set. If direction is not set, check whether sides are
- fact and dimension: set to dimension filters fact.
-
-
- Build errors:
- - if missing or nonexistent field references
- - if not a fact and dimension
- - if any property is unset that is required for an Root.Relationship
-
-
+
+
-
+
- A field derived from a platform-specific expression.
- Similar to CalculatedMeasure, this represents a computed value
- that cannot be directly translated to DAX.
+ A numeric literal payload. Single decimal-valued shape covers
+ both integer and fractional source literals — the emitter
+ formats per the value (no trailing zeros for whole numbers).
-
+
- Mapping of platforms to platform-specific expressions implementing
- the field calculation.
+ A numeric literal payload. Single decimal-valued shape covers
+ both integer and fractional source literals — the emitter
+ formats per the value (no trailing zeros for whole numbers).
-
-
- Data type of the derived field.
-
+
+
-
-
- The table containing this field.
-
+
+ A boolean literal payload.
-
-
- Constructor for DerivedField.
-
- Friendly name for display to users
- Name for internal use by the OLAP engine
- Prose describing the object
- The table containing this field
- Data type of the field
-
- Mapping of platforms to platform-specific expressions implementing
- the calculation
-
+
+ A boolean literal payload.
-
-
- Determines equality by comparing scalar properties and Expressions
- dictionary contents. Excludes parent Table to avoid circular references.
-
- The other DerivedField to compare with
-
- True if both objects have equal scalar properties and equivalent Expressions
-
+
+
-
+
- Generates hash code based on scalar properties and Expressions
- dictionary contents. Excludes parent Table to avoid circular references.
+ The null literal. Carries no payload; emitter renders per
+ target-language null form (DAX BLANK(), SQL NULL).
- A hash code that remains consistent for equivalent objects
-
+
+
+
+
- Accepts a visitor for processing this DerivedField.
+ Binary arithmetic operation. is constrained to
+ values that have direct cross-platform
+ equivalents; richer operator sets (comparison, logical, etc.) wait
+ for future slices. and are
+ recursive AAST children — structural equivalence walks into them via
+ .
-
+
- Context for analysis
+ Binary arithmetic operation. is constrained to
+ values that have direct cross-platform
+ equivalents; richer operator sets (comparison, logical, etc.) wait
+ for future slices. and are
+ recursive AAST children — structural equivalence walks into them via
+ .
-
+
+
+
+
- Collection of descriptive properties
+ Explicit parenthesization. Preserves user-written grouping that the
+ tree shape alone wouldn't capture. The emitter renders
+ (Inner) verbatim — no precedence smarts; the AAST is
+ trusted to carry the intended grouping.
-
+
- Technical name of the primary key field for this dimension.
- Null if no primary key is explicitly defined.
+ Explicit parenthesization. Preserves user-written grouping that the
+ tree shape alone wouldn't capture. The emitter renders
+ (Inner) verbatim — no precedence smarts; the AAST is
+ trusted to carry the intended grouping.
-
+
+
+
+
- Collection of hierarchies
+ Count of all rows in — DAX
+ COUNTROWS('Table'). Produced by the SQL→AAST translator for
+ COUNT(*) and COUNT(<non-null literal>); these
+ shapes are semantically equivalent (both count every row) and
+ collapse to a single AAST form. is typed as
+ so the same node serves fact and (future)
+ dim row counts; it is opaque for equivalency — the cross-reference
+ follows the same convention as .
-
+
- Reference to source system and queryable or embedded query
+ Count of all rows in — DAX
+ COUNTROWS('Table'). Produced by the SQL→AAST translator for
+ COUNT(*) and COUNT(<non-null literal>); these
+ shapes are semantically equivalent (both count every row) and
+ collapse to a single AAST form. is typed as
+ so the same node serves fact and (future)
+ dim row counts; it is opaque for equivalency — the cross-reference
+ follows the same convention as .
-
+
+
+
+
+
+ Aggregation of a single column — DAX
+ SUM('Fact'[col]), COUNT('Fact'[col]), etc. Produced
+ by the SQL→AAST translator for SUM/AVG/MIN/
+ MAX/COUNT/COUNT(DISTINCT) over a single
+ column reference. Unlike , this aggregates
+ a specific field rather than the whole table.
+ is structural (different aggregation
+ functions produce structurally-distinct expressions);
+ is opaque for equivalency — same convention
+ as and
+ .
+
+
+
+
+ Aggregation of a single column — DAX
+ SUM('Fact'[col]), COUNT('Fact'[col]), etc. Produced
+ by the SQL→AAST translator for SUM/AVG/MIN/
+ MAX/COUNT/COUNT(DISTINCT) over a single
+ column reference. Unlike , this aggregates
+ a specific field rather than the whole table.
+ is structural (different aggregation
+ functions produce structurally-distinct expressions);
+ is opaque for equivalency — same convention
+ as and
+ .
+
+
+
+
+
+
- Determines equality by comparing scalar properties and collection
- contents order-independently.
+ Operators allowed in .
+ Restricted to the basic arithmetic set that has direct equivalents
+ in both Databricks SQL and DAX.
- The other Dimension to compare with
-
- True if both objects have equal scalar properties and equivalent collections.
-
-
+
- Generates hash code based on scalar properties and collection contents.
- Fields property is not included since it's computed from Attributes.
+ Aggregation types for measures
- A hash code that remains consistent for equivalent objects
-
+
- Descriptive property in a dimension
+ A computed column on an . Carries one or more
+ platform-keyed source expressions (e.g., the Databricks SQL the field
+ was authored as). Target-platform emitters consult their key to obtain
+ the expression to translate. Doesn't reference a
+ — derived fields exist only at the
+ dimensional-model level.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning ; resolve via
+ Root.GetTable.
+
+ The data type of this field's computed values.
+
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
+
+
+ Platform-keyed source expressions for this field. null coalesces
+ to ImmutableDictionary.Empty at construction.
+
-
+
- Creates a DimensionAttribute from any IField, setting the dimension as the parent table.
+ A computed column on an . Carries one or more
+ platform-keyed source expressions (e.g., the Databricks SQL the field
+ was authored as). Target-platform emitters consult their key to obtain
+ the expression to translate. Doesn't reference a
+ — derived fields exist only at the
+ dimensional-model level.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning ; resolve via
+ Root.GetTable.
+
+ The data type of this field's computed values.
+
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
+
+
+ Platform-keyed source expressions for this field. null coalesces
+ to ImmutableDictionary.Empty at construction.
+
-
+
- Data type of the attribute
+
-
+
- Field reference in the source; the TechnicalName of the source field.
+ Reference to the owning ; resolve via
+ Root.GetTable.
-
+
+ The data type of this field's computed values.
+
+
- Indicates if this attribute is a key
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
-
+
+
+
+
+
+
+
+
+
+
+ Platform-keyed source expressions; never null.
+
+
+
+
+
- The underlying field this attribute wraps.
- Used by visitors to determine if special handling is needed (e.g., DerivedField).
+ A categorical, descriptive context table joined to a .
+ References its data source by . Fields on the
+ dimension live in Root.Fields with their OwnerId set to
+ this dimension's id; relationships between this dimension and a fact
+ are first-class objects on Root (future).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the dimension's data source; resolve via
+ Root.GetSource.
+
-
+
- Determines equality by comparing scalar properties and underlying field type,
- excluding parent Dimension to avoid circular references.
+ A categorical, descriptive context table joined to a .
+ References its data source by . Fields on the
+ dimension live in Root.Fields with their OwnerId set to
+ this dimension's id; relationships between this dimension and a fact
+ are first-class objects on Root (future).
- The other DimensionAttribute to compare with
-
- True if both objects have equal scalar properties (excluding parent reference)
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the dimension's data source; resolve via
+ Root.GetSource.
+
-
+
- Generates hash code based on scalar properties excluding parent
- Dimension to avoid circular references.
+
- A hash code that remains consistent for equivalent objects
-
+
- Determines equality by comparing scalar properties and child references,
- excluding parent Fact to avoid circular references.
+ Reference to the dimension's data source; resolve via
+ Root.GetSource.
- The other DimensionReference to compare with
-
- True if both objects have equal scalar properties and equivalent child references
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
- Generates hash code based on scalar properties and child references,
- excluding parent Fact to avoid circular references.
+ Cardinality of a field in a join/relationship
- A hash code that remains consistent for equivalent objects
@@ -281,772 +428,1495 @@
Permission levels for object rules
-
+
- Represents a business event or measurement context
+ Marks a property as a structural component of equivalence comparison.
+ Properties without this attribute are ignored by
+ — typically the
+ object's own identity and any cross-reference NodeIds it carries.
-
+
- Collection of quantifiable values
+ A business event or measurement context. The central table in a
+ dimensional model. References its data source by
+
+
+
+
+
+
+
+
+
+
+
+
+ Categorization of the fact (Transactional, Snapshot, etc.).
+
+ Reference to the fact's data source; resolve via Root.GetSource.
+
-
+
- Collection of dimension references
+ A business event or measurement context. The central table in a
+ dimensional model. References its data source by
+
+
+
+
+
+
+
+
+
+
+
+
+ Categorization of the fact (Transactional, Snapshot, etc.).
+
+ Reference to the fact's data source; resolve via Root.GetSource.
+
-
+
- Type of fact
+
-
-
- Reference to source system and queryable or embedded query
-
+
+ Categorization of the fact (Transactional, Snapshot, etc.).
-
+
- Determines equality by comparing scalar properties and collection contents order-independently.
+ Reference to the fact's data source; resolve via Root.GetSource.
- The other Fact to compare with
- True if both objects have equal scalar properties and equivalent collections
-
-
- Generates hash code based on scalar properties and collection contents.
-
- A hash code that remains consistent for equivalent objects
+
+
-
-
- Type of fact table
-
+
+
-
-
- Additivity types for measures
-
+
+
-
-
- Aggregation types for measures
-
+
+
-
+
- Determines equality by comparing scalar properties excluding parent
- Table to avoid circular references.
+ Default base for
+ implementations that want the standard abort-and-fallback semantics:
+ unimplemented Visit overloads throw
+ , and the outermost emit catches
+ once at the root and invokes .
+
+ New-platform minimum viable emitter: derive, override
+ , ship. Incrementally override per-shape
+ Visit overloads as structural emission for each construct
+ is implemented; unoverridden ones fall through to the fallback
+ automatically.
+
+
+ Recursive code in concrete overloads should call
+ Visit(child), not child.Accept(this) — the
+ Visit(AbstractExpression) override routes through Accept,
+ keeping the dispatch detail in one place. An
+ raised from any nested call propagates freely; do not catch.
+
- The other Field to compare with
-
- True if both objects have equal scalar properties (excluding
- parent reference)
-
-
-
- Generates hash code based on scalar properties excluding parent
- Table to avoid circular references.
-
- A hash code that remains consistent for equivalent objects
+
+
-
+
- Logical path for drill-down analysis
+ Polymorphic-dispatch entry. Routes through the node's
+ to the matching
+ concrete-typed Visit overload.
-
+
- Ordered collection of dimension attributes
+ Default abort. Overridden by derived classes that can render this
+ construct structurally; otherwise the emit is unwound to the root
+ and takes over.
-
-
- Indicates if hierarchy has inconsistent depth
-
+
+
-
-
- Determines equality by comparing scalar properties and Levels
- collection contents.
-
- The other Hierarchy to compare with
- True if both objects have equal scalar properties and equivalent Levels
+
+
-
-
- Generates hash code based on scalar properties and Levels
- collection contents.
-
- A hash code that remains consistent for equivalent objects
+
+
-
-
- Common properties for all model objects
-
+
+
-
-
- Friendly name for display to users
-
+
+
-
-
- Name for internal use in formulas by the OLAP engine, potentially the same as Name
-
+
+
-
-
- Prose describing the object
-
+
+
-
-
- Represents a data source system that can be referenced by model objects
-
+
+
+
+
+
-
+
- Type-specific identifier for this source system
+ Run the visitor over , catching any
+ raised at any depth and
+ returning instead. The single place
+ where the abort signal is consumed — concrete Visit overloads
+ should propagate, not catch.
-
+
- Represents a source reference with query information
+ Thrown by an Visit
+ method to abort the in-progress emission and trigger the visitor's
+ . Used to
+ unwind partial work from deeply-nested constructs (e.g., a BinaryOp
+ whose right operand cannot be emitted cleanly) so the final output is
+ either fully structural or the platform-appropriate fallback placeholder
+ — never a mix of the two.
-
+
- Reference to the source system
+ Double-dispatch visitor over nodes.
+ New AAST node types add a Visit overload here and every
+ implementation must update — compile-time enforcement that all
+ emitters / analyzers handle every node shape. Mirrors the
+ pattern: the inherited
+ Visit(AbstractExpression) entry method is the polymorphic
+ dispatcher (implementations forward through the node's Accept);
+ concrete overloads do the per-shape work. Recursive code in concrete
+ overloads should call Visit(child), never child.Accept(this).
-
+
- Database or catalog name
+ Target-platform-appropriate placeholder produced when emission
+ aborts. Typically wraps the whole original source in a comment so
+ the user sees their intent preserved while the emitted body is
+ functionally inert. Invoked once at the root by
+
+ when any nested Visit raises an
+ .
- Marker interface for Abstract Model objects that can accept visitors.
- All Abstract Model domain objects (Root, Fact, Dimension, Measure, etc.)
- implement this. This interface enables the visitor pattern for
- traversing the Abstract Model object graph.
+ The Accept half of the abstract-model visitor pattern.
+ Implementers route a visitor's polymorphic dispatch through their
+ concrete-typed Visit overload by the double-dispatch
+ convention visitor.Visit(this).
- Accepts a visitor that produces a result of type TResult.
- The concrete type dispatches to the appropriate Visit overload on
- the visitor based on its runtime type.
+ Dispatches to the concrete-typed
+ Visit overload that matches this record's runtime type.
- The type of value produced by the visitor
- The visitor to accept
- The result produced by the visitor
- Visitor interface for the Abstract Model object graph.
- Extends the generic IVisitor pattern with Abstract Model-specific
- visitation methods. This interface enables type-safe transformation of
- Abstract Model objects while supporting generic orchestration through
- the base IVisitor interface.
+ Visitor over records. One
+ Visit overload per concrete record type, which gives
+ compile-time exhaustiveness across every implementer: a new record
+ type cannot be processed without first adding a Visit overload
+ here. The inherited Visit(IModelObject) from
+ is the polymorphic-dispatch
+ entry point — implementations forward through the visitable's
+ Accept to the appropriate concrete Visit overload.
- The type of value produced by visiting Abstract Model objects
+ The value each Visit overload returns — e.g., a TOM
+ Model for the abstract-to-TOM emitter, or a diagnostic-bearing
+ result for a validator.
-
+
- Visits a Root (the top-level Abstract Model container).
+ Marker indicating a type supports structural equivalence. The comparison
+ itself is provided by the extension method
+ , which reflects over
+ properties tagged with .
+ Implementers carry no boilerplate beyond declaring this interface.
+
+ Structural equivalence compares own scalar properties only; it
+ deliberately ignores both the object's own Id and any
+ cross-reference NodeIds it carries (e.g., OwnerSourceId,
+ SourceSystemId) — those are allocation-specific to a particular
+ Root and don't carry meaning across independently-built trees.
+ Contrast with default record equality (==), which compares
+ everything. Cross-reference resolution (verifying that two records'
+ SourceSystemIds point at equivalent SourceSystems across two
+ Roots) is a graph-level concern handled by Root.EquivalentTo;
+ a single IEquivalent instance has no Root context.
+ The where TSelf : IEquivalent<TSelf> constraint is the
+ closest C# gets to a Self type and is what restricts the
+ extension method to legitimate self-comparisons. Family interfaces
+ (e.g., ISource) declare IEquivalent<self-interface>
+ so that interface-typed references can be compared polymorphically
+ without any per-concrete-type boilerplate — the extension method
+ dispatches on runtime type.
+
+
+ The implementing type — by convention, the record's own type or the
+ family interface for polymorphic comparison.
+
-
+
- Visits a Fact (business event or measurement context).
+ Reflection-driven equivalence operation. The marked-property list per
+ runtime type is computed once and cached; per-call cost is one
+ PropertyInfo.GetValue + value comparison pair per component.
+ Runtime-type dispatch makes a single extension overload work for both
+ concrete-typed and family-interface-typed call sites.
-
+
- Visits a Dimension (context for analysis).
+ True when and
+ have the same runtime type and agree on every property of that
+ type tagged with .
-
+
- Visits a DimensionReference (link between Fact and Dimension).
+ Equality for property values participating in equivalence. Handles
+ dictionary content comparison (order-independent, key + value
+ equality) so records carrying IReadOnlyDictionary-shaped
+ properties (e.g., DerivedField.Expressions) get sensible
+ value-equality without per-type custom EquivalentTo.
-
+
- Visits a SimpleMeasure (quantifiable value with simple aggregation).
+ Capability shared by every concrete abstract-model record: typed
+ identity plus descriptive metadata. Each implementer declares its own
+ typed *Id property in its primary constructor and satisfies
+ via explicit interface implementation.
-
+
- Visits a CalculatedMeasure (quantifiable value with
- platform-specific calculation).
+ The typed identity of this object, boxed as
+ for polymorphic access. Concrete records expose this as their own
+ typed id (e.g., FactId, SourceId).
+
+ Id is immutable: set once at construction by Root and never
+ changed afterward. Implementers expose Id as a get-only
+ property with no init accessor, so
+ record with { Id = ... } is a compile error. To modify other
+ properties of a model object, use Root.UpdateX with a lambda
+ that preserves the original Id.
+
-
-
- Visits a SimpleRelationship.
-
+
+ Friendly name for display.
-
+
- Visits a RolePlayingRelationship.
+ Name for internal use by the OLAP engine, potentially the same as
+ .
+
+ If a platform does not distinguish between technical and friendly
+ names, then we expect that TechnicalName will be set with
+ the value of the friendly name.
+
-
-
- Visits a DimensionAttribute (descriptive property in a dimension).
-
+
+ Prose describing the object.
-
+
- Visits a Hierarchy (logical drill-down path).
+ Identity capability shared by every typed *Id value-struct
+ record. The underlying integer is sequentially allocated per
+ collection by Root's AddX methods (the first Fact receives
+ FactId(0), the second FactId(1), and so on) and
+ exists only within the scope of a single Root's lifecycle.
-
+
- Visits a Field.
+ Opaque integer identity, unique among ids of the same type within
+ the lifetime of a single Root. Allocated sequentially by Root's
+ AddX methods, starting from 0 per collection; treat as an
+ identifier, not a meaningful number. The typed *Id wrapper
+ (e.g., FactId vs SourceId) prevents cross-collection
+ confusion at the type level; ids do not need to be globally unique.
+ Stable across with updates of the owning record.
-
+
- Visits a DerivedField (field with platform-specific expression).
+ Identifies an ISource (e.g., QueryableSource or QuerySource)
+ within a Root.
+
+
+
-
+
- Visits a QueryableSource (source referring to a table/view).
+ Identifies an ISource (e.g., QueryableSource or QuerySource)
+ within a Root.
+
+
+
-
+
- Visits a QuerySource (source using custom query).
+
-
-
- Visits a Perspective (named subset of model objects).
-
+
+ Identifies an ISourceSystem within a Root.
+
+
+
-
-
- Visits a SecurityModel (access control specifications).
-
+
+ Identifies an ISourceSystem within a Root.
+
+
+
-
+
- Visits a Role (security role definition).
+
-
+
- Base record for measures with common properties
+ Marker for any id that identifies an within a
+ Root. Per-kind concrete types (, future
+ DimensionId) implement this so cross-references to "any table"
+ can be typed polymorphically while each table kind keeps its own dense
+ collection and allocation counter.
-
-
- Display formatting
-
+
+ Identifies a within a Root.
+
+
+
-
-
- Constructor for base Measure record
-
- Friendly name for display to users
- Name for internal use in formulas by the OLAP engine
- Prose describing the object
- Display formatting
- Data type of the measure
+
+ Identifies a within a Root.
+
+
+
-
+
- Accepts a visitor for the appropriate measure subtype.
+
-
-
- Quantifiable value in a fact, with a simple aggregation
-
+
+ Identifies a within a Root.
+
+
+
-
-
- Field reference
-
+
+ Identifies a within a Root.
+
+
+
-
+
- Table containing the field
+
-
+
- Additivity type
+ Identifies an (SourceField, ReferenceField, or
+ DerivedField) within a Root. All field kinds share one
+ FieldId space and one Root.Fields collection.
+
+
+
-
+
- Collection of dimensions over which a semi-additive measure is additive
+ Identifies an (SourceField, ReferenceField, or
+ DerivedField) within a Root. All field kinds share one
+ FieldId space and one Root.Fields collection.
+
+
+
-
+
- Aggregation type
+
-
+
- Constructor for SimpleMeasure
+ Identifies the Root of an abstract semantic model. Singleton in
+ practice — there is one Root per model and nothing cross-references it
+ by id — but typed for consistency with other model objects.
- Friendly name for display to users
- Name for internal use in formulas by the OLAP engine
- Prose describing the object
- Display formatting
- Data type of the measure
- Field reference
- Table containing the field
- Additivity type
-
- Collection of dimensions over which a semi-additive measure is additive
+
+
- Aggregation type
-
-
-
- Determines equality by comparing scalar properties and
- AdditiveOverDimensions collection contents.
-
- The other SimpleMeasure to compare with
-
- True if both objects have equal scalar properties and equivalent collections
-
-
+
- Generates hash code based on scalar properties and
- AdditiveOverDimensions collection contents.
+ Identifies the Root of an abstract semantic model. Singleton in
+ practice — there is one Root per model and nothing cross-references it
+ by id — but typed for consistency with other model objects.
- A hash code that remains consistent for equivalent objects
+
+
+
-
+
- Quantifiable value in a fact, with a platform-specific calculation
+
- Currently no parsing, validation, or attempted translation for these
-
+
- Mapping of platforms to platform-specific expressions implementing
- the calculation
+ Identifies a (Simple or Calculated) within a
+ Root. All measure kinds share one MeasureId space and one
+ Root.Measures collection.
+
+
+
-
+
- Constructor for CalculatedMeasure
+ Identifies a (Simple or Calculated) within a
+ Root. All measure kinds share one MeasureId space and one
+ Root.Measures collection.
- Friendly name for display to users
- Name for internal use in formulas by the OLAP engine
- Prose describing the object
- Display formatting
- Data type of the measure
-
- Mapping of platforms to platform-specific expressions implementing
- the calculation
+
+
-
+
- Determines equality by comparing scalar properties and Expressions
- dictionary contents.
+
- The other CalculatedMeasure to compare with
-
- True if both objects have equal scalar properties and equivalent Expressions
-
-
+
- Generates hash code based on scalar properties and Expressions
- dictionary contents.
+ Identifies a within a Root. The model
+ holds a flat collection of relationships on Root.Relationships
+ — role-playing and snowflake patterns express themselves as
+ multiple entries rather than as
+ polymorphic id types.
- A hash code that remains consistent for equivalent objects
+
+
+
-
+
- Named subset of model objects for specific usage
+ Identifies a within a Root. The model
+ holds a flat collection of relationships on Root.Relationships
+ — role-playing and snowflake patterns express themselves as
+ multiple entries rather than as
+ polymorphic id types.
+
+
+
-
+
- Collection of included model objects
+
-
+
- Documentation of intended users
+ Represents a data source system that a source connects to. Source
+ systems are platform-specific and represent the connection details
+ necessary for that system.
-
-
- Determines equality by comparing scalar properties and ModelObjects
- collection contents.
-
- The other Perspective to compare with
-
- True if both objects have equal scalar properties and equivalent ModelObjects
-
+
+ Typed identity narrowing .
-
+
- Generates hash code based on scalar properties and ModelObjects
- collection contents.
+ Type-specific identifier for this source system. Used as the
+ dispatch key for cross-platform source-rendering strategies.
- A hash code that remains consistent for equivalent objects
-
+
- Cardinality of a field in a join/relationship
+ A data source referenced by a Fact or Dimension. This is roughly
+ equivalent to a partition definition.
-
-
- Abstract representation of a dimensional model
-
+
+ Typed identity, narrowing .
-
+
- Collection of facts in the model
+ Reference to the source system this source connects to.
-
+
- Collection of dimensions in the model
+ A table-like object in the dimensional model: a or
+ Dimension. Each concrete kind has its own dense collection on
+ and its own typed id (, etc.),
+ but cross-references to "any table" use the
+ marker so they remain polymorphic over kinds. No IEquivalent
+ declaration here — Tables collections are split-typed, so equivalence
+ compares concrete-typed elements directly.
-
-
- Collection of perspectives in the model
-
+
+ Typed identity, narrowing .
-
+
- Security model
+ A column-like object: a (a source's physical
+ column), a (a table column that maps to a
+ source column), or a (a computed table
+ column). All field kinds share one space and one
+ Root.Fields collection.
-
-
- Determines equality by comparing scalar properties and collection contents order-independently.
-
- The other Root to compare with
- True if both objects have equal scalar properties and equivalent collections
+
+ Typed identity, narrowing .
-
-
- Generates hash code based on scalar properties and collection contents.
-
- A hash code that remains consistent for equivalent objects
+
+ The data type of this field's values.
-
+
- Creates a dimension reference between a fact and dimension with a
- simple equi-join relationship.
+ A quantitative computation on a .
+ is the only measure type, with
+ expressions carried for downstream translation. An empty
+ collection signals the
+ "no expression" / placeholder case; the Abstract→TOM emitter
+ materializes it as a placeholder body plus a diagnostic.
- Name of the fact to add the dimension reference to
- Name of the dimension to reference
- Foreign key field in the fact
- Primary key field in the dimension
-
- Filter direction for the relationship (defaults to RightFiltersLeft)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning ; resolve via
+ Root.GetFact.
- The created dimension reference
+
+ Platform-format string applied at emit time (e.g., "#,##0.00");
+ empty string when the caller has no opinion.
+
+ The data type of this measure's result.
-
+
- Creates a dimension reference between a fact and dimension with a
- simple equi-join relationship, looking up fields by name.
+ A quantitative computation on a .
+ is the only measure type, with
+ expressions carried for downstream translation. An empty
+ collection signals the
+ "no expression" / placeholder case; the Abstract→TOM emitter
+ materializes it as a placeholder body plus a diagnostic.
- Name of the fact to add the dimension reference to
- Name of the dimension to reference
- Name of the foreign key field in the fact
- Name of the primary key field in the dimension
-
- Filter direction for the relationship (defaults to RightFiltersLeft)
+
+
+
+
+
+
+
+
+
+
+
- The created dimension reference
+
+ Reference to the owning ; resolve via
+ Root.GetFact.
+
+
+ Platform-format string applied at emit time (e.g., "#,##0.00");
+ empty string when the caller has no opinion.
+
+ The data type of this measure's result.
-
+
- Creates a dimension reference between a fact and dimension with the
- specified relationship.
+
- Name of the fact to add the dimension reference to
- Name of the dimension to reference
- The relationship defining how fact and dimension connect
- The created dimension reference
-
+
- Row level security rule
+ Reference to the owning ; resolve via
+ Root.GetFact.
-
+
- Row level security rule
+ Platform-format string applied at emit time (e.g., "#,##0.00");
+ empty string when the caller has no opinion.
-
-
- Target table or dimension
-
+
+ The data type of this measure's result.
-
-
- Filter expression
-
+
+
+
+
+
+
+
+
+
+
+
-
+
- Object level security rule
+ A measure expressed as a platform-keyed expression string. Target
+ emitters consult their platform key to obtain the source to
+ translate (or carry verbatim with a warning). An empty
+ collection signals the placeholder
+ case — the emitter materializes a placeholder body and emits a
+ diagnostic.
+
+ Platform-keyed source expressions for this measure. null
+ coalesces to ImmutableDictionary.Empty at construction.
+
-
+
- Object level security rule
+ A measure expressed as a platform-keyed expression string. Target
+ emitters consult their platform key to obtain the source to
+ translate (or carry verbatim with a warning). An empty
+ collection signals the placeholder
+ case — the emitter materializes a placeholder body and emits a
+ diagnostic.
+
+ Platform-keyed source expressions for this measure. null
+ coalesces to ImmutableDictionary.Empty at construction.
+
-
+
+ Platform-keyed source expressions; never null.
+
+
- Target object
+ Structural AAST body produced by the platform's
+ SQL→AAST translator. Downstream emitters render via the AAST
+ when its shape is structural; otherwise they fall back to
+ for verbatim text. Null at
+ construction coalesces to
+ with empty verbatim — the safest default when a caller hasn't
+ supplied a structural body.
-
+
- Permission level
+ Pre-rendered, platform-specific representation of an unsupported
+ windowing / cumulative / semiadditive specification carried
+ verbatim from the source measure (e.g. the Databricks window spec
+ re-serialized to its source YAML). null when the source
+ declares no such spec.
+
+ When set, the windowing semantics are not representable in the
+ target language, so the target emitter must not emit
+ as a live expression. Instead it documents
+ the original source, the (window-unaware) attempted
+ translation, and this spec as an inert comment, leaving the
+ measure for the user to author manually.
+
+ TODO (#6347): replace this carry-through with real windowed /
+ cumulative / semiadditive measure translation.
-
+
+
+
+
- Security role definition
+ Construction-time validation and defaulting for the
+ Name / TechnicalName contract shared by every
+ record. Target visitors are responsible
+ for canonicalizing both values to their target's identifier rules;
+ the abstract model imposes no syntax requirements beyond non-empty
+ TechnicalName.
-
+
- Expressions restricting data access by dimension values
+ Returns when it is non-empty and
+ non-whitespace; throws otherwise.
+ Caller name is captured automatically for the exception message.
-
+
- Settings controlling object visibility
+ Returns when non-empty/whitespace;
+ otherwise returns .
-
+
- Users who belong to a given role
+ A source that refers to a specific named queryable object in a source
+ system, e.g., a table or view. Contrast with QuerySource (custom
+ query text).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The database or catalog name within the source system.
+ The schema name within the database.
+
+ The name of the queryable object (table or view) within the schema.
+
-
+
- Determines equality by comparing scalar properties and collection contents.
+ A source that refers to a specific named queryable object in a source
+ system, e.g., a table or view. Contrast with QuerySource (custom
+ query text).
- The other Role to compare with
-
- True if both objects have equal scalar properties and equivalent collections
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The database or catalog name within the source system.
+ The schema name within the database.
+
+ The name of the queryable object (table or view) within the schema.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The database or catalog name within the source system.
+
+
+ The schema name within the database.
+
+
+
+ The name of the queryable object (table or view) within the schema.
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
- Generates hash code based on scalar properties and collection contents.
+ A source whose contents are defined by a query expression rather than a
+ named object in the source system. Contrast with
+ (a named table or view).
- A hash code that remains consistent for equivalent objects
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The query expression that produces this source's rows.
-
+
- Access control specifications
+ A source whose contents are defined by a query expression rather than a
+ named object in the source system. Contrast with
+ (a named table or view).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The query expression that produces this source's rows.
-
+
- Collection of roles
+
-
+
- Determines equality by comparing scalar properties and Roles
- collection contents.
+
- The other SecurityModel to compare with
- True if both objects have equal scalar properties and equivalent Roles
-
+
+ The query expression that produces this source's rows.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Generates hash code based on scalar properties and Roles
- collection contents.
+ A column on an (Fact or Dimension) that maps to a
+ . The reference is by typed
+ ; the legacy stringly-typed wiring via
+ TechnicalName matching is gone. defaults
+ to the referenced source field's data type at construction time when
+ not specified explicitly; type-compatibility validation is a downstream
+ analyzer concern, not enforced here.
- A hash code that remains consistent for equivalent objects
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning (Fact or Dimension);
+ resolve via Root.GetTable.
+
+
+ Reference to the underlying this field maps
+ to; resolve via Root.GetField.
+
+ The data type of this field.
+
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
+
-
+
- Represents a source that refers to a specific queryable object (table/view)
+ A column on an (Fact or Dimension) that maps to a
+ . The reference is by typed
+ ; the legacy stringly-typed wiring via
+ TechnicalName matching is gone. defaults
+ to the referenced source field's data type at construction time when
+ not specified explicitly; type-compatibility validation is a downstream
+ analyzer concern, not enforced here.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning (Fact or Dimension);
+ resolve via Root.GetTable.
+
+
+ Reference to the underlying this field maps
+ to; resolve via Root.GetField.
+
+ The data type of this field.
+
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
+
-
+
- Determines equality by comparing scalar properties and Fields
- dictionary contents.
+
- The other QueryableSource to compare with
- True if both objects have equal scalar properties and equivalent Fields
-
+
- Generates hash code based on scalar properties and Fields
- dictionary contents.
+ Reference to the owning (Fact or Dimension);
+ resolve via Root.GetTable.
- A hash code that remains consistent for equivalent objects
-
+
+
+ Reference to the underlying this field maps
+ to; resolve via Root.GetField.
+
+
+
+ The data type of this field.
+
+
+
+ Platform-format string applied at emit time (e.g., "#,##0.00",
+ "yyyy-MM-dd"); empty string when no format opinion.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Represents a source that uses a custom query
+ An edge between two s — typically a fact's
+ foreign key and a dimension's primary key. The model holds a flat
+ collection of relationships on Root.Relationships; role-playing
+ and snowflake patterns express themselves as multiple
+ entries in this collection rather than as
+ polymorphic relationship variants.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The "left side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the fact-side foreign-key
+ .
+
+
+ The "right side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the dim-side primary-key
+ .
+
+
+ Multiplicity of the left side. for
+ the conventional fact-side FK.
+
+
+ Multiplicity of the right side. for
+ the conventional dim-side PK.
+
+
+ Which side filters which.
+ for the
+ conventional dim-filters-fact.
+
-
+
- Determines equality by comparing scalar properties and Fields
- dictionary contents.
+ An edge between two s — typically a fact's
+ foreign key and a dimension's primary key. The model holds a flat
+ collection of relationships on Root.Relationships; role-playing
+ and snowflake patterns express themselves as multiple
+ entries in this collection rather than as
+ polymorphic relationship variants.
- The other QuerySource to compare with
- True if both objects have equal scalar properties and equivalent Fields
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The "left side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the fact-side foreign-key
+ .
+
+
+ The "right side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the dim-side primary-key
+ .
+
+
+ Multiplicity of the left side. for
+ the conventional fact-side FK.
+
+
+ Multiplicity of the right side. for
+ the conventional dim-side PK.
+
+
+ Which side filters which.
+ for the
+ conventional dim-filters-fact.
+
-
+
- Generates hash code based on scalar properties and Fields
- dictionary contents.
+
- A hash code that remains consistent for equivalent objects
-
+
- Databricks source system
+ The "left side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the fact-side foreign-key
+ .
-
- Friendly name for display to users
- Name for internal use by the OLAP engine
- Description of the source system
- Databricks host address
- HTTP path for the Databricks workspace
- Optional database name
- Optional schema name
- Optional port number (default is 443)
+
+
+ The "right side" of the edge. For a conventional fact ↔ dim
+ relationship, this is the dim-side primary-key
+ .
+
-
+
- Host name or IP address
+ Multiplicity of the left side. for
+ the conventional fact-side FK.
-
+
- HTTP path for the Databricks workspace
+ Multiplicity of the right side. for
+ the conventional dim-side PK.
-
+
- Port number (default is 443)
+ Which side filters which.
+ for the
+ conventional dim-filters-fact.
-
+
+
+
+
+
+
+
+
+
+
-
+
- Generates an M (Power Query) expression for the specified source.
- Dispatches to type-specific generation methods based on ISource implementation.
+ The top-level container of an abstract semantic model. Holds every
+ model object in flat top-level collections keyed only by typed
+ *Id references — there are no parent-owned child collections;
+ navigation across the graph is via Root's lookup methods
+ (, , etc.).
-
- The source to generate an M expression for (QueryableSource or QuerySource)
-
- M expression string that can be used in a Tabular Model partition
-
- Thrown when the source type is not supported
+
+ Root is an immutable record. "Mutation" methods (
+ et al.) are pure functions returning a tuple of
+ (newRoot, addedObject). Cross-collection invariants are checked
+ at the construction site; violations throw an exception which a
+ platform-level wrapper catches and converts to a
+ TransformationResult diagnostic at the public-API boundary.
+ Storage is dense per-collection: each AddX allocates the next id
+ as new TId(Collection.Length) before appending, so ids equal
+ array indices and lookups are direct indexing. The typed *Id
+ structs prevent cross-collection confusion at the type level; ids are
+ not globally unique. Deletion is not a part of the current API.
+
+
+
+
+ The top-level container of an abstract semantic model. Holds every
+ model object in flat top-level collections keyed only by typed
+ *Id references — there are no parent-owned child collections;
+ navigation across the graph is via Root's lookup methods
+ (, , etc.).
+
+
+ Root is an immutable record. "Mutation" methods (
+ et al.) are pure functions returning a tuple of
+ (newRoot, addedObject). Cross-collection invariants are checked
+ at the construction site; violations throw an exception which a
+ platform-level wrapper catches and converts to a
+ TransformationResult diagnostic at the public-API boundary.
+ Storage is dense per-collection: each AddX allocates the next id
+ as new TId(Collection.Length) before appending, so ids equal
+ array indices and lookups are direct indexing. The typed *Id
+ structs prevent cross-collection confusion at the type level; ids are
+ not globally unique. Deletion is not a part of the current API.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The empty Root. Use as the starting point for incremental
+ construction: (root, var fact) = Root.Empty.AddFact(...).
+
+
+
+
+ Add a to this Root. Returns the new
+ Root and the newly-allocated source with its assigned
+ .
+
+
+
+
+ Add a to this Root. Returns the new Root
+ and the newly-allocated source with its assigned
+ .
+
+
+
+ Add a to this Root.
+
+ Thrown when does not yet exist in
+ .
-
+
+ Add a to this Root.
+
+ Thrown when does not yet exist in
+ .
+
+
+
- Generates M expression for a QueryableSource (table/view reference).
- Creates Power Query M code that references a Databricks catalog object.
+ Add an to this Root via a factory that
+ receives the newly-allocated . Open to
+ any concrete ISourceSystem implementation — source platforms
+ (Databricks, Snowflake, etc.) supply the factory.
+
+
+
+
+ Add a to this Root. Owns by the supplied
+ .
+
+
+ Thrown when does not yet exist in
+ .
+
+
+
+
+ Add a to this Root mapping the
+ specified table column to a . When
+ is omitted, the resulting field's
+ DataType defaults to the referenced source field's
+ DataType; compatibility validation is a downstream concern.
+
+
+ Thrown when does not resolve to a table
+ in this Root, or when does not
+ exist in .
+
+
+
+
+ Add a (computed table column) to this
+ Root.
+
+
+ Thrown when does not resolve to a table
+ in this Root.
+
+
+
+
+ Add a — an expression-based
+ measure — to this Root. An empty or null
+ signals the placeholder case; the
+ Abstract→TOM emitter materializes it as a placeholder body plus a
+ diagnostic.
+
+
+ Thrown when does not resolve to a
+ in this Root.
+
+
+
+
+ Add a to this Root. The model holds a
+ flat collection of edges; role-playing and snowflake chains express
+ themselves as multiple Relationship entries with distinct
+ /
+ pairs.
+
+
+ Thrown when or
+ does not exist in
+ .
+
+
+
+
+ Update an existing field by id via a typed updater lambda. Replaces
+ the field at its dense-array slot and returns the new Root. Enforces
+ that the field at is of type
+ and that the updater preserves the original
+ Id (see ).
+
+
+ The concrete kind expected at
+ . Constrained to class because all
+ field records are reference types.
+
+
+ Thrown when does not resolve in
+ .
+
+
+ Thrown when the field at is not of type
+ , or when the updater returns a field with
+ a different Id.
+
+
+
+
+ Resolve a polymorphic reference to its
+ . Dispatches on the id's concrete kind.
+
+
+
+ True when the polymorphic id resolves to a table in this Root.
+
+
+
+ Fields owned by — only
+ instances live under a source.
-
- The queryable source containing database, schema, and object names
-
- M expression referencing the Databricks object
-
+
- Generates M expression for a QuerySource (custom SQL query).
- Wraps a SQL query in Databricks connection context.
+ Fields owned by — a mix of
+ and .
- The query source containing the SQL query text
- M expression that executes the query against Databricks
-
+
- Determines equality by comparing scalar properties and Properties dictionary contents.
+ Measures owned by .
- The other GenericSourceSystem to compare with
- True if both objects have equal scalar properties and equivalent Properties
-
+
- Generates hash code based on scalar properties and Properties dictionary contents.
+ Structural equivalence with another Root. Two Roots are equivalent
+ if their collections contain pairwise-equivalent objects and all
+ scalar root-level properties are equal.
- A hash code that remains consistent for equivalent objects
-
+
- ODBC source system
+ Cross-reference walk over an AAST body. Mirrors the pointer
+ resolution that does for
+ /:
+ each opaque Target on the body resolves through its owning
+ Root, and the resolved , ,
+ or on each side is compared structurally
+ via its own EquivalentTo. Body shape was already validated
+ by the caller's — this
+ pass only verifies that the AAST pointers point at equivalent
+ records.
-
- Friendly name for display to users
- Name for internal use by the OLAP engine
- Description of the source system
- DSN name or connection identifier
+
+
+ does not declare
+ at the family level (its concrete
+ kinds live in split-typed collections), so equivalence between two
+ ITable values dispatches on concrete kind.
+
-
+
- DSN name or connection identifier
+ True when every item in finds at least
+ one item in for which
+ returns true. O(n^2) by design:
+ scale-appropriate for the abstract model's collection sizes, and
+ keeps the implementation honestly dependent on the production
+ EquivalentTo rather than on any external key.
-
+
-
+
- SQL Server source system
+ A physical column on an . A leaf field — it
+ doesn't reference any other field. Table-side fields
+ () map to a SourceField via
+ SourceFieldId.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning source; resolve via Root.GetSource.
+
+ The data type of this column.
-
- Friendly name for display to users
- Name for internal use by the OLAP engine
- Description of the source system
- Server DNS name or IP address
- Optional port number (default is 1433)
+
+
+ A physical column on an . A leaf field — it
+ doesn't reference any other field. Table-side fields
+ () map to a SourceField via
+ SourceFieldId.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Reference to the owning source; resolve via Root.GetSource.
+
+ The data type of this column.
-
+
- Server DNS name or IP address
+
-
+
- Port number for SQL Server connection
+ Reference to the owning source; resolve via Root.GetSource.
-
+
+ The data type of this column.
+
+
+
+
+
+
+
+
+
+
+
@@ -1088,6 +1958,37 @@
Generic visitor interface for traversing object graphs.
+
+
+ Result type for any transformation step in the Semantic Bridge.
+
+
+
+
+
+ Diagnostic messages related to this result. Success cases may carry
+ warning and other non-failure informational messages.
+
+
+
+
+ Add diagnostic messages to the result. This is useful for multi-phase
+ validations or processing.
+
+ The same result with additional diagnostics includes
+
+
+
+ A successful transformation or validation. Any non-failure
+ diagnostics are available in `Diagnostics` for review.
+
+
+
+
+ The transformation or validation failed. Messages explaining why
+ are available in `Diagnostics` for review.
+
+
Databricks MetricView operations and state management service.
@@ -1161,7 +2062,7 @@
The validation function receives both the object and the validation context.
- Type of MetricView object the rule applies to (View, Join, Dimension, or Measure)
+ Type of MetricView object the rule applies to (View, Join, Field, or Measure)
Unique name for the validation rule
Category for organizational purposes (e.g., "Naming", "Structure")
@@ -1172,12 +2073,20 @@
A validation rule that can be used with
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Validation function
+ Minimum spec version this rule applies to (e.g. "1.1")
+
Creates a validation rule for a specific type of MetricView object with simple predicate validation.
- Type of MetricView object the rule applies to (View, Join, Dimension, or Measure)
+ Type of MetricView object the rule applies to (View, Join, Field, or Measure)
Unique name for the validation rule
Category for organizational purposes (e.g., "Naming", "Structure")
@@ -1187,6 +2096,14 @@
A validation rule that can be used with
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
Creates a validation rule for the root View object.
@@ -1197,6 +2114,14 @@
Predicate function to determine if the view is invalid.
A validation rule for use in validation.
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the view is invalid
+ Predicate function that returns true when the view is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
Creates a validation rule specifically for Join objects.
@@ -1207,15 +2132,31 @@
Predicate function that returns true when the join is invalid
A validation rule for Join objects
-
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the join is invalid
+ Predicate function that returns true when the join is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
- Creates a validation rule specifically for Dimension objects.
+ Creates a validation rule specifically for Field objects.
Unique name for the validation rule
Category for organizational purposes
- Error message returned when the dimension is invalid
- Predicate function that returns true when the dimension is invalid
- A validation rule for Dimension objects
+ Error message returned when the field is invalid
+ Predicate function that returns true when the field is invalid
+ A validation rule for Field objects
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the field is invalid
+ Predicate function that returns true when the field is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
@@ -1227,7 +2168,15 @@
Predicate function that returns true when the measure is invalid
A validation rule for Measure objects
-
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the measure is invalid
+ Predicate function that returns true when the measure is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
Converts the currently loaded Databricks MetricView to a Tabular Model.
@@ -1236,6 +2185,7 @@
Databricks HTTP path for connection.
Diagnostic messages from validation and conversion.
If true, abort on validation errors before creating TOM objects.
+ The name of the database to be used for any native SQL queries
True if conversion succeeded, false if critical errors occurred.
Thrown when no MetricView is currently loaded.
@@ -1257,41 +2207,248 @@
Thrown when no MetricView is currently loaded.
-
+
- Marker interface for all MetricView domain objects.
- Used for type safety and identification in public API
+ Legacy name for . Produces
+ a ValidationRule<Dimension> via the generic
+ MakeValidationRule<T> factory with T inferred
+ as . The validation visitor picks up
+ ValidationRule<Dimension> rules alongside
+ ValidationRule<Field> rules and applies both against
+ each field in .
-
+
+
+ Minimum spec version this rule applies to (e.g. "1.1").
+
+
- Interface for validation rules that can be applied to metric view objects.
- ValidMetricViewRules encapsulate a specific validation check that produces
- diagnostic messages when validation fails.
+ Databricks source system definition. Carries connection details
+ (, ) and optional
+ default-context fields (, ,
+ ).
+
+
+
+
+
+
+
+
+
+
+
+
+ Databricks host name or address.
+ HTTP path for the Databricks workspace.
+ Optional default catalog/database.
+ Optional default schema.
+ Port number (default 443).
-
+
- Gets the unique name of the validation rule.
- Names should be descriptive and indicate what the rule validates.
+ Databricks source system definition. Carries connection details
+ (, ) and optional
+ default-context fields (, ,
+ ).
+
+
+
+
+
+
+
+
+
+
+
+
+ Databricks host name or address.
+ HTTP path for the Databricks workspace.
+ Optional default catalog/database.
+ Optional default schema.
+ Port number (default 443).
-
+
- Gets the category of the validation rule for organizational purposes.
- Categories help group related rules (e.g., "Names", "Structure", "Expressions").
+
-
+
+ Databricks host name or address.
+
+
+ HTTP path for the Databricks workspace.
+
+
+ Optional default catalog/database.
+
+
+ Optional default schema.
+
+
+ Port number (default 443).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Gets the type of object this rule is designed to validate.
- This allows for efficient filtering and application of rules.
+ Convenience extension for adding a
+ to a . Wraps Root.AddSourceSystem with the
+ Databricks-specific construction.
-
+
- Validates the target object using the provided read-only context.
- ValidMetricViewRules receive a read-only view to prevent accidental
+ Thrown when a version-gated property is set on a MetricView object
+ whose version does not support it.
+
+
+
+
+ Builds an AAST from a parsed
+ . Structural shapes the visitor recognizes
+ (currently only ) produce
+ matching AAST nodes; anything else falls through the base class's
+ abort path to , which collapses the body to
+ carrying the original
+ verbatim source for downstream platform-keyed emission.
+
+
+
+
+ Translate to an AAST in the context of
+ a measure named at
+ . is
+ the original source text (used as the
+ payload when the
+ translation can't structurally model the shape).
+ looks up a declared
+ measure by name (case-insensitive in production); returns null for
+ unknown names.
+ is the fact this measure belongs
+ to — used when a node's structural translation references the
+ owning table (e.g.,
+ for COUNT(*)).
+ A metric view's measure body always reduces over the fact (dims
+ are left-outer-joined), so the owner is constrained to
+ ; the AAST node's
+ stays
+ for emit-side flexibility.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ COUNT(*) or COUNT(<non-null literal>), no
+ DISTINCT. COUNT(NULL) is excluded — it returns 0 in
+ SQL regardless of row count, so it's semantically not a row-count.
+
+
+
+
+ One of SUM/AVG/AVERAGE/MIN/MAX/
+ COUNT over a single column reference. DISTINCT is
+ only accepted in combination with COUNT (becomes
+ ); on any other
+ aggregation it's rejected.
+
+
+
+
+ Surface-only peek at the top-level structural aggregation kind of
+ : returns the same answer
+ would build the
+ AAST node from — without resolving the column ref, so callers can
+ read intent even when the ref is unresolved and the AAST falls
+ back to . Used by
+ the visitor to preserve aggregation-driven measure-type inference
+ in the dim-unresolved recovery case.
+
+
+
+
+ Marker interface for all MetricView domain objects.
+ Used for type safety and identification in public API
+
+
+
+
+ Interface for validation rules that can be applied to metric view objects.
+ ValidMetricViewRules encapsulate a specific validation check that produces
+ diagnostic messages when validation fails.
+
+
+
+
+ Gets the unique name of the validation rule.
+ Names should be descriptive and indicate what the rule validates.
+
+
+
+
+ Gets the category of the validation rule for organizational purposes.
+ Categories help group related rules (e.g., "Names", "Structure", "Expressions").
+
+
+
+
+ Gets the type of object this rule is designed to validate.
+ This allows for efficient filtering and application of rules.
+
+
+
+
+ Gets the version constraint for this rule, declaring which metric view
+ spec versions the rule applies to. Defaults to .
+
+
+
+
+ Validates the target object using the provided read-only context.
+ ValidMetricViewRules receive a read-only view to prevent accidental
mutation of validation state.
The object to validate
@@ -1314,7 +2471,7 @@
Accepts a visitor that produces a result of type TResult.
The concrete type dispatches to the appropriate Visit overload on
- the visitor based on its runtime type (View, Join, Dimension, or
+ the visitor based on its runtime type (View, Join, Field, or
Measure).
The type of value produced by the visitor
@@ -1340,9 +2497,9 @@
Visits a Join (dimension relationship) in the MetricView.
-
+
- Visits a Dimension (attribute) in the MetricView.
+ Visits a Field (attribute) in the MetricView.
@@ -1350,1293 +2507,3529 @@
Visits a Measure (metric) in the MetricView.
-
+
- Entry point for generic visitor pattern orchestration.
- Delegates to the visitable object's Accept method for double dispatch,
- which calls back to the appropriate type-specific Visit method (View, Join, Dimension, or Measure).
- This method enables generic orchestration code to work with MetricView objects
- through the IVisitor interface while maintaining complete type safety.
- The compiler enforces that only IMetricViewVisitable objects can be passed to this method.
+ Shared SQL-expression analysis primitive consumed by
+ , , and
+ Join.On analysis. Captures the parsed expression tree, the resolved
+ column references (deduped + canonicalized against the context's
+ implicit table), and parser/translator diagnostics.
- The MetricView object to visit (View, Join, Dimension, or Measure)
- The builder with fragments added based on the visited object
+
+ Each carries the table the column
+ effectively belongs to. Bare column references and references whose
+ qualifier matches the implicit table (case-insensitively) are reported
+ with the implicit-table literal as Table; explicit qualifiers
+ that do not match are preserved as written. Dedup is by record
+ equality on (Table, ColumnName).
+
-
+
- Create relationship and dimension reference fragments from the join.
- Ensure that the fields referenced are in the fact and dimension.
- Ensure the dimension exists.
+ Shared SQL-expression analysis primitive consumed by
+ , , and
+ Join.On analysis. Captures the parsed expression tree, the resolved
+ column references (deduped + canonicalized against the context's
+ implicit table), and parser/translator diagnostics.
-
-
+
+ Each carries the table the column
+ effectively belongs to. Bare column references and references whose
+ qualifier matches the implicit table (case-insensitively) are reported
+ with the implicit-table literal as Table; explicit qualifiers
+ that do not match are preserved as written. Dedup is by record
+ equality on (Table, ColumnName).
+
-
+
- Helper for managing field fragments during Metric View to Abstract Model mapping.
- Handles field lookup, creation, and type updates for fields referenced by measures.
+ A column reference from the analyzed expression, resolved against
+ the context's implicit table. is the canonical
+ table this column effectively belongs to;
+ is the column name as written in the SQL.
-
- This helper encapsulates the logic for ensuring fields exist in both the fact table
- and its source, managing data type updates when measures require Decimal types,
- and searching for existing fields by name or technical name.
-
-
- Creates a new FieldFragmentHelper for managing field fragments.
-
- The model builder containing all fragments
- The fact fragment to manage fields for
- The source fragment for the fact
-
+
- Helper for managing field fragments during Metric View to Abstract Model mapping.
- Handles field lookup, creation, and type updates for fields referenced by measures.
+ A column reference from the analyzed expression, resolved against
+ the context's implicit table. is the canonical
+ table this column effectively belongs to;
+ is the column name as written in the SQL.
+
+
+
+
+ Equality on (Table, ColumnName) using
+ . Databricks
+ SQL identifiers are case-insensitive, so refs differing only in
+ casing represent the same column.
+
+
+
+
+ Parse , extract resolved column
+ references against (deduped by
+ (Table, ColumnName)), and build diagnostics from the parse
+ result. identifies what is being
+ analyzed for kind-aware diagnostic factory selection.
+
+
+
+
+ MEASURE references are only legal in measure bodies. In any other
+ context (field expression, join ON clause) every occurrence becomes a
+ pre-flight diagnostic. One per call site — per-occurrence visibility
+ lets the user fix each one in isolation.
+
+
+
+
+ Routing decision for a field's resulting field: the fact table, or
+ a specific dimension table identified by name. FieldTarget.Fact
+ is the default when the analyzer cannot conclusively resolve refs to a
+ single non-source dim table (errors, source refs, multi-dim refs, zero
+ refs, parse errors, defense-in-depth fallback all route to Fact).
+
+
+
+
+ The field being visited and the abstract-model field kind it
+ becomes.
+
+
+
+
+ The field being visited and the abstract-model field kind it
+ becomes.
+
+
+
+
+ The field expression resolves to a single column reference: the
+ resulting abstract is a ReferenceField pointing at a SourceField
+ named .
+
+
+
+
+ The field expression resolves to a single column reference: the
+ resulting abstract is a ReferenceField pointing at a SourceField
+ named .
+
+
+
+
+ The field expression is complex: the resulting abstract is a
+ DerivedField carrying the verbatim .
+ lists the columns the
+ expression depends on; the visitor ensures each one as a
+ ReferenceField + SourceField pair before creating the DerivedField.
+
+
+
+
+ The field expression is complex: the resulting abstract is a
+ DerivedField carrying the verbatim .
+ lists the columns the
+ expression depends on; the visitor ensures each one as a
+ ReferenceField + SourceField pair before creating the DerivedField.
+
+
+
+
+ The field expression is empty or whitespace-only: the resulting
+ abstract is a DerivedField with empty Expressions. Downstream
+ Abstract→TOM emits DERIVED_FIELD_NO_EXPRESSION and a
+ placeholder column body.
+
+
+
+
+ The field expression is empty or whitespace-only: the resulting
+ abstract is a DerivedField with empty Expressions. Downstream
+ Abstract→TOM emits DERIVED_FIELD_NO_EXPRESSION and a
+ placeholder column body.
+
+
+
+
+ Result of analyzing a Metric View for
+ translation into the abstract model. Composed atop a shared
+ (parsing, ref extraction, parse-level
+ diagnostics). Adds the field-specific kind decision
+ () and routing decision
+ ().
+
+
+
+
+ Result of analyzing a Metric View for
+ translation into the abstract model. Composed atop a shared
+ (parsing, ref extraction, parse-level
+ diagnostics). Adds the field-specific kind decision
+ () and routing decision
+ ().
-
- This helper encapsulates the logic for ensuring fields exist in both the fact table
- and its source, managing data type updates when measures require Decimal types,
- and searching for existing fields by name or technical name.
-
-
- Creates a new FieldFragmentHelper for managing field fragments.
-
- The model builder containing all fragments
- The fact fragment to manage fields for
- The source fragment for the fact
-
+
- Finds the field fragment key for a given column reference.
- Searches fact fields first, then dimension fields.
- Matches by technical name or name.
+ Analyze a Metric View field to determine the abstract-model
+ field shape it should produce.
- The column reference to find
- The field fragment key if found, otherwise null
-
+
- Ensures a field exists for a measure, creating one if needed.
- For aggregations that imply numeric values (SUM, AVG, MIN, MAX), updates
- existing String fields to Decimal. COUNT aggregations don't imply a
- particular field type, so the field's DataType is preserved.
+ Routes a Simple subject's target based on the single column ref's
+ qualifier. Unqualified or matching the implicit table -> Fact. Any
+ other qualifier -> Dimension named after that qualifier (case
+ preserved from the SQL).
+
+
+
+
+ Field-Root operations used by the MV→Abstract visitor: pair-creation
+ primitives ( for user-declared subjects,
+ for Expr-derived refs), the
+ placement-resolver wrapper (), and
+ post-hoc type opinion ().
- Column reference from the measure expression
- The aggregation type of the measure
- Field fragment key for the field
- This method handles two scenarios:
-
- - Field exists (e.g., created by a dimension): Updates DataType to Decimal
- - Field doesn't exist: Creates new field with Decimal type
-
+ The shared core is private — only the
+ two named frontends call it. This enforces at the type level that
+ callers commit to declaration vs. upstream intent rather than reaching
+ past the abstraction.
-
+
+
+ Materialize or reuse a +
+ pair. Idempotent by
+ on
+ (case-insensitive). Bails (returns the existing id unchanged) when
+ any field already sits at that TechnicalName, including a
+ (bail rule for the derived-aggregation
+ case). Newly-created fields use ;
+ callers apply type opinions separately via
+ . and
+ are applied to a newly-created
+ ReferenceField only; existing fields are returned unchanged. When
+ is empty, the field's Name falls
+ back to TechnicalName via Names.Or. SourceField description stays
+ empty (internal, never user-visible).
+
+
+
+
+ Materialize or refine a +
+ pair for a user-declared MV subject
+ (Subject.Simple from an MV field). Caller supplies the full
+ metadata bundle, the resolved placement, the visitor's set of
+ already-declared field ids (consulted to distinguish placeholders
+ from declarations), and the diagnostics list (for collision
+ reporting).
+
+ When an existing field at
+ is a placeholder (not in )
+ with the same source binding, the declaration's metadata is
+ applied to it — empty slots filled in, existing non-empty
+ metadata preserved. The FieldId is unchanged; relationships
+ and other references survive.
+
+
+ The returned FieldId is added to
+ when the result is a
+ ReferenceField, so later calls can distinguish this declared
+ field from placeholders.
+
+
+
+
- Updates an existing field fragment and its corresponding source field
- to the specified DataType, but only if the current type is String.
- Non-String types (e.g., Integer keys) are preserved.
+ Compute a dedup-suffix name by repeating
+ separated by underscores until the
+ result is unique among fields on
+ (case-insensitive). Pathological collisions yield ugly names like
+ pk_pk_pk; that's accepted in exchange for trivial dedup
+ logic.
- Key of the field fragment to update
- New data type for the field
-
+
- Creates new field fragments (fact and source) for a measure that
- references a non-existent field.
- Both Name and TechnicalName are set to the column name.
+ Materialize or reuse a +
+ pair for an implicitly-discovered
+ reference (a column extracted from an Expr or ON clause). Has no
+ metadata to apply — the caller is an upstream-ref site, not a
+ user-declared subject. Resulting field's display name falls back to
+ TechnicalName via Names.Or.
+
+ Lookup is by TechnicalName first. When the name-match is a
+ declaration whose source binding differs from
+ (the result of an
+ rename collision), the upstream
+ ref isn't asking for that declaration — it's asking for the
+ field backed by the requested SQL column. Falls back to
+ finding any non-declared ReferenceField backed by that
+ SourceField.
+
- Column reference from the measure expression
- Key of the created fact field fragment
-
+
- Traverses a MetricView object graph and returns all nodes using the visitor pattern.
+ Placement resolver for : resolves
+ against Root.Dimensions, delegates to
+ on the resolved branch (source-side
+ -> Fact, dim-side -> matching dim), and falls back to a Fact-side
+ placeholder named "table.column"
+ plus an UNRESOLVED_DIMENSION_REFERENCE warning on the
+ unresolved branch. Newly-created fields are always
+ ; type opinions flow through
+ separately.
-
+
- Returns all objects in the MetricView graph.
+ Sets a field's . Updates a
+ AND its linked
+ in lockstep, OR a on its own (no
+ SourceField behind it). Direct hits on a
+ id are a no-op — SourceField data types flow through the
+ ReferenceField lockstep, not direct mutation. The caller decides
+ whether to call; there's no "no opinion" sentinel inside the
+ function. Silently swallows a stale or unknown
+ rather than throw — id-integrity bugs
+ are caught upstream by the /
+ returns the visitor threads through.
-
+
- Static wrapper/convenience class for use in C# scripts
+ Sets a field's Format. Applies to
+ and alike; has
+ no Format (it's internal, never user-visible). Silently swallows a
+ stale or unknown , matching the
+ robustness pattern.
-
+
- Loads a MetricView from a YAML file
+ Result of analyzing a Metric View for
+ translation into the abstract model. Composed atop a shared
+ (parsing, ref extraction, parse-level
+ diagnostics). The record itself is the kind discriminator: a measure
+ analyzed expression resolves to ,
+ or .
- full path to the yaml file on disk
- an unvalidated MetricView
-
- thrown when the YAML is invalid, but doesn't check for internal
- consistency of the model
-
-
+
- Deserialize a MetricView from a YAML string
+ Result of analyzing a Metric View for
+ translation into the abstract model. Composed atop a shared
+ (parsing, ref extraction, parse-level
+ diagnostics). The record itself is the kind discriminator: a measure
+ analyzed expression resolves to ,
+ or .
- the YAML string to deserialize
- an unvalidated MetricView
-
- thrown when the YAML is invalid, but doesn't check for internal
- consistency of the model
-
-
+
- Serialize the MetricView to YAML and save to disk
+ The measure expression is complex: multi-arg aggregation, nested
+ function, arithmetic, CASE, an unknown function, or anything else
+ that doesn't fit the Simple pattern. The resulting abstract is a
+ calculated measure carrying the verbatim .
+ lists the columns the expression
+ depends on so the visitor can ensure them before creating the
+ calculated measure.
- the MetricView to serialize
- the path to save the YAML file
-
+
- Serialize a MetricView to a YAML string
+ The measure expression is complex: multi-arg aggregation, nested
+ function, arithmetic, CASE, an unknown function, or anything else
+ that doesn't fit the Simple pattern. The resulting abstract is a
+ calculated measure carrying the verbatim .
+ lists the columns the expression
+ depends on so the visitor can ensure them before creating the
+ calculated measure.
- the MetricView to serialize
- the serialized YAML string
-
+
- The default validation rules to use when validating MetricViews.
- Automatically used when calling `Validate(MetricView)` overload
+ The measure expression is empty or whitespace-only: the resulting
+ abstract is a placeholder calculated measure with no expression.
+ Downstream Abstract→TOM emits the placeholder body and a warning.
-
+
- Validate a MetricView using the provided validator
+ The measure expression is empty or whitespace-only: the resulting
+ abstract is a placeholder calculated measure with no expression.
+ Downstream Abstract→TOM emits the placeholder body and a warning.
- the MetricView to validate
- the validator to use
- enumerable of diagnostic messages resulting from the validation rules
-
+
- Validate a MetricView using the default set of validation rules
+ Analyze a Metric View measure to determine the abstract-model
+ measure shape it should produce. After the
+ AAST landed, classification
+ collapsed to (empty body) and
+ (everything else): structural recognition
+ happens at AAST-build time in , not here.
- MetricView to validate
- enumerable of diagnostic messages resulting from the validation rules
- The set of rules is available as `MetricViews.DefaultValidationRules`
-
+
- Validate a MetricView using the provided set of rules
+ Emitted when an MV format spec cannot be translated to TOM
+ FormatString without information loss. Covers two flavors:
+ (a) lossy translation — a best-effort FormatString is emitted but
+ some user intent is dropped (e.g., locale_short_month maps to
+ Long Date, losing the "short" specificity); (b) untranslatable
+ drop with ISO fallback — no FormatString equivalent exists, and
+ the translator falls back to an ISO date/time form so the user
+ gets an unambiguous rendering rather than nothing. Warning
+ severity in both cases — the user's explicit format intent is
+ not fully honored.
- the MetricView to validate
- the set of validation rules to apply
- enumerable of diagnostic messages resulting from the validation rules
- does not use any of the default rules unless you explicitly include these
-
+
- Make a new MetricViewValidationVisitor with the default set of rules
+ Emitted when a user-declared field collides with an existing
+ implementation-detail placeholder field at the same
+ on the target table, with a
+ different SQL source binding. The placeholder is renamed to
+ (preserving the relationship
+ wiring that referenced it); the declaration takes the original
+ name with its declared source. Information severity — the rename
+ is a deterministic accommodation of the user's explicit
+ declaration, not a problem to fix.
- a reusable MetricViewValidationVisitor to use as a validator
-
+
- Make a new MetricViewValidationVisitor with the provided set of
- rules, optionally including the default rules
+ Emitted by EnsureField when a column reference's table
+ qualifier does not resolve to a known dimension (and is not
+ "source"). The visitor recovers by placing a placeholder
+
+ on the Fact preserving the original ref text; this diagnostic
+ surfaces that the dim wiring is missing so the user can either
+ declare the join or fix the typo.
- the set of validation rules to use in the validator
-
- whether to include the default rules (default: `true`)
+
+
+
+ Emitted when a join's On clause is empty or whitespace.
+ The dim and its source are created, but no FK/PK pair is wired —
+ downstream model is structurally incomplete on the join side.
+
+
+
+
+ Emitted when a join's On clause can't be parsed or doesn't
+ take the expected shape of a single equality (e.g., a different
+ comparison operator, unparseable SQL). The dim and its source
+ are created, but no FK/PK pair is wired.
+
+
+
+
+ Emitted when a join's On clause is a binary equality but
+ the two refs don't pair a source-qualified column with a dim-
+ qualified column — either both refs land on the same side, or
+ one of them carries an unrelated qualifier. The dim and its
+ source are created, but no FK/PK pair is wired.
+
+
+
+
+ Emitted when a join declares cardinality: one_to_many. The
+ v1.1 spec treats the joined table as an independent fact source
+ aggregated separately at the source grain; the translator does
+ not currently model that shape. The joined table is still mapped
+ so it stays visible in the resulting model, but the FK/PK
+ relationship to the source is skipped. Measures that reference
+ columns from this table must be reviewed and evaluated by hand
+ — without the relationship the generated DAX cannot bring those
+ columns into context and will produce wrong or empty results at
+ refresh.
+
+
+
+
+ Emitted when a join would create a dimension whose name collides
+ with an existing dimension — e.g. the same join name nested under
+ two different parents. Join names are unique across a metric view
+ (enforced by the UniqueJoinName validation rule), so this only fires
+ when validation was bypassed; the duplicate dimension is skipped (the
+ existing one stands) and translation continues. Warning severity —
+ the model is incomplete for the skipped branch.
+
+
+
+
+ Emitted when a dimension expression references a joined table as a
+ whole-row or nested struct value (e.g. customer or
+ customer.nation, where the referenced name is itself a join)
+ rather than a scalar column. Tabular has no column equivalent for a
+ struct/row value: the column is still emitted so the model stays
+ buildable, but it binds to a non-existent source column and will not
+ resolve at refresh. Warning severity — the reference is valid in the
+ metric view but untranslatable here.
+
+
+
+
+ Used for surviving Unknown nodes — constructs that parsed cleanly
+ into the AST but for which we have no translation path. Matches the
+ downstream Tabular-side "could not be translated" diagnostic so the
+ end user sees a single, consistent message regardless of which
+ pipeline stage gave up.
+
+
+
+
+ Used when ANTLR's lexer or parser reports an error against a
+ dimension expression — i.e., the source SQL itself didn't parse.
+ Distinct from , which signals
+ a parsed-but-unhandled construct. As the parser grows in coverage
+ this code becomes a clear "the user's SQL is the problem" signal
+ rather than "we don't translate this yet."
+
+ canonical dimension path (anchor for navigation)
+
+ the offending source slice — preferably the tight span of the
+ surviving Unknown that overlapped this error; falls back to the
+ parser's own context text otherwise
- a reusable MetricViewValidationVisitor to use as a validator
+ parser/lexer error context (typically short)
+ parser/lexer error message (typically longer)
-
+
- Creates a validation rule for a specific type of MetricView object.
+ Defense-in-depth diagnostic for the case-analysis fallback in
+ FieldAnalysis.Analyze. The case analysis is exhaustive
+ today, so this should never fire; if it does, future grammar or
+ visitor changes have broken our routing invariants. We surface a
+ distinct code so the failure is identifiable in support requests,
+ and we route the dimension to a Fact field as the safe default
+ rather than throw.
+
+ dimension name (for the user-facing message)
+ canonical dimension path (anchor for navigation)
+
+ diagnostic context — typically the dimension expression and a brief
+ description of which routing branches were considered
+
+
+
+
+ Kind-aware overload of .
+ identifies what is being analyzed
+ (typeof(Field), typeof(Measure),
+ typeof(Join)) for future kind-aware code/message branching;
+ currently delegates to the dimension-flavored factory.
+
+
+
+
+ Kind-aware overload of .
+ identifies what is being analyzed
+ for future kind-aware code/message branching; currently delegates
+ to the dimension-flavored factory.
+
+
+
+
+ Emitted when a MEASURE(name) reference appears in an
+ expression context that does not permit it (dimension expressions
+ and join ON clauses). The expression continues to flow through the
+ existing best-effort emission path; this diagnostic surfaces the
+ structural violation pre-flight so the user can correct the MV.
+ One diagnostic is emitted per occurrence — per-call-site visibility
+ is preferred over a single summary so each site can be fixed in
+ isolation.
+
+
+
+
+ Emitted when a MEASURE(name) reference cannot be resolved to
+ a measure declared in the Root under construction. The MV spec
+ forbids forward references, so this typically indicates a typo or
+ a missing measure declaration. The AAST collapses to
+ Unstructured(verbatim); downstream emission falls back to
+ the platform-keyed source text with the usual untranslated warning.
+
+
+
+
+ Create a warning diagnostic with a templatized message indicating
+ that the warning originated during deserialization.
+
+
+
+
+ Used when the format specification is missing the required `type`
+ property in yaml.
+
+
+
+
+ Use when the metric view is missing required `version` property in
+ yaml.
+
+
+
+
+ The format type provided (yaml `type` property) is not known.
+
+
+
+
+ Format abbreviation value didn't match any known abbreviation.
+ The format keeps no abbreviation (null).
+
+
+
+
+ date_format was omitted on a Date/DateTime format.
+ Defaults to year_month_day.
+
+
+
+
+ date_format value didn't match any known DateFormatSpec.
+ Defaults to year_month_day.
+
+
+
+
+ time_format was omitted on a DateTime format.
+ Defaults to locale_hour_minute_second.
+
+
+
+
+ time_format value didn't match any known TimeFormatSpec.
+ Defaults to locale_hour_minute_second.
+
+
+
+
+ decimal_places.type was omitted. Defaults to all.
+
+
+
+
+ decimal_places.type value didn't match any known
+ DecimalType. Defaults to all.
+
+
+
+
+ semiadditive was omitted on a window spec.
+ Defaults to Last.
+
+
+
+
+ semiadditive value didn't match any known
+ SemiadditiveType. Defaults to Last.
+
+
+
+
+ materialization.mode was omitted. Defaults to relaxed.
+
+
+
+
+ materialization.mode value didn't match any known
+ MaterializationMode. Defaults to relaxed.
+
+
+
+
+ type was omitted on a materialized view spec.
+ Defaults to unaggregated.
+
+
+
+
+ type value on a materialized view spec didn't match
+ any known MaterializedViewType. Defaults to unaggregated.
+
+
+
+
+ Setting a versioned property raised a
+ MetricViewVersionException through reflection — the
+ property exists but isn't valid for the view's declared version.
+ The message text comes from the underlying exception.
+
+
+
+
+ Emitted when a metric view's YAML uses the legacy
+ dimensions: keyword at the top level on a v1.1-or-later
+ view. The canonical form starting in v1.1 is fields:; both
+ keywords continue to work, so this is informational. Fires at most
+ once per file. Scope is the top-level keyword only — the
+ materialization block's dimensions: field-name list is
+ canonical at all versions and does not trigger this diagnostic.
+
+
+
+
+ Emitted when a metric view's YAML uses the fields: keyword
+ at the top level on a pre-v1.1 view. The fields: alias
+ became canonical in v1.1; on earlier versions dimensions:
+ is canonical. We don't refuse the read — Databricks doesn't
+ document fields: as illegal in older versions — but
+ surface the mismatch as a soft warning. Fires at most once per
+ file.
+
+
+
+
+ The value of a join's cardinality: field was not a known
+ value. The join's cardinality
+ defaults to on this
+ path.
+
+
+
+
+ A metric view's YAML declared both top-level fields: and
+ dimensions:. The two keywords are aliases for the same
+ collection; declaring both is ambiguous, so deserialization
+ fails. The fields/dimensions block is skipped on this path
+ (the resulting view has no fields) and the diagnostic is
+ surfaced as a .
+
+
+
+
+ Visitor that maps a MetricView () to an
+ abstract-model . Constructs the Root directly via
+ Root.AddX pure-functional operations — no builder or fragment
+ intermediate layer. Accumulates the in-progress Root across Visit calls
+ via ; each Visit returns the (updated) Root.
+ Diagnostics encountered during traversal are exposed via
+ .
+
+
+
+
+ Visitor that maps a MetricView () to an
+ abstract-model . Constructs the Root directly via
+ Root.AddX pure-functional operations — no builder or fragment
+ intermediate layer. Accumulates the in-progress Root across Visit calls
+ via ; each Visit returns the (updated) Root.
+ Diagnostics encountered during traversal are exposed via
+ .
+
+
+
+
+ An empty tagged for MetricView translation.
+ Shared between the visitor's internal seed state and test setup
+ helpers so expected/actual roots agree on Name and
+ TechnicalName trivially.
+
+
+
+
+ Wires this join's foreign-key/primary-key
+ pair and the resulting . The upstream side
+ of the ON clause is the parent join's table: the metric-view source
+ ("source") for a top-level join, or the parent dimension for a
+ nested (snowflake) join. Best-effort — a malformed ON clause emits a
+ classified JOIN_ON_* diagnostic and returns without wiring; the
+ dimension table created by the caller stands.
+
+
+
+
+ Translates a user-declared MV format and applies it (plus the
+ resulting inferred DataType) to the abstract field at
+ . No-op when
+ is null. Used by every dim-side branch (Subject.Simple normal,
+ Subject.Simple recovery, Subject.Derived, Subject.Placeholder)
+ after the field has been created or refined.
+
+
+
+
+ Translates a user-declared MV measure format to a TOM FormatString
+ and appends any lossy-translation diagnostics. Returns empty when
+ no format is declared. Caller is responsible for using the result
+ as the measure's Format value.
+
+
+
+
+ Builds an body for a measure
+ about to be added as . Routes
+ through , which resolves MEASURE
+ references against the in-progress Root (case-insensitive
+ name match) and falls back to
+ for shapes it
+ doesn't yet model structurally. Diagnostics from the translation
+ are appended to .
+
+
+
+
+ Resolves a SQL to its
+ in the in-progress Root. The caller is
+ expected to have already ensured the field (via
+ ); this lookup is
+ read-only and returns null when the ref doesn't resolve, which
+ causes the AAST builder to abort and fall back.
+
+ Table resolution mirrors
+ 's rule: bare or
+ source-qualified refs land on the owning Fact;
+ dim-qualified refs target the named dim. Field resolution
+ within the table follows source binding first (so a renamed
+ placeholder whose TechnicalName no longer matches the
+ SQL column still resolves correctly), preferring the field
+ whose own TechnicalName also matches the SQL column
+ (the canonical placeholder over a same-source user
+ declaration). Falls back to a name match for
+ targets, which have no source
+ binding.
+
+
+
+
+
+ Walks the AAST yielding every
+ reachable from . Used by the measure
+ visitor to apply per-field type opinions after the body has been
+ translated.
+
+
+
+
+ Apply the aggregation's field-type opinion to the field at
+ via
+ : String → Decimal
+ under SUM/AVG/MIN/MAX, no opinion under counts, key Integer
+ preserved against non-date opinions.
+
+
+
+
+ Picks the opinion the body
+ contributes to the measure's DataType inference: a top-level
+ column aggregation contributes its kind; a top-level row count
+ contributes ; anything else
+ contributes nothing (caller falls back to format-driven type or
+ the Decimal default).
+
+
+
+
+ Case-insensitive name lookup against the in-progress
+ cache. Forward references are
+ forbidden by the MV spec, so the cache is authoritative at the
+ moment of translation — every previously-emitted measure has been
+ indexed.
+
+
+
+
+ Re-serializes a measure's window specification(s) to a source-shaped
+ YAML fragment, or returns null when the measure declares none.
+ Carried on the abstract measure as
+ .
+ TODO (#6347): drop once windowed measures are translated natively.
+
+
+
+
+ Appends an derived from
+ to , linked to
+ and labeled with
+ . parsed as a
+ 3-part identifier produces a ; anything
+ else produces a carrying the string
+ verbatim.
+
+
+
+
+ Traverses a MetricView object graph and returns all nodes using the visitor pattern.
+
+
+
+
+ Returns all objects in the MetricView graph.
+
+
+
+
+ Parses a 3-part SQL table name into its constituent parts.
+
+ The source string to parse
+ Database, schema, and table names if parsing succeeds; null otherwise
+
+
+
+ Static wrapper/convenience class for use in C# scripts
+
+
+
+
+ Loads a MetricView from a YAML file
+
+ full path to the yaml file on disk
+ an unvalidated MetricView
+
+ Thrown in exceptional failures of deserialization; we should always see a result
+
+
+
+
+ Deserialize a MetricView from a YAML string
+
+ the YAML string to deserialize
+ an unvalidated MetricView
+
+ thrown in exceptional failures of deserialization; we should always see a result
+
+
+
+
+ Serialize the MetricView to YAML and save to disk
+
+ the MetricView to serialize
+ the path to save the YAML file
+
+
+
+ Serialize a MetricView to a YAML string
+
+ the MetricView to serialize
+ the serialized YAML string
+
+
+
+ The default validation rules to use when validating MetricViews.
+ Automatically used when calling `Validate(MetricView)` overload
+
+
+
+
+ Validate a MetricView using the provided validator
+
+ the MetricView to validate
+ the validator to use
+ enumerable of diagnostic messages resulting from the validation rules
+
+
+
+ Validate a MetricView using the default set of validation rules
+
+ MetricView to validate
+ enumerable of diagnostic messages resulting from the validation rules
+ The set of rules is available as `MetricViews.DefaultValidationRules`
+
+
+
+ Validate a MetricView using the provided set of rules
+
+ the MetricView to validate
+ the set of validation rules to apply
+ enumerable of diagnostic messages resulting from the validation rules
+ does not use any of the default rules unless you explicitly include these
+
+
+
+ Make a new MetricViewValidationVisitor with the default set of rules
+
+ a reusable MetricViewValidationVisitor to use as a validator
+
+
+
+ Make a new MetricViewValidationVisitor with the provided set of
+ rules, optionally including the default rules
+
+ the set of validation rules to use in the validator
+
+ whether to include the default rules (default: `true`)
+
+ a reusable MetricViewValidationVisitor to use as a validator
+
+
+
+ Creates a validation rule for a specific type of MetricView object.
+
+
+ type of MetricView object the rule applies to. One of `MetricView`,
+ `MetricViewField`, `MetricViewJoin`, `MetricViewMeasure`
+
+ name of the rule
+ category for the rule (you can use any text)
+ validation function
+ a validation rule for use in a validator
+
+ the validation function `validate` is a function of two arguments:
+ 1. the metric view object to which the rule is applied
+ 2. the validation context
+ validation context is a `IReadOnlyValidationContext` object which
+ provides:
+ - `PathStack`: identifies the exact object currently being
+ examined, with all of its parents (in reverse order from this
+ object to the root). In general you probably don't need to do
+ much with this.
+ - `JoinNames`: set of strings of all join names already seen
+ during validation
+ - `FieldNames`: set of strings of all field names already
+ seen
+ - `MeasureNames`: set of strings of all measure names already seen
+ - `MakeError(message, property)`: function to create a diagnostic
+ error. **You should use this to create the errors you return**.
+ The first arg is a string describing the error. The second arg
+ is an optional property name (e.g. "Name") to append to the path.
+ **Only use the name of a MetricView object property**, not any
+ arbitrary string.
+ Your function must return an enumerable of DiagnosticMessage objects.
+ If there are no problems, return an empty enumerable (e.g. `[]`).
+ If the object is invalid according to the rule (your conditional
+ checks), then return an enumerable with one or more errors created
+ with the context's `MakeError` method. You can inspect any properties
+ of the object (the first arg to your function) or anything in the
+ context object.
+
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Validation function
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Create a validation rule for a specific MetricView object type
+
+
+ type of MetricView object the rule applies to. One of `MetricView`,
+ `MetricViewField`, `MetricViewJoin`, `MetricViewMeasure`
+
+ name of the rule
+ category for the rule (you can use any text)
+ the message returned in the error if the object is invalid
+ a predicate function to determine if the object is invalid
+ a validation rule for use in a validator
+
+ the function `isInvalid` is a simple predicate function that can
+ only inspect the properties of the current MetricView object. If you
+ need to inspect other context, you should use the other overload of
+ `MakeValidationRule`
+
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Create a validation rule for the root MetricView object
+
+ name of the rule
+ category for the rule (you can use any text)
+ the message returned in the error if the object is invalid
+ a predicate function to determine if the object is invalid
+ a validation rule for use in a validator
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Create a validation rule for MetricViewJoin objects
+
+ name of the rule
+ category for the rule (you can use any text)
+
+ the message returned in the error if the MetricViewJoin is invalid
+
+
+ a predicate function to determine if the MetricViewJoin is invalid
+
+ a validation rule for use in a validator
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Create a validation rule for MetricViewField objects
+
+ name of the rule
+ category for the rule (you can use any text)
+
+ the message returned in the error if the MetricViewField is invalid
+
+
+ a predicate function to determine if the MetricViewField is invalid
+
+ a validation rule for use in a validator
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Create a validation rule for MetricViewMeasure objects
+
+ name of the rule
+ category for the rule (you can use any text)
+
+ the message returned in the error if the MetricViewMeasure is invalid
+
+
+ a predicate function to determine if the MetricViewMeasure is invalid
+
+ a validation rule for use in a validator
+
+
+
+ Unique name for the validation rule
+ Category for organizational purposes
+ Error message returned when the object is invalid
+ Predicate function that returns true when the object is invalid
+ Minimum spec version this rule applies to (e.g. "1.1")
+
+
+
+ Companion to that routes through the
+ AbstractModel.Next visitor pipeline. Same return contract and
+ diagnostic semantics; the two coexist while the new pipeline is
+ completed.
+
+
+
+
+ DTO for Databricks Metric View YAML serialization.
+ Uses snake_case naming convention via YamlDotNet configuration.
+
+
+
+
+ DTO for field definitions in YAML
+
+
+
+
+ DTO for measure definitions in YAML
+
+
+
+
+ DTO for join definitions in YAML
+
+
+
+
+ DTO for the v1.1 rely: map on joins.
+
+
+
+
+ DTO for format specification in YAML
+
+
+
+
+ DTO for decimal places specification
+
+
+
+
+ DTO for window specification
+
+
+
+
+ DTO for materialization configuration
+
+
+
+
+ DTO for materialized view specification
+
+
+
+
+ Represents a field definition in a Databricks Metric View
+
+
+ A field in a Metric View is a single field. There is no namespacing
+ or delineation of separate named collections of fields.
+
+
+
+
+ Masks the runtime type name introduced by
+ the legacy shim so logs, debugger tooltips, and default
+ ToString() consumers always see the canonical "Field" label
+ regardless of which subtype currently backs the instance.
+
+
+
+
+ The YAML name for the field
+
+
+
+
+
+
+
+ The YAML string representing the expression for this field,
+ either a field reference or scalar SQL expression.
+
+
+
+
+ Description of the field. Requires version 1.1+.
+
+
+
+
+ Human-readable display name. Requires version 1.1+.
+
+
+
+
+ Alternative names for AI/search. Requires version 1.1+.
+
+
+
+
+ Display format specification. Requires version 1.1+.
+
+
+
+
+ Legacy name for . Retained as an obsolete subclass
+ so external code still compiles during the deprecation window. Every
+ instance constructed via
+ or is actually a
+ at runtime, so a cast ((Dimension)field) succeeds and returns the
+ same reference.
+
+
+
+
+ Databricks Metric View format specifications
+
+
+
+
+ The type of format (i.e., "number", "currency", "percentage",
+ "byte", "date", "datetime")
+
+
+
+
+ Date: Use date format for date values with various display options.
+
+
+
+
+
+
+
+ Controls the way the date is displayed
+
+
+
+
+ Controls whether single digit numbers are preceded by a zero
+
+
+
+
+ DateTime format specification
+
+
+ When working with a `DateTime` type, at least one of `DateFormat`
+ or `TimeFormat` must specify a value other than `NoDate` or
+ `NoTime`.
+
+
+
+
+
+
+
+ Time format specification
+
+
+
+
+ Controls the way the date is displayed
+
+
+
+
+ >
+ Date is hidden (only valid for DateTime, not for Date)
+
+
+
+
+ Displays the date with an abbreviated month
+
+
+
+
+ Displays the date with the full name of the month
+
+
+
+
+ Formats the date as YYYY-MM-DD
+
+
+
+
+ Displays the date with a month as a number
+
+
+
+
+ Formats the date as a year and a week number. For example, `2025-W1`
+
+
+
+
+ Controls the way the time is displayed
+
+
+
+
+ Time is hidden
+
+
+
+
+ Displays the hour and minute
+
+
+
+
+ Displays the hour, minute, and second
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Number: Use plain number format for general numeric values with optional
+ decimal place control and abbreviation options.
+
+
+
+
+
+
+
+ Abbreviation style: none, compact, or scientific
+
+
+
+
+ Currency: Use currency format for monetary values with ISO-4217 currency codes.
+
+
+
+
+
+
+
+ ISO 4217 currency code (e.g., "USD", "EUR", "JPY")
+
+
+
+
+ Percentage: Use percentage format for ratio values expressed as percentages.
+
+
+
+
+
+
+
+ Byte: Use byte format for data size values displayed with appropriate
+ byte units (KB, MB, GB, etc.).
+
+
+
+
+
+
+
+ Specifies decimal place formatting.
+
+
+
+
+ Type of decimal formatting: "max", "exact", or "all"
+
+
+
+
+ Number of decimal places (0-10). Null if not specified.
+
+
+
+
+ Decimal places configuration
+
+
+
+
+ Whether to hide the group separator (e.g., commas in 1,000)
+
+
+
+
+ The type of format (i.e., "number", "currency", "percentage",
+ "byte", "date", "datetime")
+
+
+
+
+ Represents a join definition in a Databricks Metric View
+
+
+
+
+ Parent join if this is a nested join, null if this is a top-level join.
+
+
+
+
+ Source table or query for the join
+
+
+
+
+ Optional SQL boolean expression for the join condition
+
+
+
+
+ Optional list of column names to use for join
+
+
+
+
+ Child joins that are part of this join definition
+
+
+
+
+ Controls the relationship between the source and the joined table.
+ Per spec, cardinality: defaults to many_to_one: the
+ joined table acts as a dimension lookup. Set
+ to aggregate the joined
+ table as a separate fact source. Three states round-trip faithfully:
+ null (YAML omitted; spec-equivalent to many_to_one),
+ (explicit), and
+ . Requires YAML spec 1.1+.
+
+
+
+
+ Optimizer hints about the join's relationship to its source.
+ Currently the map only carries ;
+ the spec is shaped as an extensible map for future keys.
+ Conservatively gated to YAML spec 1.1+: rely: was not
+ part of the v0.1 spec, so emitting it on a v0.1 view would
+ produce YAML that pre-v1.1 tooling can't read. The current
+ spec's feature-availability table ties rely.at_most_one_match
+ to DBR 18.1 without restating a YAML version requirement; we
+ keep the YAML gate as a compatibility restriction.
+
+
+
+
+ Name of the joined table
+
+
+
+
+
+
+
+ Adds a child join to this join definition
+
+
+
+
+ Optimizer hints about a join's relationship to its source. Today this
+ carries only ; the Databricks spec models
+ rely: as an extensible map so additional keys may appear in
+ future spec revisions.
+ An explicitly-empty rely: {} in YAML deserializes to a non-null
+ with all-null fields, distinct from an omitted
+ rely: (which leaves null). Both states
+ round-trip faithfully. Faithful round-trips are a goal of our Metric
+ View serialization and deserialization.
+
+
+
+
+ When true, declares that the join has no fan-out on the
+ "one" side: on a many-to-one join, each source row matches at most
+ one row in the joined table; on a one-to-many join, each joined
+ row matches at most one source row. Databricks recommends setting
+ rely on both cardinalities when the constraint holds: it
+ lets the engine skip unnecessary joins and reduce data scanned,
+ especially for queries that filter on fields from the joined
+ table. Not validated at runtime; if the asserted side actually
+ fans out, measures return incorrect results.
+
+
+
+
+ The cardinality of a join's relationship between source and joined
+ table. Drives whether the joined table is treated as a dimension
+ lookup () or as an independent fact source
+ that the engine aggregates separately ().
+ Per the Databricks v1.1 spec, omitting the field defaults to
+ ; additionally
+ requires Databricks Runtime 18.1+.
+
+
+
+
+ Each source row matches at most one row in the joined table —
+ the joined table acts as a dimension lookup. Default per spec
+ when cardinality: is omitted.
+
+
+
+
+ The joined table can have multiple matching rows per source
+ row; the engine aggregates it independently at the source grain
+ as a separate fact source.
+
+
+
+
+ Specifies materialization configuration for accelerating metric view queries.
+ This is an experimental feature.
+
+
+
+
+ Refresh schedule (e.g., "every 6 hours")
+
+
+
+
+ Materialization mode. Currently only "relaxed" is supported.
+
+
+
+
+ List of materialized view specifications
+
+
+
+
+ Specifies a single materialized view within the materialization configuration.
+
+
+
+
+ Name of the materialization
+
+
+
+
+ Type of materialization: aggregated or unaggregated
+
+
+
+
+ List of dimension names to materialize (for aggregated type)
+
+
+
+
+ List of measure names to materialize (for aggregated type)
+
+
+
+
+ Materialization mode. Currently only "relaxed" is supported by Databricks.
+
+
+
+
+ Type of materialized view specification.
+
+
+
+
+ Represents a measure definition in a Databricks Metric View
+
+
+
+
+
+
+
+ Aggregate SQL expression that defines the measure
+
+
+
+
+ Description of the measure. Requires version 1.1+.
+
+
+
+
+ Human-readable display name. Requires version 1.1+.
+
+
+
+
+ Alternative names for AI/search. Requires version 1.1+.
+
+
+
+
+ Display format specification. Requires version 1.1+.
+
+
+
+
+ Window specifications for windowed, cumulative, or semiadditive aggregations.
+ Requires version 1.1+. This is an experimental feature.
+
+
+
+
+ A collection of MetricView objects with name-based indexing.
+ Implements IReadOnlyList for compatibility while providing O(1) name lookups.
+
+ The type of MetricView object in the collection
+
+
+
+ Creates a new collection for a named object type
+
+
+
+
+ Gets the item at the specified index.
+
+
+
+
+ Gets the item with the specified name.
+
+ If no item with the specified name exists
+
+
+
+ Gets the number of items in the collection.
+
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+
+
+ Returns an enumerator that iterates through the collection.
+
+
+
+
+ Finds an item by name, returning null if not found.
+
+ The name to search for
+ The item with the specified name, or null if not found
+
+
+
+ Determines whether an item with the specified name exists in the collection.
+
+ The name to search for
+ True if an item with the specified name exists
+
+
+
+ Adds an item to the collection.
+
+ The item to add
+ If an item with the same name already exists
+
+
+
+ Removes an item from the collection.
+
+ The item to remove
+ True if the item was removed, false if not found
+
+
+
+ Removes all items from the collection.
+
+
+
+
+ Internal abstract base class for all MetricView domain objects.
+ Implements both the public marker interface and the internal visitable interface.
+
+
+
+
+ Reference to the root View object.
+ For View itself, this points to itself.
+ Used for version validation in property setters.
+
+
+
+
+ Escape backslashes and quotes for building paths that are valid C#.
+
+ name of some metric view object
+
+ A string that will be valid in a lookup in a C# snippet such as:
+ `Model.Fields["a \"dangerous\" name"]`
+
+
+
+
+ Indicates whether this object has been deleted from its parent collection.
+ Deleted objects become "zombies" - they retain their data but are detached from the model.
+
+
+
+
+ Deletes this object from its parent collection.
+ After deletion, the object becomes a zombie (IsDeleted=true, View=null).
+
+
+ Thrown if the object is not attached to a View or is already deleted.
+
+
+
+
+ Marks this object as deleted.
+ Called by subclasses after removing from collection.
+
+
+
+
+ Accepts a visitor that produces a result of type TResult.
+ Must be implemented by derived domain objects.
+
+
+
+
+ Validates that the current model version supports the property being set.
+ Call this in property setters for version-gated properties.
+
+
+ Auto-populated by compiler via CallerMemberName
+
+
+ Thrown if the property requires a higher version than the current model
+
+
+
+
+ Provides version comparison utilities for Databricks Metric View specifications.
+ Unknown versions are treated as greater than all known versions (forward compatible).
+
+
+
+
+ Known metric view specification versions in order
+
+
+
+
+ Version 0.1 - Initial release (Databricks Runtime 16.4 through 17.1)
+
+
+
+
+ Version 1.1 - Adds semantic metadata, comments (Databricks Runtime 17.2+)
+
+
+
+
+ Default version when not specified in YAML (Databricks defaults to 1.1)
+
+
+
+
+ Compares two version strings.
+ Unknown versions sort greater than all known versions.
+
+
+ Negative if left < right, zero if equal, positive if left > right
+
+
+
+
+ Returns true if the version is at least the specified minimum version.
+
+
+
+
+ Returns true if is strictly greater than
+ , using full version-number comparison.
+ Patch-level strings ("1.1.1") ARE greater than their parent
+ minor version ("1.1") — any version bump from Databricks
+ means a spec change we should respect. Unparseable strings on
+ either side fall back to the array-index ordering used by
+ .
+
+
+
+
+ Returns true if the version string is a known version.
+
+
+
+
+ Gets the index of a version in the known versions array.
+ Unknown versions return int.MaxValue (sort after all known).
+
+
+
+
+ Specifies the minimum metric view version required for a property.
+ Used for setter validation when setting v1.1+ properties on older versions.
+
+
+ Creates a new MinVersion attribute with the specified minimum version.
+
+ The minimum version required (e.g., "1.1")
+
+
+
+ Specifies the minimum metric view version required for a property.
+ Used for setter validation when setting v1.1+ properties on older versions.
+
+
+ Creates a new MinVersion attribute with the specified minimum version.
+
+ The minimum version required (e.g., "1.1")
+
+
+
+ The minimum version required for this property.
+
+
+
+
+ Provides cached lookups for MinVersion attributes on properties.
+
+
+
+
+ Gets the minimum version required for a property, or null if no minimum.
+
+ The type containing the property
+ The name of the property
+ The minimum version string, or null if no MinVersion attribute
+
+
+
+ Checks if the property requires a minimum version and throws if not met.
+
+ The type containing the property
+ The name of the property
+ The current model version
+
+ Thrown if the property requires a higher version than current
+
+
+
+
+ Handles deserialization of Databricks Metric Views from YAML
+
+
+
+
+ Deserializes a YAML string into a MetricView object
+
+ The YAML string to deserialize
+ A MetricView object
+ If YAML is invalid or cannot be deserialized
+
+ A TransformationResult, either:
+ - success containing the view and any non-failure-inducing
+ diagnostic messages
+ - failure containing a list of errors that caused deserialization
+ or validation to fail. There is no view available in this case.
+
+
+
+
+ Maps a DTO to the domain model, wiring up parent pointers
+
+
+
+
+ Handles serialization of Databricks Metric Views to YAML
+
+
+
+
+ Serializes a MetricView object to a YAML string
+
+ The MetricView object to serialize
+ A YAML string representation
+
+
+
+ Version-aware default keyword choice for a view with no explicit
+ . Conservative: v1.1 and earlier
+ emit dimensions:; anything strictly greater than v1.1 emits
+ fields:. The fields: alias was introduced after the
+ v1.1 spec was published, so defaulting v1.1 to dimensions:
+ stays compatible with tooling that targets the original v1.1
+ spec.
+
+
+
+
+ Serializes a measure's window specification(s) to a YAML fragment
+ using the same naming convention and DTO mapping as a full view, so
+ the output matches the window: block as authored in the
+ source metric view. Used to embed the spec verbatim in a fallback
+ comment when window measures are encountered (see #6347).
+
+ The window specifications to serialize.
+ A YAML string representation of the window list.
+
+
+
+ Maps the domain model to a DTO for serialization
+
+
+
+
+ Represents a Databricks Metric View definition
+
+
+
+
+ Version of the metric view specification
+
+
+
+
+ The source data for the metric view, playing the role of a single fact
+
+
+
+
+ Optional SQL boolean expression that applies to all queries; a WHERE
+
+
+
+
+ Description of the metric view. Requires version 1.1+.
+
+
+
+
+ Materialization configuration for query acceleration. Requires version 1.1+.
+ This is an experimental feature.
+
+
+
+
+ Optional join definitions for the metric view
+
+
+ A join is also the place where dimension sources are defined; this
+ information exists nowhere else.
+
+
+
+
+ Array of field definitions
+
+
+
+
+ Array of measure definitions
+
+
+
+
+ Adds a new field to the metric view
+
+
+
+
+ Adds a new measure to the metric view
+
+
+
+
+ Adds a new join to the metric view
+
+
+
+
+ Adds a new join to the metric view with parentName as the parent join
+
+
+
+
+ Legacy name for . Allocates a fresh
+ on each access because
+ is invariant — the same
+ instance cannot satisfy both <Field> and
+ <Dimension>. The cast to is
+ safe because constructs every field as a
+ at runtime. Item references are the same
+ instances stored in , so mutations through
+ either surface are visible through the other.
+
+
+
+
+ Internal factory used by (and indirectly
+ ) to construct every
+ instance as a at runtime.
+
+
+
+ The load-bearing piece of the legacy shim. Because the
+ getter casts items to
+ and returns
+ one, every instance backing a entry
+ must actually be a subclass at runtime.
+ The compile-time return type stays so
+ canonical callers see the canonical type; only the runtime
+ instance type differs.
+
+
+ Implications while the shim lives:
+
+ -
+ field.GetType() returns typeof(Dimension),
+ not typeof(Field), for any field constructed via
+ or .
+
+ -
+ Default object.ToString() would surface the
+ runtime Dimension type name;
+ is overridden to mask this
+ in logs and debugger tooltips.
+
+ -
+ Reflection-based code that inspects the runtime type
+ name (custom serializers, reflection-based assertions,
+ some debugger views) will observe Dimension.
+ The legacy (Dimension)field cast succeeds
+ without copying state — this is why we construct
+ eagerly rather than wrapping per-access.
+
+
+
+
+ When is eventually removed, this
+ factory and its callers revert to constructing
+ directly. The runtime type flips back —
+ any external code that hardcoded the runtime type name to
+ "Dimension" will then need to update.
+
+
+
+
+
+ Legacy name for . The returned reference is
+ typed as so call sites that assign to a
+ Dimension-typed local continue to compile; the underlying
+ instance is the same one stored in .
+
+
+
+
+ Specifies window measure behavior for windowed, cumulative, or
+ semiadditive aggregations.
+
+
+ This is an experimental feature in Databricks.
+ The Semantic Bridge performs minimal validation or enforcement of the
+ window specification.
+
+
+
+
+ Aggregation strategy for semiadditive measures.
+
+
+
+
+ Makes sure that the first cumulative value is used when
+ aggregating over fields
+
+
+
+
+ Makes sure that the last cumulative value is used when
+ aggregating over fields
+
+
+
+
+ The field name that determines the ordering of the window.
+
+
+
+
+ Defines the extent of the window.
+ Values: "current", "cumulative", "trailing N unit", "leading N unit", "all"
+
+
+
+
+ Specifies how to summarize the measure when the order field is not
+ included in the query's `GROUP BY`.
+
+
+
+
+ Optional offset that shifts the window frame backward or forward
+ along the field by a fixed interval. Treated
+ as an opaque string: we round-trip the source form verbatim and
+ do not validate.
+ Per the v1.1 spec the form is <n> <period>
+ where n is a signed integer (negative looks backward,
+ positive looks forward) and period is one of day,
+ days, month, months, year, or
+ years. Examples: -12 month, 1 year,
+ -3 days, 7 day.
+ Spec constraints we do not enforce: must be
+ a date or timestamp column; offset has no effect when
+ is all; a shifted frame outside the
+ available data evaluates to NULL at query time.
+
+
+
+
+ Parses Databricks SQL expressions into an
+ AST using and an ANTLR visitor.
+
+
+
+ Tokenize the SQL expression in `input`
+ Token stream omitting whitespace and comments
+
+
+
+ Parse the input expression and return the AST root with any errors.
+
+
+
+
+ Cache for parse results; most recently visited non-Unknown. Acts
+ as an anchor for error-recovery spans.
+
+
+
+
+ Ensure we wrap all concrete visit methods and catch those antlr
+ trees which have not been handled.
+
+
+
+
+ Route child visits through Visit instead of Accept so our error
+ handling and caching in Visit applies at every depth. ANTLR's
+ default VisitChildren uses Accept which bypasses Visit.
+
+
+
+
+ Aggressive aggregation: a non-null aggregate means we are inside
+ of a rule without an explicit visitor
+ override. Wrap the running aggregate plus the next child into an
+ that preserves structurally-
+ recognized subtrees as Inner children. Existing Unknown
+ wrappers are flattened so we never produce
+ Unknown(Unknown(...)). Effect: any unhandled grammar rule
+ surfaces as Unknown spanning its full source extent, with all
+ recognized inner expressions reachable via the standard
+ walk.
+
+
+
+
+ Find the first default-channel token at or after the last
+ successfully visited node. Falls back to last good end, then to
+ start of input.
+
+
+
+
+ Create a non-overlapping, contiguous span for the tree node.
+
+
+
+
+ Create a TextSpan for the whole range of the parser rule context.
+ Intended for use in known valid parser visit methods only.
+
+
+ Thrown when the context includes a null Stop token, which means
+ we're trying to make a span for a context where we can't. Should
+ never throw in normal operation; this is just extra defensiveness.
+
+
+
+
+ Dispatch on the matched terminal token to produce the corresponding
+ typed subtype with the parsed
+ payload. Numeric and string parsing happens once here so downstream
+ consumers (AAST builders, validators) don't need to re-derive value
+ from the raw span text.
+
+
+
+
+ Strip the outer single quotes from a SQL string literal and
+ unescape embedded '' to a single quote.
+
+
+
+
+ Parse a numeric token (DECIMAL / FLOAT / REAL) into a
+ . Uses so
+ exponential notation (1.5e2) is accepted alongside the
+ simpler integer/fractional forms.
+
+
+
+
+ Create AST node for any binary expression. All have the same 3 parts.
+
+
+
+
+ Best available context span for a parser error: the enclosing rule
+ if available, otherwise the whole line.
+
+
+
+
+ Extract a TextSpan covering the entire line (1-based) from _input.
+
+
+
+
+ Double-dispatch visitor over nodes. One
+ Visit overload per concrete leaf type — adding a new leaf to
+ the SQL AST forces every visitor to consider it (either override or
+ inherit the default abort from ).
+
+ Recursive code in concrete overloads should call
+ Visit(child), not child.Accept(this) — the
+ Visit(SqlExpression) dispatcher routes through Accept,
+ keeping the dispatch detail in one place. An
+ raised from any nested
+ Visit propagates freely; only the outermost emit (via
+ )
+ catches it and invokes .
+
+
+
+
+
+ Visitor-specific placeholder produced when emission aborts. For an
+ SQL-to-AAST builder this is typically
+ wrapping
+ the verbatim source; for other consumers (validators, dumpers) it
+ can be whatever default the visitor's result type calls for.
+ Implementors MUST override; the abstract base class declares this
+ abstract so the omission fails at compile time.
+
+
+
+
+ A parse error reported by the ANTLR parser during expression parsing.
+
+
+
+
+ ANTLR's formatted error description.
+
+
+
+
+ Surrounding context of source text where the failure occurred.
+
+
+
+
+ An error that comes from ANTLR's lexer pass
+
+
+
+
+ An error that comes from ANTLR's lexer pass
+
+
+
+
+
+
+
+
+
+
+ The position of the character in the line that caused the lexer
+ failure.
-
- type of MetricView object the rule applies to. One of `MetricView`,
- `MetricViewDimension`, `MetricViewJoin`, `MetricViewMeasure`
-
- name of the rule
- category for the rule (you can use any text)
- validation function
- a validation rule for use in a validator
-
- the validation function `validate` is a function of two arguments:
- 1. the metric view object to which the rule is applied
- 2. the validation context
- validation context is a `IReadOnlyValidationContext` object which
- provides:
- - `PathStack`: identifies the exact object currently being
- examined, with all of its parents (in reverse order from this
- object to the root). In general you probably don't need to do
- much with this.
- - `JoinNames`: set of strings of all join names already seen
- during validation
- - `DimensionNames`: set of strings of all dimension names already
- seen
- - `MeasureNames`: set of strings of all measure names already seen
- - `MakeError(message, property)`: function to create a diagnostic
- error. **You should use this to create the errors you return**.
- The first arg is a string describing the error. The second arg
- is an optional property name (e.g. "Name") to append to the path.
- **Only use the name of a MetricView object property**, not any
- arbitrary string.
- Your function must return an enumerable of DiagnosticMessage objects.
- If there are no problems, return an empty enumerable (e.g. `[]`).
- If the object is invalid according to the rule (your conditional
- checks), then return an enumerable with one or more errors created
- with the context's `MakeError` method. You can inspect any properties
- of the object (the first arg to your function) or anything in the
- context object.
-
-
+
- Create a validation rule for a specific MetricView object type
+ An error that comes from ANTLR's parse of the grammar
-
- type of MetricView object the rule applies to. One of `MetricView`,
- `MetricViewDimension`, `MetricViewJoin`, `MetricViewMeasure`
-
- name of the rule
- category for the rule (you can use any text)
- the message returned in the error if the object is invalid
- a predicate function to determine if the object is invalid
- a validation rule for use in a validator
-
- the function `isInvalid` is a simple predicate function that can
- only inspect the properties of the current MetricView object. If you
- need to inspect other context, you should use the other overload of
- `MakeValidationRule`
-
-
+
- Create a validation rule for the root MetricView object
+ An error that comes from ANTLR's parse of the grammar
- name of the rule
- category for the rule (you can use any text)
- the message returned in the error if the object is invalid
- a predicate function to determine if the object is invalid
- a validation rule for use in a validator
-
+
+
+
+
+
+
+
- Create a validation rule for MetricViewJoin objects
+ The token that caused the parse failure.
- name of the rule
- category for the rule (you can use any text)
-
- the message returned in the error if the MetricViewJoin is invalid
-
-
- a predicate function to determine if the MetricViewJoin is invalid
-
- a validation rule for use in a validator
-
+
- Create a validation rule for MetricViewDimension objects
+ A semantic error from our visit and interpretation of metric view
+ logic
- name of the rule
- category for the rule (you can use any text)
-
- the message returned in the error if the MetricViewDimension is invalid
-
-
- a predicate function to determine if the MetricViewDimension is invalid
-
- a validation rule for use in a validator
+
+
-
+
- Create a validation rule for MetricViewMeasure objects
+ A semantic error from our visit and interpretation of metric view
+ logic
- name of the rule
- category for the rule (you can use any text)
-
- the message returned in the error if the MetricViewMeasure is invalid
-
-
- a predicate function to determine if the MetricViewMeasure is invalid
-
- a validation rule for use in a validator
+
+
+
+
+
+
+
+
-
+
- Converts a Databricks MetricView to a Tabular Model.
+ Result of parsing an expression string into an AST.
+ Always contains an expression (ANTLR recovers on errors).
+ Errors, if any, indicate where recovery occurred.
-
- The target TOM model to populate with tables, columns, measures,
- and relationships
-
- The source MetricView to convert
- Databricks host name for connection
- Databricks HTTP path for connection
-
- A list of diagnostic messages indicating details of partial or full
- failues. May be populated even when the method returns true and
- does create a TOM model.
-
-
- if true, abort on validation errors before creating any TOM objects
-
-
-
-
+
- Represents a dimension definition in a Databricks Metric View
+ Result of parsing an expression string into an AST.
+ Always contains an expression (ANTLR recovers on errors).
+ Errors, if any, indicate where recovery occurred.
-
- A dimension in a Metric View is a single field. There is no namespacing
- or delineation of separate named collections of fields.
-
-
+
- The YAML name for the dimension field
+ AST node for a Databricks SQL expression. All variants carry a
+ covering their extent in the original source.
-
+
- The YAML string representing the expression for this dimension,
- either a field reference or scalar SQL expression.
+ AST node for a Databricks SQL expression. All variants carry a
+ covering their extent in the original source.
-
+
- Lightweight value representation of a single column reference within a
- Metric View expression. The parser populates only
- when a single (non‑backticked) dot qualification is present (or when a
- backticked token acts as table side). For undotted identifiers (or
- identifiers whose dot is inside backticks) is the
- empty string. Formatting policy is intentionally minimal: only quote
- when required.
+ All direct children of the SqlExpression node.
-
- Optional table/alias portion (empty string if not present or not applicable).
-
-
- The logical column identifier (never null; empty only for a
- default-initialized value).
-
-
+
- Lightweight value representation of a single column reference within a
- Metric View expression. The parser populates only
- when a single (non‑backticked) dot qualification is present (or when a
- backticked token acts as table side). For undotted identifiers (or
- identifiers whose dot is inside backticks) is the
- empty string. Formatting policy is intentionally minimal: only quote
- when required.
+ Double-dispatch hook. Each concrete subtype calls
+ visitor.Visit(this), routing to the visitor overload that
+ accepts that specific shape. Implementors should never call
+ Accept directly; use Visit(node) on the visitor
+ instead, which routes through the base
+ Visit(SqlExpression) dispatcher.
-
- Optional table/alias portion (empty string if not present or not applicable).
-
-
- The logical column identifier (never null; empty only for a
- default-initialized value).
-
-
+
+
+ Collect this node and all descendants in left-to-right DFS order.
+
+
+
+
+ All descendants (excluding self) in left-to-right DFS order.
+
+
+
+
+ A column reference in a Databricks SQL expression — either a bare
+ column name or a table-qualified column name.
+
+
+
+
+ A column reference in a Databricks SQL expression — either a bare
+ column name or a table-qualified column name.
+
+
+
+
+ A SQL column name, e.g. `field` in `SELECT field FROM aTable`.
+
+
+
+
+
+
+
+
+
+
+ A qualified SQL column name: one or more dotted qualifiers
+ preceding the column. A 2-part ref (t.field) carries a
+ single qualifier; a multi-part snowflake path (a.b.field)
+ carries the full chain. The leaf qualifier ()
+ is the column's immediate parent.
+
+
+
+
+ The dotted qualifiers preceding the column, in source order;
+ at least one. The last is the column's immediate parent.
+
+
+
+
+ The leaf qualifier — the column's immediate parent. For a
+ 2-part ref it is the only qualifier; for a multi-part path it
+ is the deepest one.
+
+
+
+ Convenience constructor for the common 2-part ref.
+
+
+
+
+
+
+
+
- Optional table/alias portion (empty string if not present or not applicable).
+ Case-insensitive equivalence check on the identifier values.
-
+
- The logical column identifier (never null; empty only for a
- default-initialized value).
+ Returns the table name for qualified refs, or
+ for unqualified refs. An unqualified column means different things depending
+ on where it appears in a metric view: in a field expression it refers to
+ the source table, while in a join ON clause it refers to the join table itself.
-
+
- Render the reference using minimal quoting rules consistent with
- the parser. Rules per side (table / column):
+ Render the reference using quoting rules as follows:
- If empty -> omitted (for table) or empty string for column.
- - Any token containing a dot is always backticked (avoids
- ambiguity and preserves original backticked literals like
- `orders.amount`).
+ - Any token containing a dot is always backticked (e.g. `a.b` is one part)
+ - Any token that is also a keyword is backticked, despite Databricks
+ allowing more permissive naming
- Bare identifier pattern [A-Za-z_][A-Za-z0-9_]* AND not a
reserved word -> emitted bare.
- - Otherwise wrapped in backticks (parser strips existing backticks
- so internal backticks not expected).
-
+
+
+ The argument content of a function call — either a list of
+ expressions or a wildcard (*).
+
+
+
+ Zero or more expression arguments.
+
+
+ Zero or more expression arguments.
+
+
+ Wildcard argument: *.
+
+
- Lightweight, heuristic parser for extracting column identifiers from
- Databricks Metric View expressions. Focused only on documented patterns
- (bare identifiers and backtick-delimited identifiers) and deliberately
- avoids full SQL parsing. Silent on malformed input, returning what can
- be confidently identified.
+ A function call: SUM(amount), COUNT(*),
+ COUNT(DISTINCT col1, col2), etc.
-
+
- Databricks reserved keywords that must be backtick-quoted to be
- part of an identifier.
+ A function call: SUM(amount), COUNT(*),
+ COUNT(DISTINCT col1, col2), etc.
-
+
+
+
+
+
+
+
- Attempt to determine if an expression is exactly a single column
- reference. Returns a structured
- (table + column). Supports:
- * Bare identifier (non-reserved)
- * Backticked identifier (any content except stray backticks)
- * Single dotted qualification outside backticks (table.column)
- with rules:
- - At most one dot outside backticks (multi-dot => throw
- )
- - No whitespace adjacent to the dot (spaced forms return false)
- - BOTH sides must be bare (non-reserved) or individually
- backticked. A bare reserved keyword is rejected on EITHER side;
- backticks required to treat it literally.
- * Entire expression backticked is treated as undotted column even
- if inner text contains dots
- All other forms return false (silent failure posture) except
- multi-dot which throws.
+ A MEASURE reference: MEASURE(measure_name). References
+ another measure by name within a measure expression.
+ is a
+ rather than a so the inner name does
+ not surface as a in descendant walks.
-
+
- Convenience wrapper over .
+ A MEASURE reference: MEASURE(measure_name). References
+ another measure by name within a measure expression.
+ is a
+ rather than a so the inner name does
+ not surface as a in descendant walks.
-
+
+
+
+
+
+
+
+ Binary operator: a + b, x AND y.
+
+
+ Binary operator: a + b, x AND y.
+
+
+
+
+
+
+
+
+ Unary operator: -a, NOT x.
+
+
+ Unary operator: -a, NOT x.
+
+
+
+
+
+
+
+
- Extract distinct structured column references (first-seen order,
- case-insensitive distinctness via linear scan). Dotted
- (table.column) pairs are produced only when syntactically valid with
- a single dot outside backticks and no whitespace adjacency.
- Multi-dot contiguous sequences (a.b.c or variants mixing
- backticked segments) throw .
- Spaced-dot patterns yield separate undotted identifiers. Backticked
- whole tokens with internal dots may still act as table side when
- followed immediately by ".identifier" (e.g.
- `orders.amount`.field -> table:"orders.amount", column:"field"). If
- a backticked left side is followed by a bare reserved right side
- (e.g. `orders`.CASE) both sides are skipped (zero references) to
- avoid surfacing an unusable partial reference. Bare left reserved
- (CASE.amount) is ignored and the right side is surfaced undotted.
- Bare reserved right (orders.CASE) causes only the left side to be
- surfaced undotted. Backticked right sides always pass regardless of
- reserved status. Function heads (identifier immediately followed
- by '(') are excluded.
+ CASE expression. Two forms share and
+ on the base.
-
+
- Extract distinct structured column references with their source positions
- (first-seen order, case-insensitive distinctness via linear scan).
- Returns position information for each reference, enabling delimiter-aware parsing.
+ CASE expression. Two forms share and
+ on the base.
-
- Position spans include the entire reference from start to end, including:
- - Backticks (if present)
- - Table qualification and dot (if present)
- - Column name
- Follows the same parsing rules as .
-
-
+
+ Searched: CASE WHEN cond THEN result ... END.
+
+
+ Searched: CASE WHEN cond THEN result ... END.
+
+
+
+
+
+
+
+
+ Simple: CASE expr WHEN value THEN result ... END.
+
+
+ Simple: CASE expr WHEN value THEN result ... END.
+
+
+
+
+
+
+
+
+ Parenthesized expression: (expr).
+
+
+ Parenthesized expression: (expr).
+
+
+
+
+
+
+
+
- Parse one side of a potential dotted identifier (used only by
- single-column detection). Bare reserved words are rejected on
- BOTH sides; backticks required to treat them literally.
+ Literal value. Abstract intermediate; each concrete subtype carries
+ the typed payload extracted by the parser visitor — so consumers
+ don't have to re-parse the span text.
-
+
- Remove all block (`/* ... */`) and line (`-- ...\n`) comments from
- expr. Handles nested comments and normalizes line endings to `\n`.
+ Literal value. Abstract intermediate; each concrete subtype carries
+ the typed payload extracted by the parser visitor — so consumers
+ don't have to re-parse the span text.
- Databricks SQL expression
-
- A string with all comments removed, with '\n' line endings, and all
- leading and trailing whitespace removed (this leading and trailing
- space is trimmed after comment removal). Leading whitespace on an
- individual line is not removed.
-
-
+
+
+
+
+ String literal — payload with quote-escaping already resolved.
+
+
+ String literal — payload with quote-escaping already resolved.
+
+
+
+
+
- Represents the position and length of a column reference in source text.
- Used for delimiter-aware parsing and error reporting.
+ Numeric literal. Covers DECIMAL, FLOAT, and REAL grammar
+ productions; the source-level kind difference doesn't survive
+ into the AST.
-
+
- Zero-based index where the column reference starts in the source string.
+ Numeric literal. Covers DECIMAL, FLOAT, and REAL grammar
+ productions; the source-level kind difference doesn't survive
+ into the AST.
-
+
+
+
+
+ Boolean literal — TRUE or FALSE.
+
+
+ Boolean literal — TRUE or FALSE.
+
+
+
+
+
+ Null literal — NULL.
+
+
+ Null literal — NULL.
+
+
+
+
+
- Length of the column reference in characters, including any backticks or qualifiers.
+ Fallback for parse errors or unrecognized constructs. May wrap
+ structurally-recognized subtrees that were preserved while the
+ surrounding rule itself was not understood.
-
+
- Zero-based index of the character after the last character of the reference.
+ Fallback for parse errors or unrecognized constructs. May wrap
+ structurally-recognized subtrees that were preserved while the
+ surrounding rule itself was not understood.
-
+
+ Terminal-Unknown convenience: no preserved subtrees.
+
+
+
+
+
+
+
+
- Checks if a given position falls within this span.
+ Recognized-invalid construct with a specific diagnostic.
+ Unlike , this means we matched a known-bad
+ pattern and can describe the problem precisely.
- Zero-based character position to check
- True if position is within [Start, End), false otherwise
-
+
- Creates a new span with the given start position and length.
+ Recognized-invalid construct with a specific diagnostic.
+ Unlike , this means we matched a known-bad
+ pattern and can describe the problem precisely.
- Zero-based start position
- Length in characters
-
- Thrown when start or length is negative
-
-
+
+
+
+
- A column reference with associated source position information.
- Used when you need both the parsed reference and its location in source text.
+ Default base for
+ implementations that want the standard abort-and-fallback semantics:
+ unimplemented Visit overloads throw
+ , and the outermost emit catches
+ once at the root and invokes .
+
+ New-visitor minimum viable shape: derive, override
+ , ship. Override per-shape Visit
+ overloads incrementally for the constructs the visitor knows how
+ to translate; everything else falls through to the abort and
+ then to at the root.
+
+
+ Recursive code in concrete overloads should call
+ Visit(child), not child.Accept(this) — the
+ override routes through
+ Accept, keeping the dispatch detail in one place. An
+ raised from any nested
+ call propagates freely; do not catch it inside a Visit overload.
+
-
+
+
+
+
- The parsed column reference (table name and column name).
+ Polymorphic-dispatch entry. Routes through the node's
+ to the matching
+ concrete-typed Visit overload.
-
+
- The position and length of this reference in the source text.
+ Default abort. Overridden by derived classes that can translate
+ this construct structurally; otherwise the emit is unwound to the
+ root and takes over.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- The table name (may be empty for unqualified references).
+ Run the visitor over , catching any
+ raised at any depth and
+ returning instead. The single place where
+ the abort signal is consumed — concrete Visit overloads should
+ propagate, not catch.
-
+
- The column name.
+ An identifier in Databricks SQL — bare or backtick-quoted.
+ Wraps a and provides clean access to
+ the identifier value without quoting characters.
-
+
- Whether this is a qualified reference (table.column).
+ An identifier in Databricks SQL — bare or backtick-quoted.
+ Wraps a and provides clean access to
+ the identifier value without quoting characters.
-
+
- Zero-based start position in source text.
+ The identifier text with backtick quoting removed if present.
-
+
- Length in characters.
+ True if the identifier was backtick-quoted in the source.
-
+
- Zero-based end position (exclusive).
+ A slice of original expression text. Start is inclusive, End is
+ exclusive. Carries a reference to the source so it is self-contained.
-
+
- Creates a new reference with position information.
+ The raw text of this span in the original source.
- The parsed column reference
- The position span in source text
-
+
- Creates a new reference with position information.
+ Extension members for ANTLR tokens to support keyword-as-identifier handling.
- The parsed column reference
- Zero-based start position
- Length in characters
+
+ Databricks does not enforce reserved keywords by default, so keywords
+ like KEY, TABLE, SCHEMA can appear as identifiers in dotted-name contexts.
+ See: https://docs.databricks.com/aws/en/sql/language-manual/sql-ref-identifiers
+
-
+
- Checks if a given position falls within this reference's span.
+ All keyword strings from the lexer grammar, case-insensitive.
+ Derived from the vocabulary at startup — no manual maintenance.
+ Used by formatting logic to decide whether a bare identifier
+ needs backtick quoting.
- Zero-based character position
- True if position is within this span, false otherwise
-
+
+
+
+
+
+
+
- Converts to SQL syntax (ignores position information).
+ True if the token is an identifier or a keyword that can serve
+ as an unquoted identifier in Databricks SQL.
- SQL representation of the column reference
-
+
- Represents the semantic analysis of a Databricks Metric View dimension.
- Contains information about whether the dimension is a simple field reference
- or a derived expression, along with field references and target table determination.
+ Returns the token's text with backtick quoting removed if present.
-
-
- This is a discriminated union represented through inheritance.
- Use pattern matching to determine whether the dimension is simple or derived,
- then access the appropriate properties.
-
-
- A simple dimension is one that directly references a single column from
- the source or a joined table. A derived dimension contains a complex
- expression that must be represented as a calculated column in the target.
-
-
-
+
- The name of the dimension as it appears in the Metric View.
+ A condition/result pair inside a SQL CASE expression.
-
+
- The complete expression string from the dimension.
+ A condition/result pair inside a SQL CASE expression.
-
+
- Analysis result for a simple dimension that directly references a column.
+ This class provides an empty implementation of ,
+ which can be extended to create a visitor which only needs to handle a subset
+ of the available methods.
+ The return type of the visit operation.
-
+
- The single field reference that this dimension maps to.
+ Visit a parse tree produced by .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- Analysis result for a derived dimension with a complex expression
- that must be represented as a calculated column.
+ Visit a parse tree produced by the orExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- All column references found in the dimension expression.
+ Visit a parse tree produced by the columnRefExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- The target table for the derived field.
- This is determined by the source of the referenced fields:
- - If all fields are from a single dimension, the derived field goes on that dimension
- - If fields are from multiple tables or the source, the derived field goes on the fact
+ Visit a parse tree produced by the measureRefExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- Represents the target table for a derived field.
+ Visit a parse tree produced by the parenExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- The derived field should be placed on the fact table.
+ Visit a parse tree produced by the searchedCaseExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- The derived field should be placed on a specific dimension table.
+ Visit a parse tree produced by the concatExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- The name of the dimension (join alias) where the derived field belongs.
+ Visit a parse tree produced by the simpleCaseExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- Extension methods for analyzing and converting Databricks Metric View dimensions.
+ Visit a parse tree produced by the notExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- Analyzes a dimension expression to determine if it's a simple field reference
- or a complex derived expression, and identifies the target table.
+ Visit a parse tree produced by the unaryMinusExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
- The Metric View dimension to analyze
-
- A DimensionAnalysis indicating whether the dimension is simple or derived,
- with appropriate field references and target table information.
-
+ The parse tree.
+ The visitor result.
-
+
- Determines the target table for a derived field based on the tables
- referenced by its constituent fields.
+ Visit a parse tree produced by the addExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
- The column references from the expression
-
- A DerivedFieldTarget indicating whether the field should go on the fact
- or a specific dimension table.
-
-
- Target determination rules:
-
- - All fields from source/empty table -> Fact
- - All fields from a single dimension -> that Dimension
- - Fields from multiple dimensions -> Fact
- - Mix of source and dimension fields -> Fact
-
-
+ The parse tree.
+ The visitor result.
-
+
- Parses join fields from MetricViewJoin. Handles 'Using' and 'On'.
- Returns (factFieldKey, dimensionFieldKey) tuple or null if parsing fails.
+ Visit a parse tree produced by the literalExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- Extracts LHS and RHS from an equality join expression
+ Visit a parse tree produced by the compExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
-
-
-
- We do not handle inequality joins or fields with spaces in their names.
- We expect fully qualified names on both sides.
- See: https://docs.databricks.com/aws/en/metric-views/yaml-ref#joins
-
+ The parse tree.
+ The visitor result.
-
+
- Creates a SourceFragment for a join's dimension source
+ Visit a parse tree produced by the functionCallExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
-
- Pattern:
- ^\\s*(?<table1>\\w+)\\.(?<field1>\\w+)\\s*=\\s*(?<table2>\\w+)\\.(?<field2>\\w+)\\s*$
- Explanation:
-
- ○ Match if at the beginning of the string.
- ○ Match a whitespace character atomically any number of times.
- ○ "table1" capture group.
- ○ Match a word character atomically at least once.
- ○ Match '.'.
- ○ "field1" capture group.
- ○ Match a word character atomically at least once.
- ○ Match a whitespace character atomically any number of times.
- ○ Match '='.
- ○ Match a whitespace character atomically any number of times.
- ○ "table2" capture group.
- ○ Match a word character atomically at least once.
- ○ Match '.'.
- ○ "field2" capture group.
- ○ Match a word character atomically at least once.
- ○ Match a whitespace character greedily any number of times.
- ○ Match if at the end of the string or if before an ending newline.
-
-
+
+
+ Visit a parse tree produced by the mulExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+
+ The parse tree.
+ The visitor result.
-
+
- Represents the semantic analysis of a Databricks Metric View measure.
- Contains information about the measure's type, aggregation function,
- and field references extracted from the expression.
+ Visit a parse tree produced by the unaryPlusExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
-
-
- This is a discriminated union represented through inheritance.
- Use pattern matching or type checks to determine whether the measure
- is simple or calculated, then access the appropriate properties.
-
-
- A simple measure is one that can be translated to a basic aggregation in the
- target platform. It must:
-
-
- - Use a supported aggregation function (SUM, COUNT, MIN, MAX, AVG, COUNT DISTINCT)
- - Reference exactly one field
- - Have no complex expressions (arithmetic, nested functions, etc.)
-
-
- Calculated measures contain more complex expressions that cannot be automatically
- translated and must be handled platform-specifically.
-
-
+ The parse tree.
+ The visitor result.
-
+
- The name of the measure as it appears in the Metric View.
+ Visit a parse tree produced by the andExpr
+ labeled alternative in .
+
+ The default implementation returns the result of calling
+ on .
+
+ The parse tree.
+ The visitor result.
-
+
- The complete expression string from the measure.
+ Visit a parse tree produced by .
+
+ The default implementation returns the result of calling