google-cloud-spanner 0.21.0 → 0.22.0
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 +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:
|