From 4a01d4c263249af6a7e4e1abb2d85163c6dca616 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Wed, 24 Jun 2020 16:43:53 +0800 Subject: [PATCH] Create join table with ReorderModels --- migrator/migrator.go | 37 +++++++++----------------------- tests/multi_primary_keys_test.go | 27 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/migrator/migrator.go b/migrator/migrator.go index c8fe17ab..799bf433 100644 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -116,20 +116,6 @@ func (m Migrator) AutoMigrate(values ...interface{}) error { } } } - - // create join table - if rel.JoinTable != nil { - joinValue := reflect.New(rel.JoinTable.ModelType).Interface() - if !tx.Migrator().HasTable(rel.JoinTable.Table) { - defer func(table string, joinValue interface{}) { - errr = tx.Table(table).Migrator().CreateTable(joinValue) - }(rel.JoinTable.Table, joinValue) - } else { - defer func(table string, joinValue interface{}) { - errr = tx.Table(table).Migrator().AutoMigrate(joinValue) - }(rel.JoinTable.Table, joinValue) - } - } } return nil }); err != nil { @@ -193,16 +179,6 @@ func (m Migrator) CreateTable(values ...interface{}) error { } } } - - // create join table - if rel.JoinTable != nil { - joinValue := reflect.New(rel.JoinTable.ModelType).Interface() - if !tx.Migrator().HasTable(rel.JoinTable.Table) { - defer func(table string, joinValue interface{}) { - errr = tx.Table(table).Migrator().CreateTable(joinValue) - }(rel.JoinTable.Table, joinValue) - } - } } for _, chk := range stmt.Schema.ParseCheckConstraints() { @@ -551,9 +527,10 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i orderedModelNamesMap = map[string]bool{} valuesMap = map[string]Dependency{} insertIntoOrderedList func(name string) + parseDependence func(value interface{}, addToList bool) ) - parseDependence := func(value interface{}, addToList bool) { + parseDependence = func(value interface{}, addToList bool) { dep := Dependency{ Statement: &gorm.Statement{DB: m.DB, Dest: value}, } @@ -564,8 +541,14 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i dep.Depends = append(dep.Depends, c.ReferenceSchema) } - if rel.JoinTable != nil && rel.Schema != rel.FieldSchema { - dep.Depends = append(dep.Depends, rel.FieldSchema) + if rel.JoinTable != nil { + if rel.Schema != rel.FieldSchema { + dep.Depends = append(dep.Depends, rel.FieldSchema) + } + // append join value + defer func(joinValue interface{}) { + parseDependence(joinValue, autoAdd) + }(reflect.New(rel.JoinTable.ModelType).Interface()) } } diff --git a/tests/multi_primary_keys_test.go b/tests/multi_primary_keys_test.go index 05267bbb..617010c5 100644 --- a/tests/multi_primary_keys_test.go +++ b/tests/multi_primary_keys_test.go @@ -4,6 +4,8 @@ import ( "reflect" "sort" "testing" + + "gorm.io/gorm" ) type Blog struct { @@ -11,7 +13,7 @@ type Blog struct { Locale string `gorm:"primary_key"` Subject string Body string - Tags []Tag `gorm:"many2many:blog_tags;"` + Tags []Tag `gorm:"many2many:blogs_tags;"` SharedTags []Tag `gorm:"many2many:shared_blog_tags;ForeignKey:id;References:id"` LocaleTags []Tag `gorm:"many2many:locale_blog_tags;ForeignKey:id,locale;References:id"` } @@ -38,7 +40,16 @@ func TestManyToManyWithMultiPrimaryKeys(t *testing.T) { t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment") } - DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags") + if name := DB.Dialector.Name(); name == "postgres" { + stmt := gorm.Statement{DB: DB} + stmt.Parse(&Blog{}) + stmt.Schema.LookUpField("ID").Unique = true + stmt.Parse(&Tag{}) + stmt.Schema.LookUpField("ID").Unique = true + // postgers only allow unique constraint matching given keys + } + + DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil { t.Fatalf("Failed to auto migrate, got error: %v", err) } @@ -127,7 +138,11 @@ func TestManyToManyWithCustomizedForeignKeys(t *testing.T) { t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment") } - DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags") + if name := DB.Dialector.Name(); name == "postgres" { + t.Skip("skip postgers due to it only allow unique constraint matching given keys") + } + + DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil { t.Fatalf("Failed to auto migrate, got error: %v", err) } @@ -248,7 +263,11 @@ func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) { t.Skip("skip sqlite, sqlserver due to it doesn't support multiple primary keys with auto increment") } - DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags") + if name := DB.Dialector.Name(); name == "postgres" { + t.Skip("skip postgers due to it only allow unique constraint matching given keys") + } + + DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") if err := DB.AutoMigrate(&Blog{}, &Tag{}); err != nil { t.Fatalf("Failed to auto migrate, got error: %v", err) }