@@ -58,7 +58,7 @@ describe('patched Drizzle push against PostgreSQL', () => {
5858 async function schema ( source : string ) {
5959 await writeFile (
6060 join ( directory , 'schema.ts' ) ,
61- `import { pgTable, pgSchema, pgEnum, text, integer, bigint, boolean, check } from ${ JSON . stringify ( import . meta. resolve ( 'drizzle-orm/pg-core' ) ) }
61+ `import { pgTable, pgSchema, pgEnum, text, integer, bigint, boolean, check, index } from ${ JSON . stringify ( import . meta. resolve ( 'drizzle-orm/pg-core' ) ) }
6262import { sql } from ${ JSON . stringify ( import . meta. resolve ( 'drizzle-orm' ) ) }
6363${ source } `
6464 )
@@ -195,7 +195,7 @@ export const knowledgeBases = pgTable('knowledge_base', {
195195 await schema ( `export const projects = pgTable('project', { id: text('id').primaryKey() })
196196export const workspaces = pgTable('workspace', {
197197 id: text('id').primaryKey(), forkedFromWorkspaceId: text('forked_from_workspace_id'), projectId: text('project_id'),
198- })
198+ }, (table) => [index('workspace_project_id_id_idx').on(table.projectId, table.id)] )
199199export const memberships = pgTable('project_workspace', {
200200 projectId: text('project_id').notNull(), workspaceId: text('workspace_id').notNull().unique(),
201201})` )
@@ -212,8 +212,15 @@ export const memberships = pgTable('project_workspace', {
212212 ] )
213213 await sql `UPDATE project_workspace SET project_id = 'singleton' WHERE workspace_id = 'fork'`
214214 await sql `UPDATE workspace SET project_id = 'family' WHERE id = 'standalone'`
215+ const indexBeforeReplay = await sql `SELECT indexrelid, indisvalid FROM pg_index
216+ WHERE indexrelid = 'workspace_project_id_id_idx'::regclass`
217+ expect ( indexBeforeReplay ) . toEqual ( [ { indexrelid : expect . any ( Number ) , indisvalid : true } ] )
215218 const repeated = runPush ( [ '--force' ] )
216219 expect ( repeated . error , repeated . stderr ) . toBeUndefined ( )
220+ expect (
221+ await sql `SELECT indexrelid, indisvalid FROM pg_index
222+ WHERE indexrelid = 'workspace_project_id_id_idx'::regclass`
223+ ) . toEqual ( indexBeforeReplay )
217224 expect (
218225 await sql `SELECT w.id, w.project_id, pw.project_id AS legacy FROM workspace w
219226 JOIN project_workspace pw ON pw.workspace_id = w.id ORDER BY w.id`
@@ -224,6 +231,42 @@ export const memberships = pgTable('project_workspace', {
224231 ] )
225232 } , 60_000 )
226233
234+ it ( 'repairs an interrupted Project index build during schema-push reconciliation' , async ( ) => {
235+ await sql `CREATE TABLE project (id text PRIMARY KEY)`
236+ await sql `CREATE TABLE workspace (id text PRIMARY KEY, project_id text)`
237+ await sql `CREATE TABLE project_workspace (project_id text NOT NULL, workspace_id text NOT NULL UNIQUE)`
238+ await sql `INSERT INTO project VALUES ('family')`
239+ await sql `INSERT INTO workspace VALUES ('root', 'family'), ('fork', 'family')`
240+ await expect (
241+ sql `CREATE UNIQUE INDEX CONCURRENTLY workspace_project_id_id_idx ON workspace(project_id)`
242+ ) . rejects . toMatchObject ( { code : '23505' } )
243+ expect (
244+ await sql `SELECT indisvalid FROM pg_index WHERE indexrelid = 'workspace_project_id_id_idx'::regclass`
245+ ) . toEqual ( [ { indisvalid : false } ] )
246+ const result = spawnSync (
247+ 'bun' ,
248+ [
249+ '--no-env-file' ,
250+ fileURLToPath ( new URL ( './reconcile-project-membership.ts' , import . meta. url ) ) ,
251+ ] ,
252+ {
253+ env : { ...process . env , DATABASE_URL : fixtureUrl , MIGRATION_DATABASE_URL : fixtureUrl } ,
254+ encoding : 'utf8' ,
255+ timeout : 15_000 ,
256+ }
257+ )
258+ expect ( result . error ) . toBeUndefined ( )
259+ expect ( result . status , result . stdout + result . stderr ) . toBe ( 0 )
260+ expect (
261+ await sql `SELECT indisvalid, indisunique FROM pg_index
262+ WHERE indexrelid = 'workspace_project_id_id_idx'::regclass`
263+ ) . toEqual ( [ { indisvalid : true , indisunique : false } ] )
264+ expect ( await sql `SELECT id, project_id FROM workspace ORDER BY id` ) . toEqual ( [
265+ { id : 'fork' , project_id : 'family' } ,
266+ { id : 'root' , project_id : 'family' } ,
267+ ] )
268+ } )
269+
227270 it ( 'refuses a schema downgrade before recreating the retired Project connector' , async ( ) => {
228271 await sql `CREATE TABLE project (id text PRIMARY KEY)`
229272 await sql `CREATE TABLE workspace (id text PRIMARY KEY, project_id text NOT NULL)`
0 commit comments