Test override foreign key, reference
This commit is contained in:
		
							parent
							
								
									aa959ec383
								
							
						
					
					
						commit
						49310d0974
					
				| @ -168,31 +168,76 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | |||||||
| 		joinTableFields []reflect.StructField | 		joinTableFields []reflect.StructField | ||||||
| 		fieldsMap       = map[string]*Field{} | 		fieldsMap       = map[string]*Field{} | ||||||
| 		ownFieldsMap    = map[string]bool{} // fix self join many2many
 | 		ownFieldsMap    = map[string]bool{} // fix self join many2many
 | ||||||
|  | 		joinForeignKeys = toColumns(field.TagSettings["JOINFOREIGNKEY"]) | ||||||
|  | 		joinReferences  = toColumns(field.TagSettings["JOINREFERENCES"]) | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	for _, s := range []*Schema{schema, relation.FieldSchema} { | 	ownForeignFields := schema.PrimaryFields | ||||||
| 		for _, primaryField := range s.PrimaryFields { | 	refForeignFields := relation.FieldSchema.PrimaryFields | ||||||
| 			fieldName := s.Name + primaryField.Name |  | ||||||
| 			if _, ok := fieldsMap[fieldName]; ok { |  | ||||||
| 				if field.Name != s.Name { |  | ||||||
| 					fieldName = inflection.Singular(field.Name) + primaryField.Name |  | ||||||
| 				} else { |  | ||||||
| 					fieldName = s.Name + primaryField.Name + "Reference" |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				ownFieldsMap[fieldName] = true |  | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			fieldsMap[fieldName] = primaryField | 	if len(relation.foreignKeys) > 0 { | ||||||
| 			joinTableFields = append(joinTableFields, reflect.StructField{ | 		ownForeignFields = []*Field{} | ||||||
| 				Name:    fieldName, | 		for _, foreignKey := range relation.foreignKeys { | ||||||
| 				PkgPath: primaryField.StructField.PkgPath, | 			if field := schema.LookUpField(foreignKey); field != nil { | ||||||
| 				Type:    primaryField.StructField.Type, | 				ownForeignFields = append(ownForeignFields, field) | ||||||
| 				Tag:     removeSettingFromTag(primaryField.StructField.Tag, "column"), | 			} else { | ||||||
| 			}) | 				schema.err = fmt.Errorf("invalid foreign key: %v", foreignKey) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if len(relation.primaryKeys) > 0 { | ||||||
|  | 		refForeignFields = []*Field{} | ||||||
|  | 		for _, foreignKey := range relation.primaryKeys { | ||||||
|  | 			if field := relation.FieldSchema.LookUpField(foreignKey); field != nil { | ||||||
|  | 				refForeignFields = append(refForeignFields, field) | ||||||
|  | 			} else { | ||||||
|  | 				schema.err = fmt.Errorf("invalid foreign key: %v", foreignKey) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for idx, ownField := range ownForeignFields { | ||||||
|  | 		joinFieldName := schema.Name + ownField.Name | ||||||
|  | 		if len(joinForeignKeys) > idx { | ||||||
|  | 			joinFieldName = joinForeignKeys[idx] | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ownFieldsMap[joinFieldName] = true | ||||||
|  | 		fieldsMap[joinFieldName] = ownField | ||||||
|  | 		joinTableFields = append(joinTableFields, reflect.StructField{ | ||||||
|  | 			Name:    joinFieldName, | ||||||
|  | 			PkgPath: ownField.StructField.PkgPath, | ||||||
|  | 			Type:    ownField.StructField.Type, | ||||||
|  | 			Tag:     removeSettingFromTag(ownField.StructField.Tag, "column"), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for idx, relField := range refForeignFields { | ||||||
|  | 		joinFieldName := relation.FieldSchema.Name + relField.Name | ||||||
|  | 		if len(joinReferences) > idx { | ||||||
|  | 			joinFieldName = joinReferences[idx] | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if _, ok := ownFieldsMap[joinFieldName]; ok { | ||||||
|  | 			if field.Name != relation.FieldSchema.Name { | ||||||
|  | 				joinFieldName = inflection.Singular(field.Name) + relField.Name | ||||||
|  | 			} else { | ||||||
|  | 				joinFieldName += "Reference" | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		fieldsMap[joinFieldName] = relField | ||||||
|  | 		joinTableFields = append(joinTableFields, reflect.StructField{ | ||||||
|  | 			Name:    joinFieldName, | ||||||
|  | 			PkgPath: relField.StructField.PkgPath, | ||||||
|  | 			Type:    relField.StructField.Type, | ||||||
|  | 			Tag:     removeSettingFromTag(relField.StructField.Tag, "column"), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil { | 	if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil { | ||||||
| 		schema.err = err | 		schema.err = err | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										199
									
								
								schema/relationship_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								schema/relationship_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | |||||||
|  | package schema_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"sync" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jinzhu/gorm" | ||||||
|  | 	"github.com/jinzhu/gorm/schema" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func checkStructRelation(t *testing.T, data interface{}, relations ...Relation) { | ||||||
|  | 	if s, err := schema.Parse(data, &sync.Map{}, schema.NamingStrategy{}); err != nil { | ||||||
|  | 		t.Errorf("Failed to parse schema") | ||||||
|  | 	} else { | ||||||
|  | 		for _, rel := range relations { | ||||||
|  | 			checkSchemaRelation(t, s, rel) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestBelongsToOverrideForeignKey(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name string | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profile      Profile `gorm:"ForeignKey:ProfileRefer"` | ||||||
|  | 		ProfileRefer int | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"ID", "Profile", "ProfileRefer", "User", "", false}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestBelongsToOverrideReferences(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Refer string | ||||||
|  | 		Name  string | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profile   Profile `gorm:"ForeignKey:ProfileID;References:Refer"` | ||||||
|  | 		ProfileID int | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.BelongsTo, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"Refer", "Profile", "ProfileID", "User", "", false}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestHasOneOverrideForeignKey(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name      string | ||||||
|  | 		UserRefer uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profile Profile `gorm:"ForeignKey:UserRefer"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestHasOneOverrideReferences(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name   string | ||||||
|  | 		UserID uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Refer   string | ||||||
|  | 		Profile Profile `gorm:"ForeignKey:UserID;References:Refer"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.HasOne, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestHasManyOverrideForeignKey(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name      string | ||||||
|  | 		UserRefer uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profile []Profile `gorm:"ForeignKey:UserRefer"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"ID", "User", "UserRefer", "Profile", "", true}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestHasManyOverrideReferences(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name   string | ||||||
|  | 		UserID uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Refer   string | ||||||
|  | 		Profile []Profile `gorm:"ForeignKey:UserID;References:Refer"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profile", Type: schema.HasMany, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		References: []Reference{{"Refer", "User", "UserID", "Profile", "", true}}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMany2ManyOverrideForeignKeyAndReferences(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name      string | ||||||
|  | 		UserRefer uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;JoinForeignKey:UserReferID;References:UserRefer;JoinReferences:ProfileRefer"` | ||||||
|  | 		Refer    uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"}, | ||||||
|  | 		References: []Reference{ | ||||||
|  | 			{"Refer", "User", "UserReferID", "user_profiles", "", true}, | ||||||
|  | 			{"UserRefer", "Profile", "ProfileRefer", "user_profiles", "", false}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMany2ManyOverrideForeignKey(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name      string | ||||||
|  | 		UserRefer uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profiles []Profile `gorm:"many2many:user_profiles;ForeignKey:Refer;References:UserRefer"` | ||||||
|  | 		Refer    uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"}, | ||||||
|  | 		References: []Reference{ | ||||||
|  | 			{"Refer", "User", "UserRefer", "user_profiles", "", true}, | ||||||
|  | 			{"UserRefer", "Profile", "ProfileUserRefer", "user_profiles", "", false}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMany2ManyOverrideJoinForeignKey(t *testing.T) { | ||||||
|  | 	type Profile struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Name      string | ||||||
|  | 		UserRefer uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type User struct { | ||||||
|  | 		gorm.Model | ||||||
|  | 		Profiles []Profile `gorm:"many2many:user_profiles;JoinForeignKey:UserReferID;JoinReferences:ProfileRefer"` | ||||||
|  | 		Refer    uint | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	checkStructRelation(t, &User{}, Relation{ | ||||||
|  | 		Name: "Profiles", Type: schema.Many2Many, Schema: "User", FieldSchema: "Profile", | ||||||
|  | 		JoinTable: JoinTable{Name: "user_profiles", Table: "user_profiles"}, | ||||||
|  | 		References: []Reference{ | ||||||
|  | 			{"ID", "User", "UserReferID", "user_profiles", "", true}, | ||||||
|  | 			{"ID", "Profile", "ProfileRefer", "user_profiles", "", false}, | ||||||
|  | 		}, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
| @ -127,7 +127,7 @@ func checkSchemaRelation(t *testing.T, s *schema.Schema, relation Relation) { | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if r.FieldSchema.Name != relation.FieldSchema { | 			if r.FieldSchema.Name != relation.FieldSchema { | ||||||
| 				t.Errorf("schema %v relation's schema expects %v, but got %v", s, relation.Schema, r.Schema.Name) | 				t.Errorf("schema %v field relation's schema expects %v, but got %v", s, relation.FieldSchema, r.FieldSchema.Name) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if r.Polymorphic != nil { | 			if r.Polymorphic != nil { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu