google-cloud-datastore 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|