From 3b6b4ff687ad01f4edc66791bc574d4595aa5bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Matczuk?= Date: Thu, 3 Aug 2017 12:02:23 +0200 Subject: [PATCH] select: reduce allocations and improve code structure --- iterx.go | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/iterx.go b/iterx.go index 4e7cae5..8f37741 100644 --- a/iterx.go +++ b/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,38 +141,34 @@ 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 { - 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 { - break - } + var ( + vp reflect.Value + ok bool + ) + for { + // create a new struct type (which returns PtrTo) and indirect it + vp = reflect.New(base) - if isPtr { - direct.Set(reflect.Append(direct, vp)) - } else { - direct.Set(reflect.Append(direct, v)) - } + // scan into the struct field pointers + if !scannable { + ok = iter.StructScan(vp.Interface()) + } else { + ok = iter.Scan(vp.Interface()) + } + if !ok { + break } - } 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))) - } + if isPtr { + v = reflect.Append(v, vp) + } else { + v = reflect.Append(v, reflect.Indirect(vp)) } } + // update dest + reflect.Indirect(value).Set(v) + return iter.err }