Commit f1a0a0fd authored by Tommi Virtanen's avatar Tommi Virtanen

Implement mount Query, in a dumb way

parent 27fe4c12
......@@ -7,6 +7,7 @@ import (
"strings"
"github.com/jbenet/go-datastore"
"github.com/jbenet/go-datastore/keytransform"
"github.com/jbenet/go-datastore/query"
)
......@@ -34,19 +35,19 @@ type Datastore struct {
var _ datastore.Datastore = (*Datastore)(nil)
func (d *Datastore) lookup(key datastore.Key) (datastore.Datastore, datastore.Key) {
func (d *Datastore) lookup(key datastore.Key) (ds datastore.Datastore, mountpoint, rest datastore.Key) {
for _, m := range d.mounts {
if m.Prefix.IsAncestorOf(key) {
if m.Prefix.Equal(key) || m.Prefix.IsAncestorOf(key) {
s := strings.TrimPrefix(key.String(), m.Prefix.String())
k := datastore.NewKey(s)
return m.Datastore, k
return m.Datastore, m.Prefix, k
}
}
return nil, key
return nil, datastore.NewKey("/"), key
}
func (d *Datastore) Put(key datastore.Key, value interface{}) error {
ds, k := d.lookup(key)
ds, _, k := d.lookup(key)
if ds == nil {
return ErrNoMount
}
......@@ -54,7 +55,7 @@ func (d *Datastore) Put(key datastore.Key, value interface{}) error {
}
func (d *Datastore) Get(key datastore.Key) (value interface{}, err error) {
ds, k := d.lookup(key)
ds, _, k := d.lookup(key)
if ds == nil {
return nil, datastore.ErrNotFound
}
......@@ -62,7 +63,7 @@ func (d *Datastore) Get(key datastore.Key) (value interface{}, err error) {
}
func (d *Datastore) Has(key datastore.Key) (exists bool, err error) {
ds, k := d.lookup(key)
ds, _, k := d.lookup(key)
if ds == nil {
return false, nil
}
......@@ -70,7 +71,7 @@ func (d *Datastore) Has(key datastore.Key) (exists bool, err error) {
}
func (d *Datastore) Delete(key datastore.Key) error {
ds, k := d.lookup(key)
ds, _, k := d.lookup(key)
if ds == nil {
return datastore.ErrNotFound
}
......@@ -78,5 +79,38 @@ func (d *Datastore) Delete(key datastore.Key) error {
}
func (d *Datastore) Query(q query.Query) (query.Results, error) {
return nil, errors.New("TODO")
if len(q.Filters) > 0 ||
len(q.Orders) > 0 ||
q.Limit > 0 ||
q.Offset > 0 {
// TODO this is overly simplistic, but the only caller is
// `ipfs refs local` for now, and this gets us moving.
return nil, errors.New("mount only supports listing all prefixed keys in random order")
}
key := datastore.NewKey(q.Prefix)
ds, mount, k := d.lookup(key)
if ds == nil {
return nil, errors.New("mount only supports listing a mount point")
}
// TODO support listing cross mount points too
// delegate the query to the mounted datastore, while adjusting
// keys in and out
q2 := q
q2.Prefix = k.String()
wrapDS := keytransform.Wrap(ds, &keytransform.Pair{
Convert: func(datastore.Key) datastore.Key {
panic("this should never be called")
},
Invert: func(k datastore.Key) datastore.Key {
return mount.Child(k)
},
})
r, err := wrapDS.Query(q2)
if err != nil {
return nil, err
}
r = query.ResultsReplaceQuery(r, q)
return r, nil
}
......@@ -5,6 +5,7 @@ import (
"github.com/jbenet/go-datastore"
"github.com/jbenet/go-datastore/mount"
"github.com/jbenet/go-datastore/query"
)
func TestPutBadNothing(t *testing.T) {
......@@ -205,3 +206,36 @@ func TestDelete(t *testing.T) {
t.Fatalf("wrong value: %v != %v", g, e)
}
}
func TestQuerySimple(t *testing.T) {
mapds := datastore.NewMapDatastore()
m := mount.New([]mount.Mount{
{Prefix: datastore.NewKey("/quux"), Datastore: mapds},
})
const myKey = "/quux/thud"
if err := m.Put(datastore.NewKey(myKey), []byte("foobar")); err != nil {
t.Fatalf("Put error: %v", err)
}
res, err := m.Query(query.Query{Prefix: "/quux"})
if err != nil {
t.Fatalf("Query fail: %v\n", err)
}
entries, err := res.Rest()
if err != nil {
t.Fatalf("Query Results.Rest fail: %v\n", err)
}
seen := false
for _, e := range entries {
switch e.Key {
case datastore.NewKey(myKey).String():
seen = true
default:
t.Errorf("saw unexpected key: %q", e.Key)
}
}
if !seen {
t.Errorf("did not see wanted key %q in %+v", myKey, entries)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment