Fix NamedArguments with nested struct, close #3596

This commit is contained in:
Jinzhu 2020-10-13 15:32:25 +08:00
parent 689d6e2331
commit 08ecef8e0b
2 changed files with 22 additions and 9 deletions

View File

@ -91,19 +91,28 @@ func (expr NamedExpr) Build(builder Builder) {
namedMap[k] = v namedMap[k] = v
} }
default: default:
reflectValue := reflect.Indirect(reflect.ValueOf(value)) var appendFieldsToMap func(reflect.Value)
appendFieldsToMap = func(reflectValue reflect.Value) {
reflectValue = reflect.Indirect(reflectValue)
switch reflectValue.Kind() { switch reflectValue.Kind() {
case reflect.Struct: case reflect.Struct:
modelType := reflectValue.Type() modelType := reflectValue.Type()
for i := 0; i < modelType.NumField(); i++ { for i := 0; i < modelType.NumField(); i++ {
if fieldStruct := modelType.Field(i); ast.IsExported(fieldStruct.Name) { if fieldStruct := modelType.Field(i); ast.IsExported(fieldStruct.Name) {
namedMap[fieldStruct.Name] = reflectValue.Field(i).Interface() namedMap[fieldStruct.Name] = reflectValue.Field(i).Interface()
if fieldStruct.Anonymous {
appendFieldsToMap(reflectValue.Field(i))
} }
} }
} }
} }
} }
appendFieldsToMap(reflect.ValueOf(value))
}
}
name := make([]byte, 0, 10) name := make([]byte, 0, 10)
for _, v := range []byte(expr.SQL) { for _, v := range []byte(expr.SQL) {

View File

@ -37,9 +37,13 @@ func TestExpr(t *testing.T) {
} }
func TestNamedExpr(t *testing.T) { func TestNamedExpr(t *testing.T) {
type Base struct {
Name2 string
}
type NamedArgument struct { type NamedArgument struct {
Name1 string Name1 string
Name2 string Base
} }
results := []struct { results := []struct {
@ -73,7 +77,7 @@ func TestNamedExpr(t *testing.T) {
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil}, ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil},
}, { }, {
SQL: "@@test AND name1 = @Name1 AND name2 = @Name2 AND name3 = @Name1 @Notexist", SQL: "@@test AND name1 = @Name1 AND name2 = @Name2 AND name3 = @Name1 @Notexist",
Vars: []interface{}{NamedArgument{Name1: "jinzhu", Name2: "jinzhu2"}}, Vars: []interface{}{NamedArgument{Name1: "jinzhu", Base: Base{Name2: "jinzhu2"}}},
Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? ?", Result: "@@test AND name1 = ? AND name2 = ? AND name3 = ? ?",
ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil}, ExpectedVars: []interface{}{"jinzhu", "jinzhu2", "jinzhu", nil},
}, { }, {