google-cloud-spanner 0.21.0 → 0.22.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/lib/google/cloud/spanner.rb +9 -5
- data/lib/google/cloud/spanner/admin/database/v1/database_admin_client_config.json +1 -3
- data/lib/google/cloud/spanner/admin/instance/v1/instance_admin_client_config.json +1 -3
- data/lib/google/cloud/spanner/client.rb +43 -17
- data/lib/google/cloud/spanner/convert.rb +0 -42
- data/lib/google/cloud/spanner/database/job.rb +2 -0
- data/lib/google/cloud/spanner/errors.rb +2 -2
- data/lib/google/cloud/spanner/instance.rb +1 -1
- data/lib/google/cloud/spanner/instance/job.rb +2 -0
- data/lib/google/cloud/spanner/policy.rb +0 -14
- data/lib/google/cloud/spanner/pool.rb +11 -13
- data/lib/google/cloud/spanner/project.rb +7 -4
- data/lib/google/cloud/spanner/results.rb +1 -1
- data/lib/google/cloud/spanner/service.rb +0 -30
- data/lib/google/cloud/spanner/transaction.rb +31 -4
- data/lib/google/cloud/spanner/v1/spanner_client_config.json +1 -3
- data/lib/google/cloud/spanner/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d52caffdd789f039f91609da3f8dba633459c82
|
4
|
+
data.tar.gz: ecc7cca28368c261123342f43e9b055f13c22d70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfd38cc3172d32788a6891d78e44e349b8410c23285bcaa2bd79b582a58a48ce167f45251fec7ceff4df44b8f9fc6484f83d4feb7d744958ca6d8c99b1f2d457
|
7
|
+
data.tar.gz: 41f84f6f1432833bc79ca731f8b99d29ea6edd70bc71ebdc6b34afe7a7b16f0b1709968d2d358aee5ba6df91f052cd6324a53590a6d7c5d8d73e544b42f5b9df
|
data/lib/google/cloud/spanner.rb
CHANGED
@@ -132,7 +132,7 @@ module Google
|
|
132
132
|
#
|
133
133
|
# db = spanner.client "my-instance", "my-database"
|
134
134
|
#
|
135
|
-
# results =
|
135
|
+
# results = db.execute "SELECT 1"
|
136
136
|
#
|
137
137
|
# results.rows.each do |row|
|
138
138
|
# puts row
|
@@ -160,8 +160,8 @@ module Google
|
|
160
160
|
# db = spanner.client "my-instance", "my-database"
|
161
161
|
#
|
162
162
|
# db.commit do |c|
|
163
|
-
# c.update "users", [{ id: 1,
|
164
|
-
# c.insert "users", [{ id: 2,
|
163
|
+
# c.update "users", [{ id: 1, username: "charlie94", name: "Charlie" }]
|
164
|
+
# c.insert "users", [{ id: 2, username: "harvey00", name: "Harvey" }]
|
165
165
|
# end
|
166
166
|
# ```
|
167
167
|
#
|
@@ -232,7 +232,7 @@ module Google
|
|
232
232
|
# # Read the second album budget.
|
233
233
|
# second_album_result = tx.read "Albums", ["marketing_budget"],
|
234
234
|
# keys: [[2, 2]], limit: 1
|
235
|
-
# second_album_row = second_album_result.first
|
235
|
+
# second_album_row = second_album_result.rows.first
|
236
236
|
# second_album_budget = second_album_row.values.first
|
237
237
|
#
|
238
238
|
# transfer_amount = 200000
|
@@ -245,7 +245,7 @@ module Google
|
|
245
245
|
# # Read the first album's budget.
|
246
246
|
# first_album_result = tx.read "Albums", ["marketing_budget"],
|
247
247
|
# keys: [[1, 1]], limit: 1
|
248
|
-
# first_album_row = first_album_result.first
|
248
|
+
# first_album_row = first_album_result.rows.first
|
249
249
|
# first_album_budget = first_album_row.values.first
|
250
250
|
#
|
251
251
|
# # Update the budgets.
|
@@ -366,12 +366,16 @@ module Google
|
|
366
366
|
def self.new project: nil, keyfile: nil, scope: nil, timeout: nil,
|
367
367
|
client_config: nil
|
368
368
|
project ||= Google::Cloud::Spanner::Project.default_project
|
369
|
+
project = project.to_s # Always cast to a string
|
370
|
+
fail ArgumentError, "project is missing" if project.empty?
|
371
|
+
|
369
372
|
if keyfile.nil?
|
370
373
|
credentials = Google::Cloud::Spanner::Credentials.default scope: scope
|
371
374
|
else
|
372
375
|
credentials = Google::Cloud::Spanner::Credentials.new(
|
373
376
|
keyfile, scope: scope)
|
374
377
|
end
|
378
|
+
|
375
379
|
Google::Cloud::Spanner::Project.new(
|
376
380
|
Google::Cloud::Spanner::Service.new(
|
377
381
|
project, credentials, timeout: timeout,
|
@@ -51,13 +51,11 @@ module Google
|
|
51
51
|
class Client
|
52
52
|
##
|
53
53
|
# @private Creates a new Spanner Client instance.
|
54
|
-
def initialize project, instance_id, database_id,
|
55
|
-
keepalive: 1800, write_ratio: 0.3, fail: true
|
54
|
+
def initialize project, instance_id, database_id, opts = {}
|
56
55
|
@project = project
|
57
56
|
@instance_id = instance_id
|
58
57
|
@database_id = database_id
|
59
|
-
@pool = Pool.new self,
|
60
|
-
write_ratio: write_ratio, fail: fail
|
58
|
+
@pool = Pool.new self, opts
|
61
59
|
end
|
62
60
|
|
63
61
|
# The unique identifier for the project.
|
@@ -663,6 +661,9 @@ module Google
|
|
663
661
|
end
|
664
662
|
end
|
665
663
|
|
664
|
+
# rubocop:disable Metrics/AbcSize
|
665
|
+
# rubocop:disable Metrics/MethodLength
|
666
|
+
|
666
667
|
##
|
667
668
|
# Creates a transaction for reads and writes that execute atomically at
|
668
669
|
# a single logical point in time across columns, rows, and tables in a
|
@@ -699,8 +700,8 @@ module Google
|
|
699
700
|
# puts "User #{row[:id]} is #{row[:name]}"
|
700
701
|
# end
|
701
702
|
#
|
702
|
-
#
|
703
|
-
#
|
703
|
+
# tx.update "users", [{ id: 1, name: "Charlie", active: false }]
|
704
|
+
# tx.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
704
705
|
# end
|
705
706
|
#
|
706
707
|
# @example Manually rollback the transaction using {Rollback}:
|
@@ -710,8 +711,8 @@ module Google
|
|
710
711
|
# db = spanner.client "my-instance", "my-database"
|
711
712
|
#
|
712
713
|
# db.transaction do |tx|
|
713
|
-
#
|
714
|
-
#
|
714
|
+
# tx.update "users", [{ id: 1, name: "Charlie", active: false }]
|
715
|
+
# tx.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
715
716
|
#
|
716
717
|
# if something_wrong?
|
717
718
|
# # Rollback the transaction without passing on the error
|
@@ -722,6 +723,9 @@ module Google
|
|
722
723
|
#
|
723
724
|
def transaction deadline: 120, &block
|
724
725
|
ensure_service!
|
726
|
+
unless Thread.current[:transaction_id].nil?
|
727
|
+
fail "Nested transactions are not allowed"
|
728
|
+
end
|
725
729
|
|
726
730
|
deadline = validate_deadline deadline
|
727
731
|
backoff = 1.0
|
@@ -729,13 +733,19 @@ module Google
|
|
729
733
|
|
730
734
|
@pool.with_transaction do |tx|
|
731
735
|
begin
|
736
|
+
Thread.current[:transaction_id] = tx.transaction_id
|
732
737
|
block.call tx
|
733
738
|
commit_resp = @project.service.commit \
|
734
739
|
tx.session.path, tx.mutations, transaction_id: tx.transaction_id
|
735
740
|
return Convert.timestamp_to_time commit_resp.commit_timestamp
|
736
|
-
rescue Google::Cloud::AbortedError => err
|
741
|
+
rescue GRPC::Aborted, Google::Cloud::AbortedError => err
|
737
742
|
# Re-raise if deadline has passed
|
738
|
-
|
743
|
+
if current_time - start_time > deadline
|
744
|
+
if err.is_a? GRPC::BadStatus
|
745
|
+
err = Google::Cloud::Error.from_error err
|
746
|
+
end
|
747
|
+
raise err
|
748
|
+
end
|
739
749
|
# Sleep the amount from RetryDelay, or incremental backoff
|
740
750
|
sleep(delay_from_aborted(err) || backoff *= 1.3)
|
741
751
|
# Create new transaction on the session and retry the block
|
@@ -748,10 +758,15 @@ module Google
|
|
748
758
|
return nil if err.is_a? Rollback
|
749
759
|
# Re-raise error.
|
750
760
|
raise err
|
761
|
+
ensure
|
762
|
+
Thread.current[:transaction_id] = nil
|
751
763
|
end
|
752
764
|
end
|
753
765
|
end
|
754
766
|
|
767
|
+
# rubocop:enable Metrics/AbcSize
|
768
|
+
# rubocop:enable Metrics/MethodLength
|
769
|
+
|
755
770
|
##
|
756
771
|
# Creates a snapshot read-only transaction for reads that execute
|
757
772
|
# atomically at a single logical point in time across columns, rows, and
|
@@ -811,14 +826,24 @@ module Google
|
|
811
826
|
read_timestamp: read_timestamp,
|
812
827
|
staleness: staleness,
|
813
828
|
exact_staleness: exact_staleness
|
829
|
+
|
814
830
|
ensure_service!
|
831
|
+
unless Thread.current[:transaction_id].nil?
|
832
|
+
fail "Nested snapshots are not allowed"
|
833
|
+
end
|
834
|
+
|
815
835
|
@pool.with_session do |session|
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
836
|
+
begin
|
837
|
+
snp_grpc = @project.service.create_snapshot \
|
838
|
+
session.path, strong: strong,
|
839
|
+
timestamp: (timestamp || read_timestamp),
|
840
|
+
staleness: (staleness || exact_staleness)
|
841
|
+
Thread.current[:transaction_id] = snp_grpc.id
|
842
|
+
snp = Snapshot.from_grpc(snp_grpc, session)
|
843
|
+
yield snp if block_given?
|
844
|
+
ensure
|
845
|
+
Thread.current[:transaction_id] = nil
|
846
|
+
end
|
822
847
|
end
|
823
848
|
nil
|
824
849
|
end
|
@@ -1011,7 +1036,8 @@ module Google
|
|
1011
1036
|
end
|
1012
1037
|
|
1013
1038
|
##
|
1014
|
-
# Retrieves the delay value from Google::Cloud::AbortedError
|
1039
|
+
# Retrieves the delay value from Google::Cloud::AbortedError or
|
1040
|
+
# GRPC::Aborted
|
1015
1041
|
def delay_from_aborted err
|
1016
1042
|
return nil if err.nil?
|
1017
1043
|
if err.respond_to?(:metadata) && err.metadata["retryDelay"]
|
@@ -209,48 +209,6 @@ module Google
|
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
212
|
-
##
|
213
|
-
# @private Convert an Object to a Google::Protobuf::Value.
|
214
|
-
def object_to_value obj
|
215
|
-
case obj
|
216
|
-
when NilClass then Google::Protobuf::Value.new null_value:
|
217
|
-
:NULL_VALUE
|
218
|
-
when Numeric then Google::Protobuf::Value.new number_value: obj
|
219
|
-
when String then Google::Protobuf::Value.new string_value: obj
|
220
|
-
when TrueClass then Google::Protobuf::Value.new bool_value: true
|
221
|
-
when FalseClass then Google::Protobuf::Value.new bool_value: false
|
222
|
-
when Hash then Google::Protobuf::Value.new struct_value:
|
223
|
-
hash_to_struct(obj)
|
224
|
-
when Array then Google::Protobuf::Value.new list_value:
|
225
|
-
Google::Protobuf::ListValue.new(values:
|
226
|
-
obj.map { |o| object_to_value(o) })
|
227
|
-
else
|
228
|
-
# TODO: Could raise ArgumentError here, or convert to a string
|
229
|
-
Google::Protobuf::Value.new string_value: obj.to_s
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
##
|
234
|
-
# @private Convert a Google::Protobuf::Value to an Object.
|
235
|
-
def value_to_object value
|
236
|
-
# TODO: ArgumentError if struct is not a Google::Protobuf::Value
|
237
|
-
if value.kind == :null_value
|
238
|
-
nil
|
239
|
-
elsif value.kind == :number_value
|
240
|
-
value.number_value
|
241
|
-
elsif value.kind == :string_value
|
242
|
-
value.string_value
|
243
|
-
elsif value.kind == :bool_value
|
244
|
-
value.bool_value
|
245
|
-
elsif value.kind == :struct_value
|
246
|
-
struct_to_hash value.struct_value
|
247
|
-
elsif value.kind == :list_value
|
248
|
-
value.list_value.values.map { |v| value_to_object(v) }
|
249
|
-
else
|
250
|
-
nil # just in case
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
212
|
def number_to_duration number
|
255
213
|
return nil if number.nil?
|
256
214
|
|
@@ -31,8 +31,8 @@ module Google
|
|
31
31
|
# db = spanner.client "my-instance", "my-database"
|
32
32
|
#
|
33
33
|
# db.transaction do |tx|
|
34
|
-
#
|
35
|
-
#
|
34
|
+
# tx.update "users", [{ id: 1, name: "Charlie", active: false }]
|
35
|
+
# tx.insert "users", [{ id: 2, name: "Harvey", active: true }]
|
36
36
|
#
|
37
37
|
# if something_wrong?
|
38
38
|
# # Rollback the transaction without passing on the error
|
@@ -279,7 +279,7 @@ module Google
|
|
279
279
|
#
|
280
280
|
# spanner = Google::Cloud::Spanner.new
|
281
281
|
# instance = spanner.instance "my-instance"
|
282
|
-
# database = instance.database "my-database"
|
282
|
+
# database = instance.database "my-database" # nil
|
283
283
|
#
|
284
284
|
def database database_id
|
285
285
|
ensure_service!
|
@@ -158,20 +158,6 @@ module Google
|
|
158
158
|
roles[role_name] ||= []
|
159
159
|
end
|
160
160
|
|
161
|
-
##
|
162
|
-
# Returns a deep copy of the policy.
|
163
|
-
#
|
164
|
-
# @return [Policy]
|
165
|
-
#
|
166
|
-
def deep_dup
|
167
|
-
dup.tap do |p|
|
168
|
-
roles_dup = p.roles.each_with_object({}) do |(k, v), memo|
|
169
|
-
memo[k] = v.dup rescue value
|
170
|
-
end
|
171
|
-
p.instance_variable_set "@roles", roles_dup
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
161
|
##
|
176
162
|
# @private Convert the Policy to a Google::Iam::V1::Policy object.
|
177
163
|
def to_grpc
|
@@ -33,7 +33,7 @@ module Google
|
|
33
33
|
attr_accessor :all_sessions, :session_queue, :transaction_queue
|
34
34
|
|
35
35
|
def initialize client, min: 10, max: 100, keepalive: 1800,
|
36
|
-
write_ratio: 0.3, fail: true
|
36
|
+
write_ratio: 0.3, fail: true, threads: nil
|
37
37
|
@client = client
|
38
38
|
@min = min
|
39
39
|
@max = max
|
@@ -42,6 +42,7 @@ module Google
|
|
42
42
|
@write_ratio = 0 if write_ratio < 0
|
43
43
|
@write_ratio = 1 if write_ratio > 1
|
44
44
|
@fail = fail
|
45
|
+
@threads = threads || [2, Concurrent.processor_count * 2].max
|
45
46
|
|
46
47
|
@mutex = Mutex.new
|
47
48
|
@resource = ConditionVariable.new
|
@@ -86,11 +87,11 @@ module Google
|
|
86
87
|
end
|
87
88
|
|
88
89
|
def checkin_session session
|
89
|
-
unless all_sessions.include? session
|
90
|
-
fail ArgumentError, "Cannot checkin session"
|
91
|
-
end
|
92
|
-
|
93
90
|
@mutex.synchronize do
|
91
|
+
unless all_sessions.include? session
|
92
|
+
fail ArgumentError, "Cannot checkin session"
|
93
|
+
end
|
94
|
+
|
94
95
|
session_queue.push session
|
95
96
|
|
96
97
|
@resource.signal
|
@@ -144,11 +145,11 @@ module Google
|
|
144
145
|
end
|
145
146
|
|
146
147
|
def checkin_transaction tx
|
147
|
-
unless all_sessions.include? tx.session
|
148
|
-
fail ArgumentError, "Cannot checkin session"
|
149
|
-
end
|
150
|
-
|
151
148
|
@mutex.synchronize do
|
149
|
+
unless all_sessions.include? tx.session
|
150
|
+
fail ArgumentError, "Cannot checkin session"
|
151
|
+
end
|
152
|
+
|
152
153
|
transaction_queue.push tx
|
153
154
|
|
154
155
|
@resource.signal
|
@@ -215,10 +216,7 @@ module Google
|
|
215
216
|
|
216
217
|
def init
|
217
218
|
# init the thread pool
|
218
|
-
@thread_pool = Concurrent::FixedThreadPool.new
|
219
|
-
[2, Concurrent.processor_count].max * 2,
|
220
|
-
fallback_policy: :caller_runs
|
221
|
-
)
|
219
|
+
@thread_pool = Concurrent::FixedThreadPool.new @threads
|
222
220
|
# init the queues
|
223
221
|
@new_sessions_in_process = @min.to_i
|
224
222
|
@all_sessions = []
|
@@ -158,7 +158,7 @@ module Google
|
|
158
158
|
# require "google/cloud/spanner"
|
159
159
|
#
|
160
160
|
# spanner = Google::Cloud::Spanner.new
|
161
|
-
# instance = spanner.instance "non-existing"
|
161
|
+
# instance = spanner.instance "non-existing" # nil
|
162
162
|
#
|
163
163
|
def instance instance_id
|
164
164
|
ensure_service!
|
@@ -288,7 +288,7 @@ module Google
|
|
288
288
|
# require "google/cloud/spanner"
|
289
289
|
#
|
290
290
|
# spanner = Google::Cloud::Spanner.new
|
291
|
-
# config = spanner.instance_config "non-existing"
|
291
|
+
# config = spanner.instance_config "non-existing" # nil
|
292
292
|
#
|
293
293
|
def instance_config instance_config_id
|
294
294
|
ensure_service!
|
@@ -355,7 +355,7 @@ module Google
|
|
355
355
|
# require "google/cloud/spanner"
|
356
356
|
#
|
357
357
|
# spanner = Google::Cloud::Spanner.new
|
358
|
-
# database = spanner.database "my-instance", "my-database"
|
358
|
+
# database = spanner.database "my-instance", "my-database" # nil
|
359
359
|
#
|
360
360
|
def database instance_id, database_id
|
361
361
|
ensure_service!
|
@@ -432,6 +432,8 @@ module Google
|
|
432
432
|
# {SessionLimitError} when the client has allocated the `max` number
|
433
433
|
# of sessions. When `false` the client blocks until a session
|
434
434
|
# becomes available. The default is `true`.
|
435
|
+
# * `:threads` (Integer) The number of threads in the thread pool. The
|
436
|
+
# default is twice the number of available CPUs.
|
435
437
|
#
|
436
438
|
# @return [Client] The newly created client.
|
437
439
|
#
|
@@ -471,7 +473,8 @@ module Google
|
|
471
473
|
|
472
474
|
def valid_session_pool_options opts = {}
|
473
475
|
{ min: opts[:min], max: opts[:max], keepalive: opts[:keepalive],
|
474
|
-
write_ratio: opts[:write_ratio], fail: opts[:fail]
|
476
|
+
write_ratio: opts[:write_ratio], fail: opts[:fail],
|
477
|
+
threads: opts[:threads]
|
475
478
|
}.delete_if { |_k, v| v.nil? }
|
476
479
|
end
|
477
480
|
end
|
@@ -272,24 +272,6 @@ module Google
|
|
272
272
|
end
|
273
273
|
end
|
274
274
|
|
275
|
-
def execute_sql session_name, sql, transaction: nil, params: nil
|
276
|
-
input_params = nil
|
277
|
-
input_param_types = nil
|
278
|
-
unless params.nil?
|
279
|
-
input_param_pairs = Convert.to_query_params params
|
280
|
-
input_params = Google::Protobuf::Struct.new(
|
281
|
-
fields: Hash[input_param_pairs.map { |k, v| [k, v.first] }])
|
282
|
-
input_param_types = Hash[
|
283
|
-
input_param_pairs.map { |k, v| [k, v.last] }]
|
284
|
-
end
|
285
|
-
opts = default_options_from_session session_name
|
286
|
-
execute do
|
287
|
-
service.execute_sql \
|
288
|
-
session_name, sql, transaction: transaction, params: input_params,
|
289
|
-
param_types: input_param_types, options: opts
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
275
|
def streaming_execute_sql session_name, sql, transaction: nil,
|
294
276
|
params: nil, types: nil, resume_token: nil
|
295
277
|
input_params = nil
|
@@ -310,18 +292,6 @@ module Google
|
|
310
292
|
end
|
311
293
|
end
|
312
294
|
|
313
|
-
def read_table session_name, table_name, columns, keys: nil, index: nil,
|
314
|
-
transaction: nil, limit: nil
|
315
|
-
columns.map!(&:to_s)
|
316
|
-
opts = default_options_from_session session_name
|
317
|
-
execute do
|
318
|
-
service.read \
|
319
|
-
session_name, table_name, columns, key_set(keys),
|
320
|
-
transaction: transaction, index: index, limit: limit,
|
321
|
-
options: opts
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
295
|
def streaming_read_table session_name, table_name, columns, keys: nil,
|
326
296
|
index: nil, transaction: nil, limit: nil,
|
327
297
|
resume_token: nil
|
@@ -38,11 +38,38 @@ module Google
|
|
38
38
|
# db = spanner.client "my-instance", "my-database"
|
39
39
|
#
|
40
40
|
# db.transaction do |tx|
|
41
|
-
#
|
41
|
+
# # Read the second album budget.
|
42
|
+
# second_album_result = tx.read "Albums", ["marketing_budget"],
|
43
|
+
# keys: [[2, 2]], limit: 1
|
44
|
+
# second_album_row = second_album_result.rows.first
|
45
|
+
# second_album_budget = second_album_row.values.first
|
42
46
|
#
|
43
|
-
#
|
44
|
-
#
|
47
|
+
# transfer_amount = 200000
|
48
|
+
#
|
49
|
+
# if second_album_budget < 300000
|
50
|
+
# # Raising an exception will automatically roll back the
|
51
|
+
# # transaction.
|
52
|
+
# raise "The second album doesn't have enough funds to transfer"
|
45
53
|
# end
|
54
|
+
#
|
55
|
+
# # Read the first album's budget.
|
56
|
+
# first_album_result = tx.read "Albums", ["marketing_budget"],
|
57
|
+
# keys: [[1, 1]], limit: 1
|
58
|
+
# first_album_row = first_album_result.rows.first
|
59
|
+
# first_album_budget = first_album_row.values.first
|
60
|
+
#
|
61
|
+
# # Update the budgets.
|
62
|
+
# second_album_budget -= transfer_amount
|
63
|
+
# first_album_budget += transfer_amount
|
64
|
+
# puts "Setting first album's budget to #{first_album_budget} and " \
|
65
|
+
# "the second album's budget to #{second_album_budget}."
|
66
|
+
#
|
67
|
+
# # Update the rows.
|
68
|
+
# rows = [
|
69
|
+
# {singer_id: 1, album_id: 1, marketing_budget: first_album_budget},
|
70
|
+
# {singer_id: 2, album_id: 2, marketing_budget: second_album_budget}
|
71
|
+
# ]
|
72
|
+
# tx.update "Albums", rows
|
46
73
|
# end
|
47
74
|
#
|
48
75
|
class Transaction
|
@@ -423,7 +450,7 @@ module Google
|
|
423
450
|
# db = spanner.client "my-instance", "my-database"
|
424
451
|
#
|
425
452
|
# db.transaction do |tx|
|
426
|
-
# users_types =
|
453
|
+
# users_types = tx.fields_for "users"
|
427
454
|
# tx.insert "users", [{ id: 1, name: "Charlie", active: false },
|
428
455
|
# { id: 2, name: "Harvey", active: true }],
|
429
456
|
# types: users_types
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-spanner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-07-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-cloud-core
|
@@ -197,16 +197,16 @@ dependencies:
|
|
197
197
|
name: yard-doctest
|
198
198
|
requirement: !ruby/object:Gem::Requirement
|
199
199
|
requirements:
|
200
|
-
- - "
|
200
|
+
- - "<="
|
201
201
|
- !ruby/object:Gem::Version
|
202
|
-
version: 0.1.
|
202
|
+
version: 0.1.8
|
203
203
|
type: :development
|
204
204
|
prerelease: false
|
205
205
|
version_requirements: !ruby/object:Gem::Requirement
|
206
206
|
requirements:
|
207
|
-
- - "
|
207
|
+
- - "<="
|
208
208
|
- !ruby/object:Gem::Version
|
209
|
-
version: 0.1.
|
209
|
+
version: 0.1.8
|
210
210
|
description: google-cloud-spanner is the official library for Google Cloud Spanner
|
211
211
|
API.
|
212
212
|
email:
|