Fix compile error for preload

This commit is contained in:
Jinzhu 2015-07-30 18:19:49 +08:00
parent fea291e796
commit 4e8272cf9d
2 changed files with 34 additions and 31 deletions

View File

@ -205,7 +205,7 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
var foreignKeys []string var foreignKeys []string
if foreignKey, ok := gormSettings["FOREIGNKEY"]; ok { if foreignKey, ok := gormSettings["FOREIGNKEY"]; ok {
foreignKeys := append(foreignKeys, gormSettings["FOREIGNKEY"]) foreignKeys = append(foreignKeys, foreignKey)
} }
switch indirectType.Kind() { switch indirectType.Kind() {
case reflect.Slice: case reflect.Slice:

View File

@ -8,12 +8,15 @@ import (
"strings" "strings"
) )
func getRealValue(value reflect.Value, field string) interface{} { func getRealValue(value reflect.Value, columns []string) (results []interface{}) {
result := reflect.Indirect(value).FieldByName(field).Interface() for _, column := range columns {
if r, ok := result.(driver.Valuer); ok { result := reflect.Indirect(value).FieldByName(column).Interface()
result, _ = r.Value() if r, ok := result.(driver.Valuer); ok {
result, _ = r.Value()
}
results = append(results, result)
} }
return result return
} }
func equalAsString(a interface{}, b interface{}) bool { func equalAsString(a interface{}, b interface{}) bool {
@ -97,26 +100,23 @@ func makeSlice(typ reflect.Type) interface{} {
} }
func (scope *Scope) handleHasOnePreload(field *Field, conditions []interface{}) { func (scope *Scope) handleHasOnePreload(field *Field, conditions []interface{}) {
primaryName := scope.PrimaryField().Name relation := field.Relationship
primaryKeys := scope.getColumnAsArray(primaryName) primaryKeys := scope.getColumnAsArray(relation.AssociationForeignFieldNames)
if len(primaryKeys) == 0 { if len(primaryKeys) == 0 {
return return
} }
results := makeSlice(field.Struct.Type) results := makeSlice(field.Struct.Type)
relation := field.Relationship scope.Err(scope.NewDB().Where(fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.ForeignDBNames), toQueryMarks(primaryKeys)), toQueryValues(primaryKeys)...).Find(results, conditions...).Error)
condition := fmt.Sprintf("%v IN (?)", scope.Quote(relation.ForeignDBName))
scope.Err(scope.NewDB().Where(condition, primaryKeys).Find(results, conditions...).Error)
resultValues := reflect.Indirect(reflect.ValueOf(results)) resultValues := reflect.Indirect(reflect.ValueOf(results))
for i := 0; i < resultValues.Len(); i++ { for i := 0; i < resultValues.Len(); i++ {
result := resultValues.Index(i) result := resultValues.Index(i)
if scope.IndirectValue().Kind() == reflect.Slice { if scope.IndirectValue().Kind() == reflect.Slice {
value := getRealValue(result, relation.ForeignFieldName) value := getRealValue(result, relation.ForeignFieldNames)
objects := scope.IndirectValue() objects := scope.IndirectValue()
for j := 0; j < objects.Len(); j++ { for j := 0; j < objects.Len(); j++ {
if equalAsString(getRealValue(objects.Index(j), primaryName), value) { if equalAsString(getRealValue(objects.Index(j), relation.AssociationForeignFieldNames), value) {
reflect.Indirect(objects.Index(j)).FieldByName(field.Name).Set(result) reflect.Indirect(objects.Index(j)).FieldByName(field.Name).Set(result)
break break
} }
@ -131,27 +131,24 @@ func (scope *Scope) handleHasOnePreload(field *Field, conditions []interface{})
} }
func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{}) { func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{}) {
primaryName := scope.PrimaryField().Name relation := field.Relationship
primaryKeys := scope.getColumnAsArray(primaryName) primaryKeys := scope.getColumnAsArray(relation.AssociationForeignFieldNames)
if len(primaryKeys) == 0 { if len(primaryKeys) == 0 {
return return
} }
results := makeSlice(field.Struct.Type) results := makeSlice(field.Struct.Type)
relation := field.Relationship scope.Err(scope.NewDB().Where(fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.ForeignDBNames), toQueryMarks(primaryKeys)), toQueryValues(primaryKeys)...).Find(results, conditions...).Error)
condition := fmt.Sprintf("%v IN (?)", scope.Quote(relation.ForeignDBName))
scope.Err(scope.NewDB().Where(condition, primaryKeys).Find(results, conditions...).Error)
resultValues := reflect.Indirect(reflect.ValueOf(results)) resultValues := reflect.Indirect(reflect.ValueOf(results))
if scope.IndirectValue().Kind() == reflect.Slice { if scope.IndirectValue().Kind() == reflect.Slice {
for i := 0; i < resultValues.Len(); i++ { for i := 0; i < resultValues.Len(); i++ {
result := resultValues.Index(i) result := resultValues.Index(i)
value := getRealValue(result, relation.ForeignFieldName) value := getRealValue(result, relation.ForeignFieldNames)
objects := scope.IndirectValue() objects := scope.IndirectValue()
for j := 0; j < objects.Len(); j++ { for j := 0; j < objects.Len(); j++ {
object := reflect.Indirect(objects.Index(j)) object := reflect.Indirect(objects.Index(j))
if equalAsString(getRealValue(object, primaryName), value) { if equalAsString(getRealValue(object, relation.AssociationForeignFieldNames), value) {
f := object.FieldByName(field.Name) f := object.FieldByName(field.Name)
f.Set(reflect.Append(f, result)) f.Set(reflect.Append(f, result))
break break
@ -165,25 +162,23 @@ func (scope *Scope) handleHasManyPreload(field *Field, conditions []interface{})
func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{}) { func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{}) {
relation := field.Relationship relation := field.Relationship
primaryKeys := scope.getColumnAsArray(relation.ForeignFieldName) primaryKeys := scope.getColumnAsArray(relation.ForeignFieldNames)
if len(primaryKeys) == 0 { if len(primaryKeys) == 0 {
return return
} }
results := makeSlice(field.Struct.Type) results := makeSlice(field.Struct.Type)
associationPrimaryKey := scope.New(results).PrimaryField().Name scope.Err(scope.NewDB().Where(fmt.Sprintf("%v IN (%v)", toQueryCondition(scope, relation.ForeignDBNames), toQueryMarks(primaryKeys)), toQueryValues(primaryKeys)...).Find(results, conditions...).Error)
scope.Err(scope.NewDB().Where(primaryKeys).Find(results, conditions...).Error)
resultValues := reflect.Indirect(reflect.ValueOf(results)) resultValues := reflect.Indirect(reflect.ValueOf(results))
for i := 0; i < resultValues.Len(); i++ { for i := 0; i < resultValues.Len(); i++ {
result := resultValues.Index(i) result := resultValues.Index(i)
if scope.IndirectValue().Kind() == reflect.Slice { if scope.IndirectValue().Kind() == reflect.Slice {
value := getRealValue(result, associationPrimaryKey) value := getRealValue(result, relation.AssociationForeignFieldNames)
objects := scope.IndirectValue() objects := scope.IndirectValue()
for j := 0; j < objects.Len(); j++ { for j := 0; j < objects.Len(); j++ {
object := reflect.Indirect(objects.Index(j)) object := reflect.Indirect(objects.Index(j))
if equalAsString(getRealValue(object, relation.ForeignFieldName), value) { if equalAsString(getRealValue(object, relation.ForeignFieldNames), value) {
object.FieldByName(field.Name).Set(result) object.FieldByName(field.Name).Set(result)
} }
} }
@ -193,15 +188,23 @@ func (scope *Scope) handleBelongsToPreload(field *Field, conditions []interface{
} }
} }
func (scope *Scope) getColumnAsArray(column string) (columns []interface{}) { func (scope *Scope) getColumnAsArray(columns []string) (results [][]interface{}) {
values := scope.IndirectValue() values := scope.IndirectValue()
switch values.Kind() { switch values.Kind() {
case reflect.Slice: case reflect.Slice:
for i := 0; i < values.Len(); i++ { for i := 0; i < values.Len(); i++ {
columns = append(columns, reflect.Indirect(values.Index(i)).FieldByName(column).Interface()) var result []interface{}
for _, column := range columns {
result = append(result, reflect.Indirect(values.Index(i)).FieldByName(column).Interface())
}
results = append(results, result)
} }
case reflect.Struct: case reflect.Struct:
return []interface{}{values.FieldByName(column).Interface()} var result []interface{}
for _, column := range columns {
result = append(result, values.FieldByName(column).Interface())
}
return [][]interface{}{result}
} }
return return
} }