activerecord 7.2.4 → 8.1.4

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1013 -878
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/association_relation.rb +2 -1
  5. data/lib/active_record/associations/association.rb +69 -27
  6. data/lib/active_record/associations/association_scope.rb +1 -1
  7. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  8. data/lib/active_record/associations/builder/association.rb +23 -11
  9. data/lib/active_record/associations/builder/belongs_to.rb +36 -8
  10. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  11. data/lib/active_record/associations/builder/has_one.rb +1 -1
  12. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  13. data/lib/active_record/associations/collection_association.rb +7 -3
  14. data/lib/active_record/associations/collection_proxy.rb +26 -4
  15. data/lib/active_record/associations/deprecation.rb +88 -0
  16. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  17. data/lib/active_record/associations/errors.rb +3 -0
  18. data/lib/active_record/associations/foreign_association.rb +3 -1
  19. data/lib/active_record/associations/has_many_through_association.rb +3 -2
  20. data/lib/active_record/associations/has_one_association.rb +1 -0
  21. data/lib/active_record/associations/join_dependency.rb +3 -2
  22. data/lib/active_record/associations/preloader/association.rb +3 -3
  23. data/lib/active_record/associations/preloader/batch.rb +7 -1
  24. data/lib/active_record/associations/preloader/branch.rb +1 -0
  25. data/lib/active_record/associations/singular_association.rb +8 -3
  26. data/lib/active_record/associations.rb +192 -24
  27. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  28. data/lib/active_record/attribute_methods/primary_key.rb +4 -8
  29. data/lib/active_record/attribute_methods/query.rb +34 -0
  30. data/lib/active_record/attribute_methods/serialization.rb +18 -5
  31. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
  32. data/lib/active_record/attributes.rb +3 -0
  33. data/lib/active_record/autosave_association.rb +69 -27
  34. data/lib/active_record/base.rb +1 -2
  35. data/lib/active_record/callbacks.rb +1 -2
  36. data/lib/active_record/coders/column_serializer.rb +1 -1
  37. data/lib/active_record/coders/json.rb +16 -6
  38. data/lib/active_record/coders/yaml_column.rb +2 -2
  39. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
  40. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  41. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -13
  42. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +429 -93
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +148 -74
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +124 -34
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +129 -63
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +132 -65
  53. data/lib/active_record/connection_adapters/column.rb +14 -4
  54. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
  55. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  56. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  57. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -66
  59. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
  60. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
  61. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  62. data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
  63. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +79 -61
  64. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  65. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  66. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
  67. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
  69. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  70. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  71. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
  72. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
  73. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +156 -68
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
  75. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  76. data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
  77. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
  78. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
  79. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  80. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
  81. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +15 -16
  82. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +104 -37
  83. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  84. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +41 -66
  85. data/lib/active_record/connection_adapters/trilogy_adapter.rb +15 -18
  86. data/lib/active_record/connection_adapters.rb +1 -56
  87. data/lib/active_record/connection_handling.rb +25 -2
  88. data/lib/active_record/core.rb +33 -17
  89. data/lib/active_record/counter_cache.rb +35 -8
  90. data/lib/active_record/database_configurations/database_config.rb +9 -1
  91. data/lib/active_record/database_configurations/hash_config.rb +74 -9
  92. data/lib/active_record/database_configurations/url_config.rb +15 -3
  93. data/lib/active_record/database_configurations.rb +7 -3
  94. data/lib/active_record/delegated_type.rb +1 -1
  95. data/lib/active_record/disable_joins_association_relation.rb +5 -1
  96. data/lib/active_record/dynamic_matchers.rb +54 -69
  97. data/lib/active_record/encryption/config.rb +3 -1
  98. data/lib/active_record/encryption/encryptable_record.rb +8 -8
  99. data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
  100. data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
  101. data/lib/active_record/encryption/encryptor.rb +28 -8
  102. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  103. data/lib/active_record/encryption/scheme.rb +9 -2
  104. data/lib/active_record/enum.rb +33 -30
  105. data/lib/active_record/errors.rb +33 -9
  106. data/lib/active_record/explain.rb +1 -1
  107. data/lib/active_record/explain_registry.rb +51 -2
  108. data/lib/active_record/filter_attribute_handler.rb +76 -0
  109. data/lib/active_record/fixtures.rb +2 -4
  110. data/lib/active_record/future_result.rb +15 -9
  111. data/lib/active_record/gem_version.rb +2 -2
  112. data/lib/active_record/inheritance.rb +9 -4
  113. data/lib/active_record/insert_all.rb +14 -9
  114. data/lib/active_record/locking/optimistic.rb +8 -1
  115. data/lib/active_record/locking/pessimistic.rb +5 -0
  116. data/lib/active_record/log_subscriber.rb +31 -29
  117. data/lib/active_record/message_pack.rb +13 -0
  118. data/lib/active_record/middleware/shard_selector.rb +34 -17
  119. data/lib/active_record/migration/command_recorder.rb +56 -13
  120. data/lib/active_record/migration/compatibility.rb +37 -24
  121. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  122. data/lib/active_record/migration.rb +48 -42
  123. data/lib/active_record/model_schema.rb +40 -15
  124. data/lib/active_record/nested_attributes.rb +14 -12
  125. data/lib/active_record/persistence.rb +163 -133
  126. data/lib/active_record/query_cache.rb +22 -15
  127. data/lib/active_record/query_logs.rb +100 -52
  128. data/lib/active_record/query_logs_formatter.rb +17 -28
  129. data/lib/active_record/querying.rb +21 -9
  130. data/lib/active_record/railtie.rb +35 -30
  131. data/lib/active_record/railties/controller_runtime.rb +11 -6
  132. data/lib/active_record/railties/databases.rake +26 -38
  133. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  134. data/lib/active_record/railties/job_runtime.rb +10 -11
  135. data/lib/active_record/reflection.rb +54 -22
  136. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  137. data/lib/active_record/relation/batches.rb +147 -73
  138. data/lib/active_record/relation/calculations.rb +60 -43
  139. data/lib/active_record/relation/delegation.rb +25 -15
  140. data/lib/active_record/relation/finder_methods.rb +73 -43
  141. data/lib/active_record/relation/merger.rb +12 -10
  142. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
  143. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
  144. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  145. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  146. data/lib/active_record/relation/predicate_builder.rb +23 -8
  147. data/lib/active_record/relation/query_attribute.rb +3 -1
  148. data/lib/active_record/relation/query_methods.rb +200 -96
  149. data/lib/active_record/relation/spawn_methods.rb +7 -7
  150. data/lib/active_record/relation/where_clause.rb +2 -9
  151. data/lib/active_record/relation.rb +127 -87
  152. data/lib/active_record/result.rb +109 -24
  153. data/lib/active_record/runtime_registry.rb +42 -58
  154. data/lib/active_record/sanitization.rb +9 -6
  155. data/lib/active_record/schema.rb +1 -1
  156. data/lib/active_record/schema_dumper.rb +17 -10
  157. data/lib/active_record/schema_migration.rb +2 -1
  158. data/lib/active_record/scoping/named.rb +5 -2
  159. data/lib/active_record/scoping.rb +0 -1
  160. data/lib/active_record/signed_id.rb +44 -16
  161. data/lib/active_record/statement_cache.rb +24 -20
  162. data/lib/active_record/store.rb +53 -22
  163. data/lib/active_record/structured_event_subscriber.rb +85 -0
  164. data/lib/active_record/table_metadata.rb +6 -23
  165. data/lib/active_record/tasks/abstract_tasks.rb +83 -0
  166. data/lib/active_record/tasks/database_tasks.rb +85 -85
  167. data/lib/active_record/tasks/mysql_database_tasks.rb +4 -58
  168. data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
  169. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
  170. data/lib/active_record/test_databases.rb +18 -4
  171. data/lib/active_record/test_fixtures.rb +52 -6
  172. data/lib/active_record/testing/query_assertions.rb +8 -2
  173. data/lib/active_record/timestamp.rb +4 -2
  174. data/lib/active_record/token_for.rb +1 -1
  175. data/lib/active_record/transaction.rb +2 -5
  176. data/lib/active_record/transactions.rb +56 -32
  177. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  178. data/lib/active_record/type/internal/timezone.rb +7 -0
  179. data/lib/active_record/type/json.rb +13 -2
  180. data/lib/active_record/type/serialized.rb +16 -4
  181. data/lib/active_record/type/type_map.rb +1 -1
  182. data/lib/active_record/type_caster/connection.rb +2 -1
  183. data/lib/active_record/validations/associated.rb +1 -1
  184. data/lib/active_record/validations/uniqueness.rb +8 -8
  185. data/lib/active_record.rb +85 -50
  186. data/lib/arel/alias_predication.rb +2 -0
  187. data/lib/arel/collectors/bind.rb +2 -2
  188. data/lib/arel/collectors/sql_string.rb +1 -1
  189. data/lib/arel/collectors/substitute_binds.rb +2 -2
  190. data/lib/arel/crud.rb +6 -11
  191. data/lib/arel/nodes/binary.rb +1 -1
  192. data/lib/arel/nodes/count.rb +2 -2
  193. data/lib/arel/nodes/function.rb +4 -10
  194. data/lib/arel/nodes/named_function.rb +2 -2
  195. data/lib/arel/nodes/node.rb +2 -2
  196. data/lib/arel/nodes/sql_literal.rb +1 -1
  197. data/lib/arel/nodes.rb +0 -2
  198. data/lib/arel/predications.rb +1 -3
  199. data/lib/arel/select_manager.rb +7 -2
  200. data/lib/arel/table.rb +3 -7
  201. data/lib/arel/visitors/dot.rb +0 -3
  202. data/lib/arel/visitors/postgresql.rb +55 -0
  203. data/lib/arel/visitors/sqlite.rb +55 -8
  204. data/lib/arel/visitors/to_sql.rb +4 -22
  205. data/lib/arel.rb +3 -1
  206. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  207. metadata +15 -12
  208. data/lib/active_record/explain_subscriber.rb +0 -34
  209. data/lib/active_record/normalization.rb +0 -163
  210. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
