From 50adbf6755bfaa923d2af1d3bdf71324bbfa60e0 Mon Sep 17 00:00:00 2001 From: LIRANCOHEN Date: Thu, 19 Mar 2015 21:20:33 -0400 Subject: [PATCH 1/2] many2many lazy load --- model_struct.go | 6 ++++++ preload.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/model_struct.go b/model_struct.go index 02e23dfe..d25b161f 100644 --- a/model_struct.go +++ b/model_struct.go @@ -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 == "" { diff --git a/preload.go b/preload.go index d252238a..09a299a9 100644 --- a/preload.go +++ b/preload.go @@ -99,7 +99,55 @@ func Preload(scope *Scope) { } } case "many_to_many": - scope.Err(errors.New("not supported relation")) + 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")) } From 7e2b6eba617182d19e9a81a974f5aba775cc8b05 Mon Sep 17 00:00:00 2001 From: LIRANCOHEN Date: Thu, 19 Mar 2015 21:26:35 -0400 Subject: [PATCH 2/2] many2many lazy load duplicate name in struct --- model_struct.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model_struct.go b/model_struct.go index d25b161f..0dca0a43 100644 --- a/model_struct.go +++ b/model_struct.go @@ -61,7 +61,7 @@ type Relationship struct { AssociationForeignFieldName string AssociationForeignDBName string JoinTable string - AssociationForeignFieldName string + AssociationFieldName string PivotKey string PivotType string }