Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1125)

Unified Diff: service/datastore/key.go

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Lightning talk licenses. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « service/datastore/interface.go ('k') | service/datastore/key_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/key.go
diff --git a/service/datastore/key.go b/service/datastore/key.go
index 4b11735f6a8e7be2a2b6e4da1b00dac23b9c4e35..8359203eb7a879bd476a4fc6d7cbaccd1b010ddb 100644
--- a/service/datastore/key.go
+++ b/service/datastore/key.go
@@ -53,48 +53,48 @@ func (k KeyTok) Less(other KeyTok) bool {
return a.Less(&b)
}
-// Key is the type used for all datastore operations.
-type Key struct {
- appID string
- namespace string
- toks []KeyTok
+// KeyContext is the context in which a key is generated.
+type KeyContext struct {
+ AppID string
+ Namespace string
}
-var _ interface {
- json.Marshaler
- json.Unmarshaler
-} = (*Key)(nil)
+// Matches returns true iff the AppID and Namespace parameters are the same for
+// the two KeyContext instances.
+func (kc KeyContext) Matches(o KeyContext) bool {
+ return (kc.AppID == o.AppID && kc.Namespace == o.Namespace)
+}
-// NewKeyToks creates a new Key. It is the Key implementation returned from the
-// various PropertyMap serialization routines, as well as the native key
+// NewKeyToks creates a new Key. It is the Key implementation returned from
+// the various PropertyMap serialization routines, as well as the native key
// implementation for the in-memory implementation of gae.
//
-// See Interface.NewKeyToks for a version of this function which automatically
+// See NewKeyToks for a version of this function which automatically
// provides aid and ns.
-func NewKeyToks(aid, ns string, toks []KeyTok) *Key {
+func (kc KeyContext) NewKeyToks(toks []KeyTok) *Key {
if len(toks) == 0 {
return nil
}
newToks := make([]KeyTok, len(toks))
copy(newToks, toks)
- return &Key{aid, ns, newToks}
+ return &Key{kc, newToks}
}
-// NewKey is a wrapper around NewToks which has an interface similar
-// to NewKey in the SDK.
+// NewKey is a wrapper around NewToks which has an interface similar to NewKey
+// in the SDK.
//
-// See Interface.NewKey for a version of this function which automatically
-// provides aid and ns.
-func NewKey(aid, ns, kind, stringID string, intID int64, parent *Key) *Key {
+// See NewKey for a version of this function which automatically provides aid
+// and ns.
+func (kc KeyContext) NewKey(kind, stringID string, intID int64, parent *Key) *Key {
if parent == nil {
- return &Key{aid, ns, []KeyTok{{kind, intID, stringID}}}
+ return &Key{kc, []KeyTok{{kind, intID, stringID}}}
}
toks := parent.toks
newToks := make([]KeyTok, len(toks), len(toks)+1)
copy(newToks, toks)
newToks = append(newToks, KeyTok{kind, intID, stringID})
- return &Key{aid, ns, newToks}
+ return &Key{kc, newToks}
}
// MakeKey is a convenience function for manufacturing a *Key. It should only
@@ -102,7 +102,7 @@ func NewKey(aid, ns, kind, stringID string, intID int64, parent *Key) *Key {
//
// elems is pairs of (string, string|int|int32|int64) pairs, which correspond to
// Kind/id pairs. Example:
-// MakeKey("aid", "namespace", "Parent", 1, "Child", "id")
+// KeyContext{"aid", "namespace"}.MakeKey("Parent", 1, "Child", "id")
//
// Would create the key:
// aid:namespace:/Parent,1/Child,id
@@ -110,9 +110,9 @@ func NewKey(aid, ns, kind, stringID string, intID int64, parent *Key) *Key {
// If elems is not parsable (e.g. wrong length, wrong types, etc.) this method
// will panic.
//
-// See Interface.MakeKey for a version of this function which automatically
+// See MakeKey for a version of this function which automatically
// provides aid and ns.
-func MakeKey(aid, ns string, elems ...interface{}) *Key {
+func (kc KeyContext) MakeKey(elems ...interface{}) *Key {
if len(elems) == 0 {
return nil
}
@@ -147,9 +147,20 @@ func MakeKey(aid, ns string, elems ...interface{}) *Key {
}
}
- return NewKeyToks(aid, ns, toks)
+ return kc.NewKeyToks(toks)
+}
+
+// Key is the type used for all datastore operations.
+type Key struct {
+ kc KeyContext
+ toks []KeyTok
}
+var _ interface {
+ json.Marshaler
+ json.Unmarshaler
+} = (*Key)(nil)
+
// NewKeyEncoded decodes and returns a *Key
func NewKeyEncoded(encoded string) (ret *Key, err error) {
ret = &Key{}
@@ -167,8 +178,10 @@ func NewKeyEncoded(encoded string) (ret *Key, err error) {
return
}
- ret.appID = r.GetApp()
- ret.namespace = r.GetNameSpace()
+ ret.kc = KeyContext{
+ AppID: r.GetApp(),
+ Namespace: r.GetNameSpace(),
+ }
ret.toks = make([]KeyTok, len(r.Path.Element))
for i, e := range r.Path.Element {
ret.toks[i] = KeyTok{
@@ -187,10 +200,16 @@ func (k *Key) LastTok() KeyTok {
}
// AppID returns the application ID that this Key is for.
-func (k *Key) AppID() string { return k.appID }
+func (k *Key) AppID() string { return k.kc.AppID }
// Namespace returns the namespace that this Key is for.
-func (k *Key) Namespace() string { return k.namespace }
+func (k *Key) Namespace() string { return k.kc.Namespace }
+
+// KeyContext returns the KeyContext that this Key is using.
+func (k *Key) KeyContext() *KeyContext {
+ kc := k.kc
+ return &kc
+}
// Kind returns the Kind of the child KeyTok
func (k *Key) Kind() string { return k.toks[len(k.toks)-1].Kind }
@@ -205,7 +224,7 @@ func (k *Key) IntID() int64 { return k.toks[len(k.toks)-1].IntID }
// AID:NS:/Kind,id/Kind,id/...
func (k *Key) String() string {
b := bytes.NewBuffer(make([]byte, 0, 512))
- fmt.Fprintf(b, "%s:%s:", k.appID, k.namespace)
+ fmt.Fprintf(b, "%s:%s:", k.kc.AppID, k.kc.Namespace)
for _, t := range k.toks {
if t.StringID != "" {
fmt.Fprintf(b, "/%s,%q", t.Kind, t.StringID)
@@ -221,15 +240,15 @@ func (k *Key) IsIncomplete() bool {
return k.LastTok().IsIncomplete()
}
-// Valid determines if a key is valid, according to a couple rules:
+// Valid determines if a key is valid, according to a couple of rules:
// - k is not nil
// - every token of k:
// - (if !allowSpecial) token's kind doesn't start with '__'
// - token's kind and appid are non-blank
// - token is not incomplete
// - all tokens have the same namespace and appid
-func (k *Key) Valid(allowSpecial bool, aid, ns string) bool {
- if aid != k.appID || ns != k.namespace {
+func (k *Key) Valid(allowSpecial bool, kc KeyContext) bool {
+ if !kc.Matches(k.kc) {
return false
}
for _, t := range k.toks {
@@ -252,11 +271,14 @@ func (k *Key) Valid(allowSpecial bool, aid, ns string) bool {
// PartialValid returns true iff this key is suitable for use in a Put
// operation. This is the same as Valid(k, false, ...), but also allowing k to
// be IsIncomplete().
-func (k *Key) PartialValid(aid, ns string) bool {
+func (k *Key) PartialValid(kc KeyContext) bool {
if k.IsIncomplete() {
- k = NewKey(k.AppID(), k.Namespace(), k.Kind(), "", 1, k.Parent())
+ if !kc.Matches(k.kc) {
+ return false
+ }
+ k = kc.NewKey(k.Kind(), "", 1, k.Parent())
}
- return k.Valid(false, aid, ns)
+ return k.Valid(false, kc)
}
// Parent returns the parent Key of this *Key, or nil. The parent
@@ -265,7 +287,7 @@ func (k *Key) Parent() *Key {
if len(k.toks) <= 1 {
return nil
}
- return &Key{k.appID, k.namespace, k.toks[:len(k.toks)-1]}
+ return k.kc.NewKeyToks(k.toks[:len(k.toks)-1])
}
// MarshalJSON allows this key to be automatically marshaled by encoding/json.
@@ -293,11 +315,11 @@ func (k *Key) Encode() string {
}
}
var namespace *string
- if k.namespace != "" {
- namespace = &k.namespace
+ if ns := k.kc.Namespace; ns != "" {
+ namespace = &ns
}
r, err := proto.Marshal(&pb.Reference{
- App: &k.appID,
+ App: &k.kc.AppID,
NameSpace: namespace,
Path: &pb.Path{
Element: e,
@@ -351,15 +373,15 @@ func (k *Key) Root() *Key {
// Less returns true iff k would sort before other.
func (k *Key) Less(other *Key) bool {
- if k.appID < other.appID {
+ if k.kc.AppID < other.kc.AppID {
return true
- } else if k.appID > other.appID {
+ } else if k.kc.AppID > other.kc.AppID {
return false
}
- if k.namespace < other.namespace {
+ if k.kc.Namespace < other.kc.Namespace {
return true
- } else if k.namespace > other.namespace {
+ } else if k.kc.Namespace > other.kc.Namespace {
return false
}
@@ -380,7 +402,7 @@ func (k *Key) Less(other *Key) bool {
// HasAncestor returns true iff other is an ancestor of k (or if other == k).
func (k *Key) HasAncestor(other *Key) bool {
- if k.appID != other.appID || k.namespace != other.namespace {
+ if !k.kc.Matches(other.kc) {
return false
}
if len(k.toks) < len(other.toks) {
@@ -400,9 +422,9 @@ func (k *Key) HasAncestor(other *Key) bool {
// https://cloud.google.com/datastore/docs/apis/gql/gql_reference
func (k *Key) GQL() string {
ret := &bytes.Buffer{}
- fmt.Fprintf(ret, "KEY(DATASET(%s)", gqlQuoteString(k.appID))
- if k.namespace != "" {
- fmt.Fprintf(ret, ", NAMESPACE(%s)", gqlQuoteString(k.namespace))
+ fmt.Fprintf(ret, "KEY(DATASET(%s)", gqlQuoteString(k.kc.AppID))
+ if ns := k.kc.Namespace; ns != "" {
+ fmt.Fprintf(ret, ", NAMESPACE(%s)", gqlQuoteString(ns))
}
for _, t := range k.toks {
if t.IntID != 0 {
@@ -428,8 +450,7 @@ func (k *Key) Equal(other *Key) bool {
// This asserts equality for the full lineage of the key, except for its last
// token ID.
func (k *Key) IncompleteEqual(other *Key) (ret bool) {
- ret = (k.appID == other.appID &&
- k.namespace == other.namespace &&
+ ret = (k.kc.Matches(other.kc) &&
len(k.toks) == len(other.toks))
if ret {
for i, t := range k.toks {
@@ -454,7 +475,7 @@ func (k *Key) Incomplete() *Key {
if k.IsIncomplete() {
return k
}
- return NewKey(k.appID, k.namespace, k.Kind(), "", 0, k.Parent())
+ return k.kc.NewKey(k.Kind(), "", 0, k.Parent())
}
// WithID returns the key generated by setting the ID of its last token to
@@ -467,7 +488,7 @@ func (k *Key) WithID(stringID string, intID int64) *Key {
if k.StringID() == stringID && k.IntID() == intID {
return k
}
- return NewKey(k.appID, k.namespace, k.Kind(), stringID, intID, k.Parent())
+ return k.kc.NewKey(k.Kind(), stringID, intID, k.Parent())
}
// Split componentizes the key into pieces (AppID, Namespace and tokens)
@@ -477,8 +498,8 @@ func (k *Key) WithID(stringID string, intID int64) *Key {
// toks is guaranteed to be empty if and only if k is nil. If k is non-nil then
// it contains at least one token.
func (k *Key) Split() (appID, namespace string, toks []KeyTok) {
- appID = k.appID
- namespace = k.namespace
+ appID = k.kc.AppID
+ namespace = k.kc.Namespace
toks = make([]KeyTok, len(k.toks))
copy(toks, k.toks)
return
@@ -489,8 +510,8 @@ func (k *Key) Split() (appID, namespace string, toks []KeyTok) {
// It uses https://cloud.google.com/appengine/articles/storage_breakdown?csw=1
// as a guide for these values.
func (k *Key) EstimateSize() int64 {
- ret := int64(len(k.appID))
- ret += int64(len(k.namespace))
+ ret := int64(len(k.kc.AppID))
+ ret += int64(len(k.kc.Namespace))
for _, t := range k.toks {
ret += int64(len(t.Kind))
if t.StringID != "" {
« no previous file with comments | « service/datastore/interface.go ('k') | service/datastore/key_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698