fix(db): make document revision migration replay-safe
This commit is contained in:
parent
761dce559d
commit
90889c12d8
2 changed files with 79 additions and 5 deletions
|
|
@ -169,4 +169,76 @@ describeEmbeddedPostgres("applyPendingMigrations", () => {
|
||||||
},
|
},
|
||||||
20_000,
|
20_000,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it(
|
||||||
|
"replays migration 0046 safely when document revision columns already exist",
|
||||||
|
async () => {
|
||||||
|
const connectionString = await createTempDatabase();
|
||||||
|
|
||||||
|
await applyPendingMigrations(connectionString);
|
||||||
|
|
||||||
|
const sql = postgres(connectionString, { max: 1, onnotice: () => {} });
|
||||||
|
try {
|
||||||
|
const smoothSentinelsHash = await migrationHash("0046_smooth_sentinels.sql");
|
||||||
|
|
||||||
|
await sql.unsafe(
|
||||||
|
`DELETE FROM "drizzle"."__drizzle_migrations" WHERE hash = '${smoothSentinelsHash}'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const columns = await sql.unsafe<{ column_name: string; is_nullable: string; column_default: string | null }[]>(
|
||||||
|
`
|
||||||
|
SELECT column_name, is_nullable, column_default
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
AND table_name = 'document_revisions'
|
||||||
|
AND column_name IN ('title', 'format')
|
||||||
|
ORDER BY column_name
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
expect(columns).toHaveLength(2);
|
||||||
|
} finally {
|
||||||
|
await sql.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingState = await inspectMigrations(connectionString);
|
||||||
|
expect(pendingState).toMatchObject({
|
||||||
|
status: "needsMigrations",
|
||||||
|
pendingMigrations: ["0046_smooth_sentinels.sql"],
|
||||||
|
reason: "pending-migrations",
|
||||||
|
});
|
||||||
|
|
||||||
|
await applyPendingMigrations(connectionString);
|
||||||
|
|
||||||
|
const finalState = await inspectMigrations(connectionString);
|
||||||
|
expect(finalState.status).toBe("upToDate");
|
||||||
|
|
||||||
|
const verifySql = postgres(connectionString, { max: 1, onnotice: () => {} });
|
||||||
|
try {
|
||||||
|
const columns = await verifySql.unsafe<{ column_name: string; is_nullable: string; column_default: string | null }[]>(
|
||||||
|
`
|
||||||
|
SELECT column_name, is_nullable, column_default
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'public'
|
||||||
|
AND table_name = 'document_revisions'
|
||||||
|
AND column_name IN ('title', 'format')
|
||||||
|
ORDER BY column_name
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
expect(columns).toEqual([
|
||||||
|
expect.objectContaining({
|
||||||
|
column_name: "format",
|
||||||
|
is_nullable: "NO",
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
column_name: "title",
|
||||||
|
is_nullable: "YES",
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
expect(columns[0]?.column_default).toContain("'markdown'");
|
||||||
|
} finally {
|
||||||
|
await verifySql.end();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
20_000,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
ALTER TABLE "document_revisions" ADD COLUMN "title" text;--> statement-breakpoint
|
ALTER TABLE "document_revisions" ADD COLUMN IF NOT EXISTS "title" text;--> statement-breakpoint
|
||||||
ALTER TABLE "document_revisions" ADD COLUMN "format" text DEFAULT 'markdown' NOT NULL;
|
ALTER TABLE "document_revisions" ADD COLUMN IF NOT EXISTS "format" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "document_revisions" ALTER COLUMN "format" SET DEFAULT 'markdown';
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
UPDATE "document_revisions" AS "dr"
|
UPDATE "document_revisions" AS "dr"
|
||||||
SET
|
SET
|
||||||
"title" = "d"."title",
|
"title" = COALESCE("dr"."title", "d"."title"),
|
||||||
"format" = COALESCE("d"."format", 'markdown')
|
"format" = COALESCE("dr"."format", "d"."format", 'markdown')
|
||||||
FROM "documents" AS "d"
|
FROM "documents" AS "d"
|
||||||
WHERE "d"."id" = "dr"."document_id";
|
WHERE "d"."id" = "dr"."document_id";--> statement-breakpoint
|
||||||
|
ALTER TABLE "document_revisions" ALTER COLUMN "format" SET NOT NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue