Table of Contents

Validate a Metric View with Default Rules

This how-to demonstrates how to validate a loaded Metric View using the built-in validation rules and interpret the diagnostic messages.

Default validation rules

The Semantic Bridge includes these built-in validation rules:

Rule Description
JoinNameRequired Metric View Join must have a name
UniqueJoinName Metric View Join names must be unique
JoinSourceRequired Metric View Join must have a source
JoinOnOrUsingRequired Metric View Join must specify either on or using
JoinOnOrUsingExclusivity Metric View Join cannot specify both on and using
JoinOnFormat Metric View Join on clause must be a valid equijoin expression
JoinUsingColumnCount Metric View Join using clause must have exactly one column (MVP limitation)
DimensionNameRequired Metric View Dimension must have a name
UniqueDimensionName Metric View Dimension names must be unique
DimensionExprRequired Metric View Dimension must have an expression
MeasureNameRequired Metric View Measure must have a name
UniqueMeasureName Metric View Measure names must be unique
MeasureExprRequired Metric View Measure must have an expression

Run validation with default rules

Call Validate() with no arguments to use the built-in validation rules.

var diagnostics = SemanticBridge.MetricView.Validate().ToList();

Output($"Validation complete: {diagnostics.Count} issue(s) found");

Interpret diagnostic messages

Each diagnostic message contains:

  • Severity: Error, Warning, or Information
  • Message: Description of the issue
  • Path: Location of the object in the Metric View hierarchy
var diagnostics = SemanticBridge.MetricView.Validate().ToList();

var sb = new System.Text.StringBuilder();
sb.AppendLine("VALIDATION RESULTS");
sb.AppendLine("------------------");
sb.AppendLine("");

if (diagnostics.Count == 0)
{
    sb.AppendLine("No issues found.");
}
else
{
    foreach (var diag in diagnostics)
    {
        sb.AppendLine($"[{diag.Severity}] {diag.Message}");
        sb.AppendLine($"  Path: {diag.Path}");
        sb.AppendLine("");
    }
}

Output(sb.ToString());

Example with validation errors

Some rules (required fields) are enforced during deserialization. The remaining rules check for duplicates and structural issues after deserialization.

This Metric View demonstrates violations that are caught by Validate():

SemanticBridge.MetricView.Deserialize("""
    version: 0.1
    source: sales.fact.orders
    joins:
      # UniqueJoinName - duplicate name 'customer'
      - name: customer
        source: sales.dim.customer
        on: customer_id = customer.customer_id
      - name: customer
        source: sales.dim.customer_backup
        on: customer_id = customer_backup.customer_id
      # JoinOnOrUsingRequired - neither on nor using
      - name: date
        source: sales.dim.date
    dimensions:
      # UniqueDimensionName - duplicate name 'category'
      - name: category
        expr: product.category
      - name: category
        expr: product.subcategory
      - name: product_name
        expr: product.product_name
    measures:
      # UniqueMeasureName - duplicate name 'total'
      - name: total
        expr: SUM(revenue)
      - name: total
        expr: SUM(quantity)
      - name: order_count
        expr: COUNT(order_id)
    """);

var diagnostics = SemanticBridge.MetricView.Validate().ToList();

var sb = new System.Text.StringBuilder();
sb.AppendLine($"Found {diagnostics.Count} issue(s):");
sb.AppendLine("");

foreach (var diag in diagnostics)
{
    sb.AppendLine($"[{diag.Severity}] {diag.Message}");
}

Output(sb.ToString());

Output:

Found 6 issue(s):

[Error] Join 'customer' must use a simple equality condition with table prefixes (e.g. 'source.column = dimension.column')
[Error] Duplicate join name: 'customer'
[Error] Join 'customer' must use a simple equality condition with table prefixes (e.g. 'source.column = dimension.column')
[Error] Join 'date' must specify either 'on' or 'using' clause
[Error] Duplicate dimension name: 'category'
[Error] Duplicate measure name: 'total'

Filter diagnostics by severity

You can filter diagnostics to focus on errors only:

using System.Linq;
using TabularEditor.SemanticBridge.Orchestration;

var diagnostics = SemanticBridge.MetricView.Validate().ToList();
var errors = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error).ToList();

var sb = new System.Text.StringBuilder();
sb.AppendLine($"Errors: {errors.Count}");
sb.AppendLine($"Total issues: {diagnostics.Count}");
Output(sb.ToString());

Next steps

See also