| Index: service/datastore/key.go
|
| diff --git a/service/datastore/key.go b/service/datastore/key.go
|
| index faa6ab711806ce121f94d13dd638b1cc5b57655d..4b11735f6a8e7be2a2b6e4da1b00dac23b9c4e35 100644
|
| --- a/service/datastore/key.go
|
| +++ b/service/datastore/key.go
|
| @@ -23,9 +23,9 @@ type KeyTok struct {
|
| StringID string
|
| }
|
|
|
| -// Incomplete returns true iff this token doesn't define either a StringID or
|
| +// IsIncomplete returns true iff this token doesn't define either a StringID or
|
| // an IntID.
|
| -func (k KeyTok) Incomplete() bool {
|
| +func (k KeyTok) IsIncomplete() bool {
|
| return k.StringID == "" && k.IntID == 0
|
| }
|
|
|
| @@ -216,9 +216,9 @@ func (k *Key) String() string {
|
| return b.String()
|
| }
|
|
|
| -// Incomplete returns true iff k doesn't have an id yet.
|
| -func (k *Key) Incomplete() bool {
|
| - return k.LastTok().Incomplete()
|
| +// IsIncomplete returns true iff k doesn't have an id yet.
|
| +func (k *Key) IsIncomplete() bool {
|
| + return k.LastTok().IsIncomplete()
|
| }
|
|
|
| // Valid determines if a key is valid, according to a couple rules:
|
| @@ -233,7 +233,7 @@ func (k *Key) Valid(allowSpecial bool, aid, ns string) bool {
|
| return false
|
| }
|
| for _, t := range k.toks {
|
| - if t.Incomplete() {
|
| + if t.IsIncomplete() {
|
| return false
|
| }
|
| if !allowSpecial && t.Special() {
|
| @@ -251,9 +251,9 @@ 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 Incomplete().
|
| +// be IsIncomplete().
|
| func (k *Key) PartialValid(aid, ns string) bool {
|
| - if k.Incomplete() {
|
| + if k.IsIncomplete() {
|
| k = NewKey(k.AppID(), k.Namespace(), k.Kind(), "", 1, k.Parent())
|
| }
|
| return k.Valid(false, aid, ns)
|
| @@ -418,20 +418,58 @@ func (k *Key) GQL() string {
|
| }
|
|
|
| // Equal returns true iff the two keys represent identical key values.
|
| -func (k *Key) Equal(other *Key) (ret bool) {
|
| +func (k *Key) Equal(other *Key) bool {
|
| + return k.IncompleteEqual(other) && (k.LastTok() == other.LastTok())
|
| +}
|
| +
|
| +// IncompleteEqual asserts that, were the two keys incomplete, they would be
|
| +// equal.
|
| +//
|
| +// 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 &&
|
| len(k.toks) == len(other.toks))
|
| if ret {
|
| for i, t := range k.toks {
|
| - if ret = t == other.toks[i]; !ret {
|
| - return
|
| + if i == len(k.toks)-1 {
|
| + // Last token: check only Kind.
|
| + if ret = (t.Kind == other.toks[i].Kind); !ret {
|
| + return
|
| + }
|
| + } else {
|
| + if ret = t == other.toks[i]; !ret {
|
| + return
|
| + }
|
| }
|
| }
|
| }
|
| return
|
| }
|
|
|
| +// Incomplete returns an incomplete version of the key. The ID fields of the
|
| +// last token will be set to zero/empty.
|
| +func (k *Key) Incomplete() *Key {
|
| + if k.IsIncomplete() {
|
| + return k
|
| + }
|
| + return NewKey(k.appID, k.namespace, k.Kind(), "", 0, k.Parent())
|
| +}
|
| +
|
| +// WithID returns the key generated by setting the ID of its last token to
|
| +// the specified value.
|
| +//
|
| +// To generate this, k is reduced to its Incomplete form, then populated with a
|
| +// new ID. The resulting key will have the same token linage as k (i.e., will
|
| +// be IncompleteEqual).
|
| +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())
|
| +}
|
| +
|
| // Split componentizes the key into pieces (AppID, Namespace and tokens)
|
| //
|
| // Each token represents one piece of they key's 'path'.
|
|
|