mirror of
https://github.com/asdine/storm.git
synced 2025-09-27 03:06:16 +08:00
88 lines
1.7 KiB
Go
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
|
|
}
|