Commit f1a0a0fd authored by Tommi Virtanen's avatar Tommi Virtanen

Implement mount Query, in a dumb way

parent 27fe4c12
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/jbenet/go-datastore" "github.com/jbenet/go-datastore"
"github.com/jbenet/go-datastore/keytransform"
"github.com/jbenet/go-datastore/query" "github.com/jbenet/go-datastore/query"
) )
...@@ -34,19 +35,19 @@ type Datastore struct { ...@@ -34,19 +35,19 @@ type Datastore struct {
var _ datastore.Datastore = (*Datastore)(nil) 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 { 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()) s := strings.TrimPrefix(key.String(), m.Prefix.String())
k := datastore.NewKey(s) 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 { func (d *Datastore) Put(key datastore.Key, value interface{}) error {
ds, k := d.lookup(key) ds, _, k := d.lookup(key)
if ds == nil { if ds == nil {
return ErrNoMount return ErrNoMount
} }
...@@ -54,7 +55,7 @@ func (d *Datastore) Put(key datastore.Key, value interface{}) error { ...@@ -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) { func (d *Datastore) Get(key datastore.Key) (value interface{}, err error) {
ds, k := d.lookup(key) ds, _, k := d.lookup(key)
if ds == nil { if ds == nil {
return nil, datastore.ErrNotFound return nil, datastore.ErrNotFound
} }
...@@ -62,7 +63,7 @@ func (d *Datastore) Get(key datastore.Key) (value interface{}, err error) { ...@@ -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) { func (d *Datastore) Has(key datastore.Key) (exists bool, err error) {
ds, k := d.lookup(key) ds, _, k := d.lookup(key)
if ds == nil { if ds == nil {
return false, nil return false, nil
} }
...@@ -70,7 +71,7 @@ func (d *Datastore) Has(key datastore.Key) (exists bool, err error) { ...@@ -70,7 +71,7 @@ func (d *Datastore) Has(key datastore.Key) (exists bool, err error) {
} }
func (d *Datastore) Delete(key datastore.Key) error { func (d *Datastore) Delete(key datastore.Key) error {
ds, k := d.lookup(key) ds, _, k := d.lookup(key)
if ds == nil { if ds == nil {
return datastore.ErrNotFound return datastore.ErrNotFound
} }
...@@ -78,5 +79,38 @@ func (d *Datastore) Delete(key datastore.Key) error { ...@@ -78,5 +79,38 @@ func (d *Datastore) Delete(key datastore.Key) error {
} }
func (d *Datastore) Query(q query.Query) (query.Results, 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 ( ...@@ -5,6 +5,7 @@ import (
"github.com/jbenet/go-datastore" "github.com/jbenet/go-datastore"
"github.com/jbenet/go-datastore/mount" "github.com/jbenet/go-datastore/mount"
"github.com/jbenet/go-datastore/query"
) )
func TestPutBadNothing(t *testing.T) { func TestPutBadNothing(t *testing.T) {
...@@ -205,3 +206,36 @@ func TestDelete(t *testing.T) { ...@@ -205,3 +206,36 @@ func TestDelete(t *testing.T) {
t.Fatalf("wrong value: %v != %v", g, e) 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