activerecord-spanner-adapter 1.6.3 → 2.0.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.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/acceptance-tests-on-emulator.yaml +3 -7
  3. data/.github/workflows/acceptance-tests-on-production.yaml +1 -1
  4. data/.github/workflows/ci.yaml +3 -7
  5. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +4 -33
  6. data/.github/workflows/nightly-acceptance-tests-on-production.yaml +1 -1
  7. data/.github/workflows/nightly-unit-tests.yaml +5 -33
  8. data/.github/workflows/rubocop.yaml +1 -1
  9. data/.github/workflows/samples.yaml +30 -0
  10. data/.kokoro/populate-secrets.sh +5 -1
  11. data/.kokoro/release.cfg +22 -12
  12. data/.kokoro/release.sh +1 -3
  13. data/.kokoro/trampoline_v2.sh +19 -11
  14. data/.release-please-manifest.json +1 -1
  15. data/.rubocop.yml +2 -2
  16. data/.trampolinerc +6 -1
  17. data/CHANGELOG.md +37 -0
  18. data/Gemfile +7 -5
  19. data/README.md +11 -9
  20. data/Rakefile +2 -2
  21. data/acceptance/cases/migration/command_recorder_test.rb +7 -38
  22. data/acceptance/cases/migration/references_index_test.rb +2 -11
  23. data/acceptance/cases/migration/schema_dumper_test.rb +21 -9
  24. data/acceptance/cases/models/binary_identifiers.rb +97 -0
  25. data/acceptance/cases/models/insert_all_test.rb +22 -7
  26. data/acceptance/cases/sessions/session_not_found_test.rb +2 -0
  27. data/acceptance/cases/tasks/database_tasks_test.rb +1 -0
  28. data/acceptance/models/binary_project.rb +20 -0
  29. data/acceptance/models/string_io.rb +28 -0
  30. data/acceptance/models/user.rb +20 -0
  31. data/acceptance/test_helper.rb +6 -1
  32. data/activerecord-spanner-adapter.gemspec +3 -3
  33. data/benchmarks/application.rb +3 -7
  34. data/examples/snippets/Rakefile +27 -5
  35. data/examples/snippets/array-data-type/application.rb +1 -5
  36. data/examples/snippets/array-data-type/config/database.yml +1 -0
  37. data/examples/snippets/bit-reversed-sequence/application.rb +0 -4
  38. data/examples/snippets/bit-reversed-sequence/config/database.yml +1 -0
  39. data/examples/snippets/bit-reversed-sequence/db/seeds.rb +2 -2
  40. data/examples/snippets/bulk-insert/application.rb +1 -5
  41. data/examples/snippets/bulk-insert/config/database.yml +1 -0
  42. data/examples/snippets/commit-timestamp/application.rb +0 -4
  43. data/examples/snippets/commit-timestamp/config/database.yml +1 -0
  44. data/examples/snippets/config/environment.rb +5 -0
  45. data/examples/snippets/create-records/application.rb +1 -5
  46. data/examples/snippets/create-records/config/database.yml +1 -0
  47. data/examples/snippets/date-data-type/application.rb +1 -5
  48. data/examples/snippets/date-data-type/config/database.yml +1 -0
  49. data/examples/snippets/date-data-type/db/seeds.rb +1 -1
  50. data/examples/snippets/generated-column/application.rb +0 -4
  51. data/examples/snippets/generated-column/config/database.yml +1 -0
  52. data/examples/snippets/generated-column/db/seeds.rb +1 -1
  53. data/examples/snippets/hints/application.rb +0 -4
  54. data/examples/snippets/hints/config/database.yml +1 -0
  55. data/examples/snippets/hints/db/seeds.rb +1 -1
  56. data/examples/snippets/interleaved-tables/application.rb +1 -5
  57. data/examples/snippets/interleaved-tables/config/database.yml +1 -0
  58. data/examples/snippets/interleaved-tables/db/seeds.rb +1 -1
  59. data/examples/snippets/interleaved-tables/models/album.rb +6 -2
  60. data/examples/snippets/interleaved-tables/models/track.rb +5 -1
  61. data/examples/snippets/interleaved-tables-before-7.1/application.rb +1 -5
  62. data/examples/snippets/interleaved-tables-before-7.1/config/database.yml +1 -0
  63. data/examples/snippets/interleaved-tables-before-7.1/db/seeds.rb +1 -1
  64. data/examples/snippets/migrations/application.rb +0 -4
  65. data/examples/snippets/migrations/config/database.yml +1 -0
  66. data/examples/snippets/mutations/application.rb +1 -5
  67. data/examples/snippets/mutations/config/database.yml +1 -0
  68. data/examples/snippets/mutations/db/seeds.rb +1 -1
  69. data/examples/snippets/optimistic-locking/application.rb +0 -4
  70. data/examples/snippets/optimistic-locking/config/database.yml +1 -0
  71. data/examples/snippets/optimistic-locking/db/seeds.rb +1 -1
  72. data/examples/snippets/partitioned-dml/application.rb +0 -4
  73. data/examples/snippets/partitioned-dml/config/database.yml +1 -0
  74. data/examples/snippets/partitioned-dml/db/seeds.rb +1 -1
  75. data/examples/snippets/query-logs/application.rb +15 -13
  76. data/examples/snippets/query-logs/config/database.yml +1 -0
  77. data/examples/snippets/query-logs/db/seeds.rb +1 -1
  78. data/examples/snippets/quickstart/application.rb +0 -4
  79. data/examples/snippets/quickstart/config/database.yml +1 -0
  80. data/examples/snippets/quickstart/db/seeds.rb +1 -1
  81. data/examples/snippets/read-only-transactions/application.rb +0 -4
  82. data/examples/snippets/read-only-transactions/config/database.yml +1 -0
  83. data/examples/snippets/read-only-transactions/db/seeds.rb +1 -1
  84. data/examples/snippets/read-write-transactions/application.rb +2 -6
  85. data/examples/snippets/read-write-transactions/config/database.yml +1 -0
  86. data/examples/snippets/read-write-transactions/db/seeds.rb +1 -1
  87. data/examples/snippets/stale-reads/application.rb +0 -4
  88. data/examples/snippets/stale-reads/config/database.yml +1 -0
  89. data/examples/snippets/stale-reads/db/seeds.rb +1 -1
  90. data/examples/snippets/tags/application.rb +0 -4
  91. data/examples/snippets/tags/config/database.yml +1 -0
  92. data/examples/snippets/tags/db/seeds.rb +1 -1
  93. data/examples/snippets/timestamp-data-type/application.rb +0 -4
  94. data/examples/snippets/timestamp-data-type/config/database.yml +1 -0
  95. data/lib/active_record/connection_adapters/spanner/column.rb +3 -3
  96. data/lib/active_record/connection_adapters/spanner/database_statements.rb +37 -23
  97. data/lib/active_record/connection_adapters/spanner/quoting.rb +19 -6
  98. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +7 -9
  99. data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +12 -2
  100. data/lib/active_record/connection_adapters/spanner/schema_statements.rb +28 -46
  101. data/lib/active_record/connection_adapters/spanner/type_metadata.rb +4 -6
  102. data/lib/active_record/connection_adapters/spanner_adapter.rb +54 -27
  103. data/lib/active_record/tasks/spanner_database_tasks.rb +4 -4
  104. data/lib/active_record/type/spanner/array.rb +4 -0
  105. data/lib/active_record/type/spanner/bytes.rb +10 -0
  106. data/lib/activerecord-spanner-adapter.rb +5 -1
  107. data/lib/activerecord_spanner_adapter/base.rb +58 -30
  108. data/lib/activerecord_spanner_adapter/connection.rb +9 -5
  109. data/lib/activerecord_spanner_adapter/foreign_key.rb +9 -2
  110. data/lib/activerecord_spanner_adapter/index/column.rb +6 -1
  111. data/lib/activerecord_spanner_adapter/index.rb +10 -2
  112. data/lib/activerecord_spanner_adapter/information_schema.rb +1 -1
  113. data/lib/activerecord_spanner_adapter/primary_key.rb +2 -2
  114. data/lib/activerecord_spanner_adapter/table/column.rb +12 -3
  115. data/lib/activerecord_spanner_adapter/table.rb +8 -2
  116. data/lib/activerecord_spanner_adapter/transaction.rb +1 -1
  117. data/lib/activerecord_spanner_adapter/version.rb +1 -1
  118. data/lib/arel/visitors/spanner.rb +16 -11
  119. data/lib/spanner_client_ext.rb +4 -3
  120. metadata +15 -34
  121. data/examples/snippets/array-data-type/db/schema.rb +0 -31
  122. data/examples/snippets/bit-reversed-sequence/db/schema.rb +0 -31
  123. data/examples/snippets/bulk-insert/db/schema.rb +0 -31
  124. data/examples/snippets/commit-timestamp/db/schema.rb +0 -34
  125. data/examples/snippets/create-records/db/schema.rb +0 -31
  126. data/examples/snippets/date-data-type/db/schema.rb +0 -26
  127. data/examples/snippets/generated-column/db/schema.rb +0 -26
  128. data/examples/snippets/hints/db/schema.rb +0 -33
  129. data/examples/snippets/interleaved-tables/db/schema.rb +0 -39
  130. data/examples/snippets/interleaved-tables-before-7.1/db/schema.rb +0 -37
  131. data/examples/snippets/migrations/db/schema.rb +0 -38
  132. data/examples/snippets/mutations/db/schema.rb +0 -32
  133. data/examples/snippets/optimistic-locking/db/schema.rb +0 -34
  134. data/examples/snippets/partitioned-dml/db/schema.rb +0 -31
  135. data/examples/snippets/query-logs/db/schema.rb +0 -31
  136. data/examples/snippets/quickstart/db/schema.rb +0 -31
  137. data/examples/snippets/read-only-transactions/db/schema.rb +0 -31
  138. data/examples/snippets/read-write-transactions/db/schema.rb +0 -32
  139. data/examples/snippets/stale-reads/db/schema.rb +0 -31
  140. data/examples/snippets/tags/db/schema.rb +0 -31
  141. 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._insert_record values, returning = []
