activerecord-spanner-adapter 1.6.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/acceptance-tests-on-emulator.yaml +3 -7
- data/.github/workflows/acceptance-tests-on-production.yaml +1 -1
- data/.github/workflows/ci.yaml +3 -7
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +4 -33
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +1 -1
- data/.github/workflows/nightly-unit-tests.yaml +5 -33
- data/.github/workflows/rubocop.yaml +1 -1
- data/.github/workflows/samples.yaml +30 -0
- data/.kokoro/populate-secrets.sh +5 -1
- data/.kokoro/release.cfg +22 -12
- data/.kokoro/release.sh +1 -3
- data/.kokoro/trampoline_v2.sh +19 -11
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +2 -2
- data/.trampolinerc +6 -1
- data/CHANGELOG.md +37 -0
- data/Gemfile +7 -5
- data/README.md +11 -9
- data/Rakefile +2 -2
- data/acceptance/cases/migration/command_recorder_test.rb +7 -38
- data/acceptance/cases/migration/references_index_test.rb +2 -11
- data/acceptance/cases/migration/schema_dumper_test.rb +21 -9
- data/acceptance/cases/models/binary_identifiers.rb +97 -0
- data/acceptance/cases/models/insert_all_test.rb +22 -7
- data/acceptance/cases/sessions/session_not_found_test.rb +2 -0
- data/acceptance/cases/tasks/database_tasks_test.rb +1 -0
- data/acceptance/models/binary_project.rb +20 -0
- data/acceptance/models/string_io.rb +28 -0
- data/acceptance/models/user.rb +20 -0
- data/acceptance/test_helper.rb +6 -1
- data/activerecord-spanner-adapter.gemspec +3 -3
- data/benchmarks/application.rb +3 -7
- data/examples/snippets/Rakefile +27 -5
- data/examples/snippets/array-data-type/application.rb +1 -5
- data/examples/snippets/array-data-type/config/database.yml +1 -0
- data/examples/snippets/bit-reversed-sequence/application.rb +0 -4
- data/examples/snippets/bit-reversed-sequence/config/database.yml +1 -0
- data/examples/snippets/bit-reversed-sequence/db/seeds.rb +2 -2
- data/examples/snippets/bulk-insert/application.rb +1 -5
- data/examples/snippets/bulk-insert/config/database.yml +1 -0
- data/examples/snippets/commit-timestamp/application.rb +0 -4
- data/examples/snippets/commit-timestamp/config/database.yml +1 -0
- data/examples/snippets/config/environment.rb +5 -0
- data/examples/snippets/create-records/application.rb +1 -5
- data/examples/snippets/create-records/config/database.yml +1 -0
- data/examples/snippets/date-data-type/application.rb +1 -5
- data/examples/snippets/date-data-type/config/database.yml +1 -0
- data/examples/snippets/date-data-type/db/seeds.rb +1 -1
- data/examples/snippets/generated-column/application.rb +0 -4
- data/examples/snippets/generated-column/config/database.yml +1 -0
- data/examples/snippets/generated-column/db/seeds.rb +1 -1
- data/examples/snippets/hints/application.rb +0 -4
- data/examples/snippets/hints/config/database.yml +1 -0
- data/examples/snippets/hints/db/seeds.rb +1 -1
- data/examples/snippets/interleaved-tables/application.rb +1 -5
- data/examples/snippets/interleaved-tables/config/database.yml +1 -0
- data/examples/snippets/interleaved-tables/db/seeds.rb +1 -1
- data/examples/snippets/interleaved-tables/models/album.rb +6 -2
- data/examples/snippets/interleaved-tables/models/track.rb +5 -1
- data/examples/snippets/interleaved-tables-before-7.1/application.rb +1 -5
- data/examples/snippets/interleaved-tables-before-7.1/config/database.yml +1 -0
- data/examples/snippets/interleaved-tables-before-7.1/db/seeds.rb +1 -1
- data/examples/snippets/migrations/application.rb +0 -4
- data/examples/snippets/migrations/config/database.yml +1 -0
- data/examples/snippets/mutations/application.rb +1 -5
- data/examples/snippets/mutations/config/database.yml +1 -0
- data/examples/snippets/mutations/db/seeds.rb +1 -1
- data/examples/snippets/optimistic-locking/application.rb +0 -4
- data/examples/snippets/optimistic-locking/config/database.yml +1 -0
- data/examples/snippets/optimistic-locking/db/seeds.rb +1 -1
- data/examples/snippets/partitioned-dml/application.rb +0 -4
- data/examples/snippets/partitioned-dml/config/database.yml +1 -0
- data/examples/snippets/partitioned-dml/db/seeds.rb +1 -1
- data/examples/snippets/query-logs/application.rb +15 -13
- data/examples/snippets/query-logs/config/database.yml +1 -0
- data/examples/snippets/query-logs/db/seeds.rb +1 -1
- data/examples/snippets/quickstart/application.rb +0 -4
- data/examples/snippets/quickstart/config/database.yml +1 -0
- data/examples/snippets/quickstart/db/seeds.rb +1 -1
- data/examples/snippets/read-only-transactions/application.rb +0 -4
- data/examples/snippets/read-only-transactions/config/database.yml +1 -0
- data/examples/snippets/read-only-transactions/db/seeds.rb +1 -1
- data/examples/snippets/read-write-transactions/application.rb +2 -6
- data/examples/snippets/read-write-transactions/config/database.yml +1 -0
- data/examples/snippets/read-write-transactions/db/seeds.rb +1 -1
- data/examples/snippets/stale-reads/application.rb +0 -4
- data/examples/snippets/stale-reads/config/database.yml +1 -0
- data/examples/snippets/stale-reads/db/seeds.rb +1 -1
- data/examples/snippets/tags/application.rb +0 -4
- data/examples/snippets/tags/config/database.yml +1 -0
- data/examples/snippets/tags/db/seeds.rb +1 -1
- data/examples/snippets/timestamp-data-type/application.rb +0 -4
- data/examples/snippets/timestamp-data-type/config/database.yml +1 -0
- data/lib/active_record/connection_adapters/spanner/column.rb +3 -3
- data/lib/active_record/connection_adapters/spanner/database_statements.rb +37 -23
- data/lib/active_record/connection_adapters/spanner/quoting.rb +19 -6
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +7 -9
- data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +12 -2
- data/lib/active_record/connection_adapters/spanner/schema_statements.rb +28 -46
- data/lib/active_record/connection_adapters/spanner/type_metadata.rb +4 -6
- data/lib/active_record/connection_adapters/spanner_adapter.rb +54 -27
- data/lib/active_record/tasks/spanner_database_tasks.rb +4 -4
- data/lib/active_record/type/spanner/array.rb +4 -0
- data/lib/active_record/type/spanner/bytes.rb +10 -0
- data/lib/activerecord-spanner-adapter.rb +5 -1
- data/lib/activerecord_spanner_adapter/base.rb +58 -30
- data/lib/activerecord_spanner_adapter/connection.rb +9 -5
- data/lib/activerecord_spanner_adapter/foreign_key.rb +9 -2
- data/lib/activerecord_spanner_adapter/index/column.rb +6 -1
- data/lib/activerecord_spanner_adapter/index.rb +10 -2
- data/lib/activerecord_spanner_adapter/information_schema.rb +1 -1
- data/lib/activerecord_spanner_adapter/primary_key.rb +2 -2
- data/lib/activerecord_spanner_adapter/table/column.rb +12 -3
- data/lib/activerecord_spanner_adapter/table.rb +8 -2
- data/lib/activerecord_spanner_adapter/transaction.rb +1 -1
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- data/lib/arel/visitors/spanner.rb +16 -11
- data/lib/spanner_client_ext.rb +4 -3
- metadata +15 -34
- data/examples/snippets/array-data-type/db/schema.rb +0 -31
- data/examples/snippets/bit-reversed-sequence/db/schema.rb +0 -31
- data/examples/snippets/bulk-insert/db/schema.rb +0 -31
- data/examples/snippets/commit-timestamp/db/schema.rb +0 -34
- data/examples/snippets/create-records/db/schema.rb +0 -31
- data/examples/snippets/date-data-type/db/schema.rb +0 -26
- data/examples/snippets/generated-column/db/schema.rb +0 -26
- data/examples/snippets/hints/db/schema.rb +0 -33
- data/examples/snippets/interleaved-tables/db/schema.rb +0 -39
- data/examples/snippets/interleaved-tables-before-7.1/db/schema.rb +0 -37
- data/examples/snippets/migrations/db/schema.rb +0 -38
- data/examples/snippets/mutations/db/schema.rb +0 -32
- data/examples/snippets/optimistic-locking/db/schema.rb +0 -34
- data/examples/snippets/partitioned-dml/db/schema.rb +0 -31
- data/examples/snippets/query-logs/db/schema.rb +0 -31
- data/examples/snippets/quickstart/db/schema.rb +0 -31
- data/examples/snippets/read-only-transactions/db/schema.rb +0 -31
- data/examples/snippets/read-write-transactions/db/schema.rb +0 -32
- data/examples/snippets/stale-reads/db/schema.rb +0 -31
- data/examples/snippets/tags/db/schema.rb +0 -31
- data/examples/snippets/timestamp-data-type/db/schema.rb +0 -26
@@ -16,6 +16,7 @@ module ActiveRecord
|
|
16
16
|
|
17
17
|
class Base
|
18
18
|
VERSION_7_1 = Gem::Version.create "7.1.0"
|
19
|
+
VERSION_7_2 = Gem::Version.create "7.2.0"
|
19
20
|
|
20
21
|
# Creates an object (or multiple objects) and saves it to the database. This method will use mutations instead
|
21
22
|
# of DML if there is no active transaction, or if the active transaction has been created with the option
|
@@ -48,8 +49,26 @@ module ActiveRecord
|
|
48
49
|
spanner_adapter? && connection&.current_spanner_transaction&.isolation == :buffered_mutations
|
49
50
|
end
|
50
51
|
|
51
|
-
def self.
|
52
|
-
|
52
|
+
def self._should_use_standard_insert_record? values
|
53
|
+
!(buffered_mutations? || (primary_key && values.is_a?(Hash))) || !spanner_adapter?
|
54
|
+
end
|
55
|
+
|
56
|
+
def self._internal_insert_record values
|
57
|
+
if ActiveRecord.gem_version < VERSION_7_2
|
58
|
+
_insert_record values
|
59
|
+
else
|
60
|
+
_insert_record nil, values
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self._insert_record *args
|
65
|
+
if ActiveRecord.gem_version < VERSION_7_2
|
66
|
+
values, returning = args
|
67
|
+
else
|
68
|
+
_connection, values, returning = args
|
69
|
+
end
|
70
|
+
|
71
|
+
if _should_use_standard_insert_record? values
|
53
72
|
return super values if ActiveRecord.gem_version < VERSION_7_1
|
54
73
|
return super
|
55
74
|
end
|
@@ -57,7 +76,7 @@ module ActiveRecord
|
|
57
76
|
# Mutations cannot be used in combination with a sequence, as mutations do not support a THEN RETURN clause.
|
58
77
|
if buffered_mutations? && sequence_name
|
59
78
|
raise StatementInvalid, "Mutations cannot be used to create records that use a sequence " \
|
60
|
-
|
79
|
+
"to generate the primary key. #{self} uses #{sequence_name}."
|
61
80
|
end
|
62
81
|
|
63
82
|
return _buffer_record values, :insert, returning if buffered_mutations?
|
@@ -99,20 +118,30 @@ module ActiveRecord
|
|
99
118
|
keys = returning || primary_key
|
100
119
|
return primary_key_value if keys == primary_key
|
101
120
|
|
102
|
-
primary_key_values_hash =
|
103
|
-
|
104
|
-
|
105
|
-
values.append primary_key_values_hash[column]
|
121
|
+
primary_key_values_hash = primary_key.zip(primary_key_value).to_h
|
122
|
+
keys.map do |column|
|
123
|
+
primary_key_values_hash[column]
|
106
124
|
end
|
107
|
-
values
|
108
125
|
end
|
109
126
|
|
110
127
|
def self._upsert_record values, returning
|
111
128
|
_buffer_record values, :insert_or_update, returning
|
112
129
|
end
|
113
130
|
|
114
|
-
def self.insert_all
|
115
|
-
|
131
|
+
def self.insert_all attributes, returning: nil, **_kwargs
|
132
|
+
if active_transaction? && buffered_mutations?
|
133
|
+
raise NotImplementedError,
|
134
|
+
"Spanner does not support skip_duplicates for mutations. " \
|
135
|
+
"Use a transaction that uses DML, or use insert! or upsert instead."
|
136
|
+
end
|
137
|
+
super
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.insert! attributes, returning: nil, **kwargs
|
141
|
+
return super unless spanner_adapter?
|
142
|
+
return super if active_transaction? && !buffered_mutations?
|
143
|
+
|
144
|
+
insert_all! [attributes], returning: returning, **kwargs
|
116
145
|
end
|
117
146
|
|
118
147
|
def self.insert_all! attributes, returning: nil, **_kwargs
|
@@ -123,24 +152,27 @@ module ActiveRecord
|
|
123
152
|
# The mutations will be sent as one batch when the transaction is committed.
|
124
153
|
if active_transaction?
|
125
154
|
attributes.each do |record|
|
126
|
-
|
155
|
+
_internal_insert_record record
|
127
156
|
end
|
128
157
|
else
|
129
158
|
transaction isolation: :buffered_mutations do
|
130
159
|
attributes.each do |record|
|
131
|
-
|
160
|
+
_internal_insert_record record
|
132
161
|
end
|
133
162
|
end
|
134
163
|
end
|
135
164
|
end
|
136
165
|
|
137
|
-
def self.
|
166
|
+
def self.upsert attributes, returning: nil, **kwargs
|
138
167
|
return super unless spanner_adapter?
|
139
|
-
if active_transaction? && !buffered_mutations?
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
168
|
+
return super if active_transaction? && !buffered_mutations?
|
169
|
+
|
170
|
+
upsert_all [attributes], returning: returning, **kwargs
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.upsert_all attributes, returning: nil, unique_by: nil, **kwargs
|
174
|
+
return super unless spanner_adapter?
|
175
|
+
return super if active_transaction? && !buffered_mutations?
|
144
176
|
|
145
177
|
# This might seem inefficient, but is actually not, as it is only buffering a mutation locally.
|
146
178
|
# The mutations will be sent as one batch when the transaction is committed.
|
@@ -182,11 +214,9 @@ module ActiveRecord
|
|
182
214
|
end
|
183
215
|
|
184
216
|
def self._set_composite_primary_key_values primary_key, values
|
185
|
-
|
186
|
-
|
187
|
-
primary_key_value.append _set_composite_primary_key_value col, values
|
217
|
+
primary_key.map do |col|
|
218
|
+
_set_composite_primary_key_value col, values
|
188
219
|
end
|
189
|
-
primary_key_value
|
190
220
|
end
|
191
221
|
|
192
222
|
def self._set_composite_primary_key_value primary_key, values
|
@@ -385,14 +415,12 @@ module ActiveRecord
|
|
385
415
|
end
|
386
416
|
|
387
417
|
def serialize_keys metadata, keys
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
:mutation)
|
418
|
+
keys.map do |key|
|
419
|
+
ActiveRecord::Type::Spanner::SpannerActiveRecordConverter
|
420
|
+
.serialize_with_transaction_isolation_level(metadata.type(key),
|
421
|
+
attribute_in_database(key),
|
422
|
+
:mutation)
|
394
423
|
end
|
395
|
-
serialized_values
|
396
424
|
end
|
397
425
|
|
398
426
|
def _execute_version_check attempted_action # rubocop:disable Metrics/AbcSize
|
@@ -422,7 +450,7 @@ module ActiveRecord
|
|
422
450
|
|
423
451
|
# We need to check the version using a SELECT query, as a mutation cannot include a WHERE clause.
|
424
452
|
sql = "SELECT 1 FROM `#{self.class.arel_table.name}` " \
|
425
|
-
|
453
|
+
"WHERE #{pk_sql} AND `#{locking_column}` = @lock_version"
|
426
454
|
locked_row = self.class.connection.raw_connection.execute_query sql, params: params, types: param_types
|
427
455
|
raise ActiveRecord::StaleObjectError.new(self, attempted_action) unless locked_row.rows.any?
|
428
456
|
end
|
@@ -10,7 +10,9 @@ require "activerecord_spanner_adapter/information_schema"
|
|
10
10
|
|
11
11
|
module ActiveRecordSpannerAdapter
|
12
12
|
class Connection
|
13
|
-
attr_reader :instance_id
|
13
|
+
attr_reader :instance_id
|
14
|
+
attr_reader :database_id
|
15
|
+
attr_reader :spanner
|
14
16
|
attr_accessor :current_transaction
|
15
17
|
|
16
18
|
def initialize config
|
@@ -45,7 +47,7 @@ module ActiveRecordSpannerAdapter
|
|
45
47
|
|
46
48
|
def self.information_schema config
|
47
49
|
@information_schemas ||= {}
|
48
|
-
@information_schemas[database_path(config)] ||=
|
50
|
+
@information_schemas[database_path(config)] ||=
|
49
51
|
ActiveRecordSpannerAdapter::InformationSchema.new new(config)
|
50
52
|
end
|
51
53
|
|
@@ -202,7 +204,7 @@ module ActiveRecordSpannerAdapter
|
|
202
204
|
|
203
205
|
def execute_query sql, params: nil, types: nil, single_use_selector: nil, request_options: nil
|
204
206
|
if params
|
205
|
-
converted_params, types =
|
207
|
+
converted_params, types =
|
206
208
|
Google::Cloud::Spanner::Convert.to_input_params_and_types(
|
207
209
|
params, types
|
208
210
|
)
|
@@ -217,6 +219,7 @@ module ActiveRecordSpannerAdapter
|
|
217
219
|
execute_sql_request sql, converted_params, types, selector, request_options
|
218
220
|
end
|
219
221
|
|
222
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
220
223
|
def execute_sql_request sql, converted_params, types, selector, request_options = nil
|
221
224
|
res = session.execute_query \
|
222
225
|
sql,
|
@@ -224,7 +227,7 @@ module ActiveRecordSpannerAdapter
|
|
224
227
|
types: types,
|
225
228
|
transaction: selector,
|
226
229
|
request_options: request_options,
|
227
|
-
seqno:
|
230
|
+
seqno: current_transaction&.next_sequence_number
|
228
231
|
current_transaction.grpc_transaction = res.metadata.transaction \
|
229
232
|
if current_transaction && res&.metadata&.transaction
|
230
233
|
res
|
@@ -252,6 +255,7 @@ module ActiveRecordSpannerAdapter
|
|
252
255
|
# It was not the first statement, so propagate the error.
|
253
256
|
raise
|
254
257
|
end
|
258
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
255
259
|
|
256
260
|
# Creates a transaction using a BeginTransaction RPC. This is used if the first statement of a
|
257
261
|
# transaction fails, as that also means that no transaction id was returned.
|
@@ -283,7 +287,7 @@ module ActiveRecordSpannerAdapter
|
|
283
287
|
end
|
284
288
|
|
285
289
|
def transaction_selector
|
286
|
-
|
290
|
+
current_transaction&.transaction_selector if current_transaction&.active?
|
287
291
|
end
|
288
292
|
|
289
293
|
def truncate table_name
|
@@ -6,8 +6,15 @@
|
|
6
6
|
|
7
7
|
module ActiveRecordSpannerAdapter
|
8
8
|
class ForeignKey
|
9
|
-
attr_accessor :table_schema
|
10
|
-
|
9
|
+
attr_accessor :table_schema
|
10
|
+
attr_accessor :table_name
|
11
|
+
attr_accessor :name
|
12
|
+
attr_accessor :columns
|
13
|
+
attr_accessor :ref_schema
|
14
|
+
attr_accessor :ref_table
|
15
|
+
attr_accessor :ref_columns
|
16
|
+
attr_accessor :on_delete
|
17
|
+
attr_accessor :on_update
|
11
18
|
|
12
19
|
def initialize \
|
13
20
|
table_name,
|
@@ -7,7 +7,12 @@
|
|
7
7
|
module ActiveRecordSpannerAdapter
|
8
8
|
class Index
|
9
9
|
class Column
|
10
|
-
attr_accessor :table_name
|
10
|
+
attr_accessor :table_name
|
11
|
+
attr_accessor :schema_name
|
12
|
+
attr_accessor :index_name
|
13
|
+
attr_accessor :name
|
14
|
+
attr_accessor :order
|
15
|
+
attr_accessor :ordinal_position
|
11
16
|
|
12
17
|
def initialize \
|
13
18
|
table_name,
|
@@ -8,8 +8,16 @@ require "activerecord_spanner_adapter/index/column"
|
|
8
8
|
|
9
9
|
module ActiveRecordSpannerAdapter
|
10
10
|
class Index
|
11
|
-
attr_accessor :schema
|
12
|
-
|
11
|
+
attr_accessor :schema
|
12
|
+
attr_accessor :table
|
13
|
+
attr_accessor :name
|
14
|
+
attr_accessor :columns
|
15
|
+
attr_accessor :type
|
16
|
+
attr_accessor :unique
|
17
|
+
attr_accessor :null_filtered
|
18
|
+
attr_accessor :interleave_in
|
19
|
+
attr_accessor :storing
|
20
|
+
attr_accessor :state
|
13
21
|
|
14
22
|
def initialize \
|
15
23
|
table,
|
@@ -18,8 +18,8 @@ module ActiveRecord
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def fetch_primary_and_parent_key
|
21
|
-
|
22
|
-
if ActiveRecord::Base
|
21
|
+
connection.spanner_schema_cache.primary_and_parent_keys table_name \
|
22
|
+
if self != ActiveRecord::Base && table_exists?
|
23
23
|
end
|
24
24
|
|
25
25
|
def primary_and_parent_key= value
|
@@ -7,9 +7,18 @@
|
|
7
7
|
module ActiveRecordSpannerAdapter
|
8
8
|
class Table
|
9
9
|
class Column
|
10
|
-
attr_accessor :schema_name
|
11
|
-
|
12
|
-
|
10
|
+
attr_accessor :schema_name
|
11
|
+
attr_accessor :table_name
|
12
|
+
attr_accessor :name
|
13
|
+
attr_accessor :type
|
14
|
+
attr_accessor :limit
|
15
|
+
attr_accessor :ordinal_position
|
16
|
+
attr_accessor :allow_commit_timestamp
|
17
|
+
attr_accessor :default
|
18
|
+
attr_accessor :default_function
|
19
|
+
attr_accessor :generated
|
20
|
+
attr_accessor :primary_key
|
21
|
+
attr_accessor :nullable
|
13
22
|
|
14
23
|
def initialize \
|
15
24
|
table_name,
|
@@ -30,8 +30,14 @@ require "activerecord_spanner_adapter/table/column"
|
|
30
30
|
|
31
31
|
module ActiveRecordSpannerAdapter
|
32
32
|
class Table
|
33
|
-
attr_accessor :name
|
34
|
-
|
33
|
+
attr_accessor :name
|
34
|
+
attr_accessor :on_delete
|
35
|
+
attr_accessor :parent_table
|
36
|
+
attr_accessor :schema_name
|
37
|
+
attr_accessor :catalog
|
38
|
+
attr_accessor :indexes
|
39
|
+
attr_accessor :columns
|
40
|
+
attr_accessor :foreign_keys
|
35
41
|
|
36
42
|
# parent_table == interleave_in
|
37
43
|
def initialize \
|
@@ -123,7 +123,7 @@ module ActiveRecordSpannerAdapter
|
|
123
123
|
|
124
124
|
def shoot_and_forget_rollback
|
125
125
|
@connection.session.rollback @grpc_transaction.transaction_id if @committable
|
126
|
-
rescue StandardError
|
126
|
+
rescue StandardError
|
127
127
|
# Ignored
|
128
128
|
end
|
129
129
|
|
@@ -35,9 +35,7 @@ module Arel # :nodoc: all
|
|
35
35
|
sql = collector.hints[:statement_hint].value + sql if collector.hints[:statement_hint]
|
36
36
|
|
37
37
|
if binds
|
38
|
-
|
39
|
-
binds << collector.hints[:request_options] if collector.hints[:request_options]
|
40
|
-
[sql, binds]
|
38
|
+
compile_with_binds collector, sql, binds
|
41
39
|
else
|
42
40
|
sql
|
43
41
|
end
|
@@ -45,6 +43,12 @@ module Arel # :nodoc: all
|
|
45
43
|
|
46
44
|
private
|
47
45
|
|
46
|
+
def compile_with_binds collector, sql, binds
|
47
|
+
binds << collector.hints[:staleness] if collector.hints[:staleness]
|
48
|
+
binds << collector.hints[:request_options] if collector.hints[:request_options]
|
49
|
+
[sql, binds]
|
50
|
+
end
|
51
|
+
|
48
52
|
BIND_BLOCK = proc { |i| "@p#{i}" }
|
49
53
|
private_constant :BIND_BLOCK
|
50
54
|
|
@@ -62,43 +66,44 @@ module Arel # :nodoc: all
|
|
62
66
|
end
|
63
67
|
|
64
68
|
def visit_statement_hint v, collector
|
65
|
-
collector.hints[:statement_hint] =
|
69
|
+
collector.hints[:statement_hint] =
|
66
70
|
StatementHint.new v.delete_prefix("statement_hint:")
|
67
71
|
end
|
68
72
|
|
69
|
-
# rubocop:disable Naming/MethodName
|
73
|
+
# rubocop:disable Naming/MethodName, Metrics/AbcSize
|
70
74
|
def visit_Arel_Nodes_OptimizerHints o, collector
|
71
75
|
o.expr.each do |v|
|
72
76
|
visit_table_hint v, collector if v.start_with? "table_hint:"
|
73
77
|
visit_statement_hint v, collector if v.start_with? "statement_hint:"
|
74
78
|
if v.start_with? "max_staleness:"
|
75
|
-
collector.hints[:staleness] =
|
79
|
+
collector.hints[:staleness] =
|
76
80
|
StalenessHint.new max_staleness: v.delete_prefix("max_staleness:").to_f
|
77
81
|
next
|
78
82
|
end
|
79
83
|
if v.start_with? "exact_staleness:"
|
80
|
-
collector.hints[:staleness] =
|
84
|
+
collector.hints[:staleness] =
|
81
85
|
StalenessHint.new exact_staleness: v.delete_prefix("exact_staleness:").to_f
|
82
86
|
next
|
83
87
|
end
|
84
88
|
if v.start_with? "min_read_timestamp:"
|
85
89
|
time = Time.xmlschema v.delete_prefix("min_read_timestamp:")
|
86
|
-
collector.hints[:staleness] =
|
90
|
+
collector.hints[:staleness] =
|
87
91
|
StalenessHint.new min_read_timestamp: time
|
88
92
|
next
|
89
93
|
end
|
90
94
|
next unless v.start_with? "read_timestamp:"
|
91
95
|
time = Time.xmlschema v.delete_prefix("read_timestamp:")
|
92
|
-
collector.hints[:staleness] =
|
96
|
+
collector.hints[:staleness] =
|
93
97
|
StalenessHint.new read_timestamp: time
|
94
98
|
end
|
95
99
|
collector
|
96
100
|
end
|
101
|
+
# rubocop:enable Metrics/AbcSize
|
97
102
|
|
98
103
|
def visit_Arel_Nodes_Comment o, collector
|
99
|
-
o.values.each do |v|
|
104
|
+
o.values.each do |v| # rubocop:disable Style/HashEachMethods
|
100
105
|
if v.start_with?("request_tag:") || v.start_with?("transaction_tag:")
|
101
|
-
collector.hints[:request_options] ||=
|
106
|
+
collector.hints[:request_options] ||=
|
102
107
|
Google::Cloud::Spanner::V1::RequestOptions.new
|
103
108
|
end
|
104
109
|
|
data/lib/spanner_client_ext.rb
CHANGED
@@ -66,8 +66,8 @@ module Google
|
|
66
66
|
ensure_service!
|
67
67
|
|
68
68
|
snp_grpc = service.create_snapshot \
|
69
|
-
path, timestamp:
|
70
|
-
staleness:
|
69
|
+
path, timestamp: timestamp || read_timestamp,
|
70
|
+
staleness: staleness || exact_staleness
|
71
71
|
num_args = Snapshot.method(:from_grpc).arity
|
72
72
|
if num_args == 3
|
73
73
|
Snapshot.from_grpc snp_grpc, self, nil
|
@@ -105,7 +105,8 @@ module Google
|
|
105
105
|
end
|
106
106
|
|
107
107
|
class Transaction
|
108
|
-
attr_accessor :seqno
|
108
|
+
attr_accessor :seqno
|
109
|
+
attr_accessor :commit
|
109
110
|
end
|
110
111
|
end
|
111
112
|
end
|