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
- Run `cargo test -p dbt-adapter diff` and compare the Err detail from compare_sql to see the canonicalized forms that diverged
- 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)
- Check recent changes to compare_sql / compare_sql_structurally (diff.rs:32, diff.rs:1418) for order-dependent normalization and restore symmetry
- 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
- Always run canonicalization symmetrically on both sides before diffing
- Add round-trip tests: compare_sql(a,b) and compare_sql(b,a) must both pass
- Keep wrap-parentheses stripping in a single shared normalization step
- Never .expect() on AdapterResult in production code; propagate the error
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
- STRUCT field order drift should be ignored
- Forward-fill projection column order drift should be ignored
- projection order drift should be ignored
- projection order drift should be ignored even with apostroph
- should treat persisted view vs temp view as equivalent
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/ed48c33e88d05a8b.
Report an issue: GitHub.