52
- if !(buffered_mutations? || (primary_key && values.is_a?(Hash))) || !spanner_adapter?
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
- "to generate the primary key. #{self} uses #{sequence_name}."
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 = Hash[primary_key.zip(primary_key_value)]
103
- values = []
104
- keys.each do |column|
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 _attributes, **_kwargs
115
- raise NotImplementedError, "Cloud Spanner does not support skip_duplicates. Use insert! or upsert instead."
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
- _insert_record record
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
- _insert_record record
160
+ _internal_insert_record record
132
161
  end
133
162
  end
134
163
  end
135
164
  end
136
165
 
137
- def self.upsert_all attributes, returning: nil, unique_by: nil, **_kwargs
166
+ def self.upsert attributes, returning: nil, **kwargs
138
167
  return super unless spanner_adapter?
139
- if active_transaction? && !buffered_mutations?
140
- raise NotImplementedError, "Cloud Spanner does not support upsert using DML. " \
141
- "Use upsert outside a transaction block or in a transaction " \
142
- "block with isolation: :buffered_mutations"
143
- end
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
- primary_key_value = []
186
- primary_key.each do |col|
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
- serialized_values = []
389
- keys.each do |key|
390
- serialized_values << ActiveRecord::Type::Spanner::SpannerActiveRecordConverter
391
- .serialize_with_transaction_isolation_level(metadata.type(key),
392
- attribute_in_database(key),
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
- "WHERE #{pk_sql} AND `#{locking_column}` = @lock_version"
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, :database_id, :spanner
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: (current_transaction&.next_sequence_number)
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
- return current_transaction&.transaction_selector if current_transaction&.active?
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, :table_name, :name, :columns, :ref_schema, :ref_table, :ref_columns,
10
- :on_delete, :on_update
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, :schema_name, :index_name, :name, :order, :ordinal_position
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, :table, :name, :columns, :type, :unique, :null_filtered,
12
- :interleave_in, :storing, :state
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,
@@ -32,7 +32,7 @@ module ActiveRecordSpannerAdapter
32
32
 
33
33
  rows = execute_query(
34
34
  sql,
35
- schema_name: (schema_name || ""), table_name: table_name
35
+ schema_name: schema_name || "", table_name: table_name
36
36
  )
37
37
 
38
38
  rows.map do |row|
@@ -18,8 +18,8 @@ module ActiveRecord
18
18
  end
19
19
 
20
20
  def fetch_primary_and_parent_key
21
- return connection.spanner_schema_cache.primary_and_parent_keys table_name \
22
- if ActiveRecord::Base != self && table_exists?
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, :table_name, :name, :type, :limit, :ordinal_position,
11
- :allow_commit_timestamp, :default, :default_function, :generated,
12
- :primary_key, :nullable
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, :on_delete, :parent_table, :schema_name, :catalog,
34
- :indexes, :columns, :foreign_keys
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 # rubocop:disable Lint/HandleExceptions
126
+ rescue StandardError
127
127
  # Ignored
128
128
  end
129
129
 
@@ -5,5 +5,5 @@
5
5
  # https://opensource.org/licenses/MIT.
6
6
 
7
7
  module ActiveRecordSpannerAdapter
8
- VERSION = "1.6.3".freeze
8
+ VERSION = "2.0.0".freeze
9
9
  end
@@ -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
- binds << collector.hints[:staleness] if collector.hints[:staleness]
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
 
@@ -66,8 +66,8 @@ module Google
66
66
  ensure_service!
67
67
 
68
68
  snp_grpc = service.create_snapshot \
69
- path, timestamp: (timestamp || read_timestamp),
70
- staleness: (staleness || exact_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, :commit
108
+ attr_accessor :seqno
109
+ attr_accessor :commit
109
110
  end
110
111
  end
111
112
  end