many2many lazy load

This commit is contained in:
LIRANCOHEN 2015-03-19 21:20:33 -04:00
parent 17b20bcdd8
commit 50adbf6755
2 changed files with 55 additions and 1 deletions

View File

@ -61,6 +61,9 @@ type Relationship struct {
AssociationForeignFieldName string
AssociationForeignDBName string
JoinTable string
AssociationForeignFieldName string
PivotKey string
PivotType string
}
var pluralMapKeys = []*regexp.Regexp{regexp.MustCompile("ch$"), regexp.MustCompile("ss$"), regexp.MustCompile("sh$"), regexp.MustCompile("day$"), regexp.MustCompile("y$"), regexp.MustCompile("x$"), regexp.MustCompile("([^s])s?$")}
@ -206,6 +209,9 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
if many2many := gormSettings["MANY2MANY"]; many2many != "" {
relationship.Kind = "many_to_many"
relationship.JoinTable = many2many
relationship.PivotKey = gormSettings["MANY2MANY"]
relationship.PivotType = elemType.Name() + "Id"
relationship.AssociationFieldName = elemType.Name()
associationForeignKey := gormSettings["ASSOCIATIONFOREIGNKEY"]
if associationForeignKey == "" {

View File

@ -99,7 +99,55 @@ func Preload(scope *Scope) {
}
}
case "many_to_many":
if primaryKeys := scope.getColumnAsArray(primaryName); len(primaryKeys) > 0 {
var (
key1 int
key2 int
)
condition := fmt.Sprintf("%v IN (?)", scope.Quote(relation.ForeignDBName))
pResults, _ := scope.NewDB().
Table(relation.PivotKey).
Select(relation.ForeignDBName+","+relation.AssociationForeignFieldName).
Where(condition, primaryKeys).
Rows()
keyVals := map[int][]int{}
foreignKeys := []int{}
for pResults.Next() {
err := pResults.Scan(&key1, &key2)
if err != nil {
fmt.Println(err)
}
keyVals[key1] = append(keyVals[key1], key2)
foreignKeys = append(foreignKeys, key2)
}
condition = fmt.Sprintf("%v IN (?)", scope.Quote("id"))
scope.NewDB().
Where(condition, foreignKeys).Find(results, conditions...)
resultValues := reflect.Indirect(reflect.ValueOf(results))
if isSlice {
objects := scope.IndirectValue()
for j := 0; j < objects.Len(); j++ {
object := reflect.Indirect(objects.Index(j))
objP := object.FieldByName(primaryName)
objID := int(objP.Int())
objFor := keyVals[objID]
for _, fK := range objFor {
for i := 0; i < resultValues.Len(); i++ {
result := resultValues.Index(i)
if equalAsString(getRealValue(result, primaryName), fK) {
f := object.FieldByName(field.Name)
f.Set(reflect.Append(f, result))
break
}
}
}
}
} else {
scope.Err(errors.New("not supported relation"))
}
}
default:
scope.Err(errors.New("not supported relation"))
}