google-cloud-spanner 1.2.0 → 1.3.1
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 +4 -4
- data/lib/google-cloud-spanner.rb +25 -0
- data/lib/google/cloud/spanner.rb +71 -11
- data/lib/google/cloud/spanner/batch_client.rb +355 -0
- data/lib/google/cloud/spanner/batch_snapshot.rb +588 -0
- data/lib/google/cloud/spanner/client.rb +27 -20
- data/lib/google/cloud/spanner/commit.rb +6 -5
- data/lib/google/cloud/spanner/convert.rb +39 -0
- data/lib/google/cloud/spanner/credentials.rb +7 -7
- data/lib/google/cloud/spanner/data.rb +5 -5
- data/lib/google/cloud/spanner/database.rb +13 -7
- data/lib/google/cloud/spanner/database/job.rb +7 -2
- data/lib/google/cloud/spanner/database/list.rb +1 -1
- data/lib/google/cloud/spanner/fields.rb +16 -12
- data/lib/google/cloud/spanner/instance.rb +25 -13
- data/lib/google/cloud/spanner/instance/config.rb +2 -2
- data/lib/google/cloud/spanner/instance/config/list.rb +1 -1
- data/lib/google/cloud/spanner/instance/job.rb +7 -2
- data/lib/google/cloud/spanner/instance/list.rb +1 -1
- data/lib/google/cloud/spanner/partition.rb +208 -0
- data/lib/google/cloud/spanner/pool.rb +6 -6
- data/lib/google/cloud/spanner/project.rb +59 -16
- data/lib/google/cloud/spanner/results.rb +12 -5
- data/lib/google/cloud/spanner/service.rb +85 -61
- data/lib/google/cloud/spanner/session.rb +45 -9
- data/lib/google/cloud/spanner/snapshot.rb +10 -2
- data/lib/google/cloud/spanner/status.rb +6 -5
- data/lib/google/cloud/spanner/transaction.rb +11 -3
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/duration.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/struct.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/protobuf/timestamp.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/keys.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/mutation.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/query_plan.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/result_set.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/spanner.rb +138 -6
- data/lib/google/cloud/spanner/v1/doc/google/spanner/v1/transaction.rb +1 -1
- data/lib/google/cloud/spanner/v1/doc/overview.rb +6 -5
- data/lib/google/cloud/spanner/v1/spanner_client.rb +257 -33
- data/lib/google/cloud/spanner/v1/spanner_client_config.json +10 -0
- data/lib/google/cloud/spanner/version.rb +1 -1
- data/lib/google/spanner/v1/spanner_pb.rb +35 -0
- data/lib/google/spanner/v1/spanner_services_pb.rb +20 -2
- metadata +12 -9
@@ -0,0 +1,588 @@
|
|
1
|
+
# Copyright 2018 Google LLC
|
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
|
+
# https://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/spanner/convert"
|
17
|
+
require "google/cloud/spanner/session"
|
18
|
+
require "google/cloud/spanner/partition"
|
19
|
+
require "google/cloud/spanner/results"
|
20
|
+
require "json"
|
21
|
+
require "base64"
|
22
|
+
|
23
|
+
module Google
|
24
|
+
module Cloud
|
25
|
+
module Spanner
|
26
|
+
##
|
27
|
+
# # BatchSnapshot
|
28
|
+
#
|
29
|
+
# Represents a read-only transaction that can be configured to read at
|
30
|
+
# timestamps in the past and allows for exporting arbitrarily large
|
31
|
+
# amounts of data from Cloud Spanner databases. This is a snapshot which
|
32
|
+
# additionally allows to partition a read or query request. The read/query
|
33
|
+
# request can then be executed independently over each partition while
|
34
|
+
# observing the same snapshot of the database. A BatchSnapshot can also be
|
35
|
+
# shared across multiple processes/machines by passing around its
|
36
|
+
# serialized value and then recreating the transaction using
|
37
|
+
# {BatchClient#dump}.
|
38
|
+
#
|
39
|
+
# Unlike locking read-write transactions, BatchSnapshot will never abort.
|
40
|
+
# They can fail if the chosen read timestamp is garbage collected; however
|
41
|
+
# any read or query activity within an hour on the transaction avoids
|
42
|
+
# garbage collection and most applications do not need to worry about this
|
43
|
+
# in practice.
|
44
|
+
#
|
45
|
+
# See {BatchClient#batch_snapshot} and {BatchClient#load_batch_snapshot}.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# require "google/cloud/spanner"
|
49
|
+
#
|
50
|
+
# spanner = Google::Cloud::Spanner.new
|
51
|
+
#
|
52
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
53
|
+
# batch_snapshot = batch_client.batch_snapshot
|
54
|
+
#
|
55
|
+
# partitions = batch_snapshot.partition_read "users", [:id, :name]
|
56
|
+
#
|
57
|
+
# partition = partitions.first
|
58
|
+
# results = batch_snapshot.execute_partition partition
|
59
|
+
#
|
60
|
+
# batch_snapshot.close
|
61
|
+
#
|
62
|
+
class BatchSnapshot
|
63
|
+
# @private The transaction grpc object.
|
64
|
+
attr_reader :grpc
|
65
|
+
|
66
|
+
# @private The Session object.
|
67
|
+
attr_reader :session
|
68
|
+
|
69
|
+
##
|
70
|
+
# @private Creates a BatchSnapshot object.
|
71
|
+
def initialize grpc, session
|
72
|
+
@grpc = grpc
|
73
|
+
@session = session
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Identifier of the batch snapshot transaction.
|
78
|
+
# @return [String] The transaction id.
|
79
|
+
def transaction_id
|
80
|
+
return nil if grpc.nil?
|
81
|
+
grpc.id
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# The read timestamp chosen for batch snapshot.
|
86
|
+
# @return [Time] The chosen timestamp.
|
87
|
+
def timestamp
|
88
|
+
return nil if grpc.nil?
|
89
|
+
Convert.timestamp_to_time grpc.read_timestamp
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Returns a list of {Partition} objects to execute a batch query against
|
94
|
+
# a database.
|
95
|
+
#
|
96
|
+
# These partitions can be executed across multiple processes, even
|
97
|
+
# across different machines. The partition size and count can be
|
98
|
+
# configured, although the values given may not necessarily be honored
|
99
|
+
# depending on the query and options in the request.
|
100
|
+
#
|
101
|
+
# The query must have a single [distributed
|
102
|
+
# union](https://cloud.google.com/spanner/docs/query-execution-operators#distributed_union)
|
103
|
+
# operator at the root of the query plan. Such queries are
|
104
|
+
# root-partitionable. If a query cannot be partitioned at the root,
|
105
|
+
# Cloud Spanner cannot achieve the parallelism and in this case
|
106
|
+
# partition generation will fail.
|
107
|
+
#
|
108
|
+
# @param [String] sql The SQL query string. See [Query
|
109
|
+
# syntax](https://cloud.google.com/spanner/docs/query-syntax).
|
110
|
+
#
|
111
|
+
# The SQL query string can contain parameter placeholders. A parameter
|
112
|
+
# placeholder consists of "@" followed by the parameter name.
|
113
|
+
# Parameter names consist of any combination of letters, numbers, and
|
114
|
+
# underscores.
|
115
|
+
# @param [Integer] partition_size_bytes The desired data size for each
|
116
|
+
# partition generated. This is only a hint. The actual size of each
|
117
|
+
# partition may be smaller or larger than this size request.
|
118
|
+
# @param [Integer] max_partitions The desired maximum number of
|
119
|
+
# partitions to return. For example, this may be set to the number of
|
120
|
+
# workers available. This is only a hint and may provide different
|
121
|
+
# results based on the request.
|
122
|
+
# @param [Hash] params SQL parameters for the query string. The
|
123
|
+
# parameter placeholders, minus the "@", are the the hash keys, and
|
124
|
+
# the literal values are the hash values. If the query string contains
|
125
|
+
# something like "WHERE id > @msg_id", then the params must contain
|
126
|
+
# something like `:msg_id => 1`.
|
127
|
+
# @param [Hash] types Types of the SQL parameters in `params`. It is not
|
128
|
+
# always possible for Cloud Spanner to infer the right SQL type from a
|
129
|
+
# value in `params`. In these cases, the `types` hash can be used to
|
130
|
+
# specify the exact SQL type for some or all of the SQL query
|
131
|
+
# parameters.
|
132
|
+
#
|
133
|
+
# The keys of the hash should be query string parameter placeholders,
|
134
|
+
# minus the "@". The values of the hash should be Cloud Spanner type
|
135
|
+
# codes from the following list:
|
136
|
+
#
|
137
|
+
# * `:BOOL`
|
138
|
+
# * `:BYTES`
|
139
|
+
# * `:DATE`
|
140
|
+
# * `:FLOAT64`
|
141
|
+
# * `:INT64`
|
142
|
+
# * `:STRING`
|
143
|
+
# * `:TIMESTAMP`
|
144
|
+
#
|
145
|
+
# Arrays are specified by providing the type code in an array. For
|
146
|
+
# example, an array of integers are specified as `[:INT64]`.
|
147
|
+
#
|
148
|
+
# Structs are not yet supported in query parameters.
|
149
|
+
#
|
150
|
+
# Types are optional.
|
151
|
+
#
|
152
|
+
# @return [Array<Google::Cloud::Spanner::Partition>] The partitions
|
153
|
+
# created by the query partition.
|
154
|
+
#
|
155
|
+
# @example
|
156
|
+
# require "google/cloud/spanner"
|
157
|
+
#
|
158
|
+
# spanner = Google::Cloud::Spanner.new
|
159
|
+
#
|
160
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
161
|
+
# batch_snapshot = batch_client.batch_snapshot
|
162
|
+
#
|
163
|
+
# sql = "SELECT u.id, u.active FROM users AS u \
|
164
|
+
# WHERE u.id < 2000 AND u.active = false"
|
165
|
+
# partitions = batch_snapshot.partition_query sql
|
166
|
+
#
|
167
|
+
# partition = partitions.first
|
168
|
+
# results = batch_snapshot.execute_partition partition
|
169
|
+
#
|
170
|
+
# batch_snapshot.close
|
171
|
+
#
|
172
|
+
def partition_query sql, params: nil, types: nil,
|
173
|
+
partition_size_bytes: nil, max_partitions: nil
|
174
|
+
ensure_session!
|
175
|
+
|
176
|
+
params, types = Convert.to_input_params_and_types params, types
|
177
|
+
|
178
|
+
results = session.partition_query \
|
179
|
+
sql, tx_selector, params: params, types: types,
|
180
|
+
partition_size_bytes: partition_size_bytes,
|
181
|
+
max_partitions: max_partitions
|
182
|
+
|
183
|
+
results.partitions.map do |grpc|
|
184
|
+
# Convert partition protos to execute sql request protos
|
185
|
+
execute_grpc = Google::Spanner::V1::ExecuteSqlRequest.new(
|
186
|
+
{
|
187
|
+
session: session.path,
|
188
|
+
sql: sql,
|
189
|
+
params: params,
|
190
|
+
param_types: types,
|
191
|
+
transaction: tx_selector,
|
192
|
+
partition_token: grpc.partition_token
|
193
|
+
}.delete_if { |_, v| v.nil? }
|
194
|
+
)
|
195
|
+
Partition.from_execute_grpc execute_grpc
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Returns a list of {Partition} objects to read zero or more rows from a
|
201
|
+
# database.
|
202
|
+
#
|
203
|
+
# These partitions can be executed across multiple processes, even
|
204
|
+
# across different machines. The partition size and count can be
|
205
|
+
# configured, although the values given may not necessarily be honored
|
206
|
+
# depending on the query and options in the request.
|
207
|
+
#
|
208
|
+
# @param [String] table The name of the table in the database to be
|
209
|
+
# read.
|
210
|
+
# @param [Array<String, Symbol>] columns The columns of table to be
|
211
|
+
# returned for each row matching this request.
|
212
|
+
# @param [Object, Array<Object>] keys A single, or list of keys or key
|
213
|
+
# ranges to match returned data to. Values should have exactly as many
|
214
|
+
# elements as there are columns in the primary key.
|
215
|
+
# @param [String] index The name of an index to use instead of the
|
216
|
+
# table's primary key when interpreting `id` and sorting result rows.
|
217
|
+
# Optional.
|
218
|
+
# @param [Integer] partition_size_bytes The desired data size for each
|
219
|
+
# partition generated. This is only a hint. The actual size of each
|
220
|
+
# partition may be smaller or larger than this size request.
|
221
|
+
# @param [Integer] max_partitions The desired maximum number of
|
222
|
+
# partitions to return. For example, this may be set to the number of
|
223
|
+
# workers available. This is only a hint and may provide different
|
224
|
+
# results based on the request.
|
225
|
+
#
|
226
|
+
# @return [Array<Google::Cloud::Spanner::Partition>] The partitions
|
227
|
+
# created by the read partition.
|
228
|
+
#
|
229
|
+
# @example
|
230
|
+
# require "google/cloud/spanner"
|
231
|
+
#
|
232
|
+
# spanner = Google::Cloud::Spanner.new
|
233
|
+
#
|
234
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
235
|
+
# batch_snapshot = batch_client.batch_snapshot
|
236
|
+
#
|
237
|
+
# partitions = batch_snapshot.partition_read "users", [:id, :name]
|
238
|
+
#
|
239
|
+
# partition = partitions.first
|
240
|
+
# results = batch_snapshot.execute_partition partition
|
241
|
+
#
|
242
|
+
# batch_snapshot.close
|
243
|
+
#
|
244
|
+
def partition_read table, columns, keys: nil, index: nil,
|
245
|
+
partition_size_bytes: nil, max_partitions: nil
|
246
|
+
ensure_session!
|
247
|
+
|
248
|
+
columns = Array(columns).map(&:to_s)
|
249
|
+
keys = Convert.to_key_set keys
|
250
|
+
|
251
|
+
results = session.partition_read \
|
252
|
+
table, columns, tx_selector,
|
253
|
+
keys: keys, index: index,
|
254
|
+
partition_size_bytes: partition_size_bytes,
|
255
|
+
max_partitions: max_partitions
|
256
|
+
|
257
|
+
results.partitions.map do |grpc|
|
258
|
+
# Convert partition protos to read request protos
|
259
|
+
read_grpc = Google::Spanner::V1::ReadRequest.new(
|
260
|
+
{
|
261
|
+
session: session.path,
|
262
|
+
table: table,
|
263
|
+
columns: columns,
|
264
|
+
key_set: keys,
|
265
|
+
index: index,
|
266
|
+
transaction: tx_selector,
|
267
|
+
partition_token: grpc.partition_token
|
268
|
+
}.delete_if { |_, v| v.nil? }
|
269
|
+
)
|
270
|
+
Partition.from_read_grpc read_grpc
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# Execute the partition to return a {ResultSet}. The result returned
|
276
|
+
# could be zero or more rows. The row metadata may be absent if no rows
|
277
|
+
# are returned.
|
278
|
+
#
|
279
|
+
# @param [Google::Cloud::Spanner::Partition] partition The partition to
|
280
|
+
# be executed.
|
281
|
+
#
|
282
|
+
# @example
|
283
|
+
# require "google/cloud/spanner"
|
284
|
+
#
|
285
|
+
# spanner = Google::Cloud::Spanner.new
|
286
|
+
#
|
287
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
288
|
+
# batch_snapshot = batch_client.batch_snapshot
|
289
|
+
#
|
290
|
+
# partitions = batch_snapshot.partition_read "users", [:id, :name]
|
291
|
+
#
|
292
|
+
# partition = partitions.first
|
293
|
+
# results = batch_snapshot.execute_partition partition
|
294
|
+
#
|
295
|
+
# batch_snapshot.close
|
296
|
+
#
|
297
|
+
def execute_partition partition
|
298
|
+
ensure_session!
|
299
|
+
|
300
|
+
partition = Partition.load partition unless partition.is_a? Partition
|
301
|
+
# TODO: raise if partition.empty?
|
302
|
+
|
303
|
+
# TODO: raise if session.path != partition.session
|
304
|
+
# TODO: raise if grpc.transaction != partition.transaction
|
305
|
+
|
306
|
+
if partition.execute?
|
307
|
+
execute_partition_query partition
|
308
|
+
elsif partition.read?
|
309
|
+
execute_partition_read partition
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
##
|
314
|
+
# Closes the batch snapshot and releases the underlying resources.
|
315
|
+
#
|
316
|
+
# This should only be called once the batch snapshot is no longer needed
|
317
|
+
# anywhere. In particular if this batch snapshot is being used across
|
318
|
+
# multiple machines, calling this method on any of the machines will
|
319
|
+
# render the batch snapshot invalid everywhere.
|
320
|
+
#
|
321
|
+
# @example
|
322
|
+
# require "google/cloud/spanner"
|
323
|
+
#
|
324
|
+
# spanner = Google::Cloud::Spanner.new
|
325
|
+
#
|
326
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
327
|
+
# batch_snapshot = batch_client.batch_snapshot
|
328
|
+
#
|
329
|
+
# partitions = batch_snapshot.partition_read "users", [:id, :name]
|
330
|
+
#
|
331
|
+
# partition = partitions.first
|
332
|
+
# results = batch_snapshot.execute_partition partition
|
333
|
+
#
|
334
|
+
# batch_snapshot.close
|
335
|
+
#
|
336
|
+
def close
|
337
|
+
ensure_session!
|
338
|
+
|
339
|
+
session.release!
|
340
|
+
end
|
341
|
+
|
342
|
+
##
|
343
|
+
# Executes a SQL query.
|
344
|
+
#
|
345
|
+
# Arguments can be passed using `params`, Ruby types are mapped to
|
346
|
+
# Spanner types as follows:
|
347
|
+
#
|
348
|
+
# | Spanner | Ruby | Notes |
|
349
|
+
# |-------------|----------------|---|
|
350
|
+
# | `BOOL` | `true`/`false` | |
|
351
|
+
# | `INT64` | `Integer` | |
|
352
|
+
# | `FLOAT64` | `Float` | |
|
353
|
+
# | `STRING` | `String` | |
|
354
|
+
# | `DATE` | `Date` | |
|
355
|
+
# | `TIMESTAMP` | `Time`, `DateTime` | |
|
356
|
+
# | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
|
357
|
+
# | `ARRAY` | `Array` | Nested arrays are not supported. |
|
358
|
+
#
|
359
|
+
# See [Data
|
360
|
+
# types](https://cloud.google.com/spanner/docs/data-definition-language#data_types).
|
361
|
+
#
|
362
|
+
# @param [String] sql The SQL query string. See [Query
|
363
|
+
# syntax](https://cloud.google.com/spanner/docs/query-syntax).
|
364
|
+
#
|
365
|
+
# The SQL query string can contain parameter placeholders. A parameter
|
366
|
+
# placeholder consists of "@" followed by the parameter name.
|
367
|
+
# Parameter names consist of any combination of letters, numbers, and
|
368
|
+
# underscores.
|
369
|
+
# @param [Hash] params SQL parameters for the query string. The
|
370
|
+
# parameter placeholders, minus the "@", are the the hash keys, and
|
371
|
+
# the literal values are the hash values. If the query string contains
|
372
|
+
# something like "WHERE id > @msg_id", then the params must contain
|
373
|
+
# something like `:msg_id => 1`.
|
374
|
+
# @param [Hash] types Types of the SQL parameters in `params`. It is not
|
375
|
+
# always possible for Cloud Spanner to infer the right SQL type from a
|
376
|
+
# value in `params`. In these cases, the `types` hash can be used to
|
377
|
+
# specify the exact SQL type for some or all of the SQL query
|
378
|
+
# parameters.
|
379
|
+
#
|
380
|
+
# The keys of the hash should be query string parameter placeholders,
|
381
|
+
# minus the "@". The values of the hash should be Cloud Spanner type
|
382
|
+
# codes from the following list:
|
383
|
+
#
|
384
|
+
# * `:BOOL`
|
385
|
+
# * `:BYTES`
|
386
|
+
# * `:DATE`
|
387
|
+
# * `:FLOAT64`
|
388
|
+
# * `:INT64`
|
389
|
+
# * `:STRING`
|
390
|
+
# * `:TIMESTAMP`
|
391
|
+
#
|
392
|
+
# Arrays are specified by providing the type code in an array. For
|
393
|
+
# example, an array of integers are specified as `[:INT64]`.
|
394
|
+
#
|
395
|
+
# Structs are not yet supported in query parameters.
|
396
|
+
#
|
397
|
+
# Types are optional.
|
398
|
+
# @return [Google::Cloud::Spanner::Results] The results of the query
|
399
|
+
# execution.
|
400
|
+
#
|
401
|
+
# @example
|
402
|
+
# require "google/cloud/spanner"
|
403
|
+
#
|
404
|
+
# spanner = Google::Cloud::Spanner.new
|
405
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
406
|
+
# batch_snapshot = batch_client.batch_snapshot
|
407
|
+
#
|
408
|
+
# results = batch_snapshot.execute "SELECT * FROM users"
|
409
|
+
#
|
410
|
+
# results.rows.each do |row|
|
411
|
+
# puts "User #{row[:id]} is #{row[:name]}"
|
412
|
+
# end
|
413
|
+
#
|
414
|
+
# @example Query using query parameters:
|
415
|
+
# require "google/cloud/spanner"
|
416
|
+
#
|
417
|
+
# spanner = Google::Cloud::Spanner.new
|
418
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
419
|
+
# batch_snapshot = batch_client.batch_snapshot
|
420
|
+
#
|
421
|
+
# results = batch_snapshot.execute "SELECT * FROM users " \
|
422
|
+
# "WHERE active = @active",
|
423
|
+
# params: { active: true }
|
424
|
+
#
|
425
|
+
# results.rows.each do |row|
|
426
|
+
# puts "User #{row[:id]} is #{row[:name]}"
|
427
|
+
# end
|
428
|
+
#
|
429
|
+
def execute sql, params: nil, types: nil
|
430
|
+
ensure_session!
|
431
|
+
|
432
|
+
params, types = Convert.to_input_params_and_types params, types
|
433
|
+
|
434
|
+
session.execute sql, params: params, types: types,
|
435
|
+
transaction: tx_selector
|
436
|
+
end
|
437
|
+
alias query execute
|
438
|
+
|
439
|
+
##
|
440
|
+
# Read rows from a database table, as a simple alternative to
|
441
|
+
# {#execute}.
|
442
|
+
#
|
443
|
+
# @param [String] table The name of the table in the database to be
|
444
|
+
# read.
|
445
|
+
# @param [Array<String, Symbol>] columns The columns of table to be
|
446
|
+
# returned for each row matching this request.
|
447
|
+
# @param [Object, Array<Object>] keys A single, or list of keys or key
|
448
|
+
# ranges to match returned data to. Values should have exactly as many
|
449
|
+
# elements as there are columns in the primary key.
|
450
|
+
# @param [String] index The name of an index to use instead of the
|
451
|
+
# table's primary key when interpreting `id` and sorting result rows.
|
452
|
+
# Optional.
|
453
|
+
# @param [Integer] limit If greater than zero, no more than this number
|
454
|
+
# of rows will be returned. The default is no limit.
|
455
|
+
#
|
456
|
+
# @return [Google::Cloud::Spanner::Results] The results of the read
|
457
|
+
# operation.
|
458
|
+
#
|
459
|
+
# @example
|
460
|
+
# require "google/cloud/spanner"
|
461
|
+
#
|
462
|
+
# spanner = Google::Cloud::Spanner.new
|
463
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
464
|
+
# batch_snapshot = batch_client.batch_snapshot
|
465
|
+
#
|
466
|
+
# results = batch_snapshot.read "users", [:id, :name]
|
467
|
+
#
|
468
|
+
# results.rows.each do |row|
|
469
|
+
# puts "User #{row[:id]} is #{row[:name]}"
|
470
|
+
# end
|
471
|
+
#
|
472
|
+
def read table, columns, keys: nil, index: nil, limit: nil
|
473
|
+
ensure_session!
|
474
|
+
|
475
|
+
columns = Array(columns).map(&:to_s)
|
476
|
+
keys = Convert.to_key_set keys
|
477
|
+
|
478
|
+
session.read table, columns, keys: keys, index: index, limit: limit,
|
479
|
+
transaction: tx_selector
|
480
|
+
end
|
481
|
+
|
482
|
+
##
|
483
|
+
# @private
|
484
|
+
# Converts the the batch snapshot object to a Hash ready for
|
485
|
+
# serialization.
|
486
|
+
#
|
487
|
+
# @return [Hash] A hash containing a representation of the batch
|
488
|
+
# snapshot object.
|
489
|
+
#
|
490
|
+
def to_h
|
491
|
+
{
|
492
|
+
session: Base64.strict_encode64(@session.grpc.to_proto),
|
493
|
+
transaction: Base64.strict_encode64(@grpc.to_proto)
|
494
|
+
}
|
495
|
+
end
|
496
|
+
|
497
|
+
##
|
498
|
+
# Serializes the batch snapshot object so it can be recreated on another
|
499
|
+
# process. See {BatchClient#load_batch_snapshot}.
|
500
|
+
#
|
501
|
+
# @return [String] The serialized representation of the batch snapshot.
|
502
|
+
#
|
503
|
+
# @example
|
504
|
+
# require "google/cloud/spanner"
|
505
|
+
#
|
506
|
+
# spanner = Google::Cloud::Spanner.new
|
507
|
+
#
|
508
|
+
# batch_client = spanner.batch_client "my-instance", "my-database"
|
509
|
+
#
|
510
|
+
# batch_snapshot = batch_client.batch_snapshot
|
511
|
+
#
|
512
|
+
# partitions = batch_snapshot.partition_read "users", [:id, :name]
|
513
|
+
#
|
514
|
+
# partition = partitions.first
|
515
|
+
#
|
516
|
+
# serialized_snapshot = batch_snapshot.dump
|
517
|
+
# serialized_partition = partition.dump
|
518
|
+
#
|
519
|
+
# # In a separate process
|
520
|
+
# new_batch_snapshot = batch_client.load_batch_snapshot \
|
521
|
+
# serialized_snapshot
|
522
|
+
#
|
523
|
+
# new_partition = batch_client.load_partition \
|
524
|
+
# serialized_partition
|
525
|
+
#
|
526
|
+
# results = new_batch_snapshot.execute_partition \
|
527
|
+
# new_partition
|
528
|
+
#
|
529
|
+
def dump
|
530
|
+
JSON.dump to_h
|
531
|
+
end
|
532
|
+
alias serialize dump
|
533
|
+
|
534
|
+
##
|
535
|
+
# @private Loads the serialized batch snapshot. See
|
536
|
+
# {BatchClient#load_batch_snapshot}.
|
537
|
+
def self.load data, service: nil
|
538
|
+
data = JSON.parse data, symbolize_names: true unless data.is_a? Hash
|
539
|
+
|
540
|
+
session_grpc = Google::Spanner::V1::Session.decode \
|
541
|
+
Base64.decode64(data[:session])
|
542
|
+
transaction_grpc = Google::Spanner::V1::Transaction.decode \
|
543
|
+
Base64.decode64(data[:transaction])
|
544
|
+
|
545
|
+
from_grpc transaction_grpc, Session.from_grpc(session_grpc, service)
|
546
|
+
end
|
547
|
+
|
548
|
+
##
|
549
|
+
# @private Creates a new BatchSnapshot instance from a
|
550
|
+
# Google::Spanner::V1::Transaction.
|
551
|
+
def self.from_grpc grpc, session
|
552
|
+
new grpc, session
|
553
|
+
end
|
554
|
+
|
555
|
+
protected
|
556
|
+
|
557
|
+
# The TransactionSelector to be used for queries
|
558
|
+
def tx_selector
|
559
|
+
Google::Spanner::V1::TransactionSelector.new id: transaction_id
|
560
|
+
end
|
561
|
+
|
562
|
+
##
|
563
|
+
# @private Raise an error unless an active connection to the service is
|
564
|
+
# available.
|
565
|
+
def ensure_session!
|
566
|
+
raise "Must have active connection to service" unless session
|
567
|
+
end
|
568
|
+
|
569
|
+
def execute_partition_query partition
|
570
|
+
session.execute partition.execute.sql,
|
571
|
+
params: partition.execute.params,
|
572
|
+
types: partition.execute.param_types.to_h,
|
573
|
+
transaction: partition.execute.transaction,
|
574
|
+
partition_token: partition.execute.partition_token
|
575
|
+
end
|
576
|
+
|
577
|
+
def execute_partition_read partition
|
578
|
+
session.read partition.read.table,
|
579
|
+
partition.read.columns.to_a,
|
580
|
+
keys: partition.read.key_set,
|
581
|
+
index: partition.read.index,
|
582
|
+
transaction: partition.read.transaction,
|
583
|
+
partition_token: partition.read.partition_token
|
584
|
+
end
|
585
|
+
end
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|