Skip to content

Commit 4a28ba0

Browse files
committed
Add DuckDB data diff e2e coverage
1 parent 5dafa60 commit 4a28ba0

3 files changed

Lines changed: 101 additions & 17 deletions

File tree

‎docs/internal/2026-06-08-dbt-pr-review-self-improvement-loop.md‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,43 @@ Implemented result:
285285
- Real-world corpus floor preserved: 15/15 bad cases caught, 0/5 false
286286
positives.
287287

288+
## Current Acceptance Checkpoint
289+
290+
Demo matrix with local core, base artifacts in `target-base`, head artifacts in
291+
`target`, and AI disabled:
292+
293+
| Branch | Expected | Actual | Deterministic evidence |
294+
|---|---:|---:|---|
295+
| `demo/safe-refactor` | `APPROVE` | `APPROVE` | no findings |
296+
| `demo/join-key-breakage` | `REQUEST_CHANGES` | `REQUEST_CHANGES` | `altimate_core.structural_diff:SC010`, core equivalence |
297+
| `demo/test-removal` | `COMMENT` | `COMMENT` | `dbt-patterns:removed_tests` |
298+
| `demo/new-pii-exposure` | `REQUEST_CHANGES` | `REQUEST_CHANGES` | `altimate_core.classify_pii`, core equivalence |
299+
| `demo/mart-select-star` | `COMMENT` | `COMMENT` | core equivalence warning |
300+
| `demo/incremental-without-guard` | `COMMENT` | `COMMENT` | core dbt config lint + deterministic catalog cost notes |
301+
302+
DuckDB e2e proof:
303+
304+
- Branch: `demo/join-key-breakage`.
305+
- `dbt build --profiles-dir . --target dev`: passed `PASS=14 WARN=0 ERROR=0`.
306+
- Reviewer: `REQUEST_CHANGES` with critical `join_risk` from
307+
`altimate_core.structural_diff` rule `join_key_regression` (`SC010`).
308+
309+
Warehouse data-diff e2e proof:
310+
311+
- Test: `packages/opencode/test/altimate/data-diff-duckdb-e2e.test.ts`.
312+
- Connection: local DuckDB via `@altimateai/drivers/duckdb`.
313+
- Base/head relations: `base_orders` and `head_orders`.
314+
- Key columns: `order_id`; compared value column: `amount`.
315+
- Observed warehouse delta: one row only in head and one updated value.
316+
- Validation:
317+
`ALTIMATE_RUN_WAREHOUSE_E2E=1 bun test --timeout 30000 test/altimate/data-diff-duckdb-e2e.test.ts`.
318+
- Default fast-loop behavior:
319+
`bun test --timeout 30000 test/altimate/data-diff-duckdb-e2e.test.ts`
320+
skips unless `ALTIMATE_RUN_WAREHOUSE_E2E=1` is set.
321+
- Implementation note: fixed the DuckDB connector to use the two-argument
322+
constructor when no open options are required; Bun's native binding can miss
323+
the callback when `undefined` is passed as the second argument.
324+
288325
## Warehouse E2E Policy
289326

290327
Use local DuckDB first for fast end-to-end checks, then add BigQuery runs when a

‎packages/drivers/src/duckdb.ts‎

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,29 @@ export async function connect(config: ConnectionConfig): Promise<Connector> {
5656
new Promise<any>((resolve, reject) => {
5757
let resolved = false
5858
let timeout: ReturnType<typeof setTimeout> | undefined
59+
let instance: any
5960
const opts = accessMode ? { access_mode: accessMode } : undefined
60-
const instance = new duckdb.Database(
61-
dbPath,
62-
opts,
63-
(err: Error | null) => {
64-
if (resolved) { if (instance && typeof instance.close === "function") instance.close(); return }
65-
resolved = true
66-
if (timeout) clearTimeout(timeout)
67-
if (err) {
68-
const msg = err.message || String(err)
69-
if (msg.toLowerCase().includes("locked") || msg.includes("SQLITE_BUSY") || msg.includes("DUCKDB_LOCKED")) {
70-
reject(new Error("DUCKDB_LOCKED"))
71-
} else {
72-
reject(err)
73-
}
61+
const onOpen = (err: Error | null) => {
62+
if (resolved) {
63+
if (instance && typeof instance.close === "function") instance.close()
64+
return
65+
}
66+
resolved = true
67+
if (timeout) clearTimeout(timeout)
68+
if (err) {
69+
const msg = err.message || String(err)
70+
if (msg.toLowerCase().includes("locked") || msg.includes("SQLITE_BUSY") || msg.includes("DUCKDB_LOCKED")) {
71+
reject(new Error("DUCKDB_LOCKED"))
7472
} else {
75-
resolve(instance)
73+
reject(err)
7674
}
77-
},
78-
)
75+
} else {
76+
resolve(instance)
77+
}
78+
}
79+
instance = opts
80+
? new duckdb.Database(dbPath, opts, onOpen)
81+
: new duckdb.Database(dbPath, onOpen)
7982
// Bun: native callback may not fire; fall back after 2s
8083
timeout = setTimeout(() => {
8184
if (!resolved) {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { afterAll, beforeAll, describe, expect, test } from "bun:test"
2+
3+
import { runDataDiff } from "../../src/altimate/native/connections/data-diff"
4+
import * as Registry from "../../src/altimate/native/connections/registry"
5+
6+
const RUN = process.env.ALTIMATE_RUN_WAREHOUSE_E2E === "1"
7+
const e2eTest = RUN ? test : test.skip
8+
9+
describe("data.diff DuckDB e2e", () => {
10+
beforeAll(() => {
11+
process.env.ALTIMATE_TELEMETRY_DISABLED = "true"
12+
})
13+
14+
afterAll(() => {
15+
delete process.env.ALTIMATE_TELEMETRY_DISABLED
16+
Registry.reset()
17+
})
18+
19+
e2eTest("detects value and row deltas through a real DuckDB warehouse", async () => {
20+
Registry.reset()
21+
Registry.setConfigs({ duck_e2e: { type: "duckdb", path: ":memory:" } })
22+
const conn = await Registry.get("duck_e2e")
23+
24+
await conn.execute("CREATE TABLE base_orders (order_id INTEGER, amount INTEGER)")
25+
await conn.execute("CREATE TABLE head_orders (order_id INTEGER, amount INTEGER)")
26+
await conn.execute("INSERT INTO base_orders VALUES (1, 100), (2, 200)")
27+
await conn.execute("INSERT INTO head_orders VALUES (1, 100), (2, 250), (3, 300)")
28+
29+
const result = await runDataDiff({
30+
source: "base_orders",
31+
target: "head_orders",
32+
key_columns: ["order_id"],
33+
extra_columns: ["amount"],
34+
source_warehouse: "duck_e2e",
35+
target_warehouse: "duck_e2e",
36+
algorithm: "joindiff",
37+
})
38+
39+
expect(result.success).toBe(true)
40+
expect((result.outcome as any)?.mode).toBe("diff")
41+
expect((result.outcome as any)?.stats?.exclusive_table2).toBe(1)
42+
expect((result.outcome as any)?.stats?.updated).toBe(1)
43+
})
44+
})

0 commit comments

Comments
 (0)