3
  require "active_record/connection_adapters/sql_type_metadata"
5
4
  require "active_record/connection_adapters/abstract/schema_dumper"
6
5
  require "active_record/connection_adapters/abstract/schema_creation"
7
6
  require "active_support/concurrency/null_lock"
8
7
  require "active_support/concurrency/load_interlock_aware_monitor"
8
+ require "active_support/concurrency/thread_monitor"
9
9
  require "arel/collectors/bind"
10
10
  require "arel/collectors/composite"
11
11
  require "arel/collectors/sql_string"
@@ -43,6 +43,7 @@ module ActiveRecord
43
43
 
44
44
  attr_reader :pool
45
45
  attr_reader :visitor, :owner, :logger, :lock
46
+ attr_reader :allow_preconnect # :nodoc:
46
47
  attr_accessor :pinned # :nodoc:
47
48
  alias :in_use? :owner
48
49
 
@@ -52,7 +53,11 @@ module ActiveRecord
52
53
  @pool = value
53
54
  end
54
55
 
55
- set_callback :checkin, :after, :enable_lazy_transactions!
56
+ def allow_preconnect=(value) # :nodoc:
57
+ @lock.synchronize do
58
+ @allow_preconnect = value
59
+ end
60
+ end
56
61
 
57
62
  def self.type_cast_config_to_integer(config)
