mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 12:17:53 +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:
|
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 {
|
if len(relationDataMap) > 0 {
|
||||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||||
if relationFromAttrField.IsValid() {
|
if relationFromAttrField.IsValid() {
|
||||||
@ -216,7 +221,7 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
|||||||
// There's no relational data.
|
// There's no relational data.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = gconv.Struct(v, e); err != nil {
|
if err = gconv.Struct(v, element); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -229,14 +234,13 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
|||||||
// There's no relational data.
|
// There's no relational data.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = gconv.Struct(v, e); err != nil {
|
if err = gconv.Struct(v, element); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bindToAttrValue.Set(e.Addr())
|
bindToAttrValue.Set(element.Addr())
|
||||||
|
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
e := reflect.New(bindToAttrType).Elem()
|
|
||||||
if len(relationDataMap) > 0 {
|
if len(relationDataMap) > 0 {
|
||||||
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
relationFromAttrField = relationFromAttrValue.FieldByName(relationBindToSubAttrName)
|
||||||
if relationFromAttrField.IsValid() {
|
if relationFromAttrField.IsValid() {
|
||||||
@ -245,7 +249,7 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
|||||||
// There's no relational data.
|
// There's no relational data.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = gconv.Struct(relationDataItem, e); err != nil {
|
if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -258,11 +262,10 @@ func (r Result) ScanList(listPointer interface{}, bindToAttrName string, relatio
|
|||||||
// There's no relational data.
|
// There's no relational data.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = gconv.Struct(relationDataItem, e); err != nil {
|
if err = gconv.Struct(relationDataItem, bindToAttrValue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bindToAttrValue.Set(e)
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return gerror.Newf(`unsupported attribute type: %s`, bindToAttrKind.String())
|
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")
|
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) {
|
func Test_SoftDelete(t *testing.T) {
|
||||||
table := "time_test_table"
|
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||||
if _, err := db.Exec(fmt.Sprintf(`
|
if _, err := db.Exec(fmt.Sprintf(`
|
||||||
CREATE TABLE %s (
|
CREATE TABLE %s (
|
||||||
id int(11) NOT NULL,
|
id int(11) NOT NULL,
|
||||||
@ -606,7 +606,7 @@ CREATE TABLE %s (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_SoftDelete_WhereAndOr(t *testing.T) {
|
func Test_SoftDelete_WhereAndOr(t *testing.T) {
|
||||||
table := "time_test_table"
|
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||||
if _, err := db.Exec(fmt.Sprintf(`
|
if _, err := db.Exec(fmt.Sprintf(`
|
||||||
CREATE TABLE %s (
|
CREATE TABLE %s (
|
||||||
id int(11) NOT NULL,
|
id int(11) NOT NULL,
|
||||||
@ -648,7 +648,7 @@ CREATE TABLE %s (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_CreateUpdateTime_Struct(t *testing.T) {
|
func Test_CreateUpdateTime_Struct(t *testing.T) {
|
||||||
table := "time_test_table"
|
table := "time_test_table_" + gtime.TimestampNanoStr()
|
||||||
if _, err := db.Exec(fmt.Sprintf(`
|
if _, err := db.Exec(fmt.Sprintf(`
|
||||||
CREATE TABLE %s (
|
CREATE TABLE %s (
|
||||||
id int(11) NOT NULL,
|
id int(11) NOT NULL,
|
||||||
|
@ -91,27 +91,42 @@ func doStructs(params interface{}, pointer interface{}, mapping ...map[string]st
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
array = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsMaps), len(paramsMaps))
|
reflectElemArray = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsMaps), len(paramsMaps))
|
||||||
itemType = array.Index(0).Type()
|
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++ {
|
for i := 0; i < len(paramsMaps); i++ {
|
||||||
if itemType.Kind() == reflect.Ptr {
|
var tempReflectValue reflect.Value
|
||||||
// Slice element is type pointer.
|
if i < pointerRvLength {
|
||||||
e := reflect.New(itemType.Elem()).Elem()
|
tempReflectValue = pointerRvElem.Index(i).Elem()
|
||||||
if err = Struct(paramsMaps[i], e, mapping...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
array.Index(i).Set(e.Addr())
|
|
||||||
} else {
|
} else {
|
||||||
// Slice element is not type of pointer.
|
tempReflectValue = reflect.New(itemType.Elem()).Elem()
|
||||||
e := reflect.New(itemType).Elem()
|
}
|
||||||
if err = Struct(paramsMaps[i], e, mapping...); err != nil {
|
if err = Struct(paramsMaps[i], tempReflectValue, mapping...); err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user