Merge pull request #7 from scylladb/mmt/select
select: reduce allocations and improve code structure
This commit is contained in:
50
iterx.go
50
iterx.go
@@ -62,15 +62,15 @@ func (iter *Iterx) Get(dest interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterx) scanAny(dest interface{}, structOnly bool) error {
|
func (iter *Iterx) scanAny(dest interface{}, structOnly bool) error {
|
||||||
v := reflect.ValueOf(dest)
|
value := reflect.ValueOf(dest)
|
||||||
if v.Kind() != reflect.Ptr {
|
if value.Kind() != reflect.Ptr {
|
||||||
return errors.New("must pass a pointer, not a value, to StructScan destination")
|
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")
|
return errors.New("nil pointer passed to StructScan destination")
|
||||||
}
|
}
|
||||||
|
|
||||||
base := reflectx.Deref(v.Type())
|
base := reflectx.Deref(value.Type())
|
||||||
scannable := isScannable(base)
|
scannable := isScannable(base)
|
||||||
|
|
||||||
if structOnly && scannable {
|
if structOnly && scannable {
|
||||||
@@ -110,8 +110,6 @@ func (iter *Iterx) Select(dest interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
||||||
var v, vp reflect.Value
|
|
||||||
|
|
||||||
value := reflect.ValueOf(dest)
|
value := reflect.ValueOf(dest)
|
||||||
|
|
||||||
// json.Unmarshal returns errors for these
|
// json.Unmarshal returns errors for these
|
||||||
@@ -121,13 +119,15 @@ func (iter *Iterx) scanAll(dest interface{}, structOnly bool) error {
|
|||||||
if value.IsNil() {
|
if value.IsNil() {
|
||||||
return errors.New("nil pointer passed to StructScan destination")
|
return errors.New("nil pointer passed to StructScan destination")
|
||||||
}
|
}
|
||||||
direct := reflect.Indirect(value)
|
|
||||||
|
|
||||||
slice, err := baseType(value.Type(), reflect.Slice)
|
slice, err := baseType(value.Type(), reflect.Slice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allocate memory for the page data
|
||||||
|
v := reflect.MakeSlice(slice, 0, iter.Iter.NumRows())
|
||||||
|
|
||||||
isPtr := slice.Elem().Kind() == reflect.Ptr
|
isPtr := slice.Elem().Kind() == reflect.Ptr
|
||||||
base := reflectx.Deref(slice.Elem())
|
base := reflectx.Deref(slice.Elem())
|
||||||
scannable := isScannable(base)
|
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()))
|
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 {
|
for {
|
||||||
// create a new struct type (which returns PtrTo) and indirect it
|
// create a new struct type (which returns PtrTo) and indirect it
|
||||||
vp = reflect.New(base)
|
vp = reflect.New(base)
|
||||||
v = reflect.Indirect(vp)
|
|
||||||
// scan into the struct field pointers and append to our results
|
// scan into the struct field pointers
|
||||||
if ok := iter.StructScan(vp.Interface()); !ok {
|
if !scannable {
|
||||||
|
ok = iter.StructScan(vp.Interface())
|
||||||
|
} else {
|
||||||
|
ok = iter.Scan(vp.Interface())
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if isPtr {
|
if isPtr {
|
||||||
direct.Set(reflect.Append(direct, vp))
|
v = reflect.Append(v, vp)
|
||||||
} else {
|
} 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
|
// update dest
|
||||||
if isPtr {
|
reflect.Indirect(value).Set(v)
|
||||||
direct.Set(reflect.Append(direct, vp))
|
|
||||||
} else {
|
|
||||||
direct.Set(reflect.Append(direct, reflect.Indirect(vp)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return iter.err
|
return iter.err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user