58
63
  if config.is_a?(Integer)
@@ -121,7 +126,7 @@ module ActiveRecord
121
126
 
122
127
  # Opens a database console session.
123
128
  def self.dbconsole(config, options = {})
124
- raise NotImplementedError
129
+ raise NotImplementedError.new("#{self} should define `dbconsole` that accepts a db config and options to implement connecting to the db console")
125
130
  end
126
131
 
127
132
  def initialize(config_or_deprecated_connection, deprecated_logger = nil, deprecated_connection_options = nil, deprecated_config = nil) # :nodoc:
@@ -129,6 +134,7 @@ module ActiveRecord
129
134
 
130
135
  @raw_connection = nil
131
136
  @unconfigured_connection = nil
137
+ @connected_since = nil
132
138
 
133
139
  if config_or_deprecated_connection.is_a?(Hash)
134
140
  @config = config_or_deprecated_connection.symbolize_keys
@@ -141,6 +147,7 @@ module ActiveRecord
141
147
  # Soft-deprecated for now; we'll probably warn in future.
142
148
 
143
149
  @unconfigured_connection = config_or_deprecated_connection
150
+ @connected_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
144
151
  @logger = deprecated_logger || ActiveRecord::Base.logger
145
152
  if deprecated_config
146
153
  @config = (deprecated_config || {}).symbolize_keys
