@@ -26,8 +26,10 @@ type Operation interface {
26
26
27
27
// CreateTable operation creates a new table
28
28
type CreateTable struct {
29
- Name string
30
- Columns []Column
29
+ Name string
30
+ Columns []Column
31
+ ForeignKeys []ForeignKey
32
+ Indexes []Index
31
33
}
32
34
33
35
// Column represents a table column
@@ -40,6 +42,22 @@ type Column struct {
40
42
MaxLength int
41
43
}
42
44
45
+ // ForeignKey represents a foreign key constraint
46
+ type ForeignKey struct {
47
+ Columns []string
48
+ RefTable string
49
+ RefColumns []string
50
+ OnDelete string // CASCADE, SET NULL, RESTRICT, NO ACTION
51
+ OnUpdate string // CASCADE, SET NULL, RESTRICT, NO ACTION
52
+ }
53
+
54
+ // Index represents a table index
55
+ type Index struct {
56
+ Name string
57
+ Columns []string
58
+ IsUnique bool
59
+ }
60
+
43
61
// DropTable operation drops a table
44
62
type DropTable struct {
45
63
Name string
@@ -64,6 +82,30 @@ type ModifyColumn struct {
64
82
NewColumn Column
65
83
}
66
84
85
+ // CreateIndex operation creates an index
86
+ type CreateIndex struct {
87
+ Table string
88
+ Index Index
89
+ }
90
+
91
+ // DropIndex operation drops an index
92
+ type DropIndex struct {
93
+ Table string
94
+ Name string
95
+ }
96
+
97
+ // AddForeignKey operation adds a foreign key constraint
98
+ type AddForeignKey struct {
99
+ Table string
100
+ ForeignKey ForeignKey
101
+ }
102
+
103
+ // DropForeignKey operation drops a foreign key constraint
104
+ type DropForeignKey struct {
105
+ Table string
106
+ Name string
107
+ }
108
+
67
109
// SQL generates SQL for CreateTable operation
68
110
func (op * CreateTable ) SQL () string {
69
111
var cols []string
@@ -81,7 +123,41 @@ func (op *CreateTable) SQL() string {
81
123
}
82
124
cols = append (cols , def )
83
125
}
84
- return fmt .Sprintf ("CREATE TABLE %s (\n \t %s\n )" , op .Name , strings .Join (cols , ",\n \t " ))
126
+
127
+ // Add foreign key constraints
128
+ for _ , fk := range op .ForeignKeys {
129
+ def := fmt .Sprintf ("FOREIGN KEY (%s) REFERENCES %s (%s)" ,
130
+ strings .Join (fk .Columns , ", " ),
131
+ fk .RefTable ,
132
+ strings .Join (fk .RefColumns , ", " ))
133
+
134
+ if fk .OnDelete != "" {
135
+ def += fmt .Sprintf (" ON DELETE %s" , fk .OnDelete )
136
+ }
137
+ if fk .OnUpdate != "" {
138
+ def += fmt .Sprintf (" ON UPDATE %s" , fk .OnUpdate )
139
+ }
140
+ cols = append (cols , def )
141
+ }
142
+
143
+ sql := fmt .Sprintf ("CREATE TABLE %s (\n \t %s\n )" , op .Name , strings .Join (cols , ",\n \t " ))
144
+
145
+ // Create indexes
146
+ var indexes []string
147
+ for _ , idx := range op .Indexes {
148
+ idxSQL := fmt .Sprintf ("CREATE %sINDEX %s ON %s (%s)" ,
149
+ map [bool ]string {true : "UNIQUE " , false : "" }[idx .IsUnique ],
150
+ idx .Name ,
151
+ op .Name ,
152
+ strings .Join (idx .Columns , ", " ))
153
+ indexes = append (indexes , idxSQL )
154
+ }
155
+
156
+ if len (indexes ) > 0 {
157
+ sql += ";\n " + strings .Join (indexes , ";\n " )
158
+ }
159
+
160
+ return sql
85
161
}
86
162
87
163
func (c * CreateTable ) Args () []interface {} {
@@ -128,6 +204,61 @@ func (m *ModifyColumn) Args() []interface{} {
128
204
return nil
129
205
}
130
206
207
+ // SQL generates SQL for CreateIndex operation
208
+ func (c * CreateIndex ) SQL () string {
209
+ return fmt .Sprintf ("CREATE %sINDEX %s ON %s (%s)" ,
210
+ map [bool ]string {true : "UNIQUE " , false : "" }[c .Index .IsUnique ],
211
+ c .Index .Name ,
212
+ c .Table ,
213
+ strings .Join (c .Index .Columns , ", " ))
214
+ }
215
+
216
+ func (c * CreateIndex ) Args () []interface {} {
217
+ return nil
218
+ }
219
+
220
+ // SQL generates SQL for DropIndex operation
221
+ func (d * DropIndex ) SQL () string {
222
+ return fmt .Sprintf ("DROP INDEX %s" , d .Name )
223
+ }
224
+
225
+ func (d * DropIndex ) Args () []interface {} {
226
+ return nil
227
+ }
228
+
229
+ // SQL generates SQL for AddForeignKey operation
230
+ func (a * AddForeignKey ) SQL () string {
231
+ sql := fmt .Sprintf ("ALTER TABLE %s ADD CONSTRAINT %s_%s_fk FOREIGN KEY (%s) REFERENCES %s (%s)" ,
232
+ a .Table ,
233
+ a .Table ,
234
+ strings .Join (a .ForeignKey .Columns , "_" ),
235
+ strings .Join (a .ForeignKey .Columns , ", " ),
236
+ a .ForeignKey .RefTable ,
237
+ strings .Join (a .ForeignKey .RefColumns , ", " ))
238
+
239
+ if a .ForeignKey .OnDelete != "" {
240
+ sql += fmt .Sprintf (" ON DELETE %s" , a .ForeignKey .OnDelete )
241
+ }
242
+ if a .ForeignKey .OnUpdate != "" {
243
+ sql += fmt .Sprintf (" ON UPDATE %s" , a .ForeignKey .OnUpdate )
244
+ }
245
+
246
+ return sql
247
+ }
248
+
249
+ func (a * AddForeignKey ) Args () []interface {} {
250
+ return nil
251
+ }
252
+
253
+ // SQL generates SQL for DropForeignKey operation
254
+ func (d * DropForeignKey ) SQL () string {
255
+ return fmt .Sprintf ("ALTER TABLE %s DROP CONSTRAINT %s" , d .Table , d .Name )
256
+ }
257
+
258
+ func (d * DropForeignKey ) Args () []interface {} {
259
+ return nil
260
+ }
261
+
131
262
// NewMigration creates a new migration with the given name
132
263
func NewMigration (name string ) * Migration {
133
264
return & Migration {
0 commit comments