Allow shared foreign key for many2many jointable
This commit is contained in:
		
							parent
							
								
									1f634c3937
								
							
						
					
					
						commit
						3a72ba102e
					
				| @ -191,7 +191,8 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 		err             error | ||||
| 		joinTableFields []reflect.StructField | ||||
| 		fieldsMap       = map[string]*Field{} | ||||
| 		ownFieldsMap    = map[string]bool{} // fix self join many2many
 | ||||
| 		ownFieldsMap    = map[string]*Field{} // fix self join many2many
 | ||||
| 		referFieldsMap  = map[string]*Field{} | ||||
| 		joinForeignKeys = toColumns(field.TagSettings["JOINFOREIGNKEY"]) | ||||
| 		joinReferences  = toColumns(field.TagSettings["JOINREFERENCES"]) | ||||
| 	) | ||||
| @ -229,7 +230,7 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 			joinFieldName = strings.Title(joinForeignKeys[idx]) | ||||
| 		} | ||||
| 
 | ||||
| 		ownFieldsMap[joinFieldName] = true | ||||
| 		ownFieldsMap[joinFieldName] = ownField | ||||
| 		fieldsMap[joinFieldName] = ownField | ||||
| 		joinTableFields = append(joinTableFields, reflect.StructField{ | ||||
| 			Name:    joinFieldName, | ||||
| @ -242,9 +243,6 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 
 | ||||
| 	for idx, relField := range refForeignFields { | ||||
| 		joinFieldName := strings.Title(relation.FieldSchema.Name) + relField.Name | ||||
| 		if len(joinReferences) > idx { | ||||
| 			joinFieldName = strings.Title(joinReferences[idx]) | ||||
| 		} | ||||
| 
 | ||||
| 		if _, ok := ownFieldsMap[joinFieldName]; ok { | ||||
| 			if field.Name != relation.FieldSchema.Name { | ||||
| @ -254,14 +252,22 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		fieldsMap[joinFieldName] = relField | ||||
| 		joinTableFields = append(joinTableFields, reflect.StructField{ | ||||
| 			Name:    joinFieldName, | ||||
| 			PkgPath: relField.StructField.PkgPath, | ||||
| 			Type:    relField.StructField.Type, | ||||
| 			Tag: removeSettingFromTag(appendSettingFromTag(relField.StructField.Tag, "primaryKey"), | ||||
| 				"column", "autoincrement", "index", "unique", "uniqueindex"), | ||||
| 		}) | ||||
| 		if len(joinReferences) > idx { | ||||
| 			joinFieldName = strings.Title(joinReferences[idx]) | ||||
| 		} | ||||
| 
 | ||||
| 		referFieldsMap[joinFieldName] = relField | ||||
| 
 | ||||
| 		if _, ok := fieldsMap[joinFieldName]; !ok { | ||||
| 			fieldsMap[joinFieldName] = relField | ||||
| 			joinTableFields = append(joinTableFields, reflect.StructField{ | ||||
| 				Name:    joinFieldName, | ||||
| 				PkgPath: relField.StructField.PkgPath, | ||||
| 				Type:    relField.StructField.Type, | ||||
| 				Tag: removeSettingFromTag(appendSettingFromTag(relField.StructField.Tag, "primaryKey"), | ||||
| 					"column", "autoincrement", "index", "unique", "uniqueindex"), | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	joinTableFields = append(joinTableFields, reflect.StructField{ | ||||
| @ -317,31 +323,37 @@ func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Fiel | ||||
| 				f.Size = fieldsMap[f.Name].Size | ||||
| 			} | ||||
| 			relation.JoinTable.PrimaryFields = append(relation.JoinTable.PrimaryFields, f) | ||||
| 			ownPrimaryField := schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name] | ||||
| 
 | ||||
| 			if ownPrimaryField { | ||||
| 			if of, ok := ownFieldsMap[f.Name]; ok { | ||||
| 				joinRel := relation.JoinTable.Relationships.Relations[relName] | ||||
| 				joinRel.Field = relation.Field | ||||
| 				joinRel.References = append(joinRel.References, &Reference{ | ||||
| 					PrimaryKey: fieldsMap[f.Name], | ||||
| 					PrimaryKey: of, | ||||
| 					ForeignKey: f, | ||||
| 				}) | ||||
| 			} else { | ||||
| 
 | ||||
| 				relation.References = append(relation.References, &Reference{ | ||||
| 					PrimaryKey:    of, | ||||
| 					ForeignKey:    f, | ||||
| 					OwnPrimaryKey: true, | ||||
| 				}) | ||||
| 			} | ||||
| 
 | ||||
| 			if rf, ok := referFieldsMap[f.Name]; ok { | ||||
| 				joinRefRel := relation.JoinTable.Relationships.Relations[relRefName] | ||||
| 				if joinRefRel.Field == nil { | ||||
| 					joinRefRel.Field = relation.Field | ||||
| 				} | ||||
| 				joinRefRel.References = append(joinRefRel.References, &Reference{ | ||||
| 					PrimaryKey: fieldsMap[f.Name], | ||||
| 					PrimaryKey: rf, | ||||
| 					ForeignKey: f, | ||||
| 				}) | ||||
| 
 | ||||
| 				relation.References = append(relation.References, &Reference{ | ||||
| 					PrimaryKey: rf, | ||||
| 					ForeignKey: f, | ||||
| 				}) | ||||
| 			} | ||||
| 
 | ||||
| 			relation.References = append(relation.References, &Reference{ | ||||
| 				PrimaryKey:    fieldsMap[f.Name], | ||||
| 				ForeignKey:    f, | ||||
| 				OwnPrimaryKey: ownPrimaryField, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -10,7 +10,7 @@ import ( | ||||
| 
 | ||||
| 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") | ||||
| 		t.Errorf("Failed to parse schema, got error %v", err) | ||||
| 	} else { | ||||
| 		for _, rel := range relations { | ||||
| 			checkSchemaRelation(t, s, rel) | ||||
| @ -305,6 +305,33 @@ func TestMany2ManyOverrideForeignKey(t *testing.T) { | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func TestMany2ManySharedForeignKey(t *testing.T) { | ||||
| 	type Profile struct { | ||||
| 		gorm.Model | ||||
| 		Name         string | ||||
| 		Kind         string | ||||
| 		ProfileRefer uint | ||||
| 	} | ||||
| 
 | ||||
| 	type User struct { | ||||
| 		gorm.Model | ||||
| 		Profiles []Profile `gorm:"many2many:user_profiles;foreignKey:Refer,Kind;joinForeignKey:UserRefer,Kind;References:ProfileRefer,Kind;joinReferences:ProfileR,Kind"` | ||||
| 		Kind     string | ||||
| 		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}, | ||||
| 			{"Kind", "User", "Kind", "user_profiles", "", true}, | ||||
| 			{"ProfileRefer", "Profile", "ProfileR", "user_profiles", "", false}, | ||||
| 			{"Kind", "Profile", "Kind", "user_profiles", "", false}, | ||||
| 		}, | ||||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func TestMany2ManyOverrideJoinForeignKey(t *testing.T) { | ||||
| 	type Profile struct { | ||||
| 		gorm.Model | ||||
|  | ||||
							
								
								
									
										13
									
								
								tests/go.mod
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								tests/go.mod
									
									
									
									
									
								
							| @ -3,17 +3,18 @@ module gorm.io/gorm/tests | ||||
| go 1.16 | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/denisenkom/go-mssqldb v0.12.2 // indirect | ||||
| 	github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect | ||||
| 	github.com/google/uuid v1.3.0 | ||||
| 	github.com/jinzhu/now v1.1.5 | ||||
| 	github.com/lib/pq v1.10.6 | ||||
| 	github.com/mattn/go-sqlite3 v1.14.14 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect | ||||
| 	gorm.io/driver/mysql v1.3.5 | ||||
| 	gorm.io/driver/postgres v1.3.8 | ||||
| 	github.com/lib/pq v1.10.7 | ||||
| 	github.com/mattn/go-sqlite3 v1.14.15 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 // indirect | ||||
| 	gorm.io/driver/mysql v1.3.6 | ||||
| 	gorm.io/driver/postgres v1.3.10 | ||||
| 	gorm.io/driver/sqlite v1.3.6 | ||||
| 	gorm.io/driver/sqlserver v1.3.2 | ||||
| 	gorm.io/gorm v1.23.8 | ||||
| 	gorm.io/gorm v1.23.9 | ||||
| ) | ||||
| 
 | ||||
| replace gorm.io/gorm => ../ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jinzhu
						Jinzhu