github.com/astaxie/beego@v1.12.3/migration/ddl.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package migration 16 17 import ( 18 "fmt" 19 20 "github.com/astaxie/beego/logs" 21 ) 22 23 // Index struct defines the structure of Index Columns 24 type Index struct { 25 Name string 26 } 27 28 // Unique struct defines a single unique key combination 29 type Unique struct { 30 Definition string 31 Columns []*Column 32 } 33 34 //Column struct defines a single column of a table 35 type Column struct { 36 Name string 37 Inc string 38 Null string 39 Default string 40 Unsign string 41 DataType string 42 remove bool 43 Modify bool 44 } 45 46 // Foreign struct defines a single foreign relationship 47 type Foreign struct { 48 ForeignTable string 49 ForeignColumn string 50 OnDelete string 51 OnUpdate string 52 Column 53 } 54 55 // RenameColumn struct allows renaming of columns 56 type RenameColumn struct { 57 OldName string 58 OldNull string 59 OldDefault string 60 OldUnsign string 61 OldDataType string 62 NewName string 63 Column 64 } 65 66 // CreateTable creates the table on system 67 func (m *Migration) CreateTable(tablename, engine, charset string, p ...func()) { 68 m.TableName = tablename 69 m.Engine = engine 70 m.Charset = charset 71 m.ModifyType = "create" 72 } 73 74 // AlterTable set the ModifyType to alter 75 func (m *Migration) AlterTable(tablename string) { 76 m.TableName = tablename 77 m.ModifyType = "alter" 78 } 79 80 // NewCol creates a new standard column and attaches it to m struct 81 func (m *Migration) NewCol(name string) *Column { 82 col := &Column{Name: name} 83 m.AddColumns(col) 84 return col 85 } 86 87 //PriCol creates a new primary column and attaches it to m struct 88 func (m *Migration) PriCol(name string) *Column { 89 col := &Column{Name: name} 90 m.AddColumns(col) 91 m.AddPrimary(col) 92 return col 93 } 94 95 //UniCol creates / appends columns to specified unique key and attaches it to m struct 96 func (m *Migration) UniCol(uni, name string) *Column { 97 col := &Column{Name: name} 98 m.AddColumns(col) 99 100 uniqueOriginal := &Unique{} 101 102 for _, unique := range m.Uniques { 103 if unique.Definition == uni { 104 unique.AddColumnsToUnique(col) 105 uniqueOriginal = unique 106 } 107 } 108 if uniqueOriginal.Definition == "" { 109 unique := &Unique{Definition: uni} 110 unique.AddColumnsToUnique(col) 111 m.AddUnique(unique) 112 } 113 114 return col 115 } 116 117 //ForeignCol creates a new foreign column and returns the instance of column 118 func (m *Migration) ForeignCol(colname, foreigncol, foreigntable string) (foreign *Foreign) { 119 120 foreign = &Foreign{ForeignColumn: foreigncol, ForeignTable: foreigntable} 121 foreign.Name = colname 122 m.AddForeign(foreign) 123 return foreign 124 } 125 126 //SetOnDelete sets the on delete of foreign 127 func (foreign *Foreign) SetOnDelete(del string) *Foreign { 128 foreign.OnDelete = "ON DELETE" + del 129 return foreign 130 } 131 132 //SetOnUpdate sets the on update of foreign 133 func (foreign *Foreign) SetOnUpdate(update string) *Foreign { 134 foreign.OnUpdate = "ON UPDATE" + update 135 return foreign 136 } 137 138 //Remove marks the columns to be removed. 139 //it allows reverse m to create the column. 140 func (c *Column) Remove() { 141 c.remove = true 142 } 143 144 //SetAuto enables auto_increment of column (can be used once) 145 func (c *Column) SetAuto(inc bool) *Column { 146 if inc { 147 c.Inc = "auto_increment" 148 } 149 return c 150 } 151 152 //SetNullable sets the column to be null 153 func (c *Column) SetNullable(null bool) *Column { 154 if null { 155 c.Null = "" 156 157 } else { 158 c.Null = "NOT NULL" 159 } 160 return c 161 } 162 163 //SetDefault sets the default value, prepend with "DEFAULT " 164 func (c *Column) SetDefault(def string) *Column { 165 c.Default = "DEFAULT " + def 166 return c 167 } 168 169 //SetUnsigned sets the column to be unsigned int 170 func (c *Column) SetUnsigned(unsign bool) *Column { 171 if unsign { 172 c.Unsign = "UNSIGNED" 173 } 174 return c 175 } 176 177 //SetDataType sets the dataType of the column 178 func (c *Column) SetDataType(dataType string) *Column { 179 c.DataType = dataType 180 return c 181 } 182 183 //SetOldNullable allows reverting to previous nullable on reverse ms 184 func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn { 185 if null { 186 c.OldNull = "" 187 188 } else { 189 c.OldNull = "NOT NULL" 190 } 191 return c 192 } 193 194 //SetOldDefault allows reverting to previous default on reverse ms 195 func (c *RenameColumn) SetOldDefault(def string) *RenameColumn { 196 c.OldDefault = def 197 return c 198 } 199 200 //SetOldUnsigned allows reverting to previous unsgined on reverse ms 201 func (c *RenameColumn) SetOldUnsigned(unsign bool) *RenameColumn { 202 if unsign { 203 c.OldUnsign = "UNSIGNED" 204 } 205 return c 206 } 207 208 //SetOldDataType allows reverting to previous datatype on reverse ms 209 func (c *RenameColumn) SetOldDataType(dataType string) *RenameColumn { 210 c.OldDataType = dataType 211 return c 212 } 213 214 //SetPrimary adds the columns to the primary key (can only be used any number of times in only one m) 215 func (c *Column) SetPrimary(m *Migration) *Column { 216 m.Primary = append(m.Primary, c) 217 return c 218 } 219 220 //AddColumnsToUnique adds the columns to Unique Struct 221 func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique { 222 223 unique.Columns = append(unique.Columns, columns...) 224 225 return unique 226 } 227 228 //AddColumns adds columns to m struct 229 func (m *Migration) AddColumns(columns ...*Column) *Migration { 230 231 m.Columns = append(m.Columns, columns...) 232 233 return m 234 } 235 236 //AddPrimary adds the column to primary in m struct 237 func (m *Migration) AddPrimary(primary *Column) *Migration { 238 m.Primary = append(m.Primary, primary) 239 return m 240 } 241 242 //AddUnique adds the column to unique in m struct 243 func (m *Migration) AddUnique(unique *Unique) *Migration { 244 m.Uniques = append(m.Uniques, unique) 245 return m 246 } 247 248 //AddForeign adds the column to foreign in m struct 249 func (m *Migration) AddForeign(foreign *Foreign) *Migration { 250 m.Foreigns = append(m.Foreigns, foreign) 251 return m 252 } 253 254 //AddIndex adds the column to index in m struct 255 func (m *Migration) AddIndex(index *Index) *Migration { 256 m.Indexes = append(m.Indexes, index) 257 return m 258 } 259 260 //RenameColumn allows renaming of columns 261 func (m *Migration) RenameColumn(from, to string) *RenameColumn { 262 rename := &RenameColumn{OldName: from, NewName: to} 263 m.Renames = append(m.Renames, rename) 264 return rename 265 } 266 267 //GetSQL returns the generated sql depending on ModifyType 268 func (m *Migration) GetSQL() (sql string) { 269 sql = "" 270 switch m.ModifyType { 271 case "create": 272 { 273 sql += fmt.Sprintf("CREATE TABLE `%s` (", m.TableName) 274 for index, column := range m.Columns { 275 sql += fmt.Sprintf("\n `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) 276 if len(m.Columns) > index+1 { 277 sql += "," 278 } 279 } 280 281 if len(m.Primary) > 0 { 282 sql += fmt.Sprintf(",\n PRIMARY KEY( ") 283 } 284 for index, column := range m.Primary { 285 sql += fmt.Sprintf(" `%s`", column.Name) 286 if len(m.Primary) > index+1 { 287 sql += "," 288 } 289 290 } 291 if len(m.Primary) > 0 { 292 sql += fmt.Sprintf(")") 293 } 294 295 for _, unique := range m.Uniques { 296 sql += fmt.Sprintf(",\n UNIQUE KEY `%s`( ", unique.Definition) 297 for index, column := range unique.Columns { 298 sql += fmt.Sprintf(" `%s`", column.Name) 299 if len(unique.Columns) > index+1 { 300 sql += "," 301 } 302 } 303 sql += fmt.Sprintf(")") 304 } 305 for _, foreign := range m.Foreigns { 306 sql += fmt.Sprintf(",\n `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) 307 sql += fmt.Sprintf(",\n KEY `%s_%s_foreign`(`%s`),", m.TableName, foreign.Column.Name, foreign.Column.Name) 308 sql += fmt.Sprintf("\n CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) 309 310 } 311 sql += fmt.Sprintf(")ENGINE=%s DEFAULT CHARSET=%s;", m.Engine, m.Charset) 312 break 313 } 314 case "alter": 315 { 316 sql += fmt.Sprintf("ALTER TABLE `%s` ", m.TableName) 317 for index, column := range m.Columns { 318 if !column.remove { 319 logs.Info("col") 320 sql += fmt.Sprintf("\n ADD `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) 321 } else { 322 sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) 323 } 324 325 if len(m.Columns) > index+1 { 326 sql += "," 327 } 328 } 329 for index, column := range m.Renames { 330 sql += fmt.Sprintf("CHANGE COLUMN `%s` `%s` %s %s %s %s %s", column.OldName, column.NewName, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) 331 if len(m.Renames) > index+1 { 332 sql += "," 333 } 334 } 335 336 for index, foreign := range m.Foreigns { 337 sql += fmt.Sprintf("ADD `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) 338 sql += fmt.Sprintf(",\n ADD KEY `%s_%s_foreign`(`%s`)", m.TableName, foreign.Column.Name, foreign.Column.Name) 339 sql += fmt.Sprintf(",\n ADD CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) 340 if len(m.Foreigns) > index+1 { 341 sql += "," 342 } 343 } 344 sql += ";" 345 346 break 347 } 348 case "reverse": 349 { 350 351 sql += fmt.Sprintf("ALTER TABLE `%s`", m.TableName) 352 for index, column := range m.Columns { 353 if column.remove { 354 sql += fmt.Sprintf("\n ADD `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) 355 } else { 356 sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) 357 } 358 if len(m.Columns) > index+1 { 359 sql += "," 360 } 361 } 362 363 if len(m.Primary) > 0 { 364 sql += fmt.Sprintf("\n DROP PRIMARY KEY,") 365 } 366 367 for index, unique := range m.Uniques { 368 sql += fmt.Sprintf("\n DROP KEY `%s`", unique.Definition) 369 if len(m.Uniques) > index+1 { 370 sql += "," 371 } 372 373 } 374 for index, column := range m.Renames { 375 sql += fmt.Sprintf("\n CHANGE COLUMN `%s` `%s` %s %s %s %s", column.NewName, column.OldName, column.OldDataType, column.OldUnsign, column.OldNull, column.OldDefault) 376 if len(m.Renames) > index+1 { 377 sql += "," 378 } 379 } 380 381 for _, foreign := range m.Foreigns { 382 sql += fmt.Sprintf("\n DROP KEY `%s_%s_foreign`", m.TableName, foreign.Column.Name) 383 sql += fmt.Sprintf(",\n DROP FOREIGN KEY `%s_%s_foreign`", m.TableName, foreign.Column.Name) 384 sql += fmt.Sprintf(",\n DROP COLUMN `%s`", foreign.Name) 385 } 386 sql += ";" 387 } 388 case "delete": 389 { 390 sql += fmt.Sprintf("DROP TABLE IF EXISTS `%s`;", m.TableName) 391 } 392 } 393 394 return 395 }