mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
improve ScanList for package gdb; improve Structs for package gconv
This commit is contained in:
parent
72251b880a
commit
8ae0bd148b
@ -207,7 +207,12 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
e := reflect.New(bindToAttrType.Elem()).Elem()
|
||||
var element reflect.Value
|
||||
if bindToAttrValue.IsNil() {
|
||||
element = reflect.New(bindToAttrType.Elem()).Elem()
|
||||
} else {
|
||||
element = bindToAttrValue.Elem()
|
||||
}
|
||||
if len(relationDataMap) > 0 {
|
||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||
if relationFromAttrField.IsValid() {
|
||||
@ -216,7 +221,7 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
||||
// There's no relational data.
|
||||
continue
|
||||
}
|
||||
if err = gconv.Struct(v, e); err != nil {
|
||||
if err = gconv.Struct(v, element); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@ -229,14 +234,13 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
||||
// There's no relational data.
|
||||
continue
|
||||
}
|
||||
if err = gconv.Struct(v, e); err != nil {
|
||||
if err = gconv.Struct(v, element); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
bindToAttrValue.Set(e.Addr())
|
||||
bindToAttrValue.Set(element.Addr())
|
||||
|
||||
case reflect.Struct:
|
||||
e := reflect.New(bindToAttrType).Elem()
|
||||
if len(relationDataMap) > 0 {
|
||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||
if relationFromAttrField.IsValid() {
|
||||
@ -245,7 +249,7 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
||||
// There's no relational data.
|
||||
continue
|
||||
}
|
||||
if err = gconv.Struct(relationDataItem, e); err != nil {
|
||||
if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@ -258,11 +262,10 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
||||
// There's no relational data.
|
||||
continue
|
||||
}
|
||||
if err = gconv.Struct(relationDataItem, e); err != nil {
|
||||
if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
bindToAttrValue.Set(e)
|
||||
|
||||
default:
|
||||
return gerror.Newf(`unsupported attribute type: %s`, bindToAttrKind.String())
|
||||
|
@ -336,3 +336,323 @@ func TestResult_Structs1(t *testing.T) {
|
||||
t.Assert(array[1].Name, "smith")
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/1159
|
||||
func Test_ScanList_NoRecreate_PtrAttribute(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type S1 struct {
|
||||
Id int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S3 struct {
|
||||
One *S1
|
||||
}
|
||||
var (
|
||||
s []*S3
|
||||
err error
|
||||
)
|
||||
r1 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"name": gvar.New("john"),
|
||||
"age": gvar.New(16),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"name": gvar.New("smith"),
|
||||
"age": gvar.New(18),
|
||||
},
|
||||
}
|
||||
err = r1.ScanList(&s, "One")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
|
||||
r2 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"age": gvar.New(20),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"age": gvar.New(21),
|
||||
},
|
||||
}
|
||||
err = r2.ScanList(&s, "One", "One", "id:Id")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 20)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 21)
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/1159
|
||||
func Test_ScanList_NoRecreate_StructAttribute(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type S1 struct {
|
||||
Id int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S3 struct {
|
||||
One S1
|
||||
}
|
||||
var (
|
||||
s []*S3
|
||||
err error
|
||||
)
|
||||
r1 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"name": gvar.New("john"),
|
||||
"age": gvar.New(16),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"name": gvar.New("smith"),
|
||||
"age": gvar.New(18),
|
||||
},
|
||||
}
|
||||
err = r1.ScanList(&s, "One")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
|
||||
r2 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"age": gvar.New(20),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"age": gvar.New(21),
|
||||
},
|
||||
}
|
||||
err = r2.ScanList(&s, "One", "One", "id:Id")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 20)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 21)
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/1159
|
||||
func Test_ScanList_NoRecreate_SliceAttribute_Ptr(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type S1 struct {
|
||||
Id int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S2 struct {
|
||||
Id int
|
||||
Pid int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S3 struct {
|
||||
One *S1
|
||||
Many []*S2
|
||||
}
|
||||
var (
|
||||
s []*S3
|
||||
err error
|
||||
)
|
||||
r1 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"name": gvar.New("john"),
|
||||
"age": gvar.New(16),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"name": gvar.New("smith"),
|
||||
"age": gvar.New(18),
|
||||
},
|
||||
}
|
||||
err = r1.ScanList(&s, "One")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
|
||||
r2 := Result{
|
||||
Record{
|
||||
"id": gvar.New(100),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(30),
|
||||
"name": gvar.New("john"),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(200),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(31),
|
||||
"name": gvar.New("smith"),
|
||||
},
|
||||
}
|
||||
err = r2.ScanList(&s, "Many", "One", "pid:Id")
|
||||
//fmt.Printf("%+v", err)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(len(s[0].Many), 2)
|
||||
t.Assert(s[0].Many[0].Name, "john")
|
||||
t.Assert(s[0].Many[0].Age, 30)
|
||||
t.Assert(s[0].Many[1].Name, "smith")
|
||||
t.Assert(s[0].Many[1].Age, 31)
|
||||
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
t.Assert(len(s[1].Many), 0)
|
||||
|
||||
r3 := Result{
|
||||
Record{
|
||||
"id": gvar.New(100),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(40),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(200),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(41),
|
||||
},
|
||||
}
|
||||
err = r3.ScanList(&s, "Many", "One", "pid:Id")
|
||||
//fmt.Printf("%+v", err)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(len(s[0].Many), 2)
|
||||
t.Assert(s[0].Many[0].Name, "john")
|
||||
t.Assert(s[0].Many[0].Age, 40)
|
||||
t.Assert(s[0].Many[1].Name, "smith")
|
||||
t.Assert(s[0].Many[1].Age, 41)
|
||||
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
t.Assert(len(s[1].Many), 0)
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/1159
|
||||
func Test_ScanList_NoRecreate_SliceAttribute_Struct(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type S1 struct {
|
||||
Id int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S2 struct {
|
||||
Id int
|
||||
Pid int
|
||||
Name string
|
||||
Age int
|
||||
Score int
|
||||
}
|
||||
type S3 struct {
|
||||
One S1
|
||||
Many []S2
|
||||
}
|
||||
var (
|
||||
s []S3
|
||||
err error
|
||||
)
|
||||
r1 := Result{
|
||||
Record{
|
||||
"id": gvar.New(1),
|
||||
"name": gvar.New("john"),
|
||||
"age": gvar.New(16),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(2),
|
||||
"name": gvar.New("smith"),
|
||||
"age": gvar.New(18),
|
||||
},
|
||||
}
|
||||
err = r1.ScanList(&s, "One")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
|
||||
r2 := Result{
|
||||
Record{
|
||||
"id": gvar.New(100),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(30),
|
||||
"name": gvar.New("john"),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(200),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(31),
|
||||
"name": gvar.New("smith"),
|
||||
},
|
||||
}
|
||||
err = r2.ScanList(&s, "Many", "One", "pid:Id")
|
||||
//fmt.Printf("%+v", err)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(len(s[0].Many), 2)
|
||||
t.Assert(s[0].Many[0].Name, "john")
|
||||
t.Assert(s[0].Many[0].Age, 30)
|
||||
t.Assert(s[0].Many[1].Name, "smith")
|
||||
t.Assert(s[0].Many[1].Age, 31)
|
||||
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
t.Assert(len(s[1].Many), 0)
|
||||
|
||||
r3 := Result{
|
||||
Record{
|
||||
"id": gvar.New(100),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(40),
|
||||
},
|
||||
Record{
|
||||
"id": gvar.New(200),
|
||||
"pid": gvar.New(1),
|
||||
"age": gvar.New(41),
|
||||
},
|
||||
}
|
||||
err = r3.ScanList(&s, "Many", "One", "pid:Id")
|
||||
//fmt.Printf("%+v", err)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(s), 2)
|
||||
t.Assert(s[0].One.Name, "john")
|
||||
t.Assert(s[0].One.Age, 16)
|
||||
t.Assert(len(s[0].Many), 2)
|
||||
t.Assert(s[0].Many[0].Name, "john")
|
||||
t.Assert(s[0].Many[0].Age, 40)
|
||||
t.Assert(s[0].Many[1].Name, "smith")
|
||||
t.Assert(s[0].Many[1].Age, 41)
|
||||
|
||||
t.Assert(s[1].One.Name, "smith")
|
||||
t.Assert(s[1].One.Age, 18)
|
||||
t.Assert(len(s[1].Many), 0)
|
||||
})
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ CREATE TABLE %s (
|
||||
}
|
||||
|
||||
func Test_SoftDelete(t *testing.T) {
|
||||
table := "time_test_table"
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
@ -606,7 +606,7 @@ CREATE TABLE %s (
|
||||
}
|
||||
|
||||
func Test_SoftDelete_WhereAndOr(t *testing.T) {
|
||||
table := "time_test_table"
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
@ -648,7 +648,7 @@ CREATE TABLE %s (
|
||||
}
|
||||
|
||||
func Test_CreateUpdateTime_Struct(t *testing.T) {
|
||||
table := "time_test_table"
|
||||
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
id int(11) NOT NULL,
|
||||
|
@ -91,27 +91,42 @@ func doStructs(params interface{}, pointer interface{}, mapping ...map[string]st
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
array = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsMaps), len(paramsMaps))
|
||||
itemType = array.Index(0).Type()
|
||||
reflectElemArray = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsMaps), len(paramsMaps))
|
||||
itemType = reflectElemArray.Index(0).Type()
|
||||
itemTypeKind = itemType.Kind()
|
||||
pointerRvElem = pointerRv.Elem()
|
||||
pointerRvLength = pointerRvElem.Len()
|
||||
)
|
||||
if itemTypeKind == reflect.Ptr {
|
||||
// Pointer element.
|
||||
for i := 0; i < len(paramsMaps); i++ {
|
||||
if itemType.Kind() == reflect.Ptr {
|
||||
// Slice element is type pointer.
|
||||
e := reflect.New(itemType.Elem()).Elem()
|
||||
if err = Struct(paramsMaps[i], e, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
array.Index(i).Set(e.Addr())
|
||||
var tempReflectValue reflect.Value
|
||||
if i < pointerRvLength {
|
||||
tempReflectValue = pointerRvElem.Index(i).Elem()
|
||||
} else {
|
||||
// Slice element is not type of pointer.
|
||||
e := reflect.New(itemType).Elem()
|
||||
if err = Struct(paramsMaps[i], e, mapping...); err != nil {
|
||||
tempReflectValue = reflect.New(itemType.Elem()).Elem()
|
||||
}
|
||||
if err = Struct(paramsMaps[i], tempReflectValue, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
array.Index(i).Set(e)
|
||||
reflectElemArray.Index(i).Set(tempReflectValue.Addr())
|
||||
}
|
||||
} else {
|
||||
// Struct element.
|
||||
for i := 0; i < len(paramsMaps); i++ {
|
||||
var tempReflectValue reflect.Value
|
||||
if i < pointerRvLength {
|
||||
tempReflectValue = pointerRvElem.Index(i)
|
||||
} else {
|
||||
tempReflectValue = reflect.New(itemType).Elem()
|
||||
}
|
||||
if err = Struct(paramsMaps[i], tempReflectValue, mapping...); err != nil {
|
||||
return err
|
||||
}
|
||||
reflectElemArray.Index(i).Set(tempReflectValue)
|
||||
}
|
||||
}
|
||||
pointerRv.Elem().Set(array)
|
||||
pointerRv.Elem().Set(reflectElemArray)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user