@@ -4,12 +4,28 @@ export class AddIdToProjectQfRound1779182511001 implements MigrationInterface {
44 name = 'AddIdToProjectQfRound1779182511001' ;
55
66 public async up ( queryRunner : QueryRunner ) : Promise < void > {
7- // First, check if the table exists and get the current primary key constraint name
8- const tableExists = await queryRunner . hasTable ( 'project_qf_rounds_qf_round' ) ;
7+ // First, check if the table exists
8+ const tableExists = await queryRunner . hasTable (
9+ 'project_qf_rounds_qf_round' ,
10+ ) ;
911 if ( ! tableExists ) {
1012 throw new Error ( 'Table project_qf_rounds_qf_round does not exist' ) ;
1113 }
1214
15+ // Check if the table already has an 'id' column (case for synchronized DBs)
16+ const columnExists = await queryRunner . hasColumn (
17+ 'project_qf_rounds_qf_round' ,
18+ 'id' ,
19+ ) ;
20+
21+ // If 'id' column already exists, skip the primary key migration
22+ if ( columnExists ) {
23+ console . log (
24+ 'Table already has id column, skipping primary key migration' ,
25+ ) ;
26+ return ;
27+ }
28+
1329 // Get the current primary key constraint name
1430 const primaryKeyQuery = await queryRunner . query ( `
1531 SELECT constraint_name
@@ -18,84 +34,201 @@ export class AddIdToProjectQfRound1779182511001 implements MigrationInterface {
1834 AND constraint_type = 'PRIMARY KEY'
1935 ` ) ;
2036
21- const primaryKeyName = primaryKeyQuery [ 0 ] ?. constraint_name || 'PK_project_qf_rounds_qf_round' ;
37+ const primaryKeyName = primaryKeyQuery [ 0 ] ?. constraint_name ;
2238
23- // Drop the existing composite primary key
24- await queryRunner . query ( `
25- ALTER TABLE "project_qf_rounds_qf_round"
26- DROP CONSTRAINT "${ primaryKeyName } "
27- ` ) ;
39+ // Drop the existing composite primary key if it exists and if no id column
40+ if ( primaryKeyName && ! columnExists ) {
41+ try {
42+ await queryRunner . query ( `
43+ ALTER TABLE "project_qf_rounds_qf_round"
44+ DROP CONSTRAINT "${ primaryKeyName } "
45+ ` ) ;
46+ } catch ( error ) {
47+ console . log (
48+ `Failed to drop constraint ${ primaryKeyName } , trying alternative approach...` ,
49+ ) ;
50+ // Try with IF EXISTS as fallback
51+ await queryRunner . query ( `
52+ ALTER TABLE "project_qf_rounds_qf_round"
53+ DROP CONSTRAINT IF EXISTS "${ primaryKeyName } "
54+ ` ) ;
55+ }
56+ } else if ( ! primaryKeyName ) {
57+ // Fallback: try to drop with constraint detection using PostgreSQL system tables
58+ const constraintQuery = await queryRunner . query ( `
59+ SELECT conname
60+ FROM pg_constraint
61+ WHERE conrelid = (
62+ SELECT oid
63+ FROM pg_class
64+ WHERE relname = 'project_qf_rounds_qf_round'
65+ ) AND contype = 'p'
66+ ` ) ;
2867
29- // Add the new id column as auto-incrementing primary key
30- await queryRunner . query ( `
31- ALTER TABLE "project_qf_rounds_qf_round"
32- ADD COLUMN "id" SERIAL PRIMARY KEY
33- ` ) ;
68+ if ( constraintQuery [ 0 ] ?. conname ) {
69+ try {
70+ await queryRunner . query ( `
71+ ALTER TABLE "project_qf_rounds_qf_round"
72+ DROP CONSTRAINT "${ constraintQuery [ 0 ] . conname } "
73+ ` ) ;
74+ } catch ( error ) {
75+ // Final fallback with IF EXISTS
76+ await queryRunner . query ( `
77+ ALTER TABLE "project_qf_rounds_qf_round"
78+ DROP CONSTRAINT IF EXISTS "${ constraintQuery [ 0 ] . conname } "
79+ ` ) ;
80+ }
81+ }
82+ }
83+
84+ // Add the new id column as auto-incrementing primary key (only if it doesn't exist)
85+ if ( ! columnExists ) {
86+ await queryRunner . query ( `
87+ ALTER TABLE "project_qf_rounds_qf_round"
88+ ADD COLUMN "id" SERIAL PRIMARY KEY
89+ ` ) ;
90+ }
3491
35- // Add unique constraint on the composite key to maintain uniqueness
36- await queryRunner . query ( `
37- ALTER TABLE IF EXISTS "project_qf_rounds_qf_round"
38- ADD CONSTRAINT "UQ_project_qf_rounds_composite"
39- UNIQUE ("projectId", "qfRoundId")
92+ // Check if unique constraint already exists
93+ const uniqueConstraintExists = await queryRunner . query ( `
94+ SELECT constraint_name
95+ FROM information_schema.table_constraints
96+ WHERE table_name = 'project_qf_rounds_qf_round'
97+ AND constraint_name = 'UQ_project_qf_rounds_composite'
98+ AND constraint_type = 'UNIQUE'
4099 ` ) ;
41100
42- // Add indexes on projectId and qfRoundId for performance
43- await queryRunner . query ( `
44- CREATE INDEX "IDX_project_qf_rounds_projectId"
45- ON "project_qf_rounds_qf_round" ("projectId")
101+ // Add unique constraint on the composite key to maintain uniqueness (only if it doesn't exist)
102+ if ( ! uniqueConstraintExists [ 0 ] ) {
103+ await queryRunner . query ( `
104+ ALTER TABLE "project_qf_rounds_qf_round"
105+ ADD CONSTRAINT "UQ_project_qf_rounds_composite"
106+ UNIQUE ("projectId", "qfRoundId")
107+ ` ) ;
108+ }
109+
110+ // Check if indexes already exist
111+ const projectIdIndexExists = await queryRunner . query ( `
112+ SELECT indexname
113+ FROM pg_indexes
114+ WHERE tablename = 'project_qf_rounds_qf_round'
115+ AND indexname = 'IDX_project_qf_rounds_projectId'
46116 ` ) ;
47117
48- await queryRunner . query ( `
49- CREATE INDEX "IDX_project_qf_rounds_qfRoundId"
50- ON "project_qf_rounds_qf_round" ("qfRoundId")
118+ const qfRoundIdIndexExists = await queryRunner . query ( `
119+ SELECT indexname
120+ FROM pg_indexes
121+ WHERE tablename = 'project_qf_rounds_qf_round'
122+ AND indexname = 'IDX_project_qf_rounds_qfRoundId'
51123 ` ) ;
124+
125+ // Add indexes on projectId and qfRoundId for performance (only if they don't exist)
126+ if ( ! projectIdIndexExists [ 0 ] ) {
127+ await queryRunner . query ( `
128+ CREATE INDEX "IDX_project_qf_rounds_projectId"
129+ ON "project_qf_rounds_qf_round" ("projectId")
130+ ` ) ;
131+ }
132+
133+ if ( ! qfRoundIdIndexExists [ 0 ] ) {
134+ await queryRunner . query ( `
135+ CREATE INDEX "IDX_project_qf_rounds_qfRoundId"
136+ ON "project_qf_rounds_qf_round" ("qfRoundId")
137+ ` ) ;
138+ }
52139 }
53140
54141 public async down ( queryRunner : QueryRunner ) : Promise < void > {
55- // Drop the indexes first
56- await queryRunner . query ( `
57- DROP INDEX IF EXISTS "IDX_project_qf_rounds_projectId"
142+ // Check if indexes exist before dropping
143+ const projectIdIndexExists = await queryRunner . query ( `
144+ SELECT indexname
145+ FROM pg_indexes
146+ WHERE tablename = 'project_qf_rounds_qf_round'
147+ AND indexname = 'IDX_project_qf_rounds_projectId'
58148 ` ) ;
59149
60- await queryRunner . query ( `
61- DROP INDEX IF EXISTS "IDX_project_qf_rounds_qfRoundId"
150+ const qfRoundIdIndexExists = await queryRunner . query ( `
151+ SELECT indexname
152+ FROM pg_indexes
153+ WHERE tablename = 'project_qf_rounds_qf_round'
154+ AND indexname = 'IDX_project_qf_rounds_qfRoundId'
62155 ` ) ;
63156
64- // Drop the unique constraint
65- await queryRunner . query ( `
66- ALTER TABLE IF EXISTS "project_qf_rounds_qf_round"
67- DROP CONSTRAINT IF EXISTS "UQ_project_qf_rounds_composite"
68- ` ) ;
157+ // Drop the indexes if they exist
158+ if ( projectIdIndexExists [ 0 ] ) {
159+ await queryRunner . query ( `
160+ DROP INDEX "IDX_project_qf_rounds_projectId"
161+ ` ) ;
162+ }
69163
70- // Get the current primary key constraint name for the id column
71- const primaryKeyQuery = await queryRunner . query ( `
164+ if ( qfRoundIdIndexExists [ 0 ] ) {
165+ await queryRunner . query ( `
166+ DROP INDEX "IDX_project_qf_rounds_qfRoundId"
167+ ` ) ;
168+ }
169+
170+ // Check if unique constraint exists before dropping
171+ const uniqueConstraintExists = await queryRunner . query ( `
72172 SELECT constraint_name
73173 FROM information_schema.table_constraints
74174 WHERE table_name = 'project_qf_rounds_qf_round'
75- AND constraint_type = 'PRIMARY KEY '
175+ AND constraint_name = 'UQ_project_qf_rounds_composite '
76176 ` ) ;
77177
78- const primaryKeyName = primaryKeyQuery [ 0 ] ?. constraint_name ;
79-
80- if ( primaryKeyName ) {
81- // Drop the id primary key constraint
178+ // Drop the unique constraint if it exists
179+ if ( uniqueConstraintExists [ 0 ] ) {
82180 await queryRunner . query ( `
83- ALTER TABLE IF EXISTS "project_qf_rounds_qf_round"
84- DROP CONSTRAINT "${ primaryKeyName } "
181+ ALTER TABLE "project_qf_rounds_qf_round"
182+ DROP CONSTRAINT "UQ_project_qf_rounds_composite "
85183 ` ) ;
86184 }
87185
88- // Drop the id column
89- await queryRunner . query ( `
90- ALTER TABLE IF EXISTS "project_qf_rounds_qf_round"
91- DROP COLUMN IF EXISTS "id"
92- ` ) ;
186+ // Check if id column exists
187+ const columnExists = await queryRunner . hasColumn (
188+ 'project_qf_rounds_qf_round' ,
189+ 'id' ,
190+ ) ;
191+
192+ if ( columnExists ) {
193+ // Get the current primary key constraint name for the id column
194+ const primaryKeyQuery = await queryRunner . query ( `
195+ SELECT constraint_name
196+ FROM information_schema.table_constraints
197+ WHERE table_name = 'project_qf_rounds_qf_round'
198+ AND constraint_type = 'PRIMARY KEY'
199+ ` ) ;
93200
94- // Restore the composite primary key
95- await queryRunner . query ( `
96- ALTER TABLE IF EXISTS "project_qf_rounds_qf_round"
97- ADD CONSTRAINT "PK_project_qf_rounds_qf_round"
98- PRIMARY KEY ("projectId", "qfRoundId")
99- ` ) ;
201+ const primaryKeyName = primaryKeyQuery [ 0 ] ?. constraint_name ;
202+
203+ if ( primaryKeyName ) {
204+ try {
205+ // Drop the id primary key constraint
206+ await queryRunner . query ( `
207+ ALTER TABLE "project_qf_rounds_qf_round"
208+ DROP CONSTRAINT "${ primaryKeyName } "
209+ ` ) ;
210+ } catch ( error ) {
211+ // Fallback with IF EXISTS
212+ await queryRunner . query ( `
213+ ALTER TABLE "project_qf_rounds_qf_round"
214+ DROP CONSTRAINT IF EXISTS "${ primaryKeyName } "
215+ ` ) ;
216+ }
217+ }
218+
219+ // Drop the id column
220+ await queryRunner . query ( `
221+ ALTER TABLE "project_qf_rounds_qf_round" DROP COLUMN "id"
222+ ` ) ;
223+ }
224+
225+ // Only restore composite primary key if id column was actually dropped
226+ if ( columnExists ) {
227+ await queryRunner . query ( `
228+ ALTER TABLE "project_qf_rounds_qf_round"
229+ ADD CONSTRAINT "PK_project_qf_rounds_qf_round"
230+ PRIMARY KEY ("projectId", "qfRoundId")
231+ ` ) ;
232+ }
100233 }
101234}
0 commit comments