Skip to content

dbt Core 2.0: jaffle-shop validation #734

Closed

Description

@koletzilla

Sub-issue of #660. Found validating the official jaffle-shop project (ClickHouse profile) against dbt-core 2.0: dbt seed + dbt build work on dbt-clickhouse v1 but fail on v2. Root-causing the difference surfaced two previously untracked bugs (this issue) plus two already-tracked gaps (references at the bottom).

The headline: v2 could silently lose seed data while reporting success. Any statement the engine's SQL lexer cannot tokenize was dropped without executing and without any error — and the ClickHouse seed INSERT is such a statement whenever the CSV data contains a single quote. The generic silent drop is fixed on dbt-core main (merged, no public PR) and the ClickHouse-side half (lexer routing so ClickHouse SQL actually tokenizes, plus the unit-test fix) is merged in dbt-labs/dbt#16153: seed, run and build pass on main. The last seed-data gap (a ? in CSV data inserted doubled) is closed by dbt-labs/dbt#16156 (row below).

Status legend: ✅ implemented — merged and working on dbt-core 2.0 origin/main · 🟡 partial — partly working on origin/main; Notes say what works vs what fails · 🚧 in progress — implemented in an open PR (linked in Notes) · 🔴 not started — not working on origin/main · Combined status "A-🚧->B": the feature is at A on origin/main today; an open PR is driving it to B (🟡 partially working / ✅ fully working)

Feature Subfeatures / details Status Notes (PR)
jaffle-shop runs end-to-end on v2 (overall) ✅ seed, run and build pass on main (the 2 unit tests run since dbt-labs/dbt#16153, #710; seed CSV values containing ? load byte-exact since dbt-labs/dbt#16156)
Engine drops unlexable statements as silent success Adapter-agnostic dbt-core-v2 bug, upstream of any driver: execute_inner splits SQL via a dialect lexer (dialect_of has no ClickHouse arm → Trino fallback); on an unlexable token the splitter kept only the clean prefix, and an empty statement list returned Ok — the query was never sent, no error, no warning ✅ Merged on dbt-core main (no public PR; resolves the engine half of this issue): the splitter retains the unlexable remainder as the final statement, so it reaches the server and fails loudly — silent success is no longer possible (regression test test_split_unpaired_token_retains_partial_trailing; TestEscapeSingleQuotesBackslash passes on plain main). The remainder is passed through UNSPLIT — correct splitting of ClickHouse SQL with backslash escapes is the row below
Seed rows silently lost when CSV data contains ' clickhouse__load_csv_rows escapes ' as \' (valid for the ClickHouse server); the engine's statement splitter has no ClickHouse dialect and falls back to the Trino lexer, which only understands '' doubling → the string looks unterminated → the whole INSERT is dropped before reaching the driver, and the seed reports success with 0 rows ✅ Merged: the data loss is gone on main (engine row above) — the seed INSERT, \' and all, reaches the server as a single retained statement, and the server accepts ClickHouse backslash escapes; dbt-labs/dbt#16153 routes ClickHouse to a lexer that tokenizes its escapes, so multi-statement ClickHouse SQL containing backslash escapes is split correctly as well (seed.sql keeps v1's \' escaping). The deferred return to v1's FORMAT CSV macro (#731) does NOT fix this by itself: raw CSV payload is even less lexable (bare ', ; in data)
Seed values containing ? are inserted doubled clickhouse__load_csv_rows escapes ? as ?? because the 0.1.0 ADBC driver treated any literal ? as a bind param; driver 0.1.1 sends SQL verbatim and no longer unescapes ??, so the doubled ?? now reaches the server as data ✅ Driver 0.1.1 (adbc_clickhouse#53) via dbt-labs/dbt#16185 sends a literal ? verbatim, and dbt-labs/dbt#16156 retired seed.sql's ?? escape: ? in seed CSV data loads byte-exact, as in v1. The \x3F escapes elsewhere are server-side string escapes and were never affected

Tracking note: the two seed data bugs above (' loss, ? doubling) are deliberately tracked HERE and not in the seed materialization issue (#709, closed) — an exception to the one-canonical-row rule. #709 stays as-is; both are fixed on main.

Repro

Seed data loss (no longer reproduces on main; kept so the original symptom is recognisable):

# raw_products.csv contains "kevin parker's favorite!"
dbt seed --full-refresh --vars '{"load_source_data": true}'   # reported Succeeded
# raw.raw_products had 0 rows (v1: 10); no INSERT appeared in debug logs

Minimal case was: any seed CSV with a ' in a string value → table created, 0 rows, exit 0. Downstream symptom that exposed it: dbt_utils_expression_is_true_orders_order_items_subtotal_subtotal failed with 61,465 bad rows (order items joined against the empty products table lose their prices).

# build failure (no longer reproduces on `main`; tracked in #710)
dbt build
#     Failed [  0.04s] unit_test default_dbt_test__audit.test_supply_costs_sum_correctly (models/marts/order_items.yml:126:11)
#     Failed [  0.58s] unit_test default_dbt_test__audit.test_does_location_opened_at_trunc_to_date (models/staging/stg_locations.yml:12:11)
# [error] [InvalidConfig (dbt1005)]: Invalid column name(s): 'order_id', 'product_id', 'supply_cost' in row 1 of unit test fixture for expected output. Accepted columns for expected output are: []
# [error] [InvalidConfig (dbt1005)]: Invalid column name(s): 'location_id', 'location_name', 'opened_date', 'tax_rate' in row 1 of unit test fixture for expected output. Accepted columns for expected output are: []
# → 20 downstream nodes skipped (stg_locations, locations, order_items, orders, customers + their tests)
# Summary: 43 total | 21 success | 2 error | 20 skipped

Related findings already tracked elsewhere

Activity

  1. changed the title [-]dbt Core 2.0: silent SQL statement drops — seed data loss with quotes in CSV data (jaffle-shop validation)[/-] [+]dbt Core 2.0: jaffle-shop validation[/+] on Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions