activerecord 7.2.3 → 8.1.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +612 -1055
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +1 -1
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +16 -3
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attributes.rb +3 -0
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/base.rb +1 -2
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +412 -88
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +137 -75
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -32
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +150 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -52
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +139 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +102 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +25 -2
- data/lib/active_record/core.rb +33 -17
- data/lib/active_record/counter_cache.rb +33 -8
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +8 -8
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encryptor.rb +28 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +33 -30
- data/lib/active_record/errors.rb +33 -9
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +73 -0
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +15 -9
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +45 -12
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +48 -42
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +100 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +8 -8
- data/lib/active_record/railtie.rb +35 -30
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -38
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +52 -40
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +40 -24
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +140 -86
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +2 -9
- data/lib/active_record/relation.rb +107 -75
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +18 -11
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/signed_id.rb +43 -15
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +37 -16
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +84 -49
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +6 -11
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +7 -2
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/dot.rb +0 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +3 -21
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -13
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- 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
|
-
|
|
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::
|
|
198
|
+
ActiveSupport::Concurrency::ThreadMonitor.new
|
|
190
199
|
when Fiber
|
|
191
|
-
|
|
200
|
+
::Monitor.new
|
|
192
201
|
else
|
|
193
202
|
ActiveSupport::Concurrency::NullLock
|
|
194
203
|
end
|
|
195
204
|
end
|
|
196
205
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
|
247
|
+
return false if connection_descriptor.nil?
|
|
247
248
|
|
|
248
|
-
|
|
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
|
-
|
|
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
|
|
300
|
-
@pool.
|
|
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
|
-
|
|
329
|
-
|
|
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,31 @@ 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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
610
650
|
end
|
|
611
651
|
|
|
612
652
|
def advisory_locks_enabled? # :nodoc:
|
|
@@ -673,34 +713,36 @@ module ActiveRecord
|
|
|
673
713
|
deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
|
|
674
714
|
|
|
675
715
|
@lock.synchronize do
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
enable_lazy_transactions!
|
|
679
|
-
@raw_connection_dirty = false
|
|
680
|
-
@last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
681
|
-
@verified = true
|
|
716
|
+
attempt_configure_connection do
|
|
717
|
+
@allow_preconnect = false
|
|
682
718
|
|
|
683
|
-
|
|
684
|
-
clear_cache!(new_connection: true)
|
|
685
|
-
attempt_configure_connection
|
|
686
|
-
end
|
|
687
|
-
rescue => original_exception
|
|
688
|
-
translated_exception = translate_exception_class(original_exception, nil, nil)
|
|
689
|
-
retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
719
|
+
reconnect
|
|
690
720
|
|
|
691
|
-
|
|
692
|
-
|
|
721
|
+
enable_lazy_transactions!
|
|
722
|
+
@raw_connection_dirty = false
|
|
723
|
+
@last_activity = @connected_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
724
|
+
@verified = true
|
|
725
|
+
@allow_preconnect = true
|
|
693
726
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
727
|
+
reset_transaction(restore: restore_transactions) do
|
|
728
|
+
clear_cache!(new_connection: true)
|
|
729
|
+
configure_connection
|
|
697
730
|
end
|
|
698
|
-
|
|
731
|
+
rescue => original_exception
|
|
732
|
+
translated_exception = translate_exception_class(original_exception, nil, nil)
|
|
733
|
+
retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
699
734
|
|
|
700
|
-
|
|
701
|
-
|
|
735
|
+
if !retry_deadline_exceeded && retries_available > 0
|
|
736
|
+
retries_available -= 1
|
|
737
|
+
|
|
738
|
+
if retryable_connection_error?(translated_exception)
|
|
739
|
+
backoff(connection_retries - retries_available)
|
|
740
|
+
retry
|
|
741
|
+
end
|
|
742
|
+
end
|
|
702
743
|
|
|
703
|
-
|
|
744
|
+
raise translated_exception
|
|
745
|
+
end
|
|
704
746
|
end
|
|
705
747
|
end
|
|
706
748
|
|
|
@@ -711,6 +753,9 @@ module ActiveRecord
|
|
|
711
753
|
clear_cache!(new_connection: true)
|
|
712
754
|
reset_transaction
|
|
713
755
|
@raw_connection_dirty = false
|
|
756
|
+
@connected_since = nil
|
|
757
|
+
@last_activity = nil
|
|
758
|
+
@verified = false
|
|
714
759
|
end
|
|
715
760
|
end
|
|
716
761
|
|
|
@@ -733,9 +778,11 @@ module ActiveRecord
|
|
|
733
778
|
# should call super immediately after resetting the connection (and while
|
|
734
779
|
# still holding @lock).
|
|
735
780
|
def reset!
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
781
|
+
attempt_configure_connection do
|
|
782
|
+
clear_cache!(new_connection: true)
|
|
783
|
+
reset_transaction
|
|
784
|
+
configure_connection
|
|
785
|
+
end
|
|
739
786
|
end
|
|
740
787
|
|
|
741
788
|
# Removes the connection from the pool and disconnect it.
|
|
@@ -769,11 +816,14 @@ module ActiveRecord
|
|
|
769
816
|
unless active?
|
|
770
817
|
@lock.synchronize do
|
|
771
818
|
if @unconfigured_connection
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
819
|
+
attempt_configure_connection do
|
|
820
|
+
@raw_connection = @unconfigured_connection
|
|
821
|
+
@unconfigured_connection = nil
|
|
822
|
+
configure_connection
|
|
823
|
+
@last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
824
|
+
@verified = true
|
|
825
|
+
@allow_preconnect = true
|
|
826
|
+
end
|
|
777
827
|
return
|
|
778
828
|
end
|
|
779
829
|
|
|
@@ -781,6 +831,7 @@ module ActiveRecord
|
|
|
781
831
|
end
|
|
782
832
|
end
|
|
783
833
|
|
|
834
|
+
@last_activity = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
784
835
|
@verified = true
|
|
785
836
|
end
|
|
786
837
|
|
|
@@ -790,8 +841,15 @@ module ActiveRecord
|
|
|
790
841
|
end
|
|
791
842
|
|
|
792
843
|
def clean! # :nodoc:
|
|
793
|
-
|
|
794
|
-
|
|
844
|
+
_run_checkout_callbacks do
|
|
845
|
+
@raw_connection_dirty = false
|
|
846
|
+
@verified = nil
|
|
847
|
+
end
|
|
848
|
+
self
|
|
849
|
+
end
|
|
850
|
+
|
|
851
|
+
def verified? # :nodoc:
|
|
852
|
+
@verified
|
|
795
853
|
end
|
|
796
854
|
|
|
797
855
|
# Provides access to the underlying database driver for this adapter. For
|
|
@@ -879,7 +937,7 @@ module ActiveRecord
|
|
|
879
937
|
def register_class_with_precision(mapping, key, klass, **kwargs) # :nodoc:
|
|
880
938
|
mapping.register_type(key) do |*args|
|
|
881
939
|
precision = extract_precision(args.last)
|
|
882
|
-
klass.new(precision: precision, **kwargs)
|
|
940
|
+
klass.new(precision: precision, **kwargs).freeze
|
|
883
941
|
end
|
|
884
942
|
end
|
|
885
943
|
|
|
@@ -891,6 +949,10 @@ module ActiveRecord
|
|
|
891
949
|
end
|
|
892
950
|
end
|
|
893
951
|
|
|
952
|
+
def valid_type?(type) # :nodoc:
|
|
953
|
+
!native_database_types[type].nil?
|
|
954
|
+
end
|
|
955
|
+
|
|
894
956
|
private
|
|
895
957
|
def initialize_type_map(m)
|
|
896
958
|
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
|
@@ -910,7 +972,7 @@ module ActiveRecord
|
|
|
910
972
|
m.alias_type %r(number)i, "decimal"
|
|
911
973
|
m.alias_type %r(double)i, "float"
|
|
912
974
|
|
|
913
|
-
m.register_type %r(^json)i, Type::Json.new
|
|
975
|
+
m.register_type %r(^json)i, Type::Json.new.freeze
|
|
914
976
|
|
|
915
977
|
m.register_type(%r(decimal)i) do |sql_type|
|
|
916
978
|
scale = extract_scale(sql_type)
|
|
@@ -918,9 +980,9 @@ module ActiveRecord
|
|
|
918
980
|
|
|
919
981
|
if scale == 0
|
|
920
982
|
# FIXME: Remove this class as well
|
|
921
|
-
Type::DecimalWithoutScale.new(precision: precision)
|
|
983
|
+
Type::DecimalWithoutScale.new(precision: precision).freeze
|
|
922
984
|
else
|
|
923
|
-
Type::Decimal.new(precision: precision, scale: scale)
|
|
985
|
+
Type::Decimal.new(precision: precision, scale: scale).freeze
|
|
924
986
|
end
|
|
925
987
|
end
|
|
926
988
|
end
|
|
@@ -928,7 +990,7 @@ module ActiveRecord
|
|
|
928
990
|
def register_class_with_limit(mapping, key, klass)
|
|
929
991
|
mapping.register_type(key) do |*args|
|
|
930
992
|
limit = extract_limit(args.last)
|
|
931
|
-
klass.new(limit: limit)
|
|
993
|
+
klass.new(limit: limit).freeze
|
|
932
994
|
end
|
|
933
995
|
end
|
|
934
996
|
|
|
@@ -1066,7 +1128,8 @@ module ActiveRecord
|
|
|
1066
1128
|
end
|
|
1067
1129
|
|
|
1068
1130
|
def retryable_connection_error?(exception)
|
|
1069
|
-
exception.is_a?(ConnectionNotEstablished)
|
|
1131
|
+
(exception.is_a?(ConnectionNotEstablished) && !exception.is_a?(ConnectionNotDefined)) ||
|
|
1132
|
+
exception.is_a?(ConnectionFailed)
|
|
1070
1133
|
end
|
|
1071
1134
|
|
|
1072
1135
|
def invalidate_transaction(exception)
|
|
@@ -1088,7 +1151,7 @@ module ActiveRecord
|
|
|
1088
1151
|
end
|
|
1089
1152
|
|
|
1090
1153
|
def reconnect
|
|
1091
|
-
raise NotImplementedError
|
|
1154
|
+
raise NotImplementedError.new("#{self.class} should define `reconnect` to implement adapter-specific logic for reconnecting to the database")
|
|
1092
1155
|
end
|
|
1093
1156
|
|
|
1094
1157
|
# Returns a raw connection for internal use with methods that are known
|
|
@@ -1127,27 +1190,30 @@ module ActiveRecord
|
|
|
1127
1190
|
end
|
|
1128
1191
|
end
|
|
1129
1192
|
|
|
1130
|
-
def translate_exception_class(
|
|
1131
|
-
|
|
1193
|
+
def translate_exception_class(native_error, sql, binds)
|
|
1194
|
+
return native_error if native_error.is_a?(ActiveRecordError)
|
|
1132
1195
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1196
|
+
message = "#{native_error.class.name}: #{native_error.message}"
|
|
1197
|
+
|
|
1198
|
+
active_record_error = translate_exception(
|
|
1199
|
+
native_error, message: message, sql: sql, binds: binds
|
|
1135
1200
|
)
|
|
1136
|
-
|
|
1137
|
-
|
|
1201
|
+
active_record_error.set_backtrace(native_error.backtrace)
|
|
1202
|
+
active_record_error
|
|
1138
1203
|
end
|
|
1139
1204
|
|
|
1140
|
-
def log(sql, name = "SQL", binds = [], type_casted_binds = [],
|
|
1141
|
-
|
|
1205
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, allow_retry: false, &block) # :doc:
|
|
1206
|
+
instrumenter.instrument(
|
|
1142
1207
|
"sql.active_record",
|
|
1143
1208
|
sql: sql,
|
|
1144
1209
|
name: name,
|
|
1145
1210
|
binds: binds,
|
|
1146
1211
|
type_casted_binds: type_casted_binds,
|
|
1147
|
-
statement_name: statement_name,
|
|
1148
1212
|
async: async,
|
|
1213
|
+
allow_retry: allow_retry,
|
|
1149
1214
|
connection: self,
|
|
1150
1215
|
transaction: current_transaction.user_transaction.presence,
|
|
1216
|
+
affected_rows: 0,
|
|
1151
1217
|
row_count: 0,
|
|
1152
1218
|
&block
|
|
1153
1219
|
)
|
|
@@ -1155,11 +1221,8 @@ module ActiveRecord
|
|
|
1155
1221
|
raise ex.set_query(sql, binds)
|
|
1156
1222
|
end
|
|
1157
1223
|
|
|
1158
|
-
def
|
|
1159
|
-
|
|
1160
|
-
sql = transformer.call(sql, self)
|
|
1161
|
-
end
|
|
1162
|
-
sql
|
|
1224
|
+
def instrumenter # :nodoc:
|
|
1225
|
+
ActiveSupport::IsolatedExecutionState[:active_record_instrumenter] ||= ActiveSupport::Notifications.instrumenter
|
|
1163
1226
|
end
|
|
1164
1227
|
|
|
1165
1228
|
def translate_exception(exception, message:, sql:, binds:)
|
|
@@ -1172,10 +1235,6 @@ module ActiveRecord
|
|
|
1172
1235
|
end
|
|
1173
1236
|
end
|
|
1174
1237
|
|
|
1175
|
-
def without_prepared_statement?(binds)
|
|
1176
|
-
!prepared_statements || binds.empty?
|
|
1177
|
-
end
|
|
1178
|
-
|
|
1179
1238
|
def column_for(table_name, column_name)
|
|
1180
1239
|
column_name = column_name.to_s
|
|
1181
1240
|
columns(table_name).detect { |c| c.name == column_name } ||
|
|
@@ -1228,7 +1287,7 @@ module ActiveRecord
|
|
|
1228
1287
|
end
|
|
1229
1288
|
|
|
1230
1289
|
def attempt_configure_connection
|
|
1231
|
-
|
|
1290
|
+
yield
|
|
1232
1291
|
rescue Exception # Need to handle things such as Timeout::ExitException
|
|
1233
1292
|
disconnect!
|
|
1234
1293
|
raise
|