google-cloud-spanner 2.3.0 → 2.8.0
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/CHANGELOG.md +64 -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 +75 -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 +111 -3
- data/lib/google/cloud/spanner/database/backup_info.rb +12 -3
- 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 +44 -24
- 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
|
@@ -85,6 +85,18 @@ module Google
|
|
85
85
|
@grpc.name.split("/")[5]
|
86
86
|
end
|
87
87
|
|
88
|
+
# The version retention period for a database.
|
89
|
+
# @return [String]
|
90
|
+
def version_retention_period
|
91
|
+
@grpc.version_retention_period
|
92
|
+
end
|
93
|
+
|
94
|
+
# The earliest available version time for a database.
|
95
|
+
# @return [Time]
|
96
|
+
def earliest_version_time
|
97
|
+
Convert.timestamp_to_time @grpc.earliest_version_time
|
98
|
+
end
|
99
|
+
|
88
100
|
##
|
89
101
|
# The full path for the database resource. Values are of the form
|
90
102
|
# `projects/<project_id>/instances/<instance_id>/databases/<database_id>`.
|
@@ -101,6 +113,38 @@ module Google
|
|
101
113
|
@grpc.state
|
102
114
|
end
|
103
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
|
+
|
104
148
|
##
|
105
149
|
# The database is still being created. Operations on the database may
|
106
150
|
# raise with `FAILED_PRECONDITION` in this state.
|
@@ -400,6 +444,31 @@ module Google
|
|
400
444
|
# 366 days from the time the request is received. Required.
|
401
445
|
# Once the `expire_time` has passed, Cloud Spanner will delete the
|
402
446
|
# backup and free the resources used by the backup. Required.
|
447
|
+
# @param [Time] version_time Specifies the time to have an externally
|
448
|
+
# consistent copy of the database. If no version time is specified,
|
449
|
+
# it will be automatically set to the backup create time. The version
|
450
|
+
# time can be as far in the past as specified by the database earliest
|
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
|
+
#
|
403
472
|
# @return [Google::Cloud::Spanner::Backup::Job] The job representing
|
404
473
|
# the long-running, asynchronous processing of a backup create
|
405
474
|
# operation.
|
@@ -410,7 +479,36 @@ module Google
|
|
410
479
|
# spanner = Google::Cloud::Spanner.new
|
411
480
|
# database = spanner.database "my-instance", "my-database"
|
412
481
|
#
|
413
|
-
#
|
482
|
+
# backup_id = "my-backup"
|
483
|
+
# expire_time = Time.now + (24 * 60 * 60) # 1 day from now
|
484
|
+
# version_time = Time.now - (24 * 60 * 60) # 1 day ago (optional)
|
485
|
+
#
|
486
|
+
# job = database.create_backup backup_id, expire_time, version_time: version_time
|
487
|
+
#
|
488
|
+
# job.done? #=> false
|
489
|
+
# job.reload! # API call
|
490
|
+
# job.done? #=> true
|
491
|
+
#
|
492
|
+
# if job.error?
|
493
|
+
# status = job.error
|
494
|
+
# else
|
495
|
+
# backup = job.backup
|
496
|
+
# end
|
497
|
+
#
|
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
|
414
512
|
#
|
415
513
|
# job.done? #=> false
|
416
514
|
# job.reload! # API call
|
@@ -422,13 +520,23 @@ module Google
|
|
422
520
|
# backup = job.backup
|
423
521
|
# end
|
424
522
|
#
|
425
|
-
def create_backup backup_id, expire_time
|
523
|
+
def create_backup backup_id, expire_time,
|
524
|
+
version_time: nil, encryption_config: nil
|
426
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
|
+
|
427
533
|
grpc = service.create_backup \
|
428
534
|
instance_id,
|
429
535
|
database_id,
|
430
536
|
backup_id,
|
431
|
-
expire_time
|
537
|
+
expire_time,
|
538
|
+
version_time,
|
539
|
+
encryption_config: encryption_config
|
432
540
|
Backup::Job.from_grpc grpc, service
|
433
541
|
end
|
434
542
|
|
@@ -84,14 +84,23 @@ module Google
|
|
84
84
|
end
|
85
85
|
|
86
86
|
##
|
87
|
-
# The
|
88
|
-
# `source_database` at the timestamp specified by `create_time`.
|
89
|
-
# received.
|
87
|
+
# The timestamp indicating the creation of the backup.
|
90
88
|
# @return [Time]
|
91
89
|
def create_time
|
92
90
|
Convert.timestamp_to_time @grpc.create_time
|
93
91
|
end
|
94
92
|
|
93
|
+
##
|
94
|
+
# The backup contains an externally consistent copy of
|
95
|
+
# `source_database` at the timestamp specified by
|
96
|
+
# the `version_time` received. If no `version_time` was
|
97
|
+
# given during the creation of the backup, the `version_time`
|
98
|
+
# will be the same as the `create_time`.
|
99
|
+
# @return [Time]
|
100
|
+
def version_time
|
101
|
+
Convert.timestamp_to_time @grpc.version_time
|
102
|
+
end
|
103
|
+
|
95
104
|
##
|
96
105
|
# @private Creates a new Database::BackupInfo instance from a
|
97
106
|
# `Google::Cloud::Spanner::Admin::Database::V1::BackupInfo`.
|
@@ -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
|