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.
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