dbt-labs/dbt-core · error

projection order drift should be ignored

Error message

projection order drift should be ignored

What it means

Test panic from .expect at crates/dbt-adapter/src/sql/diff.rs:3559: compare_sql(actual_sql, expected_sql, AdapterType::Bigquery) returned Err even though the two BigQuery queries differ only in the order of projected columns. The differ's order-independent projection matching is expected to absorb this drift so generated and recorded SQL compare as equal.

Source

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

        let expected_sql = format!(
            "select {} from t",
            expected_alias_order
                .iter()
                .map(|a| projection_for(a))
                .collect::<Vec<_>>()
                .join(", ")
        );
        let actual_sql = format!(
            "select {} from t",
            actual_alias_order
                .iter()
                .map(|a| projection_for(a))
                .collect::<Vec<_>>()
                .join(", ")
        );

        compare_sql(&actual_sql, &expected_sql, AdapterType::Bigquery)
            .expect("projection order drift should be ignored");
    }

    #[test]
    fn test_bigquery_struct_projection_order_drift_with_comment_apostrophe_should_be_ignorable() {
        // Minimal repro for the *ordering-only* Snowplow SQL mismatch observed in replay:
        //
        // Some Jinja/adapter code paths build a list of `STRUCT(...) AS <context_alias>` projections
        // by iterating a map. Different runners/recorders may emit identical projections in
        // different orders (e.g. insertion-order vs key-sorted iteration). We treat this drift as
        // ignorable for replay via canonicalization.
        //
        // This variant includes a `--` comment containing an apostrophe (e.g. "hasn't"), which
        // appears in the real project SQL. Replay should still treat projection ordering drift as
        // ignorable.
        let expected_alias_order = [
            "service_configuration_context",
            "modal_entity",
            "experiment_entity",

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Read the Err message from compare_sql to identify the first diverging canonical projection
  2. Ensure the alias-based projection ordering normalization runs for AdapterType::Bigquery (it may only be wired for Snowflake)
  3. Fix alias extraction so reordered projections with identical alias->expression maps canonicalize identically
  4. If order is semantically required (e.g. SELECT * replacement), correct the SQL generator instead

Example fix

// before
compare_sql(&actual_sql, &expected_sql, AdapterType::Bigquery)
    .expect("projection order drift should be ignored");
// after (library-side: canonicalize projections as alias-keyed maps)
let norm = |s: &str| sort_projections_by_alias(canonicalize(s, AdapterType::Bigquery));
assert_eq!(norm(&actual_sql), norm(&expected_sql));
Defensive patterns

Strategy: validation

Validate before calling

let aliases_a: BTreeSet<&str> = extract_aliases(actual_sql).collect();
let aliases_b: BTreeSet<&str> = extract_aliases(expected_sql).collect();
if aliases_a != aliases_b { panic!("aliases differ; diff will legitimately fail"); }

Try / catch

match compare_sql(&actual_sql, &expected_sql, AdapterType::Bigquery) {
    Ok(()) => {},
    Err(e) => eprintln!("projection drift is real: {e}"),
}

Prevention

When it happens

Trigger: cargo test -p dbt-adapter with test at diff.rs:3559: queries built from the same alias list via projection_for(a).collect::<Vec<_>>().join(", ") in two different orders compare unequal under AdapterType::Bigquery, panicking the expect.

Common situations: BigQuery model compilation changes SELECT item order; the canonicalizer's projection reordering path is BigQuery-gated and was broken or not applied; replay comparisons between Mantle-generated SQL and recorded Fusion SQL start failing on pure ordering.

Related errors


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