mirror of https://github.com/go-gorm/gorm.git
Refactor JoinTableHandler
This commit is contained in:
parent
9af0563496
commit
94a5ebe5b4
|
@ -1,14 +1,16 @@
|
||||||
package gorm
|
package gorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JoinTableHandlerInterface interface {
|
type JoinTableHandlerInterface interface {
|
||||||
|
Setup(relationship *Relationship, tableName string, source reflect.Type, destination reflect.Type)
|
||||||
Table(db *DB) string
|
Table(db *DB) string
|
||||||
Add(db *DB, source1 interface{}, source2 interface{}) error
|
Add(db *DB, source interface{}, destination interface{}) error
|
||||||
Delete(db *DB, sources ...interface{}) error
|
Delete(db *DB, sources ...interface{}) error
|
||||||
JoinWith(db *DB, source interface{}) *DB
|
JoinWith(db *DB, source interface{}) *DB
|
||||||
}
|
}
|
||||||
|
@ -29,22 +31,24 @@ type JoinTableHandler struct {
|
||||||
Destination JoinTableSource `sql:"-"`
|
Destination JoinTableSource `sql:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateJoinTableHandler(relationship *Relationship) {
|
func (s *JoinTableHandler) Setup(relationship *Relationship, tableName string, source reflect.Type, destination reflect.Type) {
|
||||||
handler := relationship.JoinTableHandler.(*JoinTableHandler)
|
s.TableName = tableName
|
||||||
|
|
||||||
destinationScope := &Scope{Value: reflect.New(handler.Destination.ModelType).Interface()}
|
s.Source = JoinTableSource{ModelType: source}
|
||||||
for _, primaryField := range destinationScope.GetModelStruct().PrimaryFields {
|
sourceScope := &Scope{Value: reflect.New(source).Interface()}
|
||||||
db := relationship.AssociationForeignDBName
|
for _, primaryField := range sourceScope.GetModelStruct().PrimaryFields {
|
||||||
handler.Destination.ForeignKeys = append(handler.Destination.ForeignKeys, JoinTableForeignKey{
|
db := relationship.ForeignDBName
|
||||||
|
s.Source.ForeignKeys = append(s.Source.ForeignKeys, JoinTableForeignKey{
|
||||||
DBName: db,
|
DBName: db,
|
||||||
AssociationDBName: primaryField.DBName,
|
AssociationDBName: primaryField.DBName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceScope := &Scope{Value: reflect.New(handler.Source.ModelType).Interface()}
|
s.Destination = JoinTableSource{ModelType: destination}
|
||||||
for _, primaryField := range sourceScope.GetModelStruct().PrimaryFields {
|
destinationScope := &Scope{Value: reflect.New(destination).Interface()}
|
||||||
db := relationship.ForeignDBName
|
for _, primaryField := range destinationScope.GetModelStruct().PrimaryFields {
|
||||||
handler.Source.ForeignKeys = append(handler.Source.ForeignKeys, JoinTableForeignKey{
|
db := relationship.AssociationForeignDBName
|
||||||
|
s.Destination.ForeignKeys = append(s.Destination.ForeignKeys, JoinTableForeignKey{
|
||||||
DBName: db,
|
DBName: db,
|
||||||
AssociationDBName: primaryField.DBName,
|
AssociationDBName: primaryField.DBName,
|
||||||
})
|
})
|
||||||
|
@ -136,18 +140,10 @@ func (s JoinTableHandler) JoinWith(db *DB, source interface{}) *DB {
|
||||||
queryConditions = append(queryConditions, fmt.Sprintf("%v.%v = ?", quotedTable, scope.Quote(foreignKey.DBName)))
|
queryConditions = append(queryConditions, fmt.Sprintf("%v.%v = ?", quotedTable, scope.Quote(foreignKey.DBName)))
|
||||||
values = append(values, scope.Fields()[foreignKey.AssociationDBName].Field.Interface())
|
values = append(values, scope.Fields()[foreignKey.AssociationDBName].Field.Interface())
|
||||||
}
|
}
|
||||||
} else if s.Destination.ModelType == modelType {
|
|
||||||
for _, foreignKey := range s.Source.ForeignKeys {
|
|
||||||
sourceTableName := scope.New(reflect.New(s.Source.ModelType).Interface()).QuotedTableName()
|
|
||||||
joinConditions = append(joinConditions, fmt.Sprintf("%v.%v = %v.%v", quotedTable, scope.Quote(foreignKey.DBName), sourceTableName, scope.Quote(foreignKey.AssociationDBName)))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, foreignKey := range s.Destination.ForeignKeys {
|
|
||||||
queryConditions = append(queryConditions, fmt.Sprintf("%v.%v = ?", quotedTable, scope.Quote(foreignKey.DBName)))
|
|
||||||
values = append(values, scope.Fields()[foreignKey.AssociationDBName].Field.Interface())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return db.Joins(fmt.Sprintf("INNER JOIN %v ON %v", quotedTable, strings.Join(joinConditions, " AND "))).
|
return db.Joins(fmt.Sprintf("INNER JOIN %v ON %v", quotedTable, strings.Join(joinConditions, " AND "))).
|
||||||
Where(strings.Join(queryConditions, " AND "), values...)
|
Where(strings.Join(queryConditions, " AND "), values...)
|
||||||
|
} else {
|
||||||
|
db.Error = errors.New("wrong source type for join table handler")
|
||||||
|
return db
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,16 +15,13 @@ type Person struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PersonAddress struct {
|
type PersonAddress struct {
|
||||||
|
gorm.JoinTableHandler
|
||||||
PersonID int
|
PersonID int
|
||||||
AddressID int
|
AddressID int
|
||||||
DeletedAt time.Time
|
DeletedAt time.Time
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*PersonAddress) Table(db *gorm.DB) string {
|
|
||||||
return "person_addresses"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*PersonAddress) Add(db *gorm.DB, foreignValue interface{}, associationValue interface{}) error {
|
func (*PersonAddress) Add(db *gorm.DB, foreignValue interface{}, associationValue interface{}) error {
|
||||||
return db.Where(map[string]interface{}{
|
return db.Where(map[string]interface{}{
|
||||||
"person_id": db.NewScope(foreignValue).PrimaryKeyValue(),
|
"person_id": db.NewScope(foreignValue).PrimaryKeyValue(),
|
||||||
|
@ -32,7 +29,7 @@ func (*PersonAddress) Add(db *gorm.DB, foreignValue interface{}, associationValu
|
||||||
}).Assign(map[string]interface{}{
|
}).Assign(map[string]interface{}{
|
||||||
"person_id": foreignValue,
|
"person_id": foreignValue,
|
||||||
"address_id": associationValue,
|
"address_id": associationValue,
|
||||||
"DeletedAt": gorm.Expr("NULL"),
|
"deleted_at": gorm.Expr("NULL"),
|
||||||
}).FirstOrCreate(&PersonAddress{}).Error
|
}).FirstOrCreate(&PersonAddress{}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
main.go
5
main.go
|
@ -473,8 +473,13 @@ func (s *DB) Get(name string) (value interface{}, ok bool) {
|
||||||
func (s *DB) SetJoinTableHandler(source interface{}, column string, handler JoinTableHandlerInterface) {
|
func (s *DB) SetJoinTableHandler(source interface{}, column string, handler JoinTableHandlerInterface) {
|
||||||
for _, field := range s.NewScope(source).GetModelStruct().StructFields {
|
for _, field := range s.NewScope(source).GetModelStruct().StructFields {
|
||||||
if field.Name == column || field.DBName == column {
|
if field.Name == column || field.DBName == column {
|
||||||
|
if many2many := parseTagSetting(field.Tag.Get("gorm"))["MANY2MANY"]; many2many != "" {
|
||||||
|
source := (&Scope{Value: source}).GetModelStruct().ModelType
|
||||||
|
destination := (&Scope{Value: reflect.New(field.Struct.Type).Interface()}).GetModelStruct().ModelType
|
||||||
|
handler.Setup(field.Relationship, many2many, source, destination)
|
||||||
field.Relationship.JoinTableHandler = handler
|
field.Relationship.JoinTableHandler = handler
|
||||||
s.Table(handler.Table(s)).AutoMigrate(handler)
|
s.Table(handler.Table(s)).AutoMigrate(handler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,13 +215,10 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
|
||||||
relationship.ForeignDBName = ToDBName(foreignKey)
|
relationship.ForeignDBName = ToDBName(foreignKey)
|
||||||
relationship.AssociationForeignFieldName = associationForeignKey
|
relationship.AssociationForeignFieldName = associationForeignKey
|
||||||
relationship.AssociationForeignDBName = ToDBName(associationForeignKey)
|
relationship.AssociationForeignDBName = ToDBName(associationForeignKey)
|
||||||
relationship.JoinTableHandler = &JoinTableHandler{
|
|
||||||
TableName: many2many,
|
|
||||||
Source: JoinTableSource{ModelType: scopeType},
|
|
||||||
Destination: JoinTableSource{ModelType: elemType},
|
|
||||||
}
|
|
||||||
updateJoinTableHandler(relationship)
|
|
||||||
|
|
||||||
|
joinTableHandler := JoinTableHandler{}
|
||||||
|
joinTableHandler.Setup(relationship, many2many, scopeType, elemType)
|
||||||
|
relationship.JoinTableHandler = &joinTableHandler
|
||||||
field.Relationship = relationship
|
field.Relationship = relationship
|
||||||
} else {
|
} else {
|
||||||
relationship.Kind = "has_many"
|
relationship.Kind = "has_many"
|
||||||
|
|
Loading…
Reference in New Issue