ReorderModels reorder models according to constraint dependencies
(values []interface{}, autoAdd bool)
| 917 | |
| 918 | // ReorderModels reorder models according to constraint dependencies |
| 919 | func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []interface{}) { |
| 920 | type Dependency struct { |
| 921 | *gorm.Statement |
| 922 | Depends []*schema.Schema |
| 923 | } |
| 924 | |
| 925 | var ( |
| 926 | modelNames, orderedModelNames []string |
| 927 | orderedModelNamesMap = map[string]bool{} |
| 928 | parsedSchemas = map[*schema.Schema]bool{} |
| 929 | valuesMap = map[string]Dependency{} |
| 930 | insertIntoOrderedList func(name string) |
| 931 | parseDependence func(value interface{}, addToList bool) |
| 932 | ) |
| 933 | |
| 934 | parseDependence = func(value interface{}, addToList bool) { |
| 935 | dep := Dependency{ |
| 936 | Statement: &gorm.Statement{DB: m.DB, Dest: value}, |
| 937 | } |
| 938 | beDependedOn := map[*schema.Schema]bool{} |
| 939 | // support for special table name |
| 940 | if err := dep.ParseWithSpecialTableName(value, m.DB.Statement.Table); err != nil { |
| 941 | m.DB.Logger.Error(context.Background(), "failed to parse value %#v, got error %v", value, err) |
| 942 | } |
| 943 | if _, ok := parsedSchemas[dep.Statement.Schema]; ok { |
| 944 | return |
| 945 | } |
| 946 | parsedSchemas[dep.Statement.Schema] = true |
| 947 | |
| 948 | if !m.DB.IgnoreRelationshipsWhenMigrating { |
| 949 | for _, rel := range dep.Schema.Relationships.Relations { |
| 950 | if rel.Field.IgnoreMigration { |
| 951 | continue |
| 952 | } |
| 953 | if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema { |
| 954 | dep.Depends = append(dep.Depends, c.ReferenceSchema) |
| 955 | } |
| 956 | |
| 957 | if rel.Type == schema.HasOne || rel.Type == schema.HasMany { |
| 958 | beDependedOn[rel.FieldSchema] = true |
| 959 | } |
| 960 | |
| 961 | if rel.JoinTable != nil { |
| 962 | // append join value |
| 963 | defer func(rel *schema.Relationship, joinValue interface{}) { |
| 964 | if !beDependedOn[rel.FieldSchema] { |
| 965 | dep.Depends = append(dep.Depends, rel.FieldSchema) |
| 966 | } else { |
| 967 | fieldValue := reflect.New(rel.FieldSchema.ModelType).Interface() |
| 968 | parseDependence(fieldValue, autoAdd) |
| 969 | } |
| 970 | parseDependence(joinValue, autoAdd) |
| 971 | }(rel, reflect.New(rel.JoinTable.ModelType).Interface()) |
| 972 | } |
| 973 | } |
| 974 | } |
| 975 | |
| 976 | valuesMap[dep.Schema.Table] = dep |
no test coverage detected