Index: impl/prod/datastore_key.go |
diff --git a/impl/prod/datastore_key.go b/impl/prod/datastore_key.go |
index bbc65eaaca2ce8aad0ff74bd881598440f22fc2a..0892ca20735dd6ca37310fb4a559f1e943c089a3 100644 |
--- a/impl/prod/datastore_key.go |
+++ b/impl/prod/datastore_key.go |
@@ -6,7 +6,8 @@ package prod |
import ( |
ds "github.com/luci/gae/service/datastore" |
- "github.com/luci/gae/service/datastore/dskey" |
+ "golang.org/x/net/context" |
+ "google.golang.org/appengine" |
"google.golang.org/appengine/datastore" |
) |
@@ -14,51 +15,55 @@ type dsKeyImpl struct { |
*datastore.Key |
} |
-var _ ds.Key = dsKeyImpl{} |
- |
-func (k dsKeyImpl) Parent() ds.Key { return dsR2F(k.Key.Parent()) } |
-func (k dsKeyImpl) Incomplete() bool { return k.Key.Incomplete() } |
-func (k dsKeyImpl) Valid(allowSpecial bool, aid, ns string) bool { |
- return dskey.Valid(k, allowSpecial, aid, ns) |
-} |
-func (k dsKeyImpl) PartialValid(aid, ns string) bool { |
- return dskey.PartialValid(k, aid, ns) |
-} |
- |
// dsR2F (DS real-to-fake) converts an SDK Key to a ds.Key |
-func dsR2F(k *datastore.Key) ds.Key { |
+func dsR2F(k *datastore.Key) *ds.Key { |
if k == nil { |
return nil |
} |
- return dsKeyImpl{k} |
+ aid := k.AppID() |
+ ns := k.Namespace() |
+ toks := []ds.KeyTok(nil) |
dnj
2015/09/18 16:47:57
Since this will be executed frequently, it may be
iannucci
2015/09/18 22:25:48
done
|
+ for k != nil { |
+ toks = append(toks, ds.KeyTok{ |
+ Kind: k.Kind(), StringID: k.StringID(), IntID: k.IntID()}) |
+ k = k.Parent() |
+ } |
+ for i, j := 0, len(toks)-1; i < j; i, j = i+1, j-1 { |
+ toks[i], toks[j] = toks[j], toks[i] |
+ } |
+ return ds.NewKeyToks(aid, ns, toks) |
} |
// dsF2R (DS fake-to-real) converts a DSKey back to an SDK *Key. |
-func dsF2R(k ds.Key) *datastore.Key { |
+func dsF2R(ctx context.Context, k *ds.Key) (*datastore.Key, error) { |
if k == nil { |
- return nil |
- } |
- if rkey, ok := k.(dsKeyImpl); ok { |
- return rkey.Key |
+ return nil, nil |
} |
- // we should always hit the fast case above, but just in case, safely round |
- // trip through the proto encoding. |
- rkey, err := datastore.DecodeKey(dskey.Encode(k)) |
+ |
+ // drop aid. |
+ _, ns, toks := k.Split() |
iannucci
2015/09/18 04:31:52
We drop the appid here... we can't actually contro
dnj
2015/09/18 16:47:57
Please document this in a formal comment.
Note th
iannucci
2015/09/18 22:25:48
Noted in doc.go as a BUG.
|
+ err := error(nil) |
+ ctx, err = appengine.Namespace(ctx, ns) |
if err != nil { |
- // should never happen in a good program, but it's not ignorable, and |
- // passing an error back makes this function too cumbersome (and it causes |
- // this `if err != nil { panic(err) }` logic to show up in a bunch of |
- // places. Realistically, everything should hit the early exit clause above. |
- panic(err) |
+ return nil, err |
} |
- return rkey |
+ |
+ ret := datastore.NewKey(ctx, toks[0].Kind, toks[0].StringID, toks[0].IntID, nil) |
+ for _, t := range toks[1:] { |
+ ret = datastore.NewKey(ctx, t.Kind, t.StringID, t.IntID, ret) |
+ } |
+ |
+ return ret, nil |
} |
// dsMF2R (DS multi-fake-to-fake) converts a slice of wrapped keys to SDK keys. |
-func dsMF2R(ks []ds.Key) []*datastore.Key { |
+func dsMF2R(ctx context.Context, ks []*ds.Key) ([]*datastore.Key, error) { |
+ err := error(nil) |
dnj
2015/09/18 16:47:57
Does it make sense to use a MultiError here?
iannucci
2015/09/18 22:25:47
yuuuup
|
ret := make([]*datastore.Key, len(ks)) |
for i, k := range ks { |
- ret[i] = dsF2R(k) |
+ if ret[i], err = dsF2R(ctx, k); err != nil { |
+ return nil, err |
+ } |
} |
- return ret |
+ return ret, nil |
} |