@@ -153,9 +160,9 @@ module ActiveRecord
153
160
 
154
161
  @owner = nil
155
162
  @pinned = false
156
- @instrumenter = ActiveSupport::Notifications.instrumenter
157
163
  @pool = ActiveRecord::ConnectionAdapters::NullPool.new
158
164
  @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
165
+ @allow_preconnect = false
159
166
  @visitor = arel_visitor
160
167
  @statements = build_statement_pool
161
168
  self.lock_thread = nil
@@ -173,6 +180,8 @@ module ActiveRecord
173
180
  @raw_connection_dirty = false
174
181
  @last_activity = nil
175
182
  @verified = false
183
+
184
+ @pool_jitter = rand * max_jitter
176
185
  end
177
186
 
178
187
  def inspect # :nodoc:
@@ -186,31 +195,23 @@ module ActiveRecord
186
195
  @lock =
187
196
  case lock_thread
188
197
  when Thread
189
- ActiveSupport::Concurrency::ThreadLoadInterlockAwareMonitor.new
198
+ ActiveSupport::Concurrency::ThreadMonitor.new
190
199
  when Fiber
191
- ActiveSupport::Concurrency::LoadInterlockAwareMonitor.new
200
+ ::Monitor.new
192
201
  else
193
202
  ActiveSupport::Concurrency::NullLock
194
203
  end
195
204
  end
196
205
 
197
- EXCEPTION_NEVER = { Exception => :never }.freeze # :nodoc:
198
- EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze # :nodoc:
199
- private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
200
- def with_instrumenter(instrumenter, &block) # :nodoc:
201
- Thread.handle_interrupt(EXCEPTION_NEVER) do
202
- previous_instrumenter = @instrumenter
203
- @instrumenter = instrumenter
204
- Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
205
- ensure
206
- @instrumenter = previous_instrumenter
206
+ def ensure_writes_are_allowed(sql) # :nodoc:
207
+ if preventing_writes?
208
+ raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
207
209
  end
208
210
  end
209
211
 
210
- def check_if_write_query(sql) # :nodoc:
211
- if preventing_writes? && write_query?(sql)
212
- raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
213
- end
212
+ MAX_JITTER = 0.0..1.0 # :nodoc:
213
+ def max_jitter
214
+ (@config[:pool_jitter] || 0.2).to_f.clamp(MAX_JITTER)
214
215
  end
215
216
 
216
217
  def replica?
@@ -243,9 +244,9 @@ module ActiveRecord
243
244
  # the value of +current_preventing_writes+.
244
245
  def preventing_writes?
245
246
  return true if replica?
246
- return false if connection_class.nil?
247
+ return false if connection_descriptor.nil?
247
248
 
248
- connection_class.current_preventing_writes
249
+ connection_descriptor.current_preventing_writes
249
250
  end
250
251
 
251
252
  def prepared_statements?
@@ -277,7 +278,11 @@ module ActiveRecord
277
278
  end
278
279
 
279
280
  def valid_type?(type) # :nodoc:
280
- !native_database_types[type].nil?
281
+ self.class.valid_type?(type)
282
+ end
283
+
284
+ def native_database_types # :nodoc:
285
+ self.class.native_database_types
281
286
  end
282
287
 
283
288
  # this method must only be called while holding connection pool's mutex
@@ -296,8 +301,8 @@ module ActiveRecord
296
301
  @owner = ActiveSupport::IsolatedExecutionState.context
297
302
  end
298
303
 
299
- def connection_class # :nodoc:
300
- @pool.connection_class
304
+ def connection_descriptor # :nodoc:
305
+ @pool.connection_descriptor
301
306
  end
