move current timestamp assignment above the not null check (#1286)

This commit is contained in:
Mantra 2026-03-24 10:59:05 -07:00 committed by GitHub
parent cfa6204c2d
commit d2ed9f8244
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 22 additions and 14 deletions

View File

@ -28,8 +28,13 @@ ALTER TABLE "ProjectUser" VALIDATE CONSTRAINT "ProjectUser_risk_score_bot_range"
-- RUN_OUTSIDE_TRANSACTION_SENTINEL
ALTER TABLE "ProjectUser" VALIDATE CONSTRAINT "ProjectUser_risk_score_free_trial_abuse_range";
-- Enforce `signedUpAt` after the backfill is complete. We intentionally require
-- inserts to provide the value explicitly instead of hiding that behavior in a trigger.
-- Enforce `signedUpAt` after the backfill is complete. Set a DEFAULT first so
-- that inserts omitting the column still get a sensible value (CURRENT_TIMESTAMP).
-- SPLIT_STATEMENT_SENTINEL
-- SINGLE_STATEMENT_SENTINEL
-- RUN_OUTSIDE_TRANSACTION_SENTINEL
ALTER TABLE "ProjectUser" ALTER COLUMN "signedUpAt" SET DEFAULT CURRENT_TIMESTAMP;
-- SPLIT_STATEMENT_SENTINEL
-- SINGLE_STATEMENT_SENTINEL
-- RUN_OUTSIDE_TRANSACTION_SENTINEL

View File

@ -71,7 +71,7 @@ export const postMigration = async (sql: Sql) => {
`;
expect(colInfo).toHaveLength(1);
expect(colInfo[0].is_nullable).toBe('NO');
expect(colInfo[0].column_default).toBe(null);
expect(colInfo[0].column_default).toBe('CURRENT_TIMESTAMP');
await sql`
INSERT INTO "Project" ("id", "createdAt", "updatedAt", "displayName", "description", "isProductionMode")
@ -82,7 +82,9 @@ export const postMigration = async (sql: Sql) => {
VALUES (${tenancyId}::uuid, NOW(), NOW(), ${projectId}, 'main', 'TRUE'::"BooleanTrue")
`;
await expect(sql`
// INSERT without signedUpAt should succeed — DEFAULT CURRENT_TIMESTAMP fills it in.
const defaultUserId = randomUUID();
await sql`
INSERT INTO "ProjectUser" (
"projectUserId",
"tenancyId",
@ -92,7 +94,7 @@ export const postMigration = async (sql: Sql) => {
"updatedAt",
"lastActiveAt"
) VALUES (
${userId}::uuid,
${defaultUserId}::uuid,
${tenancyId}::uuid,
${projectId},
'main',
@ -100,8 +102,17 @@ export const postMigration = async (sql: Sql) => {
NOW(),
NOW()
)
`).rejects.toThrow(/signedUpAt/);
`;
const defaultRows = await sql`
SELECT "signedUpAt"
FROM "ProjectUser"
WHERE "projectUserId" = ${defaultUserId}::uuid
`;
expect(defaultRows).toHaveLength(1);
expect(defaultRows[0].signedUpAt).not.toBeNull();
// INSERT with explicit signedUpAt should use the provided value.
await sql`
INSERT INTO "ProjectUser" (
"projectUserId",

View File

@ -1,8 +0,0 @@
-- Backward-compat: old code that doesn't know about `signedUpAt` omits it from
-- INSERT. Adding a DEFAULT lets Postgres fill it automatically.
--
-- CURRENT_TIMESTAMP is correct here: `createdAt` also defaults to
-- CURRENT_TIMESTAMP, so within the same transaction both columns receive the
-- same value. Old code never computes risk scores, so the negligible edge
-- case of an explicitly-backdated `createdAt` is harmless.
ALTER TABLE "ProjectUser" ALTER COLUMN "signedUpAt" SET DEFAULT CURRENT_TIMESTAMP;