Index: impl/prod/datastore_key.go |
diff --git a/impl/prod/datastore_key.go b/impl/prod/datastore_key.go |
index bbc65eaaca2ce8aad0ff74bd881598440f22fc2a..d5853353f41ed92cc74032d58f1d8746b0170a2e 100644 |
--- a/impl/prod/datastore_key.go |
+++ b/impl/prod/datastore_key.go |
@@ -6,7 +6,9 @@ package prod |
import ( |
ds "github.com/luci/gae/service/datastore" |
- "github.com/luci/gae/service/datastore/dskey" |
+ "github.com/luci/luci-go/common/errors" |
+ "golang.org/x/net/context" |
+ "google.golang.org/appengine" |
"google.golang.org/appengine/datastore" |
) |
@@ -14,51 +16,60 @@ 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() |
+ |
+ count := 0 |
+ for nk := k; nk != nil; nk = nk.Parent() { |
+ count++ |
+ } |
+ |
+ toks := make([]ds.KeyTok, count) |
+ |
+ for ; k != nil; k = k.Parent() { |
+ count-- |
+ toks[count].Kind = k.Kind() |
+ toks[count].StringID = k.StringID() |
+ toks[count].IntID = k.IntID() |
+ } |
+ 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 |
+ return nil, nil |
} |
- if rkey, ok := k.(dsKeyImpl); ok { |
- return rkey.Key |
- } |
- // 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() |
+ 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) { |
+ lme := errors.NewLazyMultiError(len(ks)) |
ret := make([]*datastore.Key, len(ks)) |
+ err := error(nil) |
for i, k := range ks { |
- ret[i] = dsF2R(k) |
+ ret[i], err = dsF2R(ctx, k) |
+ lme.Assign(i, err) |
} |
- return ret |
+ return ret, lme.Get() |
} |