@@ -621,8 +621,7 @@ func (r *Rows) StructScan(dest interface{}) error {
621
621
r .started = true
622
622
}
623
623
624
- octx := newObjectContext ()
625
- err := fieldsByTraversal (octx , v , r .fields , r .values )
624
+ err := fieldsByTraversal (v , r .fields , r .values )
626
625
if err != nil {
627
626
return err
628
627
}
@@ -782,9 +781,7 @@ func (r *Row) scanAny(dest interface{}, structOnly bool) error {
782
781
}
783
782
values := make ([]interface {}, len (columns ))
784
783
785
- octx := newObjectContext ()
786
-
787
- err = fieldsByTraversal (octx , v , fields , values )
784
+ err = fieldsByTraversal (v , fields , values )
788
785
if err != nil {
789
786
return err
790
787
}
@@ -951,14 +948,13 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error {
951
948
return fmt .Errorf ("missing destination name %s in %T" , columns [f ], dest )
952
949
}
953
950
values = make ([]interface {}, len (columns ))
954
- octx := newObjectContext ()
955
951
956
952
for rows .Next () {
957
953
// create a new struct type (which returns PtrTo) and indirect it
958
954
vp = reflect .New (base )
959
955
v = reflect .Indirect (vp )
960
956
961
- err = fieldsByTraversal (octx , v , fields , values )
957
+ err = fieldsByTraversal (v , fields , values )
962
958
if err != nil {
963
959
return err
964
960
}
@@ -1024,21 +1020,23 @@ func baseType(t reflect.Type, expected reflect.Kind) (reflect.Type, error) {
1024
1020
// when iterating over many rows. Empty traversals will get an interface pointer.
1025
1021
// Because of the necessity of requesting ptrs or values, it's considered a bit too
1026
1022
// specialized for inclusion in reflectx itself.
1027
- func fieldsByTraversal (octx * objectContext , v reflect.Value , traversals [][]int , values []interface {}) error {
1023
+ func fieldsByTraversal (v reflect.Value , traversals [][]int , values []interface {}) error {
1028
1024
v = reflect .Indirect (v )
1029
1025
if v .Kind () != reflect .Struct {
1030
1026
return errors .New ("argument not a struct" )
1031
1027
}
1032
1028
1033
- octx .NewRow (v )
1034
-
1035
1029
for i , traversal := range traversals {
1036
1030
if len (traversal ) == 0 {
1037
1031
values [i ] = new (interface {})
1038
- continue
1032
+ } else if len (traversal ) == 1 {
1033
+ values [i ] = reflectx .FieldByIndexes (v , traversal ).Addr ().Interface ()
1034
+ } else {
1035
+ traversal := traversal
1036
+ values [i ] = optDest (func () interface {} {
1037
+ return reflectx .FieldByIndexes (v , traversal ).Addr ().Interface ()
1038
+ })
1039
1039
}
1040
- f := octx .FieldForIndexes (traversal )
1041
- values [i ] = f .Addr ().Interface ()
1042
1040
}
1043
1041
return nil
1044
1042
}
@@ -1052,49 +1050,14 @@ func missingFields(traversals [][]int) (field int, err error) {
1052
1050
return 0 , nil
1053
1051
}
1054
1052
1055
- // objectContext provides a single layer to abstract away
1056
- // nested struct scanning functionality
1057
- type objectContext struct {
1058
- value reflect.Value
1059
- }
1060
-
1061
- func newObjectContext () * objectContext {
1062
- return & objectContext {}
1063
- }
1064
-
1065
- // NewRow updates the object reference.
1066
- // This ensures all columns point to the same object
1067
- func (o * objectContext ) NewRow (value reflect.Value ) {
1068
- o .value = value
1069
- }
1070
-
1071
- // FieldForIndexes returns the value for address. If the address is a nested struct,
1072
- // a nestedFieldScanner is returned instead of the standard value reference
1073
- func (o * objectContext ) FieldForIndexes (indexes []int ) reflect.Value {
1074
- if len (indexes ) == 1 {
1075
- return reflectx .FieldByIndexes (o .value , indexes )
1076
- }
1077
-
1078
- obj := & nestedFieldScanner {
1079
- parent : o ,
1080
- indexes : indexes ,
1081
- }
1082
-
1083
- return reflect .ValueOf (obj ).Elem ()
1084
- }
1085
-
1086
- // nestedFieldScanner will only forward the Scan to the nested value if
1053
+ // optDest will only forward the Scan to the nested value if
1087
1054
// the database value is not nil.
1088
- type nestedFieldScanner struct {
1089
- parent * objectContext
1090
- indexes []int
1091
- }
1055
+ type optDest func () interface {}
1092
1056
1093
1057
// Scan implements sql.Scanner.
1094
- func (o * nestedFieldScanner ) Scan (src interface {}) error {
1058
+ func (dest optDest ) Scan (src interface {}) error {
1095
1059
if src == nil {
1096
1060
return nil
1097
1061
}
1098
- dest := reflectx .FieldByIndexes (o .parent .value , o .indexes )
1099
- return convertAssign (dest .Addr ().Interface (), src )
1062
+ return convertAssign (dest (), src )
1100
1063
}
0 commit comments