mirror of https://github.com/go-gorm/gorm.git
Fix create database foreign keys for same type having has many/one & many2many relationships, close #3424
This commit is contained in:
parent
6de0356a57
commit
c9d5c0b07a
|
@ -586,6 +586,7 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i
|
||||||
var (
|
var (
|
||||||
modelNames, orderedModelNames []string
|
modelNames, orderedModelNames []string
|
||||||
orderedModelNamesMap = map[string]bool{}
|
orderedModelNamesMap = map[string]bool{}
|
||||||
|
parsedSchemas = map[*schema.Schema]bool{}
|
||||||
valuesMap = map[string]Dependency{}
|
valuesMap = map[string]Dependency{}
|
||||||
insertIntoOrderedList func(name string)
|
insertIntoOrderedList func(name string)
|
||||||
parseDependence func(value interface{}, addToList bool)
|
parseDependence func(value interface{}, addToList bool)
|
||||||
|
@ -595,23 +596,35 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i
|
||||||
dep := Dependency{
|
dep := Dependency{
|
||||||
Statement: &gorm.Statement{DB: m.DB, Dest: value},
|
Statement: &gorm.Statement{DB: m.DB, Dest: value},
|
||||||
}
|
}
|
||||||
|
beDependedOn := map[*schema.Schema]bool{}
|
||||||
if err := dep.Parse(value); err != nil {
|
if err := dep.Parse(value); err != nil {
|
||||||
m.DB.Logger.Error(context.Background(), "failed to parse value %#v, got error %v", value, err)
|
m.DB.Logger.Error(context.Background(), "failed to parse value %#v, got error %v", value, err)
|
||||||
}
|
}
|
||||||
|
if _, ok := parsedSchemas[dep.Statement.Schema]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parsedSchemas[dep.Statement.Schema] = true
|
||||||
|
|
||||||
for _, rel := range dep.Schema.Relationships.Relations {
|
for _, rel := range dep.Schema.Relationships.Relations {
|
||||||
if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema {
|
if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema {
|
||||||
dep.Depends = append(dep.Depends, c.ReferenceSchema)
|
dep.Depends = append(dep.Depends, c.ReferenceSchema)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rel.JoinTable != nil {
|
if rel.Type == schema.HasOne || rel.Type == schema.HasMany {
|
||||||
if rel.Schema != rel.FieldSchema {
|
beDependedOn[rel.FieldSchema] = true
|
||||||
dep.Depends = append(dep.Depends, rel.FieldSchema)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rel.JoinTable != nil {
|
||||||
// append join value
|
// append join value
|
||||||
defer func(joinValue interface{}) {
|
defer func(rel *schema.Relationship, joinValue interface{}) {
|
||||||
|
if !beDependedOn[rel.FieldSchema] {
|
||||||
|
dep.Depends = append(dep.Depends, rel.FieldSchema)
|
||||||
|
} else {
|
||||||
|
fieldValue := reflect.New(rel.FieldSchema.ModelType).Interface()
|
||||||
|
parseDependence(fieldValue, autoAdd)
|
||||||
|
}
|
||||||
parseDependence(joinValue, autoAdd)
|
parseDependence(joinValue, autoAdd)
|
||||||
}(reflect.New(rel.JoinTable.ModelType).Interface())
|
}(rel, reflect.New(rel.JoinTable.ModelType).Interface())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,8 @@ func TestEmbeddedRelations(t *testing.T) {
|
||||||
DB.Migrator().DropTable(&AdvancedUser{})
|
DB.Migrator().DropTable(&AdvancedUser{})
|
||||||
|
|
||||||
if err := DB.AutoMigrate(&AdvancedUser{}); err != nil {
|
if err := DB.AutoMigrate(&AdvancedUser{}); err != nil {
|
||||||
|
if DB.Dialector.Name() != "sqlite" {
|
||||||
t.Errorf("Failed to auto migrate advanced user, got error %v", err)
|
t.Errorf("Failed to auto migrate advanced user, got error %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue