google-cloud-datastore 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/google-cloud-datastore.rb +141 -0
- data/lib/google/cloud/datastore.rb +532 -0
- data/lib/google/cloud/datastore/commit.rb +150 -0
- data/lib/google/cloud/datastore/credentials.rb +38 -0
- data/lib/google/cloud/datastore/cursor.rb +79 -0
- data/lib/google/cloud/datastore/dataset.rb +667 -0
- data/lib/google/cloud/datastore/dataset/lookup_results.rb +222 -0
- data/lib/google/cloud/datastore/dataset/query_results.rb +389 -0
- data/lib/google/cloud/datastore/entity.rb +454 -0
- data/lib/google/cloud/datastore/errors.rb +43 -0
- data/lib/google/cloud/datastore/gql_query.rb +216 -0
- data/lib/google/cloud/datastore/grpc_utils.rb +140 -0
- data/lib/google/cloud/datastore/key.rb +289 -0
- data/lib/google/cloud/datastore/properties.rb +133 -0
- data/lib/google/cloud/datastore/query.rb +351 -0
- data/lib/google/cloud/datastore/service.rb +171 -0
- data/lib/google/cloud/datastore/transaction.rb +365 -0
- data/lib/google/cloud/datastore/version.rb +22 -0
- data/lib/google/datastore/v1/datastore_pb.rb +120 -0
- data/lib/google/datastore/v1/datastore_services_pb.rb +61 -0
- data/lib/google/datastore/v1/entity_pb.rb +63 -0
- data/lib/google/datastore/v1/query_pb.rb +131 -0
- metadata +236 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright 2014 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/errors"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Datastore
|
21
|
+
##
|
22
|
+
# # KeyError
|
23
|
+
#
|
24
|
+
# Raised when a key is not correct.
|
25
|
+
class KeyError < Google::Cloud::Error
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# # PropertyError
|
30
|
+
#
|
31
|
+
# Raised when a property is not correct.
|
32
|
+
class PropertyError < Google::Cloud::Error
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# # TransactionError
|
37
|
+
#
|
38
|
+
# General error for Transaction problems.
|
39
|
+
class TransactionError < Google::Cloud::Error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# Copyright 2016 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/datastore/entity"
|
17
|
+
require "google/cloud/datastore/key"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Datastore
|
22
|
+
##
|
23
|
+
# # GqlQuery
|
24
|
+
#
|
25
|
+
# Represents a GQL query.
|
26
|
+
#
|
27
|
+
# GQL is a SQL-like language for retrieving entities or keys from
|
28
|
+
# Datastore.
|
29
|
+
#
|
30
|
+
# @see https://cloud.google.com/datastore/docs/apis/gql/gql_reference GQL
|
31
|
+
# Reference
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
35
|
+
# gql_query.query_string = "SELECT * FROM Task ORDER BY created ASC"
|
36
|
+
# tasks = datastore.run gql_query
|
37
|
+
#
|
38
|
+
class GqlQuery
|
39
|
+
##
|
40
|
+
# Returns a new GqlQuery instance.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
44
|
+
#
|
45
|
+
def initialize
|
46
|
+
@grpc = Google::Datastore::V1::GqlQuery.new
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# The GQL query string for the query. The string may contain named or
|
51
|
+
# positional argument binding sites that start with `@`. Corresponding
|
52
|
+
# binding values should be set with {#named_bindings=} or
|
53
|
+
# {#positional_bindings=}.
|
54
|
+
#
|
55
|
+
# @return [String] a GQL statement
|
56
|
+
#
|
57
|
+
def query_string
|
58
|
+
gql = @grpc.query_string.dup
|
59
|
+
gql.freeze
|
60
|
+
gql
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Sets the GQL query string for the query. The string may contain named
|
65
|
+
# or positional argument binding sites that start with `@`.
|
66
|
+
# Corresponding binding values should be set with {#named_bindings=} or
|
67
|
+
# {#positional_bindings=}.
|
68
|
+
#
|
69
|
+
# See the [GQL
|
70
|
+
# Reference](https://cloud.google.com/datastore/docs/apis/gql/gql_reference).
|
71
|
+
#
|
72
|
+
# @param [String] new_query_string a valid GQL statement
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
76
|
+
# gql_query.query_string = "SELECT * FROM Task " \
|
77
|
+
# "WHERE done = @done " \
|
78
|
+
# "AND priority = @priority"
|
79
|
+
# gql_query.named_bindings = {done: false, priority: 4}
|
80
|
+
#
|
81
|
+
def query_string= new_query_string
|
82
|
+
@grpc.query_string = new_query_string.to_s
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Whether the query may contain literal values. When false, the query
|
87
|
+
# string must not contain any literals and instead must bind all values
|
88
|
+
# using {#named_bindings=} or {#positional_bindings=}.
|
89
|
+
#
|
90
|
+
# @return [Boolean] `true` if the query may contain literal values
|
91
|
+
#
|
92
|
+
def allow_literals
|
93
|
+
@grpc.allow_literals
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Sets whether the query may contain literal values. When false, the
|
98
|
+
# query string must not contain any literals and instead must bind all
|
99
|
+
# values using {#named_bindings=} or {#positional_bindings=}.
|
100
|
+
#
|
101
|
+
# @param [Boolean] new_allow_literals `true` if the query may contain
|
102
|
+
# literal values
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
106
|
+
# gql_query.query_string = "SELECT * FROM Task " \
|
107
|
+
# "WHERE completed = false AND priority = 4"
|
108
|
+
# gql_query.allow_literals = true
|
109
|
+
#
|
110
|
+
def allow_literals= new_allow_literals
|
111
|
+
@grpc.allow_literals = new_allow_literals
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# The named binding values for a query that contains named argument
|
116
|
+
# binding sites that start with `@`.
|
117
|
+
#
|
118
|
+
# @return [Hash] a frozen hash that maps the binding site names in the
|
119
|
+
# query string to valid GQL arguments
|
120
|
+
#
|
121
|
+
def named_bindings
|
122
|
+
bindings = Hash[@grpc.named_bindings.map do |name, gql_query_param|
|
123
|
+
if gql_query_param.parameter_type == :cursor
|
124
|
+
[name, Cursor.from_grpc(gql_query_param.cursor)]
|
125
|
+
else
|
126
|
+
[name, Core::GRPCUtils.from_value(gql_query_param.value)]
|
127
|
+
end
|
128
|
+
end]
|
129
|
+
bindings.freeze
|
130
|
+
bindings
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# Sets named binding values for a query that contains named argument
|
135
|
+
# binding sites that start with `@`.
|
136
|
+
#
|
137
|
+
# @param [Hash] new_named_bindings a hash that maps the binding site
|
138
|
+
# names in the query string to valid GQL arguments
|
139
|
+
#
|
140
|
+
# @example
|
141
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
142
|
+
# gql_query.query_string = "SELECT * FROM Task " \
|
143
|
+
# "WHERE done = @done " \
|
144
|
+
# "AND priority = @priority"
|
145
|
+
# gql_query.named_bindings = {done: false, priority: 4}
|
146
|
+
#
|
147
|
+
def named_bindings= new_named_bindings
|
148
|
+
@grpc.named_bindings.clear
|
149
|
+
new_named_bindings.map do |name, value|
|
150
|
+
if value.is_a? Google::Cloud::Datastore::Cursor
|
151
|
+
@grpc.named_bindings[name.to_s] = \
|
152
|
+
Google::Datastore::V1::GqlQueryParameter.new(
|
153
|
+
cursor: value.to_grpc)
|
154
|
+
else
|
155
|
+
@grpc.named_bindings[name.to_s] = \
|
156
|
+
Google::Datastore::V1::GqlQueryParameter.new(
|
157
|
+
value: Core::GRPCUtils.to_value(value))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# The binding values for a query that contains numbered argument binding
|
164
|
+
# sites that start with `@`.
|
165
|
+
#
|
166
|
+
# @return [Array] a frozen array containing the query arguments in the
|
167
|
+
# order of the numbered binding sites in the query string
|
168
|
+
#
|
169
|
+
def positional_bindings
|
170
|
+
bindings = @grpc.positional_bindings.map do |gql_query_param|
|
171
|
+
if gql_query_param.parameter_type == :cursor
|
172
|
+
Cursor.from_grpc gql_query_param.cursor
|
173
|
+
else
|
174
|
+
Core::GRPCUtils.from_value gql_query_param.value
|
175
|
+
end
|
176
|
+
end
|
177
|
+
bindings.freeze
|
178
|
+
bindings
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Sets the binding values for a query that contains numbered argument
|
183
|
+
# binding sites that start with `@`.
|
184
|
+
#
|
185
|
+
# @param [Array] new_positional_bindings query arguments in the order
|
186
|
+
# of the numbered binding sites in the query string
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# gql_query = Google::Cloud::Datastore::GqlQuery.new
|
190
|
+
# gql_query.query_string = "SELECT * FROM Task" \
|
191
|
+
# "WHERE completed = @1 AND priority = @2"
|
192
|
+
# gql_query.positional_bindings = [false, 4]
|
193
|
+
#
|
194
|
+
def positional_bindings= new_positional_bindings
|
195
|
+
@grpc.positional_bindings.clear
|
196
|
+
new_positional_bindings.map do |value|
|
197
|
+
if value.is_a? Google::Cloud::Datastore::Cursor
|
198
|
+
@grpc.positional_bindings << \
|
199
|
+
Google::Datastore::V1::GqlQueryParameter.new(
|
200
|
+
cursor: value.to_grpc)
|
201
|
+
else
|
202
|
+
@grpc.positional_bindings << \
|
203
|
+
Google::Datastore::V1::GqlQueryParameter.new(
|
204
|
+
value: Core::GRPCUtils.to_value(value))
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# @private
|
210
|
+
def to_grpc
|
211
|
+
@grpc
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# Copyright 2016 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
require "google/cloud/core/grpc_utils"
|
17
|
+
require "google/cloud/datastore/errors"
|
18
|
+
require "stringio"
|
19
|
+
require "base64"
|
20
|
+
|
21
|
+
module Google
|
22
|
+
module Cloud
|
23
|
+
module Core
|
24
|
+
##
|
25
|
+
# @private Conversion to/from Datastore GRPC objects.
|
26
|
+
# This file adds Datastore methods to Core::GRPCUtils.
|
27
|
+
module GRPCUtils
|
28
|
+
# rubocop:disable all
|
29
|
+
|
30
|
+
PROP_FILTER_OPS = { "<" => :LESS_THAN,
|
31
|
+
"lt" => :LESS_THAN,
|
32
|
+
"<=" => :LESS_THAN_OR_EQUAL,
|
33
|
+
"lte" => :LESS_THAN_OR_EQUAL,
|
34
|
+
">" => :GREATER_THAN,
|
35
|
+
"gt" => :GREATER_THAN,
|
36
|
+
">=" => :GREATER_THAN_OR_EQUAL,
|
37
|
+
"gte" => :GREATER_THAN_OR_EQUAL,
|
38
|
+
"=" => :EQUAL,
|
39
|
+
"eq" => :EQUAL,
|
40
|
+
"eql" => :EQUAL,
|
41
|
+
"~" => :HAS_ANCESTOR,
|
42
|
+
"~>" => :HAS_ANCESTOR,
|
43
|
+
"ancestor" => :HAS_ANCESTOR,
|
44
|
+
"has_ancestor" => :HAS_ANCESTOR,
|
45
|
+
"has ancestor" => :HAS_ANCESTOR }
|
46
|
+
|
47
|
+
##
|
48
|
+
# Get a property filter operator from op
|
49
|
+
def self.to_prop_filter_op op
|
50
|
+
PROP_FILTER_OPS[op.to_s.downcase] || :EQUAL
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Gets an object from a Google::Datastore::V1::Value.
|
55
|
+
def self.from_value grpc_value
|
56
|
+
if grpc_value.value_type == :null_value
|
57
|
+
return nil
|
58
|
+
elsif grpc_value.value_type == :key_value
|
59
|
+
return Google::Cloud::Datastore::Key.from_grpc(grpc_value.key_value)
|
60
|
+
elsif grpc_value.value_type == :entity_value
|
61
|
+
return Google::Cloud::Datastore::Entity.from_grpc(
|
62
|
+
grpc_value.entity_value)
|
63
|
+
elsif grpc_value.value_type == :boolean_value
|
64
|
+
return grpc_value.boolean_value
|
65
|
+
elsif grpc_value.value_type == :double_value
|
66
|
+
return grpc_value.double_value
|
67
|
+
elsif grpc_value.value_type == :integer_value
|
68
|
+
return grpc_value.integer_value
|
69
|
+
elsif grpc_value.value_type == :string_value
|
70
|
+
return grpc_value.string_value
|
71
|
+
elsif grpc_value.value_type == :array_value
|
72
|
+
return Array(grpc_value.array_value.values).map { |v| from_value v }
|
73
|
+
elsif grpc_value.value_type == :timestamp_value
|
74
|
+
return Time.at grpc_value.timestamp_value.seconds,
|
75
|
+
grpc_value.timestamp_value.nanos/1000.0
|
76
|
+
elsif grpc_value.value_type == :geo_point_value
|
77
|
+
return grpc_value.geo_point_value.to_hash
|
78
|
+
elsif grpc_value.value_type == :blob_value
|
79
|
+
return StringIO.new(
|
80
|
+
grpc_value.blob_value.dup.force_encoding("ASCII-8BIT"))
|
81
|
+
else
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Stores an object into a Google::Datastore::V1::Value.
|
88
|
+
def self.to_value value
|
89
|
+
v = Google::Datastore::V1::Value.new
|
90
|
+
if NilClass === value
|
91
|
+
v.null_value = :NULL_VALUE
|
92
|
+
elsif TrueClass === value
|
93
|
+
v.boolean_value = true
|
94
|
+
elsif FalseClass === value
|
95
|
+
v.boolean_value = false
|
96
|
+
elsif Integer === value
|
97
|
+
v.integer_value = value
|
98
|
+
elsif Float === value
|
99
|
+
v.double_value = value
|
100
|
+
elsif defined?(BigDecimal) && BigDecimal === value
|
101
|
+
v.double_value = value
|
102
|
+
elsif Google::Cloud::Datastore::Key === value
|
103
|
+
v.key_value = value.to_grpc
|
104
|
+
elsif Google::Cloud::Datastore::Entity === value
|
105
|
+
value.key = nil # Embedded entities can't have keys
|
106
|
+
v.entity_value = value.to_grpc
|
107
|
+
elsif String === value
|
108
|
+
v.string_value = value
|
109
|
+
elsif Array === value
|
110
|
+
v.array_value = Google::Datastore::V1::ArrayValue.new(
|
111
|
+
values: value.map { |val| to_value val }
|
112
|
+
)
|
113
|
+
elsif value.respond_to? :to_time
|
114
|
+
v.timestamp_value = Google::Protobuf::Timestamp.new(
|
115
|
+
seconds: value.to_time.to_i, nanos: value.to_time.nsec)
|
116
|
+
elsif value.respond_to?(:to_hash) &&
|
117
|
+
value.keys.sort == [:latitude, :longitude]
|
118
|
+
v.geo_point_value = Google::Type::LatLng.new(value)
|
119
|
+
elsif value.respond_to?(:read) && value.respond_to?(:rewind)
|
120
|
+
value.rewind
|
121
|
+
v.blob_value = value.read.force_encoding("ASCII-8BIT")
|
122
|
+
else
|
123
|
+
fail Google::Cloud::Datastore::PropertyError,
|
124
|
+
"A property of type #{value.class} is not supported."
|
125
|
+
end
|
126
|
+
v
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.encode_bytes bytes
|
130
|
+
Base64.strict_encode64(bytes.to_s).encode("ASCII-8BIT")
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.decode_bytes bytes
|
134
|
+
Base64.decode64(bytes.to_s).force_encoding Encoding::ASCII_8BIT
|
135
|
+
end
|
136
|
+
# rubocop:enable all
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,289 @@
|
|
1
|
+
# Copyright 2014 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Datastore
|
19
|
+
##
|
20
|
+
# # Key
|
21
|
+
#
|
22
|
+
# Every Datastore record has an identifying key, which includes the
|
23
|
+
# record's entity kind and a unique identifier. The identifier may be
|
24
|
+
# either a key name string, assigned explicitly by the application, or an
|
25
|
+
# integer numeric ID, assigned automatically by Datastore.
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
29
|
+
#
|
30
|
+
class Key
|
31
|
+
##
|
32
|
+
# The kind of the Key.
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# key = Google::Cloud::Datastore::Key.new "TaskList"
|
38
|
+
# key.kind #=> "TaskList"
|
39
|
+
# key.kind = "Task"
|
40
|
+
#
|
41
|
+
attr_accessor :kind
|
42
|
+
|
43
|
+
##
|
44
|
+
# The project of the Key.
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# require "google/cloud"
|
50
|
+
#
|
51
|
+
# gcloud = Google::Cloud.new "my-todo-project",
|
52
|
+
# "/path/to/keyfile.json"
|
53
|
+
#
|
54
|
+
# datastore = gcloud.datastore
|
55
|
+
# task = datastore.find "Task", "sampleTask"
|
56
|
+
# task.key.project #=> "my-todo-project"
|
57
|
+
#
|
58
|
+
attr_accessor :project
|
59
|
+
alias_method :dataset_id, :project
|
60
|
+
alias_method :dataset_id=, :project=
|
61
|
+
|
62
|
+
##
|
63
|
+
# The namespace of the Key.
|
64
|
+
#
|
65
|
+
# @return [String, nil]
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# require "google/cloud"
|
69
|
+
#
|
70
|
+
# gcloud = Google::Cloud.new "my-todo-project",
|
71
|
+
# "/path/to/keyfile.json"
|
72
|
+
#
|
73
|
+
# datastore = gcloud.datastore
|
74
|
+
# task = datastore.find "Task", "sampleTask"
|
75
|
+
# task.key.namespace #=> "ns~todo-project"
|
76
|
+
#
|
77
|
+
attr_accessor :namespace
|
78
|
+
|
79
|
+
##
|
80
|
+
# Create a new Key instance.
|
81
|
+
#
|
82
|
+
# @param [String] kind The kind of the Key. This is optional.
|
83
|
+
# @param [Integer, String] id_or_name The id or name of the Key. This is
|
84
|
+
# optional.
|
85
|
+
#
|
86
|
+
# @return [Google::Cloud::Datastore::Dataset::Key]
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
90
|
+
#
|
91
|
+
def initialize kind = nil, id_or_name = nil
|
92
|
+
@kind = kind
|
93
|
+
if id_or_name.is_a? Integer
|
94
|
+
@id = id_or_name
|
95
|
+
else
|
96
|
+
@name = id_or_name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# @private Set the id of the Key.
|
102
|
+
# If a name is already present it will be removed.
|
103
|
+
#
|
104
|
+
# @return [Integer, nil]
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
108
|
+
# task_key.id #=> nil
|
109
|
+
# task_key.name #=> "sampleTask"
|
110
|
+
# task_key.id = 654321
|
111
|
+
# task_key.id #=> 654321
|
112
|
+
# task_key.name #=> nil
|
113
|
+
#
|
114
|
+
def id= new_id
|
115
|
+
@name = nil if new_id
|
116
|
+
@id = new_id
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# The id of the Key.
|
121
|
+
#
|
122
|
+
# @return [Integer, nil]
|
123
|
+
#
|
124
|
+
# @example
|
125
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", 123456
|
126
|
+
# task_key.id #=> 123456
|
127
|
+
#
|
128
|
+
attr_reader :id
|
129
|
+
|
130
|
+
##
|
131
|
+
# @private Set the name of the Key.
|
132
|
+
# If an id is already present it will be removed.
|
133
|
+
#
|
134
|
+
# @return [String, nil]
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", 123456
|
138
|
+
# task_key.id #=> 123456
|
139
|
+
# task_key.name #=> nil
|
140
|
+
# task_key.name = "sampleTask"
|
141
|
+
# task_key.id #=> nil
|
142
|
+
# task_key.name #=> "sampleTask"
|
143
|
+
#
|
144
|
+
def name= new_name
|
145
|
+
@id = nil if new_name
|
146
|
+
@name = new_name
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# The name of the Key.
|
151
|
+
#
|
152
|
+
# @return [String, nil]
|
153
|
+
#
|
154
|
+
# @example
|
155
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
156
|
+
# task_key.name #=> "sampleTask"
|
157
|
+
#
|
158
|
+
attr_reader :name
|
159
|
+
|
160
|
+
##
|
161
|
+
# Set the parent of the Key.
|
162
|
+
#
|
163
|
+
# @return [Key, nil]
|
164
|
+
#
|
165
|
+
# @example
|
166
|
+
# parent_key = Google::Cloud::Datastore::Key.new "TaskList", "default"
|
167
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
168
|
+
# task_key.parent = parent_key
|
169
|
+
#
|
170
|
+
# @example With multiple levels:
|
171
|
+
# user_key = Google::Cloud::Datastore::Key.new "User", "alice"
|
172
|
+
# list_key = Google::Cloud::Datastore::Key.new "TaskList", "default"
|
173
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
174
|
+
# list_key.parent = user_key
|
175
|
+
# task_key.parent = list_key
|
176
|
+
#
|
177
|
+
def parent= new_parent
|
178
|
+
# store key if given an entity
|
179
|
+
new_parent = new_parent.key if new_parent.respond_to? :key
|
180
|
+
@parent = new_parent
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# The parent of the Key.
|
185
|
+
#
|
186
|
+
# @return [Key, nil]
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# require "google/cloud"
|
190
|
+
#
|
191
|
+
# gcloud = Google::Cloud.new
|
192
|
+
# datastore = gcloud.datastore
|
193
|
+
#
|
194
|
+
# task_list = datastore.find "TaskList", "default"
|
195
|
+
# query = datastore.query("Task").
|
196
|
+
# ancestor(task_list)
|
197
|
+
# lists = datastore.run query
|
198
|
+
# lists.first.key.parent #=> Key("TaskList", "default")
|
199
|
+
#
|
200
|
+
attr_reader :parent
|
201
|
+
|
202
|
+
##
|
203
|
+
# Represent the Key's path (including parent) as an array of arrays.
|
204
|
+
# Each inner array contains two values, the kind and the id or name.
|
205
|
+
# If neither an id or name exist then nil will be returned.
|
206
|
+
#
|
207
|
+
# @return [Array<Array<(String, String)>>]
|
208
|
+
#
|
209
|
+
# @example
|
210
|
+
# parent_key = Google::Cloud::Datastore::Key.new "TaskList", "default"
|
211
|
+
# task_key = Google::Cloud::Datastore::Key.new "Task", "sampleTask"
|
212
|
+
# task_key.parent = parent_key
|
213
|
+
# task_key.path #=> [["TaskList", "default"], ["Task", "sampleTask"]]
|
214
|
+
#
|
215
|
+
def path
|
216
|
+
new_path = parent ? parent.path : []
|
217
|
+
new_path << [kind, (id || name)]
|
218
|
+
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# Determine if the key is complete.
|
222
|
+
# A complete key has either an id or a name.
|
223
|
+
#
|
224
|
+
# Inverse of {#incomplete?}
|
225
|
+
def complete?
|
226
|
+
!incomplete?
|
227
|
+
end
|
228
|
+
|
229
|
+
##
|
230
|
+
# Determine if the key is incomplete.
|
231
|
+
# An incomplete key has neither an id nor a name.
|
232
|
+
#
|
233
|
+
# Inverse of {#complete?}
|
234
|
+
def incomplete?
|
235
|
+
kind.nil? || (id.nil? && (name.nil? || name.empty?))
|
236
|
+
end
|
237
|
+
|
238
|
+
##
|
239
|
+
# The number of bytes the Key will take to serialize during API calls.
|
240
|
+
def serialized_size
|
241
|
+
to_grpc.to_proto.length
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# @private Convert the Key to a Google::Datastore::V1::Key object.
|
246
|
+
def to_grpc
|
247
|
+
grpc_path = path.map do |pe_kind, pe_id_or_name|
|
248
|
+
path_args = { kind: pe_kind }
|
249
|
+
if pe_id_or_name.is_a? Integer
|
250
|
+
path_args[:id] = pe_id_or_name
|
251
|
+
elsif pe_id_or_name.is_a? String
|
252
|
+
path_args[:name] = pe_id_or_name unless pe_id_or_name.empty?
|
253
|
+
end
|
254
|
+
Google::Datastore::V1::Key::PathElement.new(path_args)
|
255
|
+
end
|
256
|
+
grpc = Google::Datastore::V1::Key.new(path: grpc_path)
|
257
|
+
if project || namespace
|
258
|
+
grpc.partition_id = Google::Datastore::V1::PartitionId.new(
|
259
|
+
project_id: project.to_s, namespace_id: namespace.to_s)
|
260
|
+
end
|
261
|
+
grpc
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# @private Create a new Key from a Google::Datastore::V1::Key
|
266
|
+
# object.
|
267
|
+
def self.from_grpc grpc
|
268
|
+
return nil if grpc.nil?
|
269
|
+
key_grpc = grpc.dup
|
270
|
+
key = Key.new
|
271
|
+
path_grpc = key_grpc.path.pop
|
272
|
+
if path_grpc
|
273
|
+
id_or_name =
|
274
|
+
(path_grpc.id_type == :id ? path_grpc.id : path_grpc.name)
|
275
|
+
key = Key.new path_grpc.kind, id_or_name
|
276
|
+
end
|
277
|
+
if key_grpc.partition_id
|
278
|
+
key.project = key_grpc.partition_id.project_id
|
279
|
+
key.namespace = key_grpc.partition_id.namespace_id
|
280
|
+
end
|
281
|
+
key.parent = Key.from_grpc(key_grpc) if key_grpc.path.count > 0
|
282
|
+
# Freeze the key to make it immutable.
|
283
|
+
key.freeze
|
284
|
+
key
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|