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
@@ -101,6 +101,11 @@ module Google
|
|
101
101
|
end
|
102
102
|
|
103
103
|
fields = @metadata.row_type.fields
|
104
|
+
if fields.count.zero?
|
105
|
+
@closed = true
|
106
|
+
return []
|
107
|
+
end
|
108
|
+
|
104
109
|
values = []
|
105
110
|
buffered_responses = []
|
106
111
|
buffer_upper_bound = 10
|
@@ -204,9 +209,9 @@ module Google
|
|
204
209
|
|
205
210
|
# @private
|
206
211
|
def self.execute service, session_path, sql, params: nil, types: nil,
|
207
|
-
transaction: nil
|
212
|
+
transaction: nil, partition_token: nil
|
208
213
|
execute_options = { transaction: transaction, params: params,
|
209
|
-
types: types }
|
214
|
+
types: types, partition_token: partition_token }
|
210
215
|
enum = service.streaming_execute_sql session_path, sql,
|
211
216
|
execute_options
|
212
217
|
from_enum(enum, service).tap do |results|
|
@@ -218,9 +223,11 @@ module Google
|
|
218
223
|
|
219
224
|
# @private
|
220
225
|
def self.read service, session_path, table, columns, keys: nil,
|
221
|
-
index: nil, limit: nil, transaction: nil
|
226
|
+
index: nil, limit: nil, transaction: nil,
|
227
|
+
partition_token: nil
|
222
228
|
read_options = { keys: keys, index: index, limit: limit,
|
223
|
-
transaction: transaction
|
229
|
+
transaction: transaction,
|
230
|
+
partition_token: partition_token }
|
224
231
|
enum = service.streaming_read_table \
|
225
232
|
session_path, table, columns, read_options
|
226
233
|
from_enum(enum, service).tap do |results|
|
@@ -267,7 +274,7 @@ module Google
|
|
267
274
|
return left
|
268
275
|
elsif left.kind == :struct_value
|
269
276
|
# Don't worry about this yet since Spanner isn't return STRUCT
|
270
|
-
|
277
|
+
raise "STRUCT not implemented yet"
|
271
278
|
else
|
272
279
|
raise "Can't merge #{left.kind} values"
|
273
280
|
end
|
@@ -47,7 +47,8 @@ module Google
|
|
47
47
|
timeout: timeout,
|
48
48
|
client_config: client_config,
|
49
49
|
lib_name: "gccl",
|
50
|
-
lib_version: Google::Cloud::Spanner::VERSION
|
50
|
+
lib_version: Google::Cloud::Spanner::VERSION
|
51
|
+
)
|
51
52
|
end
|
52
53
|
attr_accessor :mocked_service
|
53
54
|
|
@@ -59,7 +60,8 @@ module Google
|
|
59
60
|
timeout: timeout,
|
60
61
|
client_config: client_config,
|
61
62
|
lib_name: "gccl",
|
62
|
-
lib_version: Google::Cloud::Spanner::VERSION
|
63
|
+
lib_version: Google::Cloud::Spanner::VERSION
|
64
|
+
)
|
63
65
|
end
|
64
66
|
attr_accessor :mocked_instances
|
65
67
|
|
@@ -71,7 +73,8 @@ module Google
|
|
71
73
|
timeout: timeout,
|
72
74
|
client_config: client_config,
|
73
75
|
lib_name: "gccl",
|
74
|
-
lib_version: Google::Cloud::Spanner::VERSION
|
76
|
+
lib_version: Google::Cloud::Spanner::VERSION
|
77
|
+
)
|
75
78
|
end
|
76
79
|
attr_accessor :mocked_databases
|
77
80
|
|
@@ -110,7 +113,8 @@ module Google
|
|
110
113
|
|
111
114
|
def update_instance instance_obj
|
112
115
|
mask = Google::Protobuf::FieldMask.new(
|
113
|
-
paths: %w
|
116
|
+
paths: %w[display_name node_count labels]
|
117
|
+
)
|
114
118
|
|
115
119
|
execute do
|
116
120
|
instances.update_instance instance_obj, mask
|
@@ -252,43 +256,70 @@ module Google
|
|
252
256
|
end
|
253
257
|
|
254
258
|
def streaming_execute_sql session_name, sql, transaction: nil,
|
255
|
-
params: nil, types: nil, resume_token: nil
|
256
|
-
|
257
|
-
input_param_types = nil
|
258
|
-
unless params.nil?
|
259
|
-
input_param_pairs = Convert.to_query_params params, types
|
260
|
-
input_params = Google::Protobuf::Struct.new(
|
261
|
-
fields: Hash[input_param_pairs.map { |k, v| [k, v.first] }])
|
262
|
-
input_param_types = Hash[
|
263
|
-
input_param_pairs.map { |k, v| [k, v.last] }]
|
264
|
-
end
|
259
|
+
params: nil, types: nil, resume_token: nil,
|
260
|
+
partition_token: nil
|
265
261
|
opts = default_options_from_session session_name
|
266
262
|
execute do
|
267
263
|
service.execute_streaming_sql \
|
268
|
-
session_name, sql, transaction: transaction, params:
|
269
|
-
param_types:
|
270
|
-
resume_token: resume_token,
|
264
|
+
session_name, sql, transaction: transaction, params: params,
|
265
|
+
param_types: types,
|
266
|
+
resume_token: resume_token,
|
267
|
+
partition_token: partition_token, options: opts
|
271
268
|
end
|
272
269
|
end
|
273
270
|
|
274
271
|
def streaming_read_table session_name, table_name, columns, keys: nil,
|
275
272
|
index: nil, transaction: nil, limit: nil,
|
276
|
-
resume_token: nil
|
277
|
-
columns.map!(&:to_s)
|
273
|
+
resume_token: nil, partition_token: nil
|
278
274
|
opts = default_options_from_session session_name
|
279
275
|
execute do
|
280
276
|
service.streaming_read \
|
281
|
-
session_name, table_name, columns,
|
277
|
+
session_name, table_name, columns, keys,
|
282
278
|
transaction: transaction, index: index, limit: limit,
|
283
|
-
resume_token: resume_token,
|
279
|
+
resume_token: resume_token, partition_token: partition_token,
|
280
|
+
options: opts
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def partition_read session_name, table_name, columns, transaction,
|
285
|
+
keys: nil, index: nil, partition_size_bytes: nil,
|
286
|
+
max_partitions: nil
|
287
|
+
partition_opts = partition_options partition_size_bytes,
|
288
|
+
max_partitions
|
289
|
+
|
290
|
+
opts = default_options_from_session session_name
|
291
|
+
|
292
|
+
execute do
|
293
|
+
service.partition_read \
|
294
|
+
session_name, table_name, keys,
|
295
|
+
transaction: transaction, index: index, columns: columns,
|
296
|
+
partition_options: partition_opts, options: opts
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def partition_query session_name, sql, transaction, params: nil,
|
301
|
+
types: nil, partition_size_bytes: nil,
|
302
|
+
max_partitions: nil
|
303
|
+
partition_opts = partition_options partition_size_bytes,
|
304
|
+
max_partitions
|
305
|
+
|
306
|
+
opts = default_options_from_session session_name
|
307
|
+
|
308
|
+
execute do
|
309
|
+
service.partition_query \
|
310
|
+
session_name, sql,
|
311
|
+
transaction: transaction,
|
312
|
+
params: params, param_types: types,
|
313
|
+
partition_options: partition_opts, options: opts
|
284
314
|
end
|
285
315
|
end
|
286
316
|
|
287
317
|
def commit session_name, mutations = [], transaction_id: nil
|
288
318
|
tx_opts = nil
|
289
319
|
if transaction_id.nil?
|
290
|
-
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
291
|
-
Google::Spanner::V1::TransactionOptions::ReadWrite.new
|
320
|
+
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
321
|
+
read_write: Google::Spanner::V1::TransactionOptions::ReadWrite.new
|
322
|
+
)
|
292
323
|
end
|
293
324
|
opts = default_options_from_session session_name
|
294
325
|
execute do
|
@@ -307,8 +338,9 @@ module Google
|
|
307
338
|
end
|
308
339
|
|
309
340
|
def begin_transaction session_name
|
310
|
-
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
311
|
-
Google::Spanner::V1::TransactionOptions::ReadWrite.new
|
341
|
+
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
342
|
+
read_write: Google::Spanner::V1::TransactionOptions::ReadWrite.new
|
343
|
+
)
|
312
344
|
opts = default_options_from_session session_name
|
313
345
|
execute do
|
314
346
|
service.begin_transaction session_name, tx_opts, options: opts
|
@@ -317,13 +349,16 @@ module Google
|
|
317
349
|
|
318
350
|
def create_snapshot session_name, strong: nil, timestamp: nil,
|
319
351
|
staleness: nil
|
320
|
-
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
321
|
-
Google::Spanner::V1::TransactionOptions::ReadOnly.new(
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
352
|
+
tx_opts = Google::Spanner::V1::TransactionOptions.new(
|
353
|
+
read_only: Google::Spanner::V1::TransactionOptions::ReadOnly.new(
|
354
|
+
{
|
355
|
+
strong: strong,
|
356
|
+
read_timestamp: Convert.time_to_timestamp(timestamp),
|
357
|
+
exact_staleness: Convert.number_to_duration(staleness),
|
358
|
+
return_read_timestamp: true
|
359
|
+
}.delete_if { |_, v| v.nil? }
|
360
|
+
)
|
361
|
+
)
|
327
362
|
opts = default_options_from_session session_name
|
328
363
|
execute do
|
329
364
|
service.begin_transaction session_name, tx_opts, options: opts
|
@@ -336,37 +371,22 @@ module Google
|
|
336
371
|
|
337
372
|
protected
|
338
373
|
|
339
|
-
def key_set keys
|
340
|
-
return Google::Spanner::V1::KeySet.new(all: true) if keys.nil?
|
341
|
-
keys = [keys] unless keys.is_a? Array
|
342
|
-
return Google::Spanner::V1::KeySet.new(all: true) if keys.empty?
|
343
|
-
if keys_are_ranges? keys
|
344
|
-
keys = [keys] unless keys.is_a? Array
|
345
|
-
key_ranges = keys.map do |r|
|
346
|
-
Convert.to_key_range(r)
|
347
|
-
end
|
348
|
-
return Google::Spanner::V1::KeySet.new(ranges: key_ranges)
|
349
|
-
end
|
350
|
-
key_list = Array(keys).map do |i|
|
351
|
-
Convert.raw_to_value(Array(i)).list_value
|
352
|
-
end
|
353
|
-
Google::Spanner::V1::KeySet.new keys: key_list
|
354
|
-
end
|
355
|
-
|
356
|
-
def keys_are_ranges? keys
|
357
|
-
keys.each do |key|
|
358
|
-
return true if key.is_a? ::Range
|
359
|
-
return true if key.is_a? Google::Cloud::Spanner::Range
|
360
|
-
end
|
361
|
-
false
|
362
|
-
end
|
363
|
-
|
364
374
|
def default_options_from_session session_name
|
365
375
|
default_prefix = session_name.split("/sessions/").first
|
366
376
|
Google::Gax::CallOptions.new kwargs: \
|
367
377
|
{ "google-cloud-resource-prefix" => default_prefix }
|
368
378
|
end
|
369
379
|
|
380
|
+
def partition_options partition_size_bytes, max_partitions
|
381
|
+
return nil unless partition_size_bytes || max_partitions
|
382
|
+
partition_opts = Google::Spanner::V1::PartitionOptions.new
|
383
|
+
if partition_size_bytes
|
384
|
+
partition_opts.partition_size_bytes = partition_size_bytes
|
385
|
+
end
|
386
|
+
partition_opts.max_partitions = max_partitions if max_partitions
|
387
|
+
partition_opts
|
388
|
+
end
|
389
|
+
|
370
390
|
def project_path
|
371
391
|
Admin::Instance::V1::InstanceAdminClient.project_path project
|
372
392
|
end
|
@@ -374,23 +394,27 @@ module Google
|
|
374
394
|
def instance_path name
|
375
395
|
return name if name.to_s.include? "/"
|
376
396
|
Admin::Instance::V1::InstanceAdminClient.instance_path(
|
377
|
-
project, name
|
397
|
+
project, name
|
398
|
+
)
|
378
399
|
end
|
379
400
|
|
380
401
|
def instance_config_path name
|
381
402
|
return name if name.to_s.include? "/"
|
382
403
|
Admin::Instance::V1::InstanceAdminClient.instance_config_path(
|
383
|
-
project, name.to_s
|
404
|
+
project, name.to_s
|
405
|
+
)
|
384
406
|
end
|
385
407
|
|
386
408
|
def database_path instance_id, database_id
|
387
409
|
Admin::Database::V1::DatabaseAdminClient.database_path(
|
388
|
-
project, instance_id, database_id
|
410
|
+
project, instance_id, database_id
|
411
|
+
)
|
389
412
|
end
|
390
413
|
|
391
414
|
def session_path instance_id, database_id, session_id
|
392
415
|
V1::SpannerClient.session_path(
|
393
|
-
project, instance_id, database_id, session_id
|
416
|
+
project, instance_id, database_id, session_id
|
417
|
+
)
|
394
418
|
end
|
395
419
|
|
396
420
|
def execute
|
@@ -180,15 +180,17 @@ module Google
|
|
180
180
|
# puts "User #{row[:id]} is #{row[:name]}"
|
181
181
|
# end
|
182
182
|
#
|
183
|
-
def execute sql, params: nil, types: nil, transaction: nil
|
183
|
+
def execute sql, params: nil, types: nil, transaction: nil,
|
184
|
+
partition_token: nil
|
184
185
|
ensure_service!
|
186
|
+
|
185
187
|
results = Results.execute service, path, sql,
|
186
188
|
params: params, types: types,
|
187
|
-
transaction: transaction
|
189
|
+
transaction: transaction,
|
190
|
+
partition_token: partition_token
|
188
191
|
@last_updated_at = Time.now
|
189
192
|
results
|
190
193
|
end
|
191
|
-
alias_method :query, :execute
|
192
194
|
|
193
195
|
##
|
194
196
|
# Read rows from a database table, as a simple alternative to
|
@@ -227,12 +229,44 @@ module Google
|
|
227
229
|
# end
|
228
230
|
#
|
229
231
|
def read table, columns, keys: nil, index: nil, limit: nil,
|
230
|
-
transaction: nil
|
232
|
+
transaction: nil, partition_token: nil
|
231
233
|
ensure_service!
|
234
|
+
|
232
235
|
results = Results.read service, path, table, columns,
|
233
236
|
keys: keys, index: index, limit: limit,
|
234
|
-
transaction: transaction
|
237
|
+
transaction: transaction,
|
238
|
+
partition_token: partition_token
|
239
|
+
@last_updated_at = Time.now
|
240
|
+
results
|
241
|
+
end
|
242
|
+
|
243
|
+
def partition_query sql, transaction, params: nil, types: nil,
|
244
|
+
partition_size_bytes: nil, max_partitions: nil
|
245
|
+
ensure_service!
|
246
|
+
|
247
|
+
results = service.partition_query \
|
248
|
+
path, sql, transaction, params: params, types: types,
|
249
|
+
partition_size_bytes: partition_size_bytes,
|
250
|
+
max_partitions: max_partitions
|
251
|
+
|
235
252
|
@last_updated_at = Time.now
|
253
|
+
|
254
|
+
results
|
255
|
+
end
|
256
|
+
|
257
|
+
def partition_read table, columns, transaction, keys: nil,
|
258
|
+
index: nil, partition_size_bytes: nil,
|
259
|
+
max_partitions: nil
|
260
|
+
ensure_service!
|
261
|
+
|
262
|
+
results = service.partition_read \
|
263
|
+
path, table, columns, transaction,
|
264
|
+
keys: keys, index: index,
|
265
|
+
partition_size_bytes: partition_size_bytes,
|
266
|
+
max_partitions: max_partitions
|
267
|
+
|
268
|
+
@last_updated_at = Time.now
|
269
|
+
|
236
270
|
results
|
237
271
|
end
|
238
272
|
|
@@ -313,7 +347,7 @@ module Google
|
|
313
347
|
c.upsert table, rows
|
314
348
|
end
|
315
349
|
end
|
316
|
-
|
350
|
+
alias save upsert
|
317
351
|
|
318
352
|
##
|
319
353
|
# Inserts new rows in a table. If any of the rows already exist, the
|
@@ -503,7 +537,8 @@ module Google
|
|
503
537
|
rescue Google::Cloud::NotFoundError
|
504
538
|
@grpc = service.create_session \
|
505
539
|
Admin::Database::V1::DatabaseAdminClient.database_path(
|
506
|
-
project_id, instance_id, database_id
|
540
|
+
project_id, instance_id, database_id
|
541
|
+
)
|
507
542
|
@last_updated_at = Time.now
|
508
543
|
return self
|
509
544
|
end
|
@@ -518,7 +553,8 @@ module Google
|
|
518
553
|
rescue Google::Cloud::NotFoundError
|
519
554
|
@grpc = service.create_session \
|
520
555
|
Admin::Database::V1::DatabaseAdminClient.database_path(
|
521
|
-
project_id, instance_id, database_id
|
556
|
+
project_id, instance_id, database_id
|
557
|
+
)
|
522
558
|
return false
|
523
559
|
end
|
524
560
|
|
@@ -557,7 +593,7 @@ module Google
|
|
557
593
|
# @private Raise an error unless an active connection to the service is
|
558
594
|
# available.
|
559
595
|
def ensure_service!
|
560
|
-
|
596
|
+
raise "Must have active connection to service" unless service
|
561
597
|
end
|
562
598
|
end
|
563
599
|
end
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
+
require "google/cloud/spanner/convert"
|
16
17
|
require "google/cloud/spanner/results"
|
17
18
|
|
18
19
|
module Google
|
@@ -150,10 +151,13 @@ module Google
|
|
150
151
|
#
|
151
152
|
def execute sql, params: nil, types: nil
|
152
153
|
ensure_session!
|
154
|
+
|
155
|
+
params, types = Convert.to_input_params_and_types params, types
|
156
|
+
|
153
157
|
session.execute sql, params: params, types: types,
|
154
158
|
transaction: tx_selector
|
155
159
|
end
|
156
|
-
|
160
|
+
alias query execute
|
157
161
|
|
158
162
|
##
|
159
163
|
# Read rows from a database table, as a simple alternative to
|
@@ -191,6 +195,10 @@ module Google
|
|
191
195
|
#
|
192
196
|
def read table, columns, keys: nil, index: nil, limit: nil
|
193
197
|
ensure_session!
|
198
|
+
|
199
|
+
columns = Array(columns).map(&:to_s)
|
200
|
+
keys = Convert.to_key_set keys
|
201
|
+
|
194
202
|
session.read table, columns, keys: keys, index: index, limit: limit,
|
195
203
|
transaction: tx_selector
|
196
204
|
end
|
@@ -252,7 +260,7 @@ module Google
|
|
252
260
|
# @private Raise an error unless an active connection to the service is
|
253
261
|
# available.
|
254
262
|
def ensure_session!
|
255
|
-
|
263
|
+
raise "Must have active connection to service" unless session
|
256
264
|
end
|
257
265
|
end
|
258
266
|
end
|
@@ -42,10 +42,11 @@ module Google
|
|
42
42
|
#
|
43
43
|
# job = spanner.create_database "my-instance",
|
44
44
|
# "my-new-database"
|
45
|
+
# job.wait_until_done!
|
45
46
|
#
|
46
|
-
# job.error?
|
47
|
-
#
|
48
|
-
#
|
47
|
+
# if job.error?
|
48
|
+
# status = job.error
|
49
|
+
# end
|
49
50
|
#
|
50
51
|
class Status
|
51
52
|
attr_reader :code, :description, :message, :details
|
@@ -67,12 +68,12 @@ module Google
|
|
67
68
|
|
68
69
|
# @private Get a descriptive symbol for a google.rpc.Code integer
|
69
70
|
def self.description_for code
|
70
|
-
descriptions = %w
|
71
|
+
descriptions = %w[
|
71
72
|
OK CANCELLED UNKNOWN INVALID_ARGUMENT DEADLINE_EXCEEDED NOT_FOUND
|
72
73
|
ALREADY_EXISTS PERMISSION_DENIED RESOURCE_EXHAUSTED
|
73
74
|
FAILED_PRECONDITION ABORTED OUT_OF_RANGE UNIMPLEMENTED INTERNAL
|
74
75
|
UNAVAILABLE DATA_LOSS UNAUTHENTICATED
|
75
|
-
|
76
|
+
]
|
76
77
|
descriptions[code]
|
77
78
|
end
|
78
79
|
end
|