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")) }