key.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2011 Google Inc. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package datastore
  5. import (
  6. "bytes"
  7. "encoding/base64"
  8. "encoding/gob"
  9. "errors"
  10. "fmt"
  11. "strconv"
  12. "strings"
  13. "github.com/golang/protobuf/proto"
  14. "golang.org/x/net/context"
  15. "google.golang.org/appengine/internal"
  16. pb "google.golang.org/appengine/internal/datastore"
  17. )
  18. // Key represents the datastore key for a stored entity, and is immutable.
  19. type Key struct {
  20. kind string
  21. stringID string
  22. intID int64
  23. parent *Key
  24. appID string
  25. namespace string
  26. }
  27. // Kind returns the key's kind (also known as entity type).
  28. func (k *Key) Kind() string {
  29. return k.kind
  30. }
  31. // StringID returns the key's string ID (also known as an entity name or key
  32. // name), which may be "".
  33. func (k *Key) StringID() string {
  34. return k.stringID
  35. }
  36. // IntID returns the key's integer ID, which may be 0.
  37. func (k *Key) IntID() int64 {
  38. return k.intID
  39. }
  40. // Parent returns the key's parent key, which may be nil.
  41. func (k *Key) Parent() *Key {
  42. return k.parent
  43. }
  44. // AppID returns the key's application ID.
  45. func (k *Key) AppID() string {
  46. return k.appID
  47. }
  48. // Namespace returns the key's namespace.
  49. func (k *Key) Namespace() string {
  50. return k.namespace
  51. }
  52. // Incomplete returns whether the key does not refer to a stored entity.
  53. // In particular, whether the key has a zero StringID and a zero IntID.
  54. func (k *Key) Incomplete() bool {
  55. return k.stringID == "" && k.intID == 0
  56. }
  57. // valid returns whether the key is valid.
  58. func (k *Key) valid() bool {
  59. if k == nil {
  60. return false
  61. }
  62. for ; k != nil; k = k.parent {
  63. if k.kind == "" || k.appID == "" {
  64. return false
  65. }
  66. if k.stringID != "" && k.intID != 0 {
  67. return false
  68. }
  69. if k.parent != nil {
  70. if k.parent.Incomplete() {
  71. return false
  72. }
  73. if k.parent.appID != k.appID || k.parent.namespace != k.namespace {
  74. return false
  75. }
  76. }
  77. }
  78. return true
  79. }
  80. // Equal returns whether two keys are equal.
  81. func (k *Key) Equal(o *Key) bool {
  82. for k != nil && o != nil {
  83. if k.kind != o.kind || k.stringID != o.stringID || k.intID != o.intID || k.appID != o.appID || k.namespace != o.namespace {
  84. return false
  85. }
  86. k, o = k.parent, o.parent
  87. }
  88. return k == o
  89. }
  90. // root returns the furthest ancestor of a key, which may be itself.
  91. func (k *Key) root() *Key {
  92. for k.parent != nil {
  93. k = k.parent
  94. }
  95. return k
  96. }
  97. // marshal marshals the key's string representation to the buffer.
  98. func (k *Key) marshal(b *bytes.Buffer) {
  99. if k.parent != nil {
  100. k.parent.marshal(b)
  101. }
  102. b.WriteByte('/')
  103. b.WriteString(k.kind)
  104. b.WriteByte(',')
  105. if k.stringID != "" {
  106. b.WriteString(k.stringID)
  107. } else {
  108. b.WriteString(strconv.FormatInt(k.intID, 10))
  109. }
  110. }
  111. // String returns a string representation of the key.
  112. func (k *Key) String() string {
  113. if k == nil {
  114. return ""
  115. }
  116. b := bytes.NewBuffer(make([]byte, 0, 512))
  117. k.marshal(b)
  118. return b.String()
  119. }
  120. type gobKey struct {
  121. Kind string
  122. StringID string
  123. IntID int64
  124. Parent *gobKey
  125. AppID string
  126. Namespace string
  127. }
  128. func keyToGobKey(k *Key) *gobKey {
  129. if k == nil {
  130. return nil
  131. }
  132. return &gobKey{
  133. Kind: k.kind,
  134. StringID: k.stringID,
  135. IntID: k.intID,
  136. Parent: keyToGobKey(k.parent),
  137. AppID: k.appID,
  138. Namespace: k.namespace,
  139. }
  140. }
  141. func gobKeyToKey(gk *gobKey) *Key {
  142. if gk == nil {
  143. return nil
  144. }
  145. return &Key{
  146. kind: gk.Kind,
  147. stringID: gk.StringID,
  148. intID: gk.IntID,
  149. parent: gobKeyToKey(gk.Parent),
  150. appID: gk.AppID,
  151. namespace: gk.Namespace,
  152. }
  153. }
  154. func (k *Key) GobEncode() ([]byte, error) {
  155. buf := new(bytes.Buffer)
  156. if err := gob.NewEncoder(buf).Encode(keyToGobKey(k)); err != nil {
  157. return nil, err
  158. }
  159. return buf.Bytes(), nil
  160. }
  161. func (k *Key) GobDecode(buf []byte) error {
  162. gk := new(gobKey)
  163. if err := gob.NewDecoder(bytes.NewBuffer(buf)).Decode(gk); err != nil {
  164. return err
  165. }
  166. *k = *gobKeyToKey(gk)
  167. return nil
  168. }
  169. func (k *Key) MarshalJSON() ([]byte, error) {
  170. return []byte(`"` + k.Encode() + `"`), nil
  171. }
  172. func (k *Key) UnmarshalJSON(buf []byte) error {
  173. if len(buf) < 2 || buf[0] != '"' || buf[len(buf)-1] != '"' {
  174. return errors.New("datastore: bad JSON key")
  175. }
  176. k2, err := DecodeKey(string(buf[1 : len(buf)-1]))
  177. if err != nil {
  178. return err
  179. }
  180. *k = *k2
  181. return nil
  182. }
  183. // Encode returns an opaque representation of the key
  184. // suitable for use in HTML and URLs.
  185. // This is compatible with the Python and Java runtimes.
  186. func (k *Key) Encode() string {
  187. ref := keyToProto("", k)
  188. b, err := proto.Marshal(ref)
  189. if err != nil {
  190. panic(err)
  191. }
  192. // Trailing padding is stripped.
  193. return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=")
  194. }
  195. // DecodeKey decodes a key from the opaque representation returned by Encode.
  196. func DecodeKey(encoded string) (*Key, error) {
  197. // Re-add padding.
  198. if m := len(encoded) % 4; m != 0 {
  199. encoded += strings.Repeat("=", 4-m)
  200. }
  201. b, err := base64.URLEncoding.DecodeString(encoded)
  202. if err != nil {
  203. return nil, err
  204. }
  205. ref := new(pb.Reference)
  206. if err := proto.Unmarshal(b, ref); err != nil {
  207. return nil, err
  208. }
  209. return protoToKey(ref)
  210. }
  211. // NewIncompleteKey creates a new incomplete key.
  212. // kind cannot be empty.
  213. func NewIncompleteKey(c context.Context, kind string, parent *Key) *Key {
  214. return NewKey(c, kind, "", 0, parent)
  215. }
  216. // NewKey creates a new key.
  217. // kind cannot be empty.
  218. // Either one or both of stringID and intID must be zero. If both are zero,
  219. // the key returned is incomplete.
  220. // parent must either be a complete key or nil.
  221. func NewKey(c context.Context, kind, stringID string, intID int64, parent *Key) *Key {
  222. // If there's a parent key, use its namespace.
  223. // Otherwise, use any namespace attached to the context.
  224. var namespace string
  225. if parent != nil {
  226. namespace = parent.namespace
  227. } else {
  228. namespace = internal.NamespaceFromContext(c)
  229. }
  230. return &Key{
  231. kind: kind,
  232. stringID: stringID,
  233. intID: intID,
  234. parent: parent,
  235. appID: internal.FullyQualifiedAppID(c),
  236. namespace: namespace,
  237. }
  238. }
  239. // AllocateIDs returns a range of n integer IDs with the given kind and parent
  240. // combination. kind cannot be empty; parent may be nil. The IDs in the range
  241. // returned will not be used by the datastore's automatic ID sequence generator
  242. // and may be used with NewKey without conflict.
  243. //
  244. // The range is inclusive at the low end and exclusive at the high end. In
  245. // other words, valid intIDs x satisfy low <= x && x < high.
  246. //
  247. // If no error is returned, low + n == high.
  248. func AllocateIDs(c context.Context, kind string, parent *Key, n int) (low, high int64, err error) {
  249. if kind == "" {
  250. return 0, 0, errors.New("datastore: AllocateIDs given an empty kind")
  251. }
  252. if n < 0 {
  253. return 0, 0, fmt.Errorf("datastore: AllocateIDs given a negative count: %d", n)
  254. }
  255. if n == 0 {
  256. return 0, 0, nil
  257. }
  258. req := &pb.AllocateIdsRequest{
  259. ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)),
  260. Size: proto.Int64(int64(n)),
  261. }
  262. res := &pb.AllocateIdsResponse{}
  263. if err := internal.Call(c, "datastore_v3", "AllocateIds", req, res); err != nil {
  264. return 0, 0, err
  265. }
  266. // The protobuf is inclusive at both ends. Idiomatic Go (e.g. slices, for loops)
  267. // is inclusive at the low end and exclusive at the high end, so we add 1.
  268. low = res.GetStart()
  269. high = res.GetEnd() + 1
  270. if low+int64(n) != high {
  271. return 0, 0, fmt.Errorf("datastore: internal error: could not allocate %d IDs", n)
  272. }
  273. return low, high, nil
  274. }