gorm/tests/migrate_test.go

361 lines
11 KiB
Go
Raw Normal View History

2020-05-23 18:50:48 +03:00
package tests_test
2020-02-22 14:41:01 +03:00
import (
2020-02-22 19:18:12 +03:00
"math/rand"
2020-05-31 05:38:01 +03:00
"strings"
2020-02-22 14:41:01 +03:00
"testing"
2020-02-22 19:18:12 +03:00
"time"
2020-02-22 14:41:01 +03:00
2020-06-02 04:16:07 +03:00
"gorm.io/gorm"
2020-06-02 05:34:50 +03:00
. "gorm.io/gorm/utils/tests"
2020-02-22 14:41:01 +03:00
)
2020-05-23 18:50:48 +03:00
func TestMigrate(t *testing.T) {
2020-02-22 18:08:20 +03:00
allModels := []interface{}{&User{}, &Account{}, &Pet{}, &Company{}, &Toy{}, &Language{}}
2020-02-22 19:18:12 +03:00
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] })
2020-02-22 14:41:01 +03:00
DB.Migrator().DropTable("user_speaks", "user_friends")
2020-05-23 18:50:48 +03:00
if err := DB.Migrator().DropTable(allModels...); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to drop table, got error %v", err)
2020-02-22 15:57:29 +03:00
}
2020-05-23 18:50:48 +03:00
if err := DB.AutoMigrate(allModels...); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to auto migrate, but got error %v", err)
2020-02-22 15:57:29 +03:00
}
2020-02-22 14:41:01 +03:00
for _, m := range allModels {
2020-05-23 18:50:48 +03:00
if !DB.Migrator().HasTable(m) {
2020-06-01 19:24:16 +03:00
t.Fatalf("Failed to create table for %#v---", m)
2020-02-22 14:41:01 +03:00
}
}
for _, indexes := range [][2]string{
{"user_speaks", "fk_user_speaks_user"},
{"user_speaks", "fk_user_speaks_language"},
{"user_friends", "fk_user_friends_user"},
{"user_friends", "fk_user_friends_friends"},
{"accounts", "fk_users_account"},
{"users", "fk_users_team"},
{"users", "fk_users_company"},
} {
if !DB.Migrator().HasConstraint(indexes[0], indexes[1]) {
t.Fatalf("Failed to find index for many2many for %v %v", indexes[0], indexes[1])
}
}
}
2020-08-23 10:40:19 +03:00
func TestSmartMigrateColumn(t *testing.T) {
2020-10-22 09:00:10 +03:00
fullSupported := map[string]bool{"mysql": true, "postgres": true}[DB.Dialector.Name()]
2020-08-23 10:40:19 +03:00
type UserMigrateColumn struct {
ID uint
Name string
Salary float64
2020-10-22 09:00:10 +03:00
Birthday time.Time `gorm:"precision:4"`
2020-08-23 10:40:19 +03:00
}
DB.Migrator().DropTable(&UserMigrateColumn{})
DB.AutoMigrate(&UserMigrateColumn{})
type UserMigrateColumn2 struct {
ID uint
Name string `gorm:"size:128"`
Salary float64 `gorm:"precision:2"`
Birthday time.Time `gorm:"precision:2"`
NameIgnoreMigration string `gorm:"size:100"`
2020-08-23 10:40:19 +03:00
}
if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn2{}); err != nil {
t.Fatalf("failed to auto migrate, got error: %v", err)
}
columnTypes, err := DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{})
if err != nil {
t.Fatalf("failed to get column types, got error: %v", err)
}
for _, columnType := range columnTypes {
switch columnType.Name() {
case "name":
2020-10-22 09:00:10 +03:00
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 128 {
2020-08-23 10:40:19 +03:00
t.Fatalf("name's length should be 128, but got %v", length)
}
case "salary":
2020-10-22 09:00:10 +03:00
if precision, o, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 {
2020-08-23 10:40:19 +03:00
t.Fatalf("salary's precision should be 2, but got %v %v", precision, o)
}
case "birthday":
2020-10-22 09:00:10 +03:00
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 2 {
2020-08-23 10:40:19 +03:00
t.Fatalf("birthday's precision should be 2, but got %v", precision)
}
}
}
type UserMigrateColumn3 struct {
ID uint
Name string `gorm:"size:256"`
Salary float64 `gorm:"precision:3"`
Birthday time.Time `gorm:"precision:3"`
NameIgnoreMigration string `gorm:"size:128;-:migration"`
2020-08-23 10:40:19 +03:00
}
if err := DB.Table("user_migrate_columns").AutoMigrate(&UserMigrateColumn3{}); err != nil {
t.Fatalf("failed to auto migrate, got error: %v", err)
}
columnTypes, err = DB.Table("user_migrate_columns").Migrator().ColumnTypes(&UserMigrateColumn{})
if err != nil {
t.Fatalf("failed to get column types, got error: %v", err)
}
for _, columnType := range columnTypes {
switch columnType.Name() {
case "name":
2020-10-22 09:00:10 +03:00
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 256 {
2020-08-23 10:40:19 +03:00
t.Fatalf("name's length should be 128, but got %v", length)
}
case "salary":
2020-10-22 09:00:10 +03:00
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 {
2020-08-23 10:40:19 +03:00
t.Fatalf("salary's precision should be 2, but got %v", precision)
}
case "birthday":
2020-10-22 09:00:10 +03:00
if precision, _, _ := columnType.DecimalSize(); (fullSupported || precision != 0) && precision != 3 {
2020-08-23 10:40:19 +03:00
t.Fatalf("birthday's precision should be 2, but got %v", precision)
}
case "name_ignore_migration":
if length, _ := columnType.Length(); (fullSupported || length != 0) && length != 100 {
t.Fatalf("name_ignore_migration's length should still be 100 but got %v", length)
}
2020-08-23 10:40:19 +03:00
}
}
}
func TestMigrateWithComment(t *testing.T) {
type UserWithComment struct {
gorm.Model
Name string `gorm:"size:111;index:,comment:这是一个index;comment:this is a 字段"`
}
if err := DB.Migrator().DropTable(&UserWithComment{}); err != nil {
t.Fatalf("Failed to drop table, got error %v", err)
}
if err := DB.AutoMigrate(&UserWithComment{}); err != nil {
t.Fatalf("Failed to auto migrate, but got error %v", err)
}
2020-02-22 14:41:01 +03:00
}
2020-05-30 17:27:20 +03:00
func TestMigrateWithUniqueIndex(t *testing.T) {
type UserWithUniqueIndex struct {
ID int
Name string `gorm:"size:20;index:idx_name,unique"`
Date time.Time `gorm:"index:idx_name,unique"`
}
DB.Migrator().DropTable(&UserWithUniqueIndex{})
if err := DB.AutoMigrate(&UserWithUniqueIndex{}); err != nil {
t.Fatalf("failed to migrate, got %v", err)
}
if !DB.Migrator().HasIndex(&UserWithUniqueIndex{}, "idx_name") {
t.Errorf("Failed to find created index")
}
}
2020-07-19 16:30:24 +03:00
func TestMigrateTable(t *testing.T) {
2020-05-31 05:24:49 +03:00
type TableStruct struct {
gorm.Model
Name string
}
DB.Migrator().DropTable(&TableStruct{})
DB.AutoMigrate(&TableStruct{})
if !DB.Migrator().HasTable(&TableStruct{}) {
t.Fatalf("should found created table")
}
type NewTableStruct struct {
gorm.Model
Name string
}
if err := DB.Migrator().RenameTable(&TableStruct{}, &NewTableStruct{}); err != nil {
t.Fatalf("Failed to rename table, got error %v", err)
}
if !DB.Migrator().HasTable("new_table_structs") {
t.Fatal("should found renamed table")
}
DB.Migrator().DropTable("new_table_structs")
if DB.Migrator().HasTable(&NewTableStruct{}) {
t.Fatal("should not found droped table")
}
}
2020-07-19 16:30:24 +03:00
func TestMigrateIndexes(t *testing.T) {
2020-05-30 19:42:52 +03:00
type IndexStruct struct {
2020-05-30 17:27:20 +03:00
gorm.Model
2020-05-30 19:42:52 +03:00
Name string `gorm:"size:255;index"`
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
DB.Migrator().DropTable(&IndexStruct{})
DB.AutoMigrate(&IndexStruct{})
if err := DB.Migrator().DropIndex(&IndexStruct{}, "Name"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to drop index for user's name, got err %v", err)
2020-05-30 19:42:52 +03:00
}
if err := DB.Migrator().CreateIndex(&IndexStruct{}, "Name"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Got error when tried to create index: %+v", err)
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if !DB.Migrator().HasIndex(&IndexStruct{}, "Name") {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to find index for user's name")
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if err := DB.Migrator().DropIndex(&IndexStruct{}, "Name"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to drop index for user's name, got err %v", err)
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if DB.Migrator().HasIndex(&IndexStruct{}, "Name") {
2020-05-31 05:24:49 +03:00
t.Fatalf("Should not find index for user's name after delete")
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if err := DB.Migrator().CreateIndex(&IndexStruct{}, "Name"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Got error when tried to create index: %+v", err)
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if err := DB.Migrator().RenameIndex(&IndexStruct{}, "idx_index_structs_name", "idx_users_name_1"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("no error should happen when rename index, but got %v", err)
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if !DB.Migrator().HasIndex(&IndexStruct{}, "idx_users_name_1") {
2020-05-31 05:24:49 +03:00
t.Fatalf("Should find index for user's name after rename")
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if err := DB.Migrator().DropIndex(&IndexStruct{}, "idx_users_name_1"); err != nil {
2020-05-31 05:24:49 +03:00
t.Fatalf("Failed to drop index for user's name, got err %v", err)
2020-05-30 17:27:20 +03:00
}
2020-05-30 19:42:52 +03:00
if DB.Migrator().HasIndex(&IndexStruct{}, "idx_users_name_1") {
2020-05-31 05:24:49 +03:00
t.Fatalf("Should not find index for user's name after delete")
2020-05-30 17:27:20 +03:00
}
}
2020-05-30 19:42:52 +03:00
2020-07-19 16:30:24 +03:00
func TestMigrateColumns(t *testing.T) {
2020-05-30 19:42:52 +03:00
type ColumnStruct struct {
gorm.Model
Name string
}
DB.Migrator().DropTable(&ColumnStruct{})
if err := DB.AutoMigrate(&ColumnStruct{}); err != nil {
t.Errorf("Failed to migrate, got %v", err)
}
2020-05-31 05:38:01 +03:00
type ColumnStruct2 struct {
gorm.Model
Name string `gorm:"size:100"`
}
if err := DB.Table("column_structs").Migrator().AlterColumn(&ColumnStruct2{}, "Name"); err != nil {
2020-06-07 10:24:34 +03:00
t.Fatalf("no error should happened when alter column, but got %v", err)
2020-05-31 05:38:01 +03:00
}
if columnTypes, err := DB.Migrator().ColumnTypes(&ColumnStruct{}); err != nil {
t.Fatalf("no error should returns for ColumnTypes")
} else {
stmt := &gorm.Statement{DB: DB}
stmt.Parse(&ColumnStruct2{})
for _, columnType := range columnTypes {
if columnType.Name() == "name" {
dataType := DB.Dialector.DataTypeOf(stmt.Schema.LookUpField(columnType.Name()))
if !strings.Contains(strings.ToUpper(dataType), strings.ToUpper(columnType.DatabaseTypeName())) {
t.Errorf("column type should be correct, name: %v, length: %v, expects: %v", columnType.Name(), columnType.DatabaseTypeName(), dataType)
}
}
}
}
2020-05-30 19:42:52 +03:00
type NewColumnStruct struct {
gorm.Model
Name string
NewName string
}
if err := DB.Table("column_structs").Migrator().AddColumn(&NewColumnStruct{}, "NewName"); err != nil {
t.Fatalf("Failed to add column, got %v", err)
2020-05-30 19:42:52 +03:00
}
if !DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
t.Fatalf("Failed to find added column")
2020-05-30 19:42:52 +03:00
}
if err := DB.Table("column_structs").Migrator().DropColumn(&NewColumnStruct{}, "NewName"); err != nil {
t.Fatalf("Failed to add column, got %v", err)
2020-05-30 19:42:52 +03:00
}
if DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "NewName") {
t.Fatalf("Found deleted column")
}
if err := DB.Table("column_structs").Migrator().AddColumn(&NewColumnStruct{}, "NewName"); err != nil {
t.Fatalf("Failed to add column, got %v", err)
}
if err := DB.Table("column_structs").Migrator().RenameColumn(&NewColumnStruct{}, "NewName", "new_new_name"); err != nil {
t.Fatalf("Failed to add column, got %v", err)
}
if !DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "new_new_name") {
t.Fatalf("Failed to found renamed column")
}
if err := DB.Table("column_structs").Migrator().DropColumn(&NewColumnStruct{}, "new_new_name"); err != nil {
t.Fatalf("Failed to add column, got %v", err)
}
if DB.Table("column_structs").Migrator().HasColumn(&NewColumnStruct{}, "new_new_name") {
t.Fatalf("Found deleted column")
2020-05-30 19:42:52 +03:00
}
}
2021-01-26 08:39:34 +03:00
func TestMigrateConstraint(t *testing.T) {
if DB.Dialector.Name() == "sqlite" {
t.Skip()
}
names := []string{"Account", "fk_users_account", "Pets", "fk_users_pets", "Company", "fk_users_company", "Team", "fk_users_team", "Languages", "fk_users_languages"}
2021-01-26 08:39:34 +03:00
for _, name := range names {
if !DB.Migrator().HasConstraint(&User{}, name) {
DB.Migrator().CreateConstraint(&User{}, name)
}
if err := DB.Migrator().DropConstraint(&User{}, name); err != nil {
t.Fatalf("failed to drop constraint %v, got error %v", name, err)
}
if DB.Migrator().HasConstraint(&User{}, name) {
t.Fatalf("constraint %v should been deleted", name)
}
if err := DB.Migrator().CreateConstraint(&User{}, name); err != nil {
t.Fatalf("failed to create constraint %v, got error %v", name, err)
}
if !DB.Migrator().HasConstraint(&User{}, name) {
t.Fatalf("failed to found constraint %v", name)
}
}
}