302
307
 
303
308
  # The role (e.g. +:writing+) for the current connection. In a
@@ -316,8 +321,12 @@ module ActiveRecord
316
321
  @pool.schema_cache || (@schema_cache ||= BoundSchemaReflection.for_lone_connection(@pool.schema_reflection, self))
317
322
  end
318
323
 
324
+ def pool_jitter(duration)
325
+ duration * (1.0 - @pool_jitter)
326
+ end
327
+
319
328
  # this method must only be called while holding connection pool's mutex
320
- def expire
329
+ def expire(update_idle = true) # :nodoc:
321
330
  if in_use?
322
331
  if @owner != ActiveSupport::IsolatedExecutionState.context
323
332
  raise ActiveRecordError, "Cannot expire connection, " \
@@ -325,8 +334,12 @@ module ActiveRecord
325
334
  "Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
326
335
  end
327
336
 
328
- @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
329
- @owner = nil
337
+ _run_checkin_callbacks do
338
+ @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC) if update_idle
339
+ @owner = nil
340
+ enable_lazy_transactions!
341
+ unset_query_cache!
342
+ end
330
343
  else
331
344
  raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
332
345
  end
@@ -358,6 +371,21 @@ module ActiveRecord
358
371
  end
359
372
  end
360
373
 
374
+ # Seconds since this connection was established. nil if not
375
+ # connected; infinity if the connection has been explicitly
376
+ # retired.
377
+ def connection_age # :nodoc:
378
+ if @raw_connection && @connected_since
379
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - @connected_since
380
+ end
381
+ end
382
+
383
+ # Mark the connection as needing to be retired, as if the age has
384
+ # exceeded the maximum allowed.
385
+ def force_retirement # :nodoc:
386
+ @connected_since &&= -Float::INFINITY
387
+ end
388
+
361
389
  def unprepared_statement
362
390
  cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
363
391
  yield
@@ -572,6 +600,10 @@ module ActiveRecord
572
600
  false
573
601
  end
574
602
 
603
+ def supports_disabling_indexes?
604
+ false
605
+ end
606
+
575
607
  def return_value_after_insert?(column) # :nodoc:
576
608
  column.auto_populated?
577
609
  end
@@ -590,23 +622,36 @@ module ActiveRecord
590
622
  end
591
623
 
592
624
  # This is meant to be implemented by the adapters that support custom enum types
593
- def create_enum(*) # :nodoc:
625
+ def create_enum(...) # :nodoc:
594
626
  end
595
627
 
596
628
  # This is meant to be implemented by the adapters that support custom enum types
597
- def drop_enum(*) # :nodoc:
629
+ def drop_enum(...) # :nodoc:
598
630
  end
599
631
 
600
632
  # This is meant to be implemented by the adapters that support custom enum types
601
- def rename_enum(*) # :nodoc:
633
+ def rename_enum(...) # :nodoc:
602
634
  end
603
635
 
604
636
  # This is meant to be implemented by the adapters that support custom enum types
605
- def add_enum_value(*) # :nodoc:
637
+ def add_enum_value(...) # :nodoc:
606
638
  end
607
639
 
608
640
  # This is meant to be implemented by the adapters that support custom enum types
609
- def rename_enum_value(*) # :nodoc:
641
+ def rename_enum_value(...) # :nodoc:
642
+ end
643
+
644
+ # This is meant to be implemented by the adapters that support virtual tables
645
+ def create_virtual_table(*) # :nodoc:
646
+ end
647
+
648
+ # This is meant to be implemented by the adapters that support virtual tables
649
+ def drop_virtual_table(*) # :nodoc:
650
+ end
651
+
652
+ # Lock used to read an existing record after a duplicate INSERT in a transaction.
653
+ def create_or_find_by_lock # :nodoc:
654
+ true
610
655
  end
611
656
 
612
657
  def advisory_locks_enabled? # :nodoc:
@@ -674,12 +719,15 @@ module ActiveRecord
674
719
 
675
720
  @lock.synchronize do
676
721
  attempt_configure_connection do
722
+ @allow_preconnect = false
723
+
677
724
  reconnect
