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

Unified Diff: service/datastore/dskey/key.go

Issue 1355783002: Refactor keys and queries in datastore service and implementation. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: appease errcheck Created 5 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/dskey/generic_key.go ('k') | service/datastore/dskey/key_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: service/datastore/dskey/key.go
diff --git a/service/datastore/dskey/key.go b/service/datastore/dskey/key.go
deleted file mode 100644
index f700d518e35d2765899c0aac995961aa5b86c072..0000000000000000000000000000000000000000
--- a/service/datastore/dskey/key.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// adapted from github.com/golang/appengine/datastore
-
-package dskey
-
-import (
- "bytes"
- "encoding/base64"
- "errors"
- "strconv"
- "strings"
-
- "github.com/golang/protobuf/proto"
- ds "github.com/luci/gae/service/datastore"
- pb "github.com/luci/gae/service/datastore/internal/protos/datastore"
-)
-
-// Encode encodes the provided key as a base64-encoded protobuf.
-//
-// This encoding is compatible with the SDK-provided encoding and is agnostic
-// to the underlying implementation of the Key.
-//
-// It's encoded with the urlsafe base64 table.
-func Encode(k ds.Key) string {
- n := 0
- for i := k; i != nil; i = i.Parent() {
- n++
- }
- e := make([]*pb.Path_Element, n)
- for i := k; i != nil; i = i.Parent() {
- n--
- kind := i.Kind()
- e[n] = &pb.Path_Element{
- Type: &kind,
- }
- // At most one of {Name,Id} should be set.
- // Neither will be set for incomplete keys.
- if i.StringID() != "" {
- sid := i.StringID()
- e[n].Name = &sid
- } else if i.IntID() != 0 {
- iid := i.IntID()
- e[n].Id = &iid
- }
- }
- var namespace *string
- if k.Namespace() != "" {
- namespace = proto.String(k.Namespace())
- }
- r, err := proto.Marshal(&pb.Reference{
- App: proto.String(k.AppID()),
- NameSpace: namespace,
- Path: &pb.Path{
- Element: e,
- },
- })
- if err != nil {
- panic(err)
- }
-
- // trim padding
- return strings.TrimRight(base64.URLEncoding.EncodeToString(r), "=")
-}
-
-// ToksDecode decodes a base64-encoded protobuf representation of a Key
-// into a tokenized form. This is so that implementations of the gae wrapper
-// can decode to their own implementation of Key.
-//
-// This encoding is compatible with the SDK-provided encoding and is agnostic
-// to the underlying implementation of the Key.
-func ToksDecode(encoded string) (appID, namespace string, toks []ds.KeyTok, err error) {
- // Re-add padding
- if m := len(encoded) % 4; m != 0 {
- encoded += strings.Repeat("=", 4-m)
- }
- b, err := base64.URLEncoding.DecodeString(encoded)
- if err != nil {
- return
- }
-
- r := &pb.Reference{}
- if err = proto.Unmarshal(b, r); err != nil {
- return
- }
-
- appID = r.GetApp()
- namespace = r.GetNameSpace()
- toks = make([]ds.KeyTok, len(r.Path.Element))
- for i, e := range r.Path.Element {
- toks[i] = ds.KeyTok{
- Kind: e.GetType(),
- IntID: e.GetId(),
- StringID: e.GetName(),
- }
- }
- return
-}
-
-// MarshalJSON returns a MarshalJSON-compatible serialization of a Key.
-func MarshalJSON(k ds.Key) ([]byte, error) {
- return []byte(`"` + Encode(k) + `"`), nil
-}
-
-// UnmarshalJSON returns the tokenized version of a ds.Key as encoded by
-// MarshalJSON.
-func UnmarshalJSON(buf []byte) (appID, namespace string, toks []ds.KeyTok, err error) {
- if len(buf) < 2 || buf[0] != '"' || buf[len(buf)-1] != '"' {
- err = errors.New("datastore: bad JSON key")
- } else {
- appID, namespace, toks, err = ToksDecode(string(buf[1 : len(buf)-1]))
- }
- return
-}
-
-// Incomplete returns true iff k doesn't have an id yet.
-func Incomplete(k ds.Key) bool {
- return k != nil && k.StringID() == "" && k.IntID() == 0
-}
-
-// Valid determines if a key is valid, according to a couple 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 Valid(k ds.Key, allowSpecial bool, aid, ns string) bool {
- if k == nil {
- return false
- }
- if aid != k.AppID() || ns != k.Namespace() {
- return false
- }
- for ; k != nil; k = k.Parent() {
- if !allowSpecial && len(k.Kind()) >= 2 && k.Kind()[:2] == "__" {
- return false
- }
- if k.Kind() == "" || k.AppID() == "" {
- return false
- }
- if k.StringID() != "" && k.IntID() != 0 {
- return false
- }
- if k.Parent() != nil {
- if k.Parent().Incomplete() {
- return false
- }
- if k.Parent().AppID() != k.AppID() || k.Parent().Namespace() != k.Namespace() {
- return false
- }
- }
- }
- return true
-}
-
-// 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().
-func PartialValid(k ds.Key, aid, ns string) bool {
- if k.Incomplete() {
- k = New(k.AppID(), k.Namespace(), k.Kind(), "", 1, k.Parent())
- }
- return Valid(k, false, aid, ns)
-}
-
-// Root returns the entity root for the given key.
-func Root(k ds.Key) ds.Key {
- for k != nil && k.Parent() != nil {
- k = k.Parent()
- }
- return k
-}
-
-// Equal returns true iff the two keys represent identical key values.
-func Equal(a, b ds.Key) (ret bool) {
- ret = (a.Kind() == b.Kind() &&
- a.StringID() == b.StringID() &&
- a.IntID() == b.IntID() &&
- a.AppID() == b.AppID() &&
- a.Namespace() == b.Namespace())
- if !ret {
- return
- }
- ap, bp := a.Parent(), b.Parent()
- return (ap == nil && bp == nil) || Equal(ap, bp)
-}
-
-func marshalDSKey(b *bytes.Buffer, k ds.Key) {
- if k.Parent() != nil {
- marshalDSKey(b, k.Parent())
- }
- b.WriteByte('/')
- b.WriteString(k.Kind())
- b.WriteByte(',')
- if k.StringID() != "" {
- b.WriteString(k.StringID())
- } else {
- b.WriteString(strconv.FormatInt(k.IntID(), 10))
- }
-}
-
-// String returns a human-readable representation of the key, and is the
-// typical implementation of Key.String() (though it isn't guaranteed to be)
-func String(k ds.Key) string {
- if k == nil {
- return ""
- }
- b := bytes.NewBuffer(make([]byte, 0, 512))
- marshalDSKey(b, k)
- return b.String()
-}
-
-// Split splits the key into its constituent parts. Note that if the key is
-// not Valid, this method may not provide a round-trip for k.
-func Split(k ds.Key) (appID, namespace string, toks []ds.KeyTok) {
- if k == nil {
- return
- }
-
- if sk, ok := k.(*Generic); ok {
- if sk == nil {
- return
- }
- return sk.appID, sk.namespace, sk.toks
- }
-
- n := 0
- for i := k; i != nil; i = i.Parent() {
- n++
- }
- toks = make([]ds.KeyTok, n)
- for i := k; i != nil; i = i.Parent() {
- n--
- toks[n].IntID = i.IntID()
- toks[n].StringID = i.StringID()
- toks[n].Kind = i.Kind()
- }
- appID = k.AppID()
- namespace = k.Namespace()
- return
-}
« no previous file with comments | « service/datastore/dskey/generic_key.go ('k') | service/datastore/dskey/key_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698