select: reduce allocations and improve code structure
This commit is contained in:
42
iterx.go
42
iterx.go
@@ -110,8 +110,6 @@ func (iter *Iterx) Select(dest interface{}) error {
|
||||
}
|
||||
|
||||
func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
||||
var v, vp reflect.Value
|
||||
|
||||
value := reflect.ValueOf(dest)
|
||||
|
||||
// json.Unmarshal returns errors for these
|
||||
@@ -121,13 +119,15 @@ func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
||||
if value.IsNil() {
|
||||
return errors.New("nil pointer passed to StructScan destination")
|
||||
}
|
||||
direct := reflect.Indirect(value)
|
||||
|
||||
slice, err := baseType(value.Type(), reflect.Slice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// allocate memory for the page data
|
||||
v := reflect.MakeSlice(slice, 0, iter.Iter.NumRows())
|
||||
|
||||
isPtr := slice.Elem().Kind() == reflect.Ptr
|
||||
base := reflectx.Deref(slice.Elem())
|
||||
scannable := isScannable(base)
|
||||
@@ -141,37 +141,33 @@ func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
||||
return fmt.Errorf("non-struct dest type %s with >1 columns (%d)", base.Kind(), len(iter.Columns()))
|
||||
}
|
||||
|
||||
if !scannable {
|
||||
var (
|
||||
vp reflect.Value
|
||||
ok bool
|
||||
)
|
||||
for {
|
||||
// create a new struct type (which returns PtrTo) and indirect it
|
||||
vp = reflect.New(base)
|
||||
v = reflect.Indirect(vp)
|
||||
// scan into the struct field pointers and append to our results
|
||||
if ok := iter.StructScan(vp.Interface()); !ok {
|
||||
|
||||
// scan into the struct field pointers
|
||||
if !scannable {
|
||||
ok = iter.StructScan(vp.Interface())
|
||||
} else {
|
||||
ok = iter.Scan(vp.Interface())
|
||||
}
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
if isPtr {
|
||||
direct.Set(reflect.Append(direct, vp))
|
||||
v = reflect.Append(v, vp)
|
||||
} else {
|
||||
direct.Set(reflect.Append(direct, v))
|
||||
v = reflect.Append(v, reflect.Indirect(vp))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for {
|
||||
vp = reflect.New(base)
|
||||
if ok := iter.Scan(vp.Interface()); !ok {
|
||||
break
|
||||
}
|
||||
|
||||
// append
|
||||
if isPtr {
|
||||
direct.Set(reflect.Append(direct, vp))
|
||||
} else {
|
||||
direct.Set(reflect.Append(direct, reflect.Indirect(vp)))
|
||||
}
|
||||
}
|
||||
}
|
||||
// update dest
|
||||
reflect.Indirect(value).Set(v)
|
||||
|
||||
return iter.err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user