678
725
 
679
726
  enable_lazy_transactions!
680
727
  @raw_connection_dirty = false
681
- @last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
728
+ @last_activity = @connected_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
682
729
  @verified = true
730
+ @allow_preconnect = true
683
731
 
684
732
  reset_transaction(restore: restore_transactions) do
685
733
  clear_cache!(new_connection: true)
@@ -707,11 +755,12 @@ module ActiveRecord
707
755
  # method does nothing.
708
756
  def disconnect!
709
757
  @lock.synchronize do
710
- @last_activity = nil
711
- @verified = false
712
758
  clear_cache!(new_connection: true)
713
759
  reset_transaction
714
760
  @raw_connection_dirty = false
761
+ @connected_since = nil
762
+ @last_activity = nil
763
+ @verified = false
715
764
  end
716
765
  end
717
766
 
@@ -778,6 +827,7 @@ module ActiveRecord
778
827
  configure_connection
779
828
  @last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
780
829
  @verified = true
830
+ @allow_preconnect = true
781
831
  end
782
832
  return
783
833
  end
@@ -786,6 +836,7 @@ module ActiveRecord
786
836
  end
787
837
  end
788
838
 
839
+ @last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
789
840
  @verified = true
790
841
  end
791
842
 
@@ -795,8 +846,15 @@ module ActiveRecord
795
846
  end
796
847
 
797
848
  def clean! # :nodoc:
798
- @raw_connection_dirty = false
799
- @verified = nil
849
+ _run_checkout_callbacks do
850
+ @raw_connection_dirty = false
851
+ @verified = nil
852
+ end
853
+ self
854
+ end
855
+
856
+ def verified? # :nodoc:
857
+ @verified
800
858
  end
801
859
 
802
860
  # Provides access to the underlying database driver for this adapter. For
@@ -884,7 +942,7 @@ module ActiveRecord
884
942
  def register_class_with_precision(mapping, key, klass, **kwargs) # :nodoc:
885
943
  mapping.register_type(key) do |*args|
886
944
  precision = extract_precision(args.last)
887
- klass.new(precision: precision, **kwargs)
945
+ klass.new(precision: precision, **kwargs).freeze
888
946
  end
889
947
  end
890
948
 
@@ -896,6 +954,10 @@ module ActiveRecord
896
954
  end
897
955
  end
898
956
 
957
+ def valid_type?(type) # :nodoc:
958
+ !native_database_types[type].nil?
959
+ end
960
+
899
961
  private
900
962
  def initialize_type_map(m)
901
963
  register_class_with_limit m, %r(boolean)i, Type::Boolean
@@ -915,7 +977,7 @@ module ActiveRecord
915
977
  m.alias_type %r(number)i, "decimal"
916
978
  m.alias_type %r(double)i, "float"
917
979
 
918
- m.register_type %r(^json)i, Type::Json.new
980
+ m.register_type %r(^json)i, Type::Json.new.freeze
919
981
 
920
982
  m.register_type(%r(decimal)i) do |sql_type|
921
983
  scale = extract_scale(sql_type)
@@ -923,9 +985,9 @@ module ActiveRecord
923
985
 
924
986
  if scale == 0
925
987
  # FIXME: Remove this class as well
926
- Type::DecimalWithoutScale.new(precision: precision)
988
+ Type::DecimalWithoutScale.new(precision: precision).freeze
927
989
  else
928
- Type::Decimal.new(precision: precision, scale: scale)
990
+ Type::Decimal.new(precision: precision, scale: scale).freeze
929
991
  end
930
992
  end
931
993
  end
@@ -933,7 +995,7 @@ module ActiveRecord
933
995
  def register_class_with_limit(mapping, key, klass)
934
996
  mapping.register_type(key) do |*args|
935
997
  limit = extract_limit(args.last)
936
- klass.new(limit: limit)
998
+ klass.new(limit: limit).freeze
937
999
  end
938
1000
  end
939
1001
 
@@ -1056,6 +1118,13 @@ module ActiveRecord
1056
1118
  end
1057
1119
 
1058
1120
  raise translated_exception
