Fix create foreign keys for many2many relations
This commit is contained in:
		
							parent
							
								
									5883490aa7
								
							
						
					
					
						commit
						fee1e4aafd
					
				
							
								
								
									
										7
									
								
								gorm.go
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								gorm.go
									
									
									
									
									
								
							| @ -293,6 +293,13 @@ func (db *DB) SetupJoinTable(model interface{}, field string, joinTable interfac | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for name, rel := range relation.JoinTable.Relationships.Relations { | ||||
| 			if _, ok := joinSchema.Relationships.Relations[name]; !ok { | ||||
| 				rel.Schema = joinSchema | ||||
| 				joinSchema.Relationships.Relations[name] = rel | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		relation.JoinTable = joinSchema | ||||
| 	} else { | ||||
| 		return fmt.Errorf("failed to found relation: %v", field) | ||||
|  | ||||
| @ -88,7 +88,7 @@ func (m Migrator) AutoMigrate(values ...interface{}) error { | ||||
| 				return err | ||||
| 			} | ||||
| 		} else { | ||||
| 			if err := m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||
| 			if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) { | ||||
| 				for _, field := range stmt.Schema.FieldsByDBName { | ||||
| 					if !tx.Migrator().HasColumn(value, field.DBName) { | ||||
| 						if err := tx.Migrator().AddColumn(value, field.DBName); err != nil { | ||||
| @ -120,9 +120,13 @@ func (m Migrator) AutoMigrate(values ...interface{}) error { | ||||
| 					if rel.JoinTable != nil { | ||||
| 						joinValue := reflect.New(rel.JoinTable.ModelType).Interface() | ||||
| 						if !tx.Migrator().HasTable(rel.JoinTable.Table) { | ||||
| 							defer tx.Table(rel.JoinTable.Table).Migrator().CreateTable(joinValue) | ||||
| 							defer func() { | ||||
| 								errr = tx.Table(rel.JoinTable.Table).Migrator().CreateTable(joinValue) | ||||
| 							}() | ||||
| 						} else { | ||||
| 							defer tx.Table(rel.JoinTable.Table).Migrator().AutoMigrate(joinValue) | ||||
| 							defer func() { | ||||
| 								errr = tx.Table(rel.JoinTable.Table).Migrator().AutoMigrate(joinValue) | ||||
| 							}() | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| @ -139,7 +143,7 @@ func (m Migrator) AutoMigrate(values ...interface{}) error { | ||||
| func (m Migrator) CreateTable(values ...interface{}) error { | ||||
| 	for _, value := range m.ReorderModels(values, false) { | ||||
| 		tx := m.DB.Session(&gorm.Session{}) | ||||
| 		if err := m.RunWithValue(value, func(stmt *gorm.Statement) error { | ||||
| 		if err := m.RunWithValue(value, func(stmt *gorm.Statement) (errr error) { | ||||
| 			var ( | ||||
| 				createTableSQL          = "CREATE TABLE ? (" | ||||
| 				values                  = []interface{}{clause.Table{Name: stmt.Table}} | ||||
| @ -166,7 +170,9 @@ func (m Migrator) CreateTable(values ...interface{}) error { | ||||
| 
 | ||||
| 			for _, idx := range stmt.Schema.ParseIndexes() { | ||||
| 				if m.CreateIndexAfterCreateTable { | ||||
| 					defer tx.Migrator().CreateIndex(value, idx.Name) | ||||
| 					defer func() { | ||||
| 						errr = tx.Migrator().CreateIndex(value, idx.Name) | ||||
| 					}() | ||||
| 				} else { | ||||
| 					createTableSQL += "INDEX ? ?," | ||||
| 					values = append(values, clause.Expr{SQL: idx.Name}, tx.Migrator().(BuildIndexOptionsInterface).BuildIndexOptions(idx.Fields, stmt)) | ||||
| @ -186,7 +192,9 @@ func (m Migrator) CreateTable(values ...interface{}) error { | ||||
| 				if rel.JoinTable != nil { | ||||
| 					joinValue := reflect.New(rel.JoinTable.ModelType).Interface() | ||||
| 					if !tx.Migrator().HasTable(rel.JoinTable.Table) { | ||||
| 						defer tx.Table(rel.JoinTable.Table).Migrator().CreateTable(joinValue) | ||||
| 						defer func(table string, joinValue interface{}) { | ||||
| 							errr = tx.Table(table).Migrator().CreateTable(joinValue) | ||||
| 						}(rel.JoinTable.Table, joinValue) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| @ -204,7 +212,8 @@ func (m Migrator) CreateTable(values ...interface{}) error { | ||||
| 				createTableSQL += fmt.Sprint(tableOption) | ||||
| 			} | ||||
| 
 | ||||
| 			return tx.Exec(createTableSQL, values...).Error | ||||
| 			errr = tx.Exec(createTableSQL, values...).Error | ||||
| 			return errr | ||||
| 		}); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| @ -553,6 +562,10 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i | ||||
| 			if c := rel.ParseConstraint(); c != nil && c.Schema == dep.Statement.Schema && c.Schema != c.ReferenceSchema { | ||||
| 				dep.Depends = append(dep.Depends, c.ReferenceSchema) | ||||
| 			} | ||||
| 
 | ||||
| 			if rel.JoinTable != nil && rel.Schema != rel.FieldSchema { | ||||
| 				dep.Depends = append(dep.Depends, rel.FieldSchema) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		valuesMap[dep.Schema.Table] = dep | ||||
| @ -566,6 +579,7 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i | ||||
| 		if _, ok := orderedModelNamesMap[name]; ok { | ||||
| 			return // avoid loop
 | ||||
| 		} | ||||
| 		orderedModelNamesMap[name] = true | ||||
| 
 | ||||
| 		dep := valuesMap[name] | ||||
| 		for _, d := range dep.Depends { | ||||
| @ -578,7 +592,6 @@ func (m Migrator) ReorderModels(values []interface{}, autoAdd bool) (results []i | ||||
| 		} | ||||
| 
 | ||||
| 		orderedModelNames = append(orderedModelNames, name) | ||||
| 		orderedModelNamesMap[name] = true | ||||
| 	} | ||||
| 
 | ||||
| 	for _, value := range values { | ||||
|  | ||||
| @ -46,7 +46,7 @@ func (ns NamingStrategy) JoinTableName(str string) string { | ||||
| 
 | ||||
| // RelationshipFKName generate fk name for relation
 | ||||
| func (ns NamingStrategy) RelationshipFKName(rel Relationship) string { | ||||
| 	return fmt.Sprintf("fk_%s_%s", rel.Schema.Table, toDBName(rel.Field.Name)) | ||||
| 	return fmt.Sprintf("fk_%s_%s", rel.Schema.Table, toDBName(rel.Name)) | ||||
| } | ||||
| 
 | ||||
| // CheckerName generate checker name
 | ||||
|  | ||||
| @ -253,16 +253,63 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 	relation.JoinTable.Table = schema.namer.JoinTableName(many2many) | ||||
| 	relation.JoinTable.PrimaryFields = make([]*Field, len(relation.JoinTable.Fields)) | ||||
| 
 | ||||
| 	relName := relation.Schema.Name | ||||
| 	relRefName := relation.FieldSchema.Name | ||||
| 	if relName == relRefName { | ||||
| 		relRefName = relation.Field.Name | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := relation.JoinTable.Relationships.Relations[relName]; !ok { | ||||
| 		relation.JoinTable.Relationships.Relations[relName] = &Relationship{ | ||||
| 			Name:        relName, | ||||
| 			Type:        BelongsTo, | ||||
| 			Schema:      relation.JoinTable, | ||||
| 			FieldSchema: relation.Schema, | ||||
| 		} | ||||
| 	} else { | ||||
| 		relation.JoinTable.Relationships.Relations[relName].References = []*Reference{} | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := relation.JoinTable.Relationships.Relations[relRefName]; !ok { | ||||
| 		relation.JoinTable.Relationships.Relations[relRefName] = &Relationship{ | ||||
| 			Name:        relRefName, | ||||
| 			Type:        BelongsTo, | ||||
| 			Schema:      relation.JoinTable, | ||||
| 			FieldSchema: relation.FieldSchema, | ||||
| 		} | ||||
| 	} else { | ||||
| 		relation.JoinTable.Relationships.Relations[relRefName].References = []*Reference{} | ||||
| 	} | ||||
| 
 | ||||
| 	// build references
 | ||||
| 	for idx, f := range relation.JoinTable.Fields { | ||||
| 		// use same data type for foreign keys
 | ||||
| 		f.DataType = fieldsMap[f.Name].DataType | ||||
| 		relation.JoinTable.PrimaryFields[idx] = f | ||||
| 		ownPriamryField := schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name] | ||||
| 
 | ||||
| 		if ownPriamryField { | ||||
| 			joinRel := relation.JoinTable.Relationships.Relations[relName] | ||||
| 			joinRel.Field = relation.Field | ||||
| 			joinRel.References = append(joinRel.References, &Reference{ | ||||
| 				PrimaryKey: fieldsMap[f.Name], | ||||
| 				ForeignKey: f, | ||||
| 			}) | ||||
| 		} else { | ||||
| 			joinRefRel := relation.JoinTable.Relationships.Relations[relRefName] | ||||
| 			if joinRefRel.Field == nil { | ||||
| 				joinRefRel.Field = relation.Field | ||||
| 			} | ||||
| 			joinRefRel.References = append(joinRefRel.References, &Reference{ | ||||
| 				PrimaryKey: fieldsMap[f.Name], | ||||
| 				ForeignKey: f, | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 		relation.References = append(relation.References, &Reference{ | ||||
| 			PrimaryKey:    fieldsMap[f.Name], | ||||
| 			ForeignKey:    f, | ||||
| 			OwnPrimaryKey: schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name], | ||||
| 			OwnPrimaryKey: ownPriamryField, | ||||
| 		}) | ||||
| 	} | ||||
| 	return | ||||
|  | ||||
| @ -6,9 +6,9 @@ require ( | ||||
| 	github.com/google/uuid v1.1.1 | ||||
| 	github.com/jinzhu/now v1.1.1 | ||||
| 	github.com/lib/pq v1.6.0 | ||||
| 	gorm.io/driver/mysql v0.2.2 | ||||
| 	gorm.io/driver/mysql v0.2.3 | ||||
| 	gorm.io/driver/postgres v0.2.2 | ||||
| 	gorm.io/driver/sqlite v1.0.5 | ||||
| 	gorm.io/driver/sqlite v1.0.6 | ||||
| 	gorm.io/driver/sqlserver v0.2.2 | ||||
| 	gorm.io/gorm v0.2.9 | ||||
| ) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu