// Wrap wraps a given datastore with a key-prefix. func Wrap(child ds.Datastore, prefix ds.Key) ktds.Datastore { if child == nil { panic("child (ds.Datastore) is nil") } d := ktds.Wrap(child, PrefixTransform(prefix)) return &datastore{Datastore: d, raw: child, prefix: prefix} }
func (d *Datastore) Query(q query.Query) (query.Results, error) { 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 }
func (ks *DSSuite) TestBasic(c *C) { pair := &kt.Pair{ Convert: func(k ds.Key) ds.Key { return ds.NewKey("/abc").Child(k) }, Invert: func(k ds.Key) ds.Key { // remove abc prefix l := k.List() if l[0] != "abc" { panic("key does not have prefix. convert failed?") } return ds.KeyWithNamespaces(l[1:]) }, } mpds := ds.NewMapDatastore() ktds := kt.Wrap(mpds, pair) keys := strsToKeys([]string{ "foo", "foo/bar", "foo/bar/baz", "foo/barb", "foo/bar/bazb", "foo/bar/baz/barb", }) for _, k := range keys { err := ktds.Put(k, []byte(k.String())) c.Check(err, Equals, nil) } for _, k := range keys { v1, err := ktds.Get(k) c.Check(err, Equals, nil) c.Check(bytes.Equal(v1.([]byte), []byte(k.String())), Equals, true) v2, err := mpds.Get(ds.NewKey("abc").Child(k)) c.Check(err, Equals, nil) c.Check(bytes.Equal(v2.([]byte), []byte(k.String())), Equals, true) } run := func(d ds.Datastore, q dsq.Query) []ds.Key { r, err := d.Query(q) c.Check(err, Equals, nil) e, err := r.Rest() c.Check(err, Equals, nil) return ds.EntryKeys(e) } listA := run(mpds, dsq.Query{}) listB := run(ktds, dsq.Query{}) c.Check(len(listA), Equals, len(listB)) // sort them cause yeah. sort.Sort(ds.KeySlice(listA)) sort.Sort(ds.KeySlice(listB)) for i, kA := range listA { kB := listB[i] c.Check(pair.Invert(kA), Equals, kB) c.Check(kA, Equals, pair.Convert(kB)) } c.Log("listA: ", listA) c.Log("listB: ", listB) }