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