dbt-labs/dbt-core · error

bare vs wrapped CREATE VIEW body should compare as equal (or

Error message

bare vs wrapped CREATE VIEW body should compare as equal (order-independent)

What it means

This is a Rust test panic: compare_sql(actual, expected, AdapterType) returned Err, so .expect("bare vs wrapped CREATE VIEW body should compare as equal (order-independent)") aborted the test. The library's SQL differ failed to canonicalize a bare CREATE VIEW body and a parenthesized one to the same form, so equivalent SQL is reported as a mismatch. The diff engine normalizes formatting/parenthesization before comparing, and this expectation failing means that normalization (or its direction-independence) regressed.

Source

Thrown at crates/dbt-adapter/src/sql/diff.rs:3449

        let result = compare_sql(sql1, sql2, AdapterType::Snowflake);
        assert!(
            result.is_err(),
            "Should detect content differences even with newlines"
        );
    }

    #[test]
    fn test_create_view_as_tolerates_asymmetric_wrapping_parens() {
        // `AS (<subquery>)` and `AS <subquery>` are always semantically identical. Some code
        // paths (e.g. dbt-core's hand-rolled `latest_version` pointer-view SQL) emit the bare
        // form while others always wrap the body in parens -- see fs#13705.
        let wrapped = "create or replace view db.sch.v as (\n    select * from db.sch.t\n  );";
        let bare = "create or replace view db.sch.v as select * from db.sch.t";

        compare_sql(wrapped, bare, AdapterType::Snowflake)
            .expect("wrapped vs bare CREATE VIEW body should compare as equal");
        compare_sql(bare, wrapped, AdapterType::Snowflake)
            .expect("bare vs wrapped CREATE VIEW body should compare as equal (order-independent)");
    }

    #[test]
    fn test_create_view_as_bare_form_still_detects_real_mismatches() {
        // Guard against over-relaxing: two bare (unwrapped) bodies that are actually different
        // must still be reported as a mismatch.
        let actual = "create or replace view db.sch.v as select * from db.sch.t1";
        let expected = "create or replace view db.sch.v as select * from db.sch.t2";

        assert!(
            compare_sql(actual, expected, AdapterType::Snowflake).is_err(),
            "genuinely different bare CREATE VIEW bodies must not compare as equal"
        );
    }

    #[test]
    fn test_bigquery_struct_field_order_drift_should_be_ignorable() {
        // Minimal repro for replay SQL mismatch when a query contains:

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Run `cargo test -p dbt-adapter diff` and compare the Err detail from compare_sql to see the canonicalized forms that diverged
  2. Fix the canonicalizer so the CREATE VIEW body's optional wrapping parentheses are stripped symmetrically (before comparing, normalize both sides with the same pipeline, not actual vs expected differently)
  3. Check recent changes to compare_sql / compare_sql_structurally (diff.rs:32, diff.rs:1418) for order-dependent normalization and restore symmetry
  4. If the mismatch is genuinely expected (real DDL difference), update the test SQL rather than loosening the canonicalizer

Example fix

// before
compare_sql(wrapped, bare, AdapterType::Snowflake)
    .expect("wrapped vs bare CREATE VIEW body should compare as equal");
// after (canonicalize identically on both sides inside the library)
let canon = |s: &str| normalize_create_view_body(canonicalize(s, AdapterType::Snowflake));
assert_eq!(canon(wrapped), canon(bare));
Defensive patterns

Strategy: validation

Validate before calling

// pre-check both sides canonicalize identically before calling the API
let a = canonicalize(wrapped, AdapterType::Snowflake);
let b = canonicalize(bare, AdapterType::Snowflake);
debug_assert_eq!(strip_view_parens(a), strip_view_parens(b), "CREATE VIEW bodies diverge");

Try / catch

// compare_sql returns AdapterResult; never .expect() in library paths
match compare_sql(wrapped, bare, AdapterType::Snowflake) {
    Ok(()) => {},
    Err(e) => log::warn!("view DDL diff: {e}"), // handle instead of panicking
}

Prevention

When it happens

Trigger: Running `cargo test -p dbt-adapter` in crates/dbt-adapter/src/sql/diff.rs and the test at diff.rs:3449 panics because compare_sql(wrapped, bare, AdapterType::Snowflake) yields Err: a `create or replace view ... as ( select ... )` body and the equivalent unparenthesized `... as select ...` are not being normalized to the same canonical text in one of the two argument orders.

Common situations: A change to the SQL canonicalizer (paren stripping, statement-body normalization, or comment/whitespace trimming) altered behavior only in one comparison direction; a new adapter canonicalization path bypasses the CREATE VIEW body unwrapping; recorded-vs-fusion SQL replay comparisons start flagging visually identical view DDL as drifted.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/ed48c33e88d05a8b. Report an issue: GitHub.