1121
+ rescue Exception
1122
+ # A non-StandardError (a Timeout, or a fiber scheduler's cancel) abandoned
1123
+ # the query partway through, so we mark the connection unverified, just as
1124
+ # a failed query would, forcing a reconnect before it's used again.
1125
+ @last_activity = nil
1126
+ @verified = false
1127
+ raise
1059
1128
  ensure
1060
1129
  dirty_current_transaction if materialize_transactions
1061
1130
  end
@@ -1071,7 +1140,8 @@ module ActiveRecord
1071
1140
  end
1072
1141
 
1073
1142
  def retryable_connection_error?(exception)
1074
- exception.is_a?(ConnectionNotEstablished) || exception.is_a?(ConnectionFailed)
1143
+ (exception.is_a?(ConnectionNotEstablished) && !exception.is_a?(ConnectionNotDefined)) ||
1144
+ exception.is_a?(ConnectionFailed)
1075
1145
  end
1076
1146
 
1077
1147
  def invalidate_transaction(exception)
@@ -1093,7 +1163,7 @@ module ActiveRecord
1093
1163
  end
1094
1164
 
1095
1165
  def reconnect
1096
- raise NotImplementedError
1166
+ raise NotImplementedError.new("#{self.class} should define `reconnect` to implement adapter-specific logic for reconnecting to the database")
1097
1167
  end
1098
1168
 
1099
1169
  # Returns a raw connection for internal use with methods that are known
@@ -1132,27 +1202,30 @@ module ActiveRecord
1132
1202
  end
1133
1203
  end
1134
1204
 
1135
- def translate_exception_class(e, sql, binds)
1136
- message = "#{e.class.name}: #{e.message}"
1205
+ def translate_exception_class(native_error, sql, binds)
1206
+ return native_error if native_error.is_a?(ActiveRecordError)
1207
+
1208
+ message = "#{native_error.class.name}: #{native_error.message}"
1137
1209
 
1138
- exception = translate_exception(
1139
- e, message: message, sql: sql, binds: binds
1210
+ active_record_error = translate_exception(
1211
+ native_error, message: message, sql: sql, binds: binds
1140
1212
  )
1141
- exception.set_backtrace e.backtrace
1142
- exception
1213
+ active_record_error.set_backtrace(native_error.backtrace)
1214
+ active_record_error
1143
1215
  end
1144
1216
 
1145
- def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) # :doc:
1146
- @instrumenter.instrument(
1217
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, allow_retry: false, &block) # :doc:
1218
+ instrumenter.instrument(
1147
1219
  "sql.active_record",
1148
1220
  sql: sql,
1149
1221
  name: name,
1150
1222
  binds: binds,
1151
1223
  type_casted_binds: type_casted_binds,
1152
- statement_name: statement_name,
1153
1224
  async: async,
1225
+ allow_retry: allow_retry,
1154
1226
  connection: self,
1155
1227
  transaction: current_transaction.user_transaction.presence,
1228
+ affected_rows: 0,
1156
1229
  row_count: 0,
1157
1230
  &block
1158
1231
  )
@@ -1160,11 +1233,8 @@ module ActiveRecord
1160
1233
  raise ex.set_query(sql, binds)
1161
1234
  end
1162
1235
 
1163
- def transform_query(sql)
1164
- ActiveRecord.query_transformers.each do |transformer|
1165
- sql = transformer.call(sql, self)
1166
- end
1167
- sql
1236
+ def instrumenter # :nodoc:
1237
+ ActiveSupport::IsolatedExecutionState[:active_record_instrumenter] ||= ActiveSupport::Notifications.instrumenter
1168
1238
  end
1169
1239
 
1170
1240
  def translate_exception(exception, message:, sql:, binds:)
@@ -1177,10 +1247,6 @@ module ActiveRecord
1177
1247
  end
1178
1248
  end
1179
1249
 
1180
- def without_prepared_statement?(binds)
1181
- !prepared_statements || binds.empty?
1182
- end
1183
-
1184
1250
  def column_for(table_name, column_name)
1185
1251
  column_name = column_name.to_s
1186
1252
  columns(table_name).detect { |c| c.name == column_name } ||