fix(db): stamp the dialect into generated query files
The same generate command emitted ? one run and $1 the next, which looked like non-determinism. It is not: postgres uses $1 placeholders where sqlite and mysql use ?, and the driver comes from the active profile, so building under a different profile rewrites this committed file. The header now records the dialect it was generated for, making the flip visible in the diff and explaining check:generated-types failures instead of leaving them looking like random churn. Worth deciding separately: a committed artifact whose contents depend on the active profile will keep drifting. Either generate per dialect, or stop committing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// AUTO-GENERATED by `wrnexus db generate` — do not edit.
|
||||
// AUTO-GENERATED by `wrnexus db generate` (dialect: sqlite) — do not edit.
|
||||
import type { Db, ExecResult } from "@wrnexus/db";
|
||||
import { users } from "./schema.ts";
|
||||
|
||||
|
||||
@@ -230,5 +230,12 @@ export function generateQueriesFile(
|
||||
if (usedModels.size > 0) {
|
||||
imports.push(`import { ${[...usedModels].sort().join(", ")} } from "./schema.ts";`);
|
||||
}
|
||||
return `// AUTO-GENERATED by \`wrnexus db generate\` — do not edit.\n${imports.join("\n")}\n\n${blocks.join("\n\n")}\n`;
|
||||
// The dialect is stamped into the header because it changes the emitted SQL:
|
||||
// postgres uses $1 placeholders where sqlite and mysql use ?. Regenerating
|
||||
// under a different profile therefore rewrites this committed file, and
|
||||
// without the stamp the diff looks like unexplained churn.
|
||||
return (
|
||||
`// AUTO-GENERATED by \`wrnexus db generate\` (dialect: ${dialect}) — do not edit.\n` +
|
||||
`${imports.join("\n")}\n\n${blocks.join("\n\n")}\n`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { generateQueriesFile, parseQueries } from "../src/generate.ts";
|
||||
|
||||
const queries = parseQueries(`-- name: GetUser :one\nSELECT * FROM users WHERE email = :email;\n`);
|
||||
|
||||
test("the generated header records the dialect it was built for", () => {
|
||||
// The same command emits different SQL per dialect, so a build under another
|
||||
// profile rewrites the committed file. The stamp makes that visible in the
|
||||
// diff instead of looking like unexplained churn.
|
||||
expect(generateQueriesFile(queries, [], "sqlite")).toContain("(dialect: sqlite)");
|
||||
expect(generateQueriesFile(queries, [], "postgres")).toContain("(dialect: postgres)");
|
||||
});
|
||||
|
||||
test("placeholder style follows the dialect", () => {
|
||||
expect(generateQueriesFile(queries, [], "sqlite")).toContain("email = ?");
|
||||
expect(generateQueriesFile(queries, [], "postgres")).toContain("email = $1");
|
||||
});
|
||||
|
||||
test("generation is deterministic for a fixed dialect", () => {
|
||||
const first = generateQueriesFile(queries, [], "postgres");
|
||||
const second = generateQueriesFile(queries, [], "postgres");
|
||||
expect(first).toBe(second);
|
||||
});
|
||||
Reference in New Issue
Block a user