Fix preload many2many problem when no search results, #688

This commit is contained in:
Jinzhu 2015-11-16 12:19:25 +08:00
parent edee5f5b75
commit 2f9abdcf02
3 changed files with 15 additions and 9 deletions

View File

@ -134,7 +134,6 @@ func (s JoinTableHandler) JoinWith(handler JoinTableHandlerInterface, db *DB, so
scope := db.NewScope(source) scope := db.NewScope(source)
modelType := scope.GetModelStruct().ModelType modelType := scope.GetModelStruct().ModelType
var joinConditions []string var joinConditions []string
var queryConditions []string
var values []interface{} var values []interface{}
if s.Source.ModelType == modelType { if s.Source.ModelType == modelType {
destinationTableName := db.NewScope(reflect.New(s.Destination.ModelType).Interface()).QuotedTableName() destinationTableName := db.NewScope(reflect.New(s.Destination.ModelType).Interface()).QuotedTableName()
@ -152,12 +151,15 @@ func (s JoinTableHandler) JoinWith(handler JoinTableHandlerInterface, db *DB, so
foreignFieldValues := scope.getColumnAsArray(foreignFieldNames) foreignFieldValues := scope.getColumnAsArray(foreignFieldNames)
condString := fmt.Sprintf("%v in (%v)", toQueryCondition(scope, foreignDBNames), toQueryMarks(foreignFieldValues)) var condString string
if len(foreignFieldValues) > 0 {
condString = fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, foreignDBNames), toQueryMarks(foreignFieldValues))
keys := scope.getColumnAsArray(foreignFieldNames) keys := scope.getColumnAsArray(foreignFieldNames)
values = append(values, toQueryValues(keys)) values = append(values, toQueryValues(keys))
} else {
queryConditions = append(queryConditions, condString) condString = fmt.Sprintf("1 <> 1")
}
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(condString, toQueryValues(foreignFieldValues)...) Where(condString, toQueryValues(foreignFieldValues)...)

View File

@ -63,7 +63,7 @@ func Preload(scope *Scope) {
case "belongs_to": case "belongs_to":
currentScope.handleBelongsToPreload(field, conditions) currentScope.handleBelongsToPreload(field, conditions)
case "many_to_many": case "many_to_many":
currentScope.handleHasManyToManyPreload(field, conditions) currentScope.handleManyToManyPreload(field, conditions)
default: default:
currentScope.Err(errors.New("not supported relation")) currentScope.Err(errors.New("not supported relation"))
} }
@ -191,9 +191,8 @@ func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{
} }
} }
func (scope *Scope) handleHasManyToManyPreload(field *Field, conditions []interface{}) { func (scope *Scope) handleManyToManyPreload(field *Field, conditions []interface{}) {
relation := field.Relationship relation := field.Relationship
joinTableHandler := relation.JoinTableHandler joinTableHandler := relation.JoinTableHandler
destType := field.StructField.Struct.Type.Elem() destType := field.StructField.Struct.Type.Elem()
var isPtr bool var isPtr bool
@ -211,6 +210,7 @@ func (scope *Scope) handleHasManyToManyPreload(field *Field, conditions []interf
db := scope.NewDB().Table(scope.New(reflect.New(destType).Interface()).TableName()).Select("*") db := scope.NewDB().Table(scope.New(reflect.New(destType).Interface()).TableName()).Select("*")
preloadJoinDB := joinTableHandler.JoinWith(joinTableHandler, db, scope.Value) preloadJoinDB := joinTableHandler.JoinWith(joinTableHandler, db, scope.Value)
if len(conditions) > 0 { if len(conditions) > 0 {
preloadJoinDB = preloadJoinDB.Where(conditions[0], conditions[1:]...) preloadJoinDB = preloadJoinDB.Where(conditions[0], conditions[1:]...)
} }

View File

@ -689,6 +689,10 @@ func TestManyToManyPreloadWithMultiPrimaryKeys(t *testing.T) {
if !reflect.DeepEqual(got4, []Level2{got, got2}) { if !reflect.DeepEqual(got4, []Level2{got, got2}) {
t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2})) t.Errorf("got %s; want %s", toJSONString(got4), toJSONString([]Level2{got, got2}))
} }
if err := DB.Preload("Level1s").Find(&got4, "value IN (?)", []string{"non-existing"}).Error; err != nil {
panic(err)
}
} }
func TestManyToManyPreloadForPointer(t *testing.T) { func TestManyToManyPreloadForPointer(t *testing.T) {