Merge pull request #7 from scylladb/mmt/select

select: reduce allocations and improve code structure
This commit is contained in:
Michał Matczuk
2017-08-03 13:30:28 +02:00
committed by GitHub

View File

@@ -62,15 +62,15 @@ func (iter *Iterx) Get(dest interface{}) error {
}
func (iter *Iterx) scanAny(dest interface{}, structOnly bool) error {
v := reflect.ValueOf(dest)
if v.Kind() != reflect.Ptr {
value := reflect.ValueOf(dest)
if value.Kind() != reflect.Ptr {
return errors.New("must pass a pointer, not a value, to StructScan destination")
}
if v.IsNil() {
if value.IsNil() {
return errors.New("nil pointer passed to StructScan destination")
}
base := reflectx.Deref(v.Type())
base := reflectx.Deref(value.Type())
scannable := isScannable(base)
if structOnly && scannable {
@@ -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
}