Support
Log In

Migrate from Snowflake Semantic Views

Convert your Snowflake semantic views into governed Malloy semantic models

Snowflake semantic views and Malloy are close cousins — both are dimension, measure, and relationship graphs over SQL tables. That makes this one of the cleanest migrations: Credible reads your semantic view definition, maps it almost concept-for-concept to Malloy, and — where you connect it — validates against Snowflake's own verified queries.

What Credible Reads

Your native SEMANTIC VIEW objects — logical tables, relationships, facts, dimensions, and metrics — or any legacy Cortex Analyst YAML models. The agent works from the exported definition (the CREATE SEMANTIC VIEW DDL or the YAML). Connecting to Snowflake — via SQL (DESCRIBE SEMANTIC VIEW, SHOW SEMANTIC VIEWS) or the Snowflake-managed MCP server (Cortex) — is optional: it lets the agent read views in place and run parity queries under Snowflake's own RBAC.

What Comes Across

The everyday modeling carries over. Here's how the bigger pieces land — and where they get better:

In SnowflakeIn Credible
Semantic view: logical tables & relationshipsMalloy sources and joins
Dimensions, facts, metricsDimensions, row-level facts, and measures — facts feed measures, so you can re-aggregate at any grain
WITH SYNONYMS / COMMENT#(doc) / #(index), indexed by the AI Analytics Engine
Verified queriesParity fixtures and named views
PUBLIC / PRIVATE, RBACFine-grained access control in the model, versioned and enforced on every surface
Cortex Analyst / BI on topEvery surface — agents over MCP, data apps, notebooks, dashboards, APIs

The Migration Flow

Credible reads the semantic view definition, translates logical tables and relationships to sources and joins (facts to row-level dimensions, metrics to measures), enriches with #(doc)/#(index) tags seeded from synonyms and comments, and — where you connect it — validates against Snowflake.

What Credible Handles

  • Two coexisting formats — a deployment may use native SEMANTIC VIEW objects, legacy Cortex Analyst YAML on a stage, or both. Credible detects which and reads each accordingly.
  • Facts vs. metrics — a fact is a row-level expression; a metric is its aggregation. Credible keeps them distinct (fact → row-level dimension, metric → measure) so you can still re-aggregate at different grains. Collapsing them would lose that.
  • Verified queries are the best thing to validate against — Credible replays each question→SQL pair and diffs the result against the migrated Malloy. (Verified SQL references logical names, not physical tables.)

Before & After

A CREATE SEMANTIC VIEW statement:

CREATE OR REPLACE SEMANTIC VIEW sales.sales_analytics
  TABLES (
    orders AS sales.orders PRIMARY KEY (order_id)
      WITH SYNONYMS = ('purchase_orders')
      COMMENT = 'Order transactions at the order grain',
    customers AS sales.customers PRIMARY KEY (customer_id)
  )
  RELATIONSHIPS (
    orders_to_customers AS orders (customer_id) REFERENCES customers (customer_id)
  )
  FACTS (
    orders.line_amount AS orders.amount COMMENT = 'Per-row order amount in USD',
    PRIVATE orders.is_shipped AS CASE WHEN orders.status = 'shipped' THEN 1 ELSE 0 END
  )
  DIMENSIONS (
    orders.order_date AS CAST(orders.created_at AS DATE)
      COMMENT = 'Date the order was placed',
    customers.region AS customers.geographic_region
  )
  METRICS (
    orders.total_revenue AS SUM(orders.line_amount) COMMENT = 'Total revenue in USD',
    orders.shipped_revenue AS SUM(orders.line_amount * orders.is_shipped),
    orders.shipped_revenue_pct AS
      SUM(orders.line_amount * orders.is_shipped) / SUM(orders.line_amount)
  );
source: orders is conn.table('sales.orders') extend {
  primary_key: order_id
  join_one: customers is conn.table('sales.customers') on customer_id

  dimension:
    #(doc) Date the order was placed. Also known as: order_day
    order_date is created_at::date

    #(doc) Per-row order amount in USD (fact)
    line_amount is amount

    #(doc) Row-level shipped flag (fact)
    is_shipped is pick 1 when status = 'shipped' else 0

  measure:
    #(doc) Total revenue in USD
    # currency
    total_revenue is sum(line_amount)

    #(doc) Revenue from shipped orders
    # currency
    shipped_revenue is sum(line_amount) { where: status = 'shipped' }

    #(doc) Share of revenue that shipped
    # percent
    shipped_revenue_pct is shipped_revenue / total_revenue
}

FACTS become row-level dimensions that feed measures; METRICS become measures. WITH SYNONYMS and COMMENT fold into #(doc) (Malloy has no synonym primitive, so alternate names go in the description for retrieval), and PRIVATE facts map to access modifiers so they feed measures without being independently queryable.

More than a reformat. Semantic views map almost 1:1, so the gain is what surrounds them — composable follow-up queries, AI Analytics Engine discovery, and one model that reaches agents, apps, and BI beyond Cortex. See what you gain →

Next Steps

On this page