@@ -17,71 +17,79 @@ import (
17
17
// * Renames a duplicated column to its original name
18
18
// * Renames any foreign keys on the duplicated column to their original name.
19
19
// * Validates and renames any temporary `CHECK` constraints on the duplicated column.
20
- func RenameDuplicatedColumn (ctx context.Context , conn db.DB , table * schema.Table , column * schema.Column ) error {
20
+ type renameDuplicatedColumnAction struct {
21
+ conn db.DB
22
+ table * schema.Table
23
+ from string
24
+ to string
25
+ }
26
+
27
+ func NewRenameDuplicatedColumnAction (conn db.DB , table * schema.Table , column string ) * renameDuplicatedColumnAction {
28
+ return & renameDuplicatedColumnAction {
29
+ conn : conn ,
30
+ table : table ,
31
+ from : TemporaryName (column ),
32
+ to : column ,
33
+ }
34
+ }
35
+
36
+ func (a * renameDuplicatedColumnAction ) Execute (ctx context.Context ) error {
21
37
const (
22
- cSetNotNullSQL = `ALTER TABLE IF EXISTS %s ALTER COLUMN %s SET NOT NULL`
23
- cDropConstraintSQL = `ALTER TABLE IF EXISTS %s DROP CONSTRAINT IF EXISTS %s`
24
38
cCreateUniqueConstraintSQL = `ALTER TABLE IF EXISTS %s ADD CONSTRAINT %s UNIQUE USING INDEX %s`
25
39
cRenameIndexSQL = `ALTER INDEX IF EXISTS %s RENAME TO %s`
26
40
)
27
41
28
- err := NewRenameColumnAction (conn , table .Name , TemporaryName ( column . Name ), column . Name ).Execute (ctx )
42
+ err := NewRenameColumnAction (a . conn , a . table .Name , a . from , a . to ).Execute (ctx )
29
43
if err != nil {
30
- return fmt .Errorf ("failed to rename duplicated column %q: %w" , column . Name , err )
44
+ return fmt .Errorf ("failed to rename duplicated column %q: %w" , a . to , err )
31
45
}
32
46
33
47
// Rename any foreign keys on the duplicated column from their temporary name
34
48
// to their original name
35
- for _ , fk := range table .ForeignKeys {
49
+ for _ , fk := range a . table .ForeignKeys {
36
50
if ! IsDuplicatedName (fk .Name ) {
37
51
continue
38
52
}
39
53
40
- if slices .Contains (fk .Columns , TemporaryName ( column . Name ) ) {
41
- err = NewRenameConstraintAction (conn , table .Name , fk .Name , StripDuplicationPrefix (fk .Name )).Execute (ctx )
54
+ if slices .Contains (fk .Columns , a . from ) {
55
+ err = NewRenameConstraintAction (a . conn , a . table .Name , fk .Name , StripDuplicationPrefix (fk .Name )).Execute (ctx )
42
56
if err != nil {
43
57
return fmt .Errorf ("failed to rename foreign key constraint %q: %w" , fk .Name , err )
44
58
}
45
- delete (table .ForeignKeys , fk .Name )
59
+ delete (a . table .ForeignKeys , fk .Name )
46
60
}
47
61
}
48
62
49
63
// Validate and rename any temporary `CHECK` constraints on the duplicated
50
64
// column.
51
- for _ , cc := range table .CheckConstraints {
65
+ for _ , cc := range a . table .CheckConstraints {
52
66
if ! IsDuplicatedName (cc .Name ) {
53
67
continue
54
68
}
55
69
56
- if slices .Contains (cc .Columns , TemporaryName ( column . Name ) ) {
57
- err := NewValidateConstraintAction (conn , table .Name , cc .Name ).Execute (ctx )
70
+ if slices .Contains (cc .Columns , a . from ) {
71
+ err := NewValidateConstraintAction (a . conn , a . table .Name , cc .Name ).Execute (ctx )
58
72
if err != nil {
59
73
return fmt .Errorf ("failed to validate check constraint %q: %w" , cc .Name , err )
60
74
}
61
75
62
- err = NewRenameConstraintAction (conn , table .Name , cc .Name , StripDuplicationPrefix (cc .Name )).Execute (ctx )
76
+ err = NewRenameConstraintAction (a . conn , a . table .Name , cc .Name , StripDuplicationPrefix (cc .Name )).Execute (ctx )
63
77
if err != nil {
64
78
return fmt .Errorf ("failed to rename check constraint %q: %w" , cc .Name , err )
65
79
}
66
- delete (table .CheckConstraints , cc .Name )
80
+ delete (a . table .CheckConstraints , cc .Name )
67
81
68
82
// If the constraint is a `NOT NULL` constraint, convert the duplicated
69
83
// unchecked `NOT NULL` constraint into a `NOT NULL` attribute on the
70
84
// column.
71
85
if IsNotNullConstraintName (StripDuplicationPrefix (cc .Name )) {
72
86
// Apply `NOT NULL` attribute to the column. This uses the validated constraint
73
- setNotNullSQL := fmt .Sprintf (cSetNotNullSQL ,
74
- pq .QuoteIdentifier (table .Name ),
75
- pq .QuoteIdentifier (column .Name ),
76
- )
77
-
78
- _ , err = conn .ExecContext (ctx , setNotNullSQL )
79
- if err != nil {
87
+ if err := NewSetNotNullAction (a .conn , a .table .Name , a .to ).Execute (ctx ); err != nil {
80
88
return fmt .Errorf ("failed to set column not null: %w" , err )
81
89
}
82
90
83
91
// Drop the constraint
84
- err = NewDropConstraintAction (conn , table .Name , NotNullConstraintName (column . Name )).Execute (ctx )
92
+ err = NewDropConstraintAction (a . conn , a . table .Name , NotNullConstraintName (a . to )).Execute (ctx )
85
93
if err != nil {
86
94
return fmt .Errorf ("failed to drop not null constraint: %w" , err )
87
95
}
@@ -91,8 +99,8 @@ func RenameDuplicatedColumn(ctx context.Context, conn db.DB, table *schema.Table
91
99
92
100
// Rename any indexes on the duplicated column and use unique indexes to
93
101
// create `UNIQUE` constraints.
94
- for _ , idx := range table .Indexes {
95
- if ! IsDuplicatedName (idx .Name ) || ! slices .Contains (idx .Columns , TemporaryName ( column . Name ) ) {
102
+ for _ , idx := range a . table .Indexes {
103
+ if ! IsDuplicatedName (idx .Name ) || ! slices .Contains (idx .Columns , a . from ) {
96
104
continue
97
105
}
98
106
@@ -102,23 +110,23 @@ func RenameDuplicatedColumn(ctx context.Context, conn db.DB, table *schema.Table
102
110
pq .QuoteIdentifier (StripDuplicationPrefix (idx .Name )),
103
111
)
104
112
105
- _ , err = conn .ExecContext (ctx , renameIndexSQL )
113
+ _ , err = a . conn .ExecContext (ctx , renameIndexSQL )
106
114
if err != nil {
107
115
return fmt .Errorf ("failed to rename index %q: %w" , idx .Name , err )
108
116
}
109
117
110
118
// Index no longer exists, remove it from the table
111
- delete (table .Indexes , idx .Name )
119
+ delete (a . table .Indexes , idx .Name )
112
120
113
- if _ , ok := table .UniqueConstraints [StripDuplicationPrefix (idx .Name )]; idx .Unique && ok {
121
+ if _ , ok := a . table .UniqueConstraints [StripDuplicationPrefix (idx .Name )]; idx .Unique && ok {
114
122
// Create a unique constraint using the unique index
115
123
createUniqueConstraintSQL := fmt .Sprintf (cCreateUniqueConstraintSQL ,
116
- pq .QuoteIdentifier (table .Name ),
124
+ pq .QuoteIdentifier (a . table .Name ),
117
125
pq .QuoteIdentifier (StripDuplicationPrefix (idx .Name )),
118
126
pq .QuoteIdentifier (StripDuplicationPrefix (idx .Name )),
119
127
)
120
128
121
- _ , err = conn .ExecContext (ctx , createUniqueConstraintSQL )
129
+ _ , err = a . conn .ExecContext (ctx , createUniqueConstraintSQL )
122
130
if err != nil {
123
131
return fmt .Errorf ("failed to create unique constraint from index %q: %w" , idx .Name , err )
124
132
}
0 commit comments