google-cloud-spanner 2.0.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -0
- data/CONTRIBUTING.md +2 -2
- data/LOGGING.md +1 -1
- data/lib/google-cloud-spanner.rb +1 -0
- data/lib/google/cloud/spanner.rb +7 -5
- data/lib/google/cloud/spanner/backup.rb +10 -2
- 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 +114 -15
- data/lib/google/cloud/spanner/batch_update.rb +3 -1
- data/lib/google/cloud/spanner/client.rb +413 -78
- data/lib/google/cloud/spanner/commit_response.rb +87 -0
- data/lib/google/cloud/spanner/commit_response/commit_stats.rb +51 -0
- data/lib/google/cloud/spanner/convert.rb +9 -0
- data/lib/google/cloud/spanner/data.rb +4 -5
- data/lib/google/cloud/spanner/database.rb +25 -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 +3 -2
- 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/results.rb +105 -26
- data/lib/google/cloud/spanner/service.rb +218 -107
- data/lib/google/cloud/spanner/session.rb +361 -30
- data/lib/google/cloud/spanner/snapshot.rb +58 -4
- data/lib/google/cloud/spanner/status.rb +4 -1
- data/lib/google/cloud/spanner/transaction.rb +114 -8
- data/lib/google/cloud/spanner/version.rb +1 -1
- metadata +12 -10
@@ -0,0 +1,87 @@
|
|
1
|
+
# Copyright 2020 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/commit_response/commit_stats"
|
17
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Spanner
|
21
|
+
##
|
22
|
+
# CommitResponse is a timestamp at which the transaction committed
|
23
|
+
# with additional attributes of commit stats.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# require "google/cloud/spanner"
|
27
|
+
#
|
28
|
+
# spanner = Google::Cloud::Spanner.new
|
29
|
+
#
|
30
|
+
# db = spanner.client "my-instance", "my-database"
|
31
|
+
#
|
32
|
+
# timestamp = db.commit do |c|
|
33
|
+
# c.update "users", [{ id: 1, name: "Charlie", active: false }]
|
34
|
+
# c.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# puts timestamp
|
38
|
+
#
|
39
|
+
# @example With commit stats.
|
40
|
+
# require "google/cloud/spanner"
|
41
|
+
#
|
42
|
+
# spanner = Google::Cloud::Spanner.new
|
43
|
+
#
|
44
|
+
# db = spanner.client "my-instance", "my-database"
|
45
|
+
#
|
46
|
+
# commit_options = { return_commit_stats: true }
|
47
|
+
# commit_resp = db.commit commit_options: commit_options do |c|
|
48
|
+
# c.update "users", [{ id: 1, name: "Charlie", active: false }]
|
49
|
+
# c.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# puts commit_resp.timestamp
|
53
|
+
# puts commit_resp.stats.mutation_count
|
54
|
+
#
|
55
|
+
class CommitResponse
|
56
|
+
##
|
57
|
+
# @private Creates a new CommitResponse instance.
|
58
|
+
def initialize grpc
|
59
|
+
@grpc = grpc
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# The timestamp at which the transaction committed.
|
64
|
+
# @return [Time]
|
65
|
+
def timestamp
|
66
|
+
Convert.timestamp_to_time @grpc.commit_timestamp
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Additional statistics about a commit.
|
71
|
+
# @return [CommitStats, nil] Commit stats or nil if not stats not
|
72
|
+
# present.
|
73
|
+
def stats
|
74
|
+
CommitStats.from_grpc @grpc.commit_stats if @grpc.commit_stats
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# @private
|
79
|
+
# Creates a new Commit responsee instance from a
|
80
|
+
# `Google::Cloud::Spanner::V1::CommitResponse`.
|
81
|
+
def self.from_grpc grpc
|
82
|
+
new grpc
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright 2020 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
|
+
|
18
|
+
module Google
|
19
|
+
module Cloud
|
20
|
+
module Spanner
|
21
|
+
class CommitResponse
|
22
|
+
##
|
23
|
+
# # CommitStats
|
24
|
+
#
|
25
|
+
# Statistical information of a transaction commit.
|
26
|
+
#
|
27
|
+
class CommitStats
|
28
|
+
##
|
29
|
+
# @private Creates a new CommitStats instance.
|
30
|
+
def initialize grpc
|
31
|
+
@grpc = grpc
|
32
|
+
end
|
33
|
+
|
34
|
+
# The total number of the mutations for the transaction.
|
35
|
+
# @return [Integer]
|
36
|
+
def mutation_count
|
37
|
+
@grpc.mutation_count
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# @private
|
42
|
+
# Creates a new CommitStats instance from a
|
43
|
+
# `Google::Cloud::Spanner::V1::CommitResponse::CommitStats`.
|
44
|
+
def self.from_grpc grpc
|
45
|
+
new grpc
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -17,6 +17,7 @@ require "time"
|
|
17
17
|
require "date"
|
18
18
|
require "stringio"
|
19
19
|
require "base64"
|
20
|
+
require "bigdecimal"
|
20
21
|
require "google/cloud/spanner/data"
|
21
22
|
|
22
23
|
module Google
|
@@ -67,6 +68,9 @@ module Google
|
|
67
68
|
Google::Protobuf::Value.new bool_value: false
|
68
69
|
when Integer
|
69
70
|
Google::Protobuf::Value.new string_value: obj.to_s
|
71
|
+
# BigDecimal must be put before Numeric.
|
72
|
+
when BigDecimal
|
73
|
+
Google::Protobuf::Value.new string_value: obj.to_s("F")
|
70
74
|
when Numeric
|
71
75
|
if obj == Float::INFINITY
|
72
76
|
Google::Protobuf::Value.new string_value: "Infinity"
|
@@ -125,6 +129,9 @@ module Google
|
|
125
129
|
:BOOL
|
126
130
|
when Integer
|
127
131
|
:INT64
|
132
|
+
# BigDecimal must be put before Numeric.
|
133
|
+
when BigDecimal
|
134
|
+
:NUMERIC
|
128
135
|
when Numeric
|
129
136
|
:FLOAT64
|
130
137
|
when Time
|
@@ -214,6 +221,8 @@ module Google
|
|
214
221
|
end
|
215
222
|
when :STRUCT
|
216
223
|
Data.from_grpc value.list_value.values, type.struct_type.fields
|
224
|
+
when :NUMERIC
|
225
|
+
BigDecimal value.string_value
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|
@@ -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>`.
|
@@ -400,6 +412,11 @@ module Google
|
|
400
412
|
# 366 days from the time the request is received. Required.
|
401
413
|
# Once the `expire_time` has passed, Cloud Spanner will delete the
|
402
414
|
# backup and free the resources used by the backup. Required.
|
415
|
+
# @param [Time] version_time Specifies the time to have an externally
|
416
|
+
# consistent copy of the database. If no version time is specified,
|
417
|
+
# it will be automatically set to the backup create time. The version
|
418
|
+
# time can be as far in the past as specified by the database earliest
|
419
|
+
# version time. Optional.
|
403
420
|
# @return [Google::Cloud::Spanner::Backup::Job] The job representing
|
404
421
|
# the long-running, asynchronous processing of a backup create
|
405
422
|
# operation.
|
@@ -410,7 +427,11 @@ module Google
|
|
410
427
|
# spanner = Google::Cloud::Spanner.new
|
411
428
|
# database = spanner.database "my-instance", "my-database"
|
412
429
|
#
|
413
|
-
#
|
430
|
+
# backup_id = "my-backup"
|
431
|
+
# expire_time = Time.now + (24 * 60 * 60) # 1 day from now
|
432
|
+
# version_time = Time.now - (24 * 60 * 60) # 1 day ago (optional)
|
433
|
+
#
|
434
|
+
# job = database.create_backup backup_id, expire_time, version_time: version_time
|
414
435
|
#
|
415
436
|
# job.done? #=> false
|
416
437
|
# job.reload! # API call
|
@@ -422,13 +443,14 @@ module Google
|
|
422
443
|
# backup = job.backup
|
423
444
|
# end
|
424
445
|
#
|
425
|
-
def create_backup backup_id, expire_time
|
446
|
+
def create_backup backup_id, expire_time, version_time: nil
|
426
447
|
ensure_service!
|
427
448
|
grpc = service.create_backup \
|
428
449
|
instance_id,
|
429
450
|
database_id,
|
430
451
|
backup_id,
|
431
|
-
expire_time
|
452
|
+
expire_time,
|
453
|
+
version_time
|
432
454
|
Backup::Job.from_grpc grpc, service
|
433
455
|
end
|
434
456
|
|
@@ -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
|
@@ -133,13 +133,14 @@ module Google
|
|
133
133
|
#
|
134
134
|
def types
|
135
135
|
@grpc_fields.map(&:type).map do |type|
|
136
|
-
|
136
|
+
case type.code
|
137
|
+
when :ARRAY
|
137
138
|
if type.array_element_type.code == :STRUCT
|
138
139
|
[Fields.from_grpc(type.array_element_type.struct_type.fields)]
|
139
140
|
else
|
140
141
|
[type.array_element_type.code]
|
141
142
|
end
|
142
|
-
|
143
|
+
when :STRUCT
|
143
144
|
Fields.from_grpc type.struct_type.fields
|
144
145
|
else
|
145
146
|
type.code
|
@@ -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
|
@@ -70,7 +70,8 @@ module Google
|
|
70
70
|
# end
|
71
71
|
#
|
72
72
|
class Policy
|
73
|
-
attr_reader :etag
|
73
|
+
attr_reader :etag
|
74
|
+
attr_reader :roles
|
74
75
|
|
75
76
|
##
|
76
77
|
# @private Creates a Policy object.
|
@@ -169,7 +170,7 @@ module Google
|
|
169
170
|
role: role_name,
|
170
171
|
members: roles[role_name]
|
171
172
|
)
|
172
|
-
end
|
173
|
+
end.compact
|
173
174
|
)
|
174
175
|
end
|
175
176
|
|