Files
storm/query.go
2016-08-06 20:11:13 +02:00

88 lines
1.7 KiB
Go

package storm
import (
"reflect"
"github.com/asdine/storm/q"
"github.com/boltdb/bolt"
)
type Query struct {
limit int
skip int
tree q.Matcher
node *Node
}
func (q *Query) Skip(nb int) *Query {
q.skip = nb
return q
}
func (q *Query) Limit(nb int) *Query {
q.limit = nb
return q
}
func (q *Query) Find(to interface{}) error {
ref := reflect.ValueOf(to)
if ref.Kind() != reflect.Ptr || reflect.Indirect(ref).Kind() != reflect.Slice {
return ErrSlicePtrNeeded
}
elemType := reflect.Indirect(ref).Type().Elem()
if elemType.Kind() == reflect.Ptr {
elemType = elemType.Elem()
}
newElem := reflect.New(elemType)
info, err := extract(&newElem)
if err != nil {
return err
}
if q.node.tx != nil {
return q.query(q.node.tx, info, &ref, elemType)
}
return q.node.s.Bolt.Update(func(tx *bolt.Tx) error {
return q.query(tx, info, &ref, elemType)
})
}
func (q *Query) query(tx *bolt.Tx, info *modelInfo, ref *reflect.Value, elemType reflect.Type) error {
results := reflect.MakeSlice(reflect.Indirect(*ref).Type(), 0, 0)
bucket := q.node.GetBucket(tx, info.Name)
realType := reflect.Indirect(*ref).Type().Elem()
if bucket != nil {
c := bucket.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
if v == nil {
continue
}
newElem := reflect.New(elemType)
err := q.node.s.Codec.Decode(v, newElem.Interface())
if err != nil {
return err
}
if q.tree.Match(newElem.Interface()) {
if realType.Kind() == reflect.Ptr {
results = reflect.Append(results, newElem)
} else {
results = reflect.Append(results, reflect.Indirect(newElem))
}
}
}
}
reflect.Indirect(*ref).Set(results)
return nil
}