-
Notifications
You must be signed in to change notification settings - Fork 206
datastore: add EnableKeyConversion for compatibility with Cloud Datastore encoded keys #192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
bce4541
Adding foward compatibility for key encoding
goog-lukemc 8d736f0
splitting logic into a new file
goog-lukemc 71b3369
Added implemetnation check
goog-lukemc 1a7bf35
split code into seperate files and completed code review comments
goog-lukemc 74ebe0f
Add additional return to fix nil pointer exception
goog-lukemc 3b5c8ef
added key parent testing and as well as control tests
goog-lukemc 5721432
Fix pointer preference per review comments
goog-lukemc ee4f33d
Change variable name per comment
goog-lukemc 8e1c38a
Added documentation for datastore key conversation
goog-lukemc 5d06d01
fixed various comment nits
goog-lukemc f4a9440
fixed various comment nits and typos
goog-lukemc 7789107
Updated variable name to make it more readable
goog-lukemc 7d7c327
Removed \n and spacing issue
goog-lukemc ea111b8
Update lib alias name to newnds so that the comments and the alias ma…
goog-lukemc 300b945
Update lib alias name to newnds so that the comments and the alias ma…
goog-lukemc dc956f7
Fixed various greammer issues and string spacing
goog-lukemc 35a8464
passing unit tests
goog-lukemc 68002c3
removed dependancies on new libs
goog-lukemc 0030609
code duplication file - code copied from cloud.google.com/go/datastore
goog-lukemc a66c279
Spacing and format changes
goog-lukemc cf0b497
adjusted formating
goog-lukemc adf4e0f
added sync.Once
goog-lukemc 0fbebe6
Updated Key conversion documentation in readme.md
goog-lukemc abdd3c6
corrected spelling
goog-lukemc ac84822
Updated description
goog-lukemc 5069ace
Fixed grammar issues
goog-lukemc bb0e4f6
Renamed file
goog-lukemc a55d898
renaming file
goog-lukemc aca5ca6
restructured files to new internal package
goog-lukemc 097a587
adding new package files
goog-lukemc 65b66c1
fixed various code review issues
goog-lukemc fb6e777
datastore: cleanup keycompat
broady 2c45d7e
README
broady d3c996c
keycompat -> cloudkey
broady 98afd7e
review comments
broady File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright 2019 Google Inc. All rights reserved. | ||
// Use of this source code is governed by the Apache 2.0 | ||
// license that can be found in the LICENSE file. | ||
|
||
// Package cloudpb is a subset of types and functions, copied from cloud.google.com/go/datastore. | ||
// | ||
// They are copied here to provide compatibility to decode keys generated by the cloud.google.com/go/datastore package. | ||
package cloudkey | ||
|
||
import ( | ||
"encoding/base64" | ||
"errors" | ||
"strings" | ||
|
||
"github.com/golang/protobuf/proto" | ||
cloudpb "google.golang.org/appengine/datastore/internal/cloudpb" | ||
) | ||
|
||
///////////////////////////////////////////////////////////////////// | ||
// Code below is copied from https://github.com/googleapis/google-cloud-go/blob/master/datastore/datastore.go | ||
///////////////////////////////////////////////////////////////////// | ||
|
||
var ( | ||
// ErrInvalidKey is returned when an invalid key is presented. | ||
ErrInvalidKey = errors.New("datastore: invalid key") | ||
) | ||
|
||
///////////////////////////////////////////////////////////////////// | ||
// Code below is copied from https://github.com/googleapis/google-cloud-go/blob/master/datastore/key.go | ||
///////////////////////////////////////////////////////////////////// | ||
|
||
// Key represents the datastore key for a stored entity. | ||
type Key struct { | ||
// Kind cannot be empty. | ||
Kind string | ||
// Either ID or Name must be zero for the Key to be valid. | ||
// If both are zero, the Key is incomplete. | ||
ID int64 | ||
Name string | ||
// Parent must either be a complete Key or nil. | ||
Parent *Key | ||
|
||
// Namespace provides the ability to partition your data for multiple | ||
// tenants. In most cases, it is not necessary to specify a namespace. | ||
// See docs on datastore multitenancy for details: | ||
// https://cloud.google.com/datastore/docs/concepts/multitenancy | ||
Namespace string | ||
} | ||
|
||
// DecodeKey decodes a key from the opaque representation returned by Encode. | ||
func DecodeKey(encoded string) (*Key, 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 nil, err | ||
} | ||
|
||
pKey := new(cloudpb.Key) | ||
if err := proto.Unmarshal(b, pKey); err != nil { | ||
return nil, err | ||
} | ||
return protoToKey(pKey) | ||
} | ||
|
||
// valid returns whether the key is valid. | ||
func (k *Key) valid() bool { | ||
if k == nil { | ||
return false | ||
} | ||
for ; k != nil; k = k.Parent { | ||
if k.Kind == "" { | ||
return false | ||
} | ||
if k.Name != "" && k.ID != 0 { | ||
return false | ||
} | ||
if k.Parent != nil { | ||
if k.Parent.Incomplete() { | ||
return false | ||
} | ||
if k.Parent.Namespace != k.Namespace { | ||
return false | ||
} | ||
} | ||
} | ||
return true | ||
} | ||
|
||
// Incomplete reports whether the key does not refer to a stored entity. | ||
func (k *Key) Incomplete() bool { | ||
return k.Name == "" && k.ID == 0 | ||
} | ||
|
||
// protoToKey decodes a protocol buffer representation of a key into an | ||
// equivalent *Key object. If the key is invalid, protoToKey will return the | ||
// invalid key along with ErrInvalidKey. | ||
func protoToKey(p *cloudpb.Key) (*Key, error) { | ||
var key *Key | ||
var namespace string | ||
if partition := p.PartitionId; partition != nil { | ||
namespace = partition.NamespaceId | ||
} | ||
for _, el := range p.Path { | ||
key = &Key{ | ||
Namespace: namespace, | ||
Kind: el.Kind, | ||
ID: el.GetId(), | ||
Name: el.GetName(), | ||
Parent: key, | ||
} | ||
} | ||
if !key.valid() { // Also detects key == nil. | ||
return key, ErrInvalidKey | ||
} | ||
return key, nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be simplified to
namespace := p.GetPartitionId().GetNamespaceId()
? Normally, theGet
function for protos handlesnil
values nicely.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything under internal/cloudkey and internal/cloudpb is copied/pasted from cloud.google.com/go/datastore, we should keep as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make that more clear? I wasn't sure where the copy/paste started & stopped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully better now. Added package-level doc, too.