google-cloud-spanner 2.4.0 → 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +2 -1
- data/CHANGELOG.md +56 -0
- data/CONTRIBUTING.md +1 -1
- data/LOGGING.md +1 -1
- data/OVERVIEW.md +1 -1
- data/lib/google-cloud-spanner.rb +2 -0
- data/lib/google/cloud/spanner/backup.rb +67 -4
- data/lib/google/cloud/spanner/backup/job.rb +8 -8
- data/lib/google/cloud/spanner/backup/job/list.rb +2 -2
- data/lib/google/cloud/spanner/backup/list.rb +2 -2
- data/lib/google/cloud/spanner/batch_snapshot.rb +11 -4
- data/lib/google/cloud/spanner/batch_update.rb +3 -1
- data/lib/google/cloud/spanner/client.rb +315 -83
- data/lib/google/cloud/spanner/commit.rb +4 -0
- data/lib/google/cloud/spanner/data.rb +4 -5
- data/lib/google/cloud/spanner/database.rb +88 -2
- data/lib/google/cloud/spanner/database/job/list.rb +2 -2
- data/lib/google/cloud/spanner/database/list.rb +4 -4
- data/lib/google/cloud/spanner/fields.rb +5 -3
- data/lib/google/cloud/spanner/instance.rb +91 -3
- data/lib/google/cloud/spanner/instance/config/list.rb +4 -4
- data/lib/google/cloud/spanner/instance/list.rb +4 -4
- data/lib/google/cloud/spanner/partition.rb +4 -2
- data/lib/google/cloud/spanner/policy.rb +3 -2
- data/lib/google/cloud/spanner/pool.rb +10 -10
- data/lib/google/cloud/spanner/project.rb +65 -5
- data/lib/google/cloud/spanner/results.rb +13 -9
- data/lib/google/cloud/spanner/service.rb +42 -23
- data/lib/google/cloud/spanner/session.rb +38 -15
- data/lib/google/cloud/spanner/snapshot.rb +10 -2
- data/lib/google/cloud/spanner/status.rb +4 -1
- data/lib/google/cloud/spanner/transaction.rb +61 -6
- data/lib/google/cloud/spanner/version.rb +1 -1
- metadata +10 -10
@@ -69,6 +69,7 @@ module Google
|
|
69
69
|
# | `BOOL` | `true`/`false` | |
|
70
70
|
# | `INT64` | `Integer` | |
|
71
71
|
# | `FLOAT64` | `Float` | |
|
72
|
+
# | `NUMERIC` | `BigDecimal` | |
|
72
73
|
# | `STRING` | `String` | |
|
73
74
|
# | `DATE` | `Date` | |
|
74
75
|
# | `TIMESTAMP` | `Time`, `DateTime` | |
|
@@ -127,6 +128,7 @@ module Google
|
|
127
128
|
# | `BOOL` | `true`/`false` | |
|
128
129
|
# | `INT64` | `Integer` | |
|
129
130
|
# | `FLOAT64` | `Float` | |
|
131
|
+
# | `NUMERIC` | `BigDecimal` | |
|
130
132
|
# | `STRING` | `String` | |
|
131
133
|
# | `DATE` | `Date` | |
|
132
134
|
# | `TIMESTAMP` | `Time`, `DateTime` | |
|
@@ -184,6 +186,7 @@ module Google
|
|
184
186
|
# | `BOOL` | `true`/`false` | |
|
185
187
|
# | `INT64` | `Integer` | |
|
186
188
|
# | `FLOAT64` | `Float` | |
|
189
|
+
# | `NUMERIC` | `BigDecimal` | |
|
187
190
|
# | `STRING` | `String` | |
|
188
191
|
# | `DATE` | `Date` | |
|
189
192
|
# | `TIMESTAMP` | `Time`, `DateTime` | |
|
@@ -243,6 +246,7 @@ module Google
|
|
243
246
|
# | `BOOL` | `true`/`false` | |
|
244
247
|
# | `INT64` | `Integer` | |
|
245
248
|
# | `FLOAT64` | `Float` | |
|
249
|
+
# | `NUMERIC` | `BigDecimal` | |
|
246
250
|
# | `STRING` | `String` | |
|
247
251
|
# | `DATE` | `Date` | |
|
248
252
|
# | `TIMESTAMP` | `Time`, `DateTime` | |
|
@@ -139,9 +139,10 @@ module Google
|
|
139
139
|
#
|
140
140
|
def to_a skip_dup_check: nil
|
141
141
|
values.map do |value|
|
142
|
-
|
142
|
+
case value
|
143
|
+
when Data
|
143
144
|
value.to_h skip_dup_check: skip_dup_check
|
144
|
-
|
145
|
+
when Array
|
145
146
|
value.map do |v|
|
146
147
|
v.is_a?(Data) ? v.to_h(skip_dup_check: skip_dup_check) : v
|
147
148
|
end
|
@@ -169,9 +170,7 @@ module Google
|
|
169
170
|
# or indexes and corresponding values.
|
170
171
|
#
|
171
172
|
def to_h skip_dup_check: nil
|
172
|
-
|
173
|
-
raise DuplicateNameError if fields.duplicate_names?
|
174
|
-
end
|
173
|
+
raise DuplicateNameError if !skip_dup_check && fields.duplicate_names?
|
175
174
|
|
176
175
|
Hash[keys.zip to_a(skip_dup_check: skip_dup_check)]
|
177
176
|
end
|
@@ -113,6 +113,38 @@ module Google
|
|
113
113
|
@grpc.state
|
114
114
|
end
|
115
115
|
|
116
|
+
##
|
117
|
+
# Time at which the database creation started.
|
118
|
+
# @return [Time]
|
119
|
+
def create_time
|
120
|
+
Convert.timestamp_to_time @grpc.create_time
|
121
|
+
end
|
122
|
+
|
123
|
+
# An encryption configuration describing the encryption type and key
|
124
|
+
# resources in Cloud KMS.
|
125
|
+
#
|
126
|
+
# @return [Google::Cloud::Spanner::Admin::Database::V1::EncryptionConfig, nil]
|
127
|
+
def encryption_config
|
128
|
+
@grpc.encryption_config
|
129
|
+
end
|
130
|
+
|
131
|
+
# Encryption information for the database.
|
132
|
+
#
|
133
|
+
# For databases that are using customer managed encryption, this
|
134
|
+
# field contains the encryption information for the database, such as
|
135
|
+
# encryption state and the Cloud KMS key versions that are in use.
|
136
|
+
#
|
137
|
+
# For databases that are using Google default or other types of encryption,
|
138
|
+
# this field is empty.
|
139
|
+
#
|
140
|
+
# This field is propagated lazily from the backend. There might be a delay
|
141
|
+
# from when a key version is being used and when it appears in this field.
|
142
|
+
#
|
143
|
+
# @return [Array<Google::Cloud::Spanner::Admin::Database::V1::EncryptionInfo>]
|
144
|
+
def encryption_info
|
145
|
+
@grpc.encryption_info.to_a
|
146
|
+
end
|
147
|
+
|
116
148
|
##
|
117
149
|
# The database is still being created. Operations on the database may
|
118
150
|
# raise with `FAILED_PRECONDITION` in this state.
|
@@ -417,6 +449,26 @@ module Google
|
|
417
449
|
# it will be automatically set to the backup create time. The version
|
418
450
|
# time can be as far in the past as specified by the database earliest
|
419
451
|
# version time. Optional.
|
452
|
+
# @param [Hash] encryption_config An encryption configuration describing
|
453
|
+
# the encryption type and key resources in Cloud KMS. Optional. The
|
454
|
+
# following settings can be provided:
|
455
|
+
#
|
456
|
+
# * `:kms_key_name` (String) The name of KMS key to use which should
|
457
|
+
# be the full path, e.g., `projects/<project>/locations/<location>\
|
458
|
+
# /keyRings/<key_ring>/cryptoKeys/<kms_key_name>`
|
459
|
+
# This field should be set only when encryption type
|
460
|
+
# `:CUSTOMER_MANAGED_ENCRYPTION`.
|
461
|
+
# * `:encryption_type` (Symbol) The encryption type of the backup.
|
462
|
+
# Valid values are:
|
463
|
+
# 1. `:USE_DATABASE_ENCRYPTION` - Use the same encryption configuration as
|
464
|
+
# the database.
|
465
|
+
# 2. `:GOOGLE_DEFAULT_ENCRYPTION` - Google default encryption.
|
466
|
+
# 3. `:CUSTOMER_MANAGED_ENCRYPTION` - Use customer managed encryption.
|
467
|
+
# If specified, `:kms_key_name` must contain a valid Cloud KMS key.
|
468
|
+
#
|
469
|
+
# @raise [ArgumentError] if `:CUSTOMER_MANAGED_ENCRYPTION` specified without
|
470
|
+
# customer managed kms key.
|
471
|
+
#
|
420
472
|
# @return [Google::Cloud::Spanner::Backup::Job] The job representing
|
421
473
|
# the long-running, asynchronous processing of a backup create
|
422
474
|
# operation.
|
@@ -443,14 +495,48 @@ module Google
|
|
443
495
|
# backup = job.backup
|
444
496
|
# end
|
445
497
|
#
|
446
|
-
|
498
|
+
# @example Create backup with encryption config
|
499
|
+
# require "google/cloud/spanner"
|
500
|
+
#
|
501
|
+
# spanner = Google::Cloud::Spanner.new
|
502
|
+
# database = spanner.database "my-instance", "my-database"
|
503
|
+
#
|
504
|
+
# kms_key_name = "projects/<project>/locations/<location>/keyRings/<key_ring>/cryptoKeys/<kms_key_name>"
|
505
|
+
# encryption_config = {
|
506
|
+
# kms_key_name: kms_key_name,
|
507
|
+
# encryption_type: :CUSTOMER_MANAGED_ENCRYPTION
|
508
|
+
# }
|
509
|
+
# job = database.create_backup "my-backup",
|
510
|
+
# Time.now + 36000,
|
511
|
+
# encryption_config: encryption_config
|
512
|
+
#
|
513
|
+
# job.done? #=> false
|
514
|
+
# job.reload! # API call
|
515
|
+
# job.done? #=> true
|
516
|
+
#
|
517
|
+
# if job.error?
|
518
|
+
# status = job.error
|
519
|
+
# else
|
520
|
+
# backup = job.backup
|
521
|
+
# end
|
522
|
+
#
|
523
|
+
def create_backup backup_id, expire_time,
|
524
|
+
version_time: nil, encryption_config: nil
|
447
525
|
ensure_service!
|
526
|
+
|
527
|
+
if encryption_config&.include?(:kms_key_name) &&
|
528
|
+
encryption_config[:encryption_type] != :CUSTOMER_MANAGED_ENCRYPTION
|
529
|
+
raise Google::Cloud::InvalidArgumentError,
|
530
|
+
"kms_key_name only used with CUSTOMER_MANAGED_ENCRYPTION"
|
531
|
+
end
|
532
|
+
|
448
533
|
grpc = service.create_backup \
|
449
534
|
instance_id,
|
450
535
|
database_id,
|
451
536
|
backup_id,
|
452
537
|
expire_time,
|
453
|
-
version_time
|
538
|
+
version_time,
|
539
|
+
encryption_config: encryption_config
|
454
540
|
Backup::Job.from_grpc grpc, service
|
455
541
|
end
|
456
542
|
|
@@ -130,12 +130,12 @@ module Google
|
|
130
130
|
# job.database.database_id
|
131
131
|
# end
|
132
132
|
#
|
133
|
-
def all
|
133
|
+
def all &block
|
134
134
|
return enum_for :all unless block_given?
|
135
135
|
|
136
136
|
results = self
|
137
137
|
loop do
|
138
|
-
results.each
|
138
|
+
results.each(&block)
|
139
139
|
break unless next?
|
140
140
|
grpc.next_page
|
141
141
|
results = self.class.from_grpc grpc, service
|
@@ -71,7 +71,7 @@ module Google
|
|
71
71
|
return nil unless next?
|
72
72
|
ensure_service!
|
73
73
|
options = { token: token, max: @max }
|
74
|
-
grpc = @service.list_databases @instance_id, options
|
74
|
+
grpc = @service.list_databases @instance_id, **options
|
75
75
|
self.class.from_grpc grpc, @service, @max
|
76
76
|
end
|
77
77
|
|
@@ -123,17 +123,17 @@ module Google
|
|
123
123
|
# puts database.database_id
|
124
124
|
# end
|
125
125
|
#
|
126
|
-
def all request_limit: nil
|
126
|
+
def all request_limit: nil, &block
|
127
127
|
request_limit = request_limit.to_i if request_limit
|
128
128
|
unless block_given?
|
129
129
|
return enum_for :all, request_limit: request_limit
|
130
130
|
end
|
131
131
|
results = self
|
132
132
|
loop do
|
133
|
-
results.each
|
133
|
+
results.each(&block)
|
134
134
|
if request_limit
|
135
135
|
request_limit -= 1
|
136
|
-
break if request_limit
|
136
|
+
break if request_limit.negative?
|
137
137
|
end
|
138
138
|
break unless results.next?
|
139
139
|
results = results.next
|
@@ -57,12 +57,13 @@ module Google
|
|
57
57
|
# Hash values must contain the type value. If a Hash is used the
|
58
58
|
# fields will be created using the same order as the Hash keys.
|
59
59
|
#
|
60
|
-
# Supported type values
|
60
|
+
# Supported type values include:
|
61
61
|
#
|
62
62
|
# * `:BOOL`
|
63
63
|
# * `:BYTES`
|
64
64
|
# * `:DATE`
|
65
65
|
# * `:FLOAT64`
|
66
|
+
# * `:NUMERIC`
|
66
67
|
# * `:INT64`
|
67
68
|
# * `:STRING`
|
68
69
|
# * `:TIMESTAMP`
|
@@ -133,13 +134,14 @@ module Google
|
|
133
134
|
#
|
134
135
|
def types
|
135
136
|
@grpc_fields.map(&:type).map do |type|
|
136
|
-
|
137
|
+
case type.code
|
138
|
+
when :ARRAY
|
137
139
|
if type.array_element_type.code == :STRUCT
|
138
140
|
[Fields.from_grpc(type.array_element_type.struct_type.fields)]
|
139
141
|
else
|
140
142
|
[type.array_element_type.code]
|
141
143
|
end
|
142
|
-
|
144
|
+
when :STRUCT
|
143
145
|
Fields.from_grpc type.struct_type.fields
|
144
146
|
else
|
145
147
|
type.code
|
@@ -68,6 +68,7 @@ module Google
|
|
68
68
|
def initialize grpc, service
|
69
69
|
@grpc = grpc
|
70
70
|
@service = service
|
71
|
+
@current_values = grpc.to_h
|
71
72
|
end
|
72
73
|
|
73
74
|
# The unique identifier for the project.
|
@@ -134,6 +135,23 @@ module Google
|
|
134
135
|
end
|
135
136
|
alias node_count= nodes=
|
136
137
|
|
138
|
+
##
|
139
|
+
# The number of processing units allocated to this instance.
|
140
|
+
#
|
141
|
+
# @return [Integer]
|
142
|
+
def processing_units
|
143
|
+
@grpc.processing_units
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Updates number of processing units allocated to this instance.
|
148
|
+
#
|
149
|
+
# @param units [Integer] The number of processing units allocated
|
150
|
+
# to this instance.
|
151
|
+
def processing_units= units
|
152
|
+
@grpc.processing_units = units
|
153
|
+
end
|
154
|
+
|
137
155
|
##
|
138
156
|
# The current instance state. Possible values are `:CREATING` and
|
139
157
|
# `:READY`.
|
@@ -188,8 +206,50 @@ module Google
|
|
188
206
|
)
|
189
207
|
end
|
190
208
|
|
209
|
+
##
|
210
|
+
# Update changes.
|
211
|
+
# `display_name`, `labels`, `nodes`, `processing_units` can be
|
212
|
+
# updated. `processing_units` and `nodes` can be used interchangeably
|
213
|
+
# to update.
|
214
|
+
#
|
215
|
+
# @return [Instance::Job] The job representing the long-running,
|
216
|
+
# asynchronous processing of an instance update operation.
|
217
|
+
# @raise [ArgumentError] if both processing_units or nodes are specified.
|
218
|
+
#
|
219
|
+
# @example
|
220
|
+
# require "google/cloud/spanner"
|
221
|
+
#
|
222
|
+
# spanner = Google::Cloud::Spanner.new
|
223
|
+
#
|
224
|
+
# instance = spanner.instance "my-instance"
|
225
|
+
# instance.display_name = "prod-instance"
|
226
|
+
# instance.labels = { env: "prod", app: "api" }
|
227
|
+
# instance.nodes = 2
|
228
|
+
# # OR
|
229
|
+
# # instance.processing_units = 500
|
230
|
+
#
|
231
|
+
# job = instance.save
|
232
|
+
#
|
233
|
+
# job.done? #=> false
|
234
|
+
# job.reload! # API call
|
235
|
+
# job.done? #=> true
|
236
|
+
#
|
237
|
+
# if job.error?
|
238
|
+
# status = job.error
|
239
|
+
# else
|
240
|
+
# instance = job.instance
|
241
|
+
# end
|
242
|
+
#
|
191
243
|
def save
|
192
|
-
|
244
|
+
ensure_service!
|
245
|
+
|
246
|
+
field_mask = []
|
247
|
+
@current_values.each do |field, value|
|
248
|
+
field_mask << field unless @grpc[field.to_s] == value
|
249
|
+
end
|
250
|
+
|
251
|
+
job_grpc = service.update_instance @grpc, field_mask: field_mask
|
252
|
+
@current_values = @grpc.to_h
|
193
253
|
Instance::Job.from_grpc job_grpc, service
|
194
254
|
end
|
195
255
|
alias update save
|
@@ -306,6 +366,13 @@ module Google
|
|
306
366
|
# These statements execute atomically with the creation of the
|
307
367
|
# database: if there is an error in any statement, the database is not
|
308
368
|
# created. Optional.
|
369
|
+
# @param [Hash] encryption_config An encryption configuration describing
|
370
|
+
# the encryption type and key resources in Cloud KMS. Optional. The
|
371
|
+
# following settings can be provided:
|
372
|
+
#
|
373
|
+
# * `:kms_key_name` (String) The name of KMS key to use which should
|
374
|
+
# be the full path, e.g., `projects/<project>/locations/<location>\
|
375
|
+
# /keyRings/<key_ring>/cryptoKeys/<kms_key_name>`
|
309
376
|
#
|
310
377
|
# @return [Database::Job] The job representing the long-running,
|
311
378
|
# asynchronous processing of a database create operation.
|
@@ -328,9 +395,30 @@ module Google
|
|
328
395
|
# database = job.database
|
329
396
|
# end
|
330
397
|
#
|
331
|
-
|
398
|
+
# @example Create with encryption config
|
399
|
+
# require "google/cloud/spanner"
|
400
|
+
#
|
401
|
+
# spanner = Google::Cloud::Spanner.new
|
402
|
+
#
|
403
|
+
# instance = spanner.instance "my-instance"
|
404
|
+
#
|
405
|
+
# kms_key_name = "projects/<project>/locations/<location>/keyRings/<key_ring>/cryptoKeys/<kms_key_name>"
|
406
|
+
# job = instance.create_database "my-new-database", encryption_config: { kms_key_name: kms_key_name }
|
407
|
+
#
|
408
|
+
# job.done? #=> false
|
409
|
+
# job.reload! # API call
|
410
|
+
# job.done? #=> true
|
411
|
+
#
|
412
|
+
# if job.error?
|
413
|
+
# status = job.error
|
414
|
+
# else
|
415
|
+
# database = job.database
|
416
|
+
# end
|
417
|
+
#
|
418
|
+
def create_database database_id, statements: [], encryption_config: nil
|
332
419
|
grpc = service.create_database instance_id, database_id,
|
333
|
-
statements: statements
|
420
|
+
statements: statements,
|
421
|
+
encryption_config: encryption_config
|
334
422
|
Database::Job.from_grpc grpc, service
|
335
423
|
end
|
336
424
|
|
@@ -73,7 +73,7 @@ module Google
|
|
73
73
|
return nil unless next?
|
74
74
|
ensure_service!
|
75
75
|
options = { token: token, max: @max }
|
76
|
-
grpc = @service.list_instance_configs
|
76
|
+
grpc = @service.list_instance_configs(**options)
|
77
77
|
self.class.from_grpc grpc, @service, @max
|
78
78
|
end
|
79
79
|
|
@@ -123,17 +123,17 @@ module Google
|
|
123
123
|
# puts config.instance_config_id
|
124
124
|
# end
|
125
125
|
#
|
126
|
-
def all request_limit: nil
|
126
|
+
def all request_limit: nil, &block
|
127
127
|
request_limit = request_limit.to_i if request_limit
|
128
128
|
unless block_given?
|
129
129
|
return enum_for :all, request_limit: request_limit
|
130
130
|
end
|
131
131
|
results = self
|
132
132
|
loop do
|
133
|
-
results.each
|
133
|
+
results.each(&block)
|
134
134
|
if request_limit
|
135
135
|
request_limit -= 1
|
136
|
-
break if request_limit
|
136
|
+
break if request_limit.negative?
|
137
137
|
end
|
138
138
|
break unless results.next?
|
139
139
|
results = results.next
|
@@ -71,7 +71,7 @@ module Google
|
|
71
71
|
return nil unless next?
|
72
72
|
ensure_service!
|
73
73
|
options = { token: token, max: @max }
|
74
|
-
grpc = @service.list_instances
|
74
|
+
grpc = @service.list_instances(**options)
|
75
75
|
self.class.from_grpc grpc, @service, @max
|
76
76
|
end
|
77
77
|
|
@@ -120,17 +120,17 @@ module Google
|
|
120
120
|
# puts instance.instance_id
|
121
121
|
# end
|
122
122
|
#
|
123
|
-
def all request_limit: nil
|
123
|
+
def all request_limit: nil, &block
|
124
124
|
request_limit = request_limit.to_i if request_limit
|
125
125
|
unless block_given?
|
126
126
|
return enum_for :all, request_limit: request_limit
|
127
127
|
end
|
128
128
|
results = self
|
129
129
|
loop do
|
130
|
-
results.each
|
130
|
+
results.each(&block)
|
131
131
|
if request_limit
|
132
132
|
request_limit -= 1
|
133
|
-
break if request_limit
|
133
|
+
break if request_limit.negative?
|
134
134
|
end
|
135
135
|
break unless results.next?
|
136
136
|
results = results.next
|
@@ -45,11 +45,13 @@ module Google
|
|
45
45
|
#
|
46
46
|
class Partition
|
47
47
|
# @ private
|
48
|
-
attr_reader :execute
|
48
|
+
attr_reader :execute
|
49
|
+
attr_reader :read
|
49
50
|
|
50
51
|
##
|
51
52
|
# @private Creates a Partition object.
|
52
|
-
def initialize
|
53
|
+
def initialize
|
54
|
+
end
|
53
55
|
|
54
56
|
##
|
55
57
|
# Whether the partition was created for an execute_query/query
|