mirror of https://github.com/go-gorm/gorm.git
multpile foreign keys
This commit is contained in:
parent
82d726bbfd
commit
a29230c86f
|
@ -35,13 +35,15 @@ func Create(scope *Scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
} else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
||||||
if relationField := fields[relationship.ForeignDBName]; !scope.changeableField(relationField) {
|
for _, dbName := range relationship.ForeignDBNames {
|
||||||
|
if relationField := fields[dbName]; !scope.changeableField(relationField) {
|
||||||
columns = append(columns, scope.Quote(relationField.DBName))
|
columns = append(columns, scope.Quote(relationField.DBName))
|
||||||
sqls = append(sqls, scope.AddToVars(relationField.Field.Interface()))
|
sqls = append(sqls, scope.AddToVars(relationField.Field.Interface()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
returningKey := "*"
|
returningKey := "*"
|
||||||
primaryField := scope.PrimaryField()
|
primaryField := scope.PrimaryField()
|
||||||
|
|
|
@ -19,8 +19,13 @@ func SaveBeforeAssociations(scope *Scope) {
|
||||||
if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
||||||
value := field.Field
|
value := field.Field
|
||||||
scope.Err(scope.NewDB().Save(value.Addr().Interface()).Error)
|
scope.Err(scope.NewDB().Save(value.Addr().Interface()).Error)
|
||||||
if relationship.ForeignFieldName != "" {
|
if len(relationship.ForeignFieldNames) != 0 {
|
||||||
scope.Err(scope.SetColumn(relationship.ForeignFieldName, scope.New(value.Addr().Interface()).PrimaryKeyValue()))
|
for idx, fieldName := range relationship.ForeignFieldNames {
|
||||||
|
associationForeignName := relationship.AssociationForeignDBNames[idx]
|
||||||
|
if f, ok := scope.New(value.Addr().Interface()).FieldByName(associationForeignName); ok {
|
||||||
|
scope.Err(scope.SetColumn(fieldName, f.Field.Interface()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +49,13 @@ func SaveAfterAssociations(scope *Scope) {
|
||||||
elem := value.Index(i).Addr().Interface()
|
elem := value.Index(i).Addr().Interface()
|
||||||
newScope := newDB.NewScope(elem)
|
newScope := newDB.NewScope(elem)
|
||||||
|
|
||||||
if relationship.JoinTableHandler == nil && relationship.ForeignFieldName != "" {
|
if relationship.JoinTableHandler == nil && len(relationship.ForeignFieldNames) != 0 {
|
||||||
scope.Err(newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue()))
|
for idx, fieldName := range relationship.ForeignFieldNames {
|
||||||
|
associationForeignName := relationship.AssociationForeignDBNames[idx]
|
||||||
|
if f, ok := scope.New(value.Addr().Interface()).FieldByName(associationForeignName); ok {
|
||||||
|
scope.Err(scope.SetColumn(fieldName, f.Field.Interface()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if relationship.PolymorphicType != "" {
|
if relationship.PolymorphicType != "" {
|
||||||
|
@ -61,8 +71,13 @@ func SaveAfterAssociations(scope *Scope) {
|
||||||
default:
|
default:
|
||||||
elem := value.Addr().Interface()
|
elem := value.Addr().Interface()
|
||||||
newScope := scope.New(elem)
|
newScope := scope.New(elem)
|
||||||
if relationship.ForeignFieldName != "" {
|
if len(relationship.ForeignFieldNames) != 0 {
|
||||||
scope.Err(newScope.SetColumn(relationship.ForeignFieldName, scope.PrimaryKeyValue()))
|
for idx, fieldName := range relationship.ForeignFieldNames {
|
||||||
|
associationForeignName := relationship.AssociationForeignDBNames[idx]
|
||||||
|
if f, ok := scope.New(value.Addr().Interface()).FieldByName(associationForeignName); ok {
|
||||||
|
scope.Err(scope.SetColumn(fieldName, f.Field.Interface()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if relationship.PolymorphicType != "" {
|
if relationship.PolymorphicType != "" {
|
||||||
|
|
|
@ -55,9 +55,10 @@ func Update(scope *Scope) {
|
||||||
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface())))
|
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(field.DBName), scope.AddToVars(field.Field.Interface())))
|
||||||
}
|
}
|
||||||
} else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
} else if relationship := field.Relationship; relationship != nil && relationship.Kind == "belongs_to" {
|
||||||
if relationField := fields[relationship.ForeignDBName]; !scope.changeableField(relationField) {
|
for _, dbName := range relationship.ForeignDBNames {
|
||||||
if !relationField.IsBlank {
|
if relationField := fields[dbName]; !scope.changeableField(relationField) && !relationField.IsBlank {
|
||||||
sqls = append(sqls, fmt.Sprintf("%v = %v", scope.Quote(relationField.DBName), scope.AddToVars(relationField.Field.Interface())))
|
sql := fmt.Sprintf("%v = %v", scope.Quote(relationField.DBName), scope.AddToVars(relationField.Field.Interface()))
|
||||||
|
sqls = append(sqls, sql)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,41 +45,18 @@ func (s *JoinTableHandler) Setup(relationship *Relationship, tableName string, s
|
||||||
s.TableName = tableName
|
s.TableName = tableName
|
||||||
|
|
||||||
s.Source = JoinTableSource{ModelType: source}
|
s.Source = JoinTableSource{ModelType: source}
|
||||||
sourceScope := &Scope{Value: reflect.New(source).Interface()}
|
for idx, dbName := range relationship.ForeignFieldNames {
|
||||||
sourcePrimaryFields := sourceScope.GetModelStruct().PrimaryFields
|
|
||||||
for _, primaryField := range sourcePrimaryFields {
|
|
||||||
if relationship.ForeignDBName == "" {
|
|
||||||
relationship.ForeignFieldName = source.Name() + primaryField.Name
|
|
||||||
relationship.ForeignDBName = ToDBName(relationship.ForeignFieldName)
|
|
||||||
}
|
|
||||||
|
|
||||||
var dbName string
|
|
||||||
if len(sourcePrimaryFields) == 1 || primaryField.DBName == "id" {
|
|
||||||
dbName = relationship.ForeignDBName
|
|
||||||
} else {
|
|
||||||
dbName = ToDBName(source.Name() + primaryField.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Source.ForeignKeys = append(s.Source.ForeignKeys, JoinTableForeignKey{
|
s.Source.ForeignKeys = append(s.Source.ForeignKeys, JoinTableForeignKey{
|
||||||
DBName: dbName,
|
DBName: relationship.ForeignDBNames[idx],
|
||||||
AssociationDBName: primaryField.DBName,
|
AssociationDBName: dbName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Destination = JoinTableSource{ModelType: destination}
|
s.Destination = JoinTableSource{ModelType: destination}
|
||||||
destinationScope := &Scope{Value: reflect.New(destination).Interface()}
|
for idx, dbName := range relationship.AssociationForeignFieldNames {
|
||||||
destinationPrimaryFields := destinationScope.GetModelStruct().PrimaryFields
|
|
||||||
for _, primaryField := range destinationPrimaryFields {
|
|
||||||
var dbName string
|
|
||||||
if len(sourcePrimaryFields) == 1 || primaryField.DBName == "id" {
|
|
||||||
dbName = relationship.AssociationForeignDBName
|
|
||||||
} else {
|
|
||||||
dbName = ToDBName(destinationScope.GetModelStruct().ModelType.Name() + primaryField.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Destination.ForeignKeys = append(s.Destination.ForeignKeys, JoinTableForeignKey{
|
s.Destination.ForeignKeys = append(s.Destination.ForeignKeys, JoinTableForeignKey{
|
||||||
DBName: dbName,
|
DBName: relationship.AssociationForeignDBNames[idx],
|
||||||
AssociationDBName: primaryField.DBName,
|
AssociationDBName: dbName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -445,7 +445,7 @@ func (s *DB) Association(column string) *Association {
|
||||||
err = errors.New("primary key can't be nil")
|
err = errors.New("primary key can't be nil")
|
||||||
} else {
|
} else {
|
||||||
if field, ok := scope.FieldByName(column); ok {
|
if field, ok := scope.FieldByName(column); ok {
|
||||||
if field.Relationship == nil || field.Relationship.ForeignFieldName == "" {
|
if field.Relationship == nil || len(field.Relationship.ForeignFieldNames) == 0 {
|
||||||
err = fmt.Errorf("invalid association %v for %v", column, scope.IndirectValue().Type())
|
err = fmt.Errorf("invalid association %v for %v", column, scope.IndirectValue().Type())
|
||||||
} else {
|
} else {
|
||||||
return &Association{Scope: scope, Column: column, PrimaryKey: primaryField.Field.Interface(), Field: field}
|
return &Association{Scope: scope, Column: column, PrimaryKey: primaryField.Field.Interface(), Field: field}
|
||||||
|
|
118
model_struct.go
118
model_struct.go
|
@ -64,10 +64,10 @@ type Relationship struct {
|
||||||
Kind string
|
Kind string
|
||||||
PolymorphicType string
|
PolymorphicType string
|
||||||
PolymorphicDBName string
|
PolymorphicDBName string
|
||||||
ForeignFieldName string
|
ForeignFieldNames []string
|
||||||
ForeignDBName string
|
ForeignDBNames []string
|
||||||
AssociationForeignFieldName string
|
AssociationForeignFieldNames []string
|
||||||
AssociationForeignDBName string
|
AssociationForeignDBNames []string
|
||||||
JoinTableHandler JoinTableHandlerInterface
|
JoinTableHandler JoinTableHandlerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,12 +190,11 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
|
|
||||||
var relationship = &Relationship{}
|
var relationship = &Relationship{}
|
||||||
|
|
||||||
foreignKey := gormSettings["FOREIGNKEY"]
|
|
||||||
if polymorphic := gormSettings["POLYMORPHIC"]; polymorphic != "" {
|
if polymorphic := gormSettings["POLYMORPHIC"]; polymorphic != "" {
|
||||||
if polymorphicField := getForeignField(polymorphic+"Id", toScope.GetStructFields()); polymorphicField != nil {
|
if polymorphicField := getForeignField(polymorphic+"Id", toScope.GetStructFields()); polymorphicField != nil {
|
||||||
if polymorphicType := getForeignField(polymorphic+"Type", toScope.GetStructFields()); polymorphicType != nil {
|
if polymorphicType := getForeignField(polymorphic+"Type", toScope.GetStructFields()); polymorphicType != nil {
|
||||||
relationship.ForeignFieldName = polymorphicField.Name
|
relationship.ForeignFieldNames = []string{polymorphicField.Name}
|
||||||
relationship.ForeignDBName = polymorphicField.DBName
|
relationship.ForeignDBNames = []string{polymorphicField.DBName}
|
||||||
relationship.PolymorphicType = polymorphicType.Name
|
relationship.PolymorphicType = polymorphicType.Name
|
||||||
relationship.PolymorphicDBName = polymorphicType.DBName
|
relationship.PolymorphicDBName = polymorphicType.DBName
|
||||||
polymorphicType.IsForeignKey = true
|
polymorphicType.IsForeignKey = true
|
||||||
|
@ -204,6 +203,10 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var foreignKeys []string
|
||||||
|
if foreignKey, ok := gormSettings["FOREIGNKEY"]; ok {
|
||||||
|
foreignKeys := append(foreignKeys, gormSettings["FOREIGNKEY"])
|
||||||
|
}
|
||||||
switch indirectType.Kind() {
|
switch indirectType.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
elemType := indirectType.Elem()
|
elemType := indirectType.Elem()
|
||||||
|
@ -212,34 +215,63 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
if elemType.Kind() == reflect.Struct {
|
if elemType.Kind() == reflect.Struct {
|
||||||
if foreignKey == "" {
|
|
||||||
foreignKey = scopeType.Name() + "Id"
|
|
||||||
}
|
|
||||||
|
|
||||||
if many2many := gormSettings["MANY2MANY"]; many2many != "" {
|
if many2many := gormSettings["MANY2MANY"]; many2many != "" {
|
||||||
relationship.Kind = "many_to_many"
|
relationship.Kind = "many_to_many"
|
||||||
associationForeignKey := gormSettings["ASSOCIATIONFOREIGNKEY"]
|
|
||||||
if associationForeignKey == "" {
|
// foreign keys
|
||||||
associationForeignKey = elemType.Name() + "Id"
|
if len(foreignKeys) == 0 {
|
||||||
|
for _, field := range scope.PrimaryFields() {
|
||||||
|
foreignKeys = append(foreignKeys, field.DBName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relationship.ForeignFieldName = foreignKey
|
for _, foreignKey := range foreignKeys {
|
||||||
relationship.ForeignDBName = ToDBName(foreignKey)
|
if field, ok := scope.FieldByName(foreignKey); ok {
|
||||||
relationship.AssociationForeignFieldName = associationForeignKey
|
relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, field.DBName)
|
||||||
relationship.AssociationForeignDBName = ToDBName(associationForeignKey)
|
joinTableDBName := ToDBName(scopeType.Name()) + "_" + field.DBName
|
||||||
|
relationship.ForeignDBNames = append(relationship.ForeignDBNames, joinTableDBName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// association foreign keys
|
||||||
|
var associationForeignKeys []string
|
||||||
|
if foreignKey := gormSettings["ASSOCIATIONFOREIGNKEY"]; foreignKey != "" {
|
||||||
|
associationForeignKeys = []string{gormSettings["ASSOCIATIONFOREIGNKEY"]}
|
||||||
|
} else {
|
||||||
|
for _, field := range toScope.PrimaryFields() {
|
||||||
|
associationForeignKeys = append(associationForeignKeys, field.DBName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range associationForeignKeys {
|
||||||
|
if field, ok := toScope.FieldByName(name); ok {
|
||||||
|
relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, name)
|
||||||
|
joinTableDBName := ToDBName(elemType.Name()) + "_" + field.DBName
|
||||||
|
relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, joinTableDBName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
joinTableHandler := JoinTableHandler{}
|
joinTableHandler := JoinTableHandler{}
|
||||||
joinTableHandler.Setup(relationship, many2many, scopeType, elemType)
|
joinTableHandler.Setup(relationship, many2many, scopeType, elemType)
|
||||||
relationship.JoinTableHandler = &joinTableHandler
|
relationship.JoinTableHandler = &joinTableHandler
|
||||||
field.Relationship = relationship
|
field.Relationship = relationship
|
||||||
} else {
|
} else {
|
||||||
|
if len(foreignKeys) == 0 {
|
||||||
|
for _, field := range scope.PrimaryFields() {
|
||||||
|
foreignKeys = append(foreignKeys, scopeType.Name()+field.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
relationship.Kind = "has_many"
|
relationship.Kind = "has_many"
|
||||||
|
for _, foreignKey := range foreignKeys {
|
||||||
if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil {
|
if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil {
|
||||||
relationship.ForeignFieldName = foreignField.Name
|
relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
|
||||||
relationship.ForeignDBName = foreignField.DBName
|
relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
|
||||||
foreignField.IsForeignKey = true
|
foreignField.IsForeignKey = true
|
||||||
field.Relationship = relationship
|
}
|
||||||
} else if relationship.ForeignFieldName != "" {
|
}
|
||||||
|
|
||||||
|
if len(relationship.ForeignFieldNames) != 0 {
|
||||||
field.Relationship = relationship
|
field.Relationship = relationship
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,28 +290,42 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
belongsToForeignKey := foreignKey
|
belongsToForeignKeys := foreignKeys
|
||||||
if belongsToForeignKey == "" {
|
if len(belongsToForeignKeys) == 0 {
|
||||||
belongsToForeignKey = field.Name + "Id"
|
for _, field := range toScope.PrimaryFields() {
|
||||||
|
belongsToForeignKeys = append(belongsToForeignKeys, field.Name+field.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if foreignField := getForeignField(belongsToForeignKey, fields); foreignField != nil {
|
for _, foreignKey := range belongsToForeignKeys {
|
||||||
relationship.Kind = "belongs_to"
|
if foreignField := getForeignField(foreignKey, fields); foreignField != nil {
|
||||||
relationship.ForeignFieldName = foreignField.Name
|
relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
|
||||||
relationship.ForeignDBName = foreignField.DBName
|
relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
|
||||||
foreignField.IsForeignKey = true
|
foreignField.IsForeignKey = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(relationship.ForeignFieldNames) != 0 {
|
||||||
|
relationship.Kind = "belongs_to"
|
||||||
field.Relationship = relationship
|
field.Relationship = relationship
|
||||||
} else {
|
} else {
|
||||||
if foreignKey == "" {
|
hasOneForeignKeys := foreignKeys
|
||||||
foreignKey = modelStruct.ModelType.Name() + "Id"
|
if len(hasOneForeignKeys) == 0 {
|
||||||
|
for _, field := range toScope.PrimaryFields() {
|
||||||
|
hasOneForeignKeys = append(hasOneForeignKeys, modelStruct.ModelType.Name()+field.Name)
|
||||||
}
|
}
|
||||||
relationship.Kind = "has_one"
|
}
|
||||||
|
|
||||||
|
for _, foreignKey := range hasOneForeignKeys {
|
||||||
if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil {
|
if foreignField := getForeignField(foreignKey, toScope.GetStructFields()); foreignField != nil {
|
||||||
relationship.ForeignFieldName = foreignField.Name
|
relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
|
||||||
relationship.ForeignDBName = foreignField.DBName
|
relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
|
||||||
foreignField.IsForeignKey = true
|
foreignField.IsForeignKey = true
|
||||||
field.Relationship = relationship
|
}
|
||||||
} else if relationship.ForeignFieldName != "" {
|
}
|
||||||
|
|
||||||
|
if len(relationship.ForeignFieldNames) != 0 {
|
||||||
|
relationship.Kind = "has_one"
|
||||||
field.Relationship = relationship
|
field.Relationship = relationship
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue