activerecord 7.0.8.7 → 7.2.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 +781 -1777
- data/MIT-LICENSE +1 -1
- data/README.rdoc +30 -30
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +31 -23
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +40 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +35 -21
- data/lib/active_record/associations/collection_proxy.rb +29 -11
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +21 -14
- data/lib/active_record/associations/has_many_through_association.rb +17 -7
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -3
- data/lib/active_record/associations/join_dependency.rb +10 -10
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +354 -485
- data/lib/active_record/attribute_assignment.rb +0 -4
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +131 -32
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +153 -33
- data/lib/active_record/attributes.rb +96 -71
- data/lib/active_record/autosave_association.rb +81 -39
- data/lib/active_record/base.rb +11 -7
- data/lib/active_record/callbacks.rb +11 -25
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +123 -131
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +343 -91
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +229 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -63
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +142 -12
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +539 -111
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +289 -128
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +26 -139
- data/lib/active_record/connection_adapters/mysql/quoting.rb +60 -55
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +25 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +108 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +100 -43
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +65 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +371 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +374 -203
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +57 -45
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +14 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +51 -8
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +298 -113
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +101 -105
- data/lib/active_record/core.rb +273 -178
- data/lib/active_record/counter_cache.rb +69 -35
- data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -3
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +87 -34
- data/lib/active_record/delegated_type.rb +56 -27
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +46 -22
- data/lib/active_record/encryption/encrypted_attribute_type.rb +48 -13
- data/lib/active_record/encryption/encryptor.rb +35 -19
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -69
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +22 -21
- data/lib/active_record/encryption.rb +3 -0
- data/lib/active_record/enum.rb +130 -28
- data/lib/active_record/errors.rb +154 -34
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +48 -10
- data/lib/active_record/fixtures.rb +167 -97
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +11 -8
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +18 -22
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +106 -8
- data/lib/active_record/migration/compatibility.rb +147 -5
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +236 -118
- data/lib/active_record/model_schema.rb +90 -102
- data/lib/active_record/nested_attributes.rb +48 -11
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +168 -339
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -25
- data/lib/active_record/query_logs.rb +96 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +35 -10
- data/lib/active_record/railtie.rb +131 -87
- data/lib/active_record/railties/controller_runtime.rb +22 -7
- data/lib/active_record/railties/databases.rake +147 -155
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +267 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +270 -108
- data/lib/active_record/relation/delegation.rb +30 -19
- data/lib/active_record/relation/finder_methods.rb +97 -21
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +3 -2
- data/lib/active_record/relation/query_methods.rb +585 -109
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +15 -21
- data/lib/active_record/relation.rb +592 -92
- data/lib/active_record/result.rb +49 -48
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +70 -25
- data/lib/active_record/schema.rb +8 -7
- data/lib/active_record/schema_dumper.rb +90 -23
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +3 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +33 -11
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +190 -118
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +23 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +170 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +108 -24
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +61 -11
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +247 -33
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +3 -1
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/crud.rb +2 -0
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +7 -3
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +7 -1
- data/lib/arel/visitors/dot.rb +3 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +114 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +56 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -10,35 +10,50 @@ require "active_record/connection_adapters/abstract/connection_pool/reaper"
|
|
|
10
10
|
module ActiveRecord
|
|
11
11
|
module ConnectionAdapters
|
|
12
12
|
module AbstractPool # :nodoc:
|
|
13
|
-
|
|
14
|
-
self.schema_cache ||= SchemaCache.new(connection)
|
|
15
|
-
schema_cache.connection = connection
|
|
16
|
-
schema_cache
|
|
17
|
-
end
|
|
13
|
+
end
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
end
|
|
15
|
+
class NullPool # :nodoc:
|
|
16
|
+
include ConnectionAdapters::AbstractPool
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
class NullConfig # :nodoc:
|
|
19
|
+
def method_missing(...)
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
NULL_CONFIG = NullConfig.new # :nodoc:
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
def initialize
|
|
26
|
+
super()
|
|
27
|
+
@mutex = Mutex.new
|
|
28
|
+
@server_version = nil
|
|
28
29
|
end
|
|
29
|
-
end
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
def server_version(connection) # :nodoc:
|
|
32
|
+
@server_version || @mutex.synchronize { @server_version ||= connection.get_database_version }
|
|
33
|
+
end
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
def schema_reflection
|
|
36
|
+
SchemaReflection.new(nil)
|
|
37
|
+
end
|
|
35
38
|
|
|
39
|
+
def schema_cache; end
|
|
36
40
|
def connection_class; end
|
|
41
|
+
def query_cache; end
|
|
37
42
|
def checkin(_); end
|
|
38
43
|
def remove(_); end
|
|
39
44
|
def async_executor; end
|
|
45
|
+
|
|
46
|
+
def db_config
|
|
47
|
+
NULL_CONFIG
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def dirties_query_cache
|
|
51
|
+
true
|
|
52
|
+
end
|
|
40
53
|
end
|
|
41
54
|
|
|
55
|
+
# = Active Record Connection Pool
|
|
56
|
+
#
|
|
42
57
|
# Connection pool base class for managing Active Record database
|
|
43
58
|
# connections.
|
|
44
59
|
#
|
|
@@ -53,19 +68,17 @@ module ActiveRecord
|
|
|
53
68
|
# handle cases in which there are more threads than connections: if all
|
|
54
69
|
# connections have been checked out, and a thread tries to checkout a
|
|
55
70
|
# connection anyway, then ConnectionPool will wait until some other thread
|
|
56
|
-
# has checked in a connection.
|
|
71
|
+
# has checked in a connection, or the +checkout_timeout+ has expired.
|
|
57
72
|
#
|
|
58
73
|
# == Obtaining (checking out) a connection
|
|
59
74
|
#
|
|
60
75
|
# Connections can be obtained and used from a connection pool in several
|
|
61
76
|
# ways:
|
|
62
77
|
#
|
|
63
|
-
# 1. Simply use {ActiveRecord::Base.
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
# {ActiveRecord::Base.clear_active_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_active_connections!].
|
|
68
|
-
# This will be the default behavior for Active Record when used in conjunction with
|
|
78
|
+
# 1. Simply use {ActiveRecord::Base.lease_connection}[rdoc-ref:ConnectionHandling#lease_connection].
|
|
79
|
+
# When you're done with the connection(s) and wish it to be returned to the pool, you call
|
|
80
|
+
# {ActiveRecord::Base.connection_handler.clear_active_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_active_connections!].
|
|
81
|
+
# This is the default behavior for Active Record when used in conjunction with
|
|
69
82
|
# Action Pack's request handling cycle.
|
|
70
83
|
# 2. Manually check out a connection from the pool with
|
|
71
84
|
# {ActiveRecord::Base.connection_pool.checkout}[rdoc-ref:#checkout]. You are responsible for
|
|
@@ -78,6 +91,12 @@ module ActiveRecord
|
|
|
78
91
|
# Connections in the pool are actually AbstractAdapter objects (or objects
|
|
79
92
|
# compatible with AbstractAdapter's interface).
|
|
80
93
|
#
|
|
94
|
+
# While a thread has a connection checked out from the pool using one of the
|
|
95
|
+
# above three methods, that connection will automatically be the one used
|
|
96
|
+
# by ActiveRecord queries executing on that thread. It is not required to
|
|
97
|
+
# explicitly pass the checked out connection to \Rails models or queries, for
|
|
98
|
+
# example.
|
|
99
|
+
#
|
|
81
100
|
# == Options
|
|
82
101
|
#
|
|
83
102
|
# There are several connection-pooling-related options that you can add to
|
|
@@ -100,16 +119,111 @@ module ActiveRecord
|
|
|
100
119
|
# * private methods that require being called in a +synchronize+ blocks
|
|
101
120
|
# are now explicitly documented
|
|
102
121
|
class ConnectionPool
|
|
122
|
+
# Prior to 3.3.5, WeakKeyMap had a use after free bug
|
|
123
|
+
# https://bugs.ruby-lang.org/issues/20688
|
|
124
|
+
if ObjectSpace.const_defined?(:WeakKeyMap) && RUBY_VERSION >= "3.3.5"
|
|
125
|
+
WeakThreadKeyMap = ObjectSpace::WeakKeyMap
|
|
126
|
+
else
|
|
127
|
+
class WeakThreadKeyMap # :nodoc:
|
|
128
|
+
# FIXME: On 3.3 we could use ObjectSpace::WeakKeyMap
|
|
129
|
+
# but it currently cause GC crashes: https://github.com/byroot/rails/pull/3
|
|
130
|
+
def initialize
|
|
131
|
+
@map = {}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def clear
|
|
135
|
+
@map.clear
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def [](key)
|
|
139
|
+
@map[key]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def []=(key, value)
|
|
143
|
+
@map.select! { |c, _| c&.alive? }
|
|
144
|
+
@map[key] = value
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
class Lease # :nodoc:
|
|
150
|
+
attr_accessor :connection, :sticky
|
|
151
|
+
|
|
152
|
+
def initialize
|
|
153
|
+
@connection = nil
|
|
154
|
+
@sticky = nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def release
|
|
158
|
+
conn = @connection
|
|
159
|
+
@connection = nil
|
|
160
|
+
@sticky = nil
|
|
161
|
+
conn
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def clear(connection)
|
|
165
|
+
if @connection == connection
|
|
166
|
+
@connection = nil
|
|
167
|
+
@sticky = nil
|
|
168
|
+
true
|
|
169
|
+
else
|
|
170
|
+
false
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class LeaseRegistry # :nodoc:
|
|
176
|
+
def initialize
|
|
177
|
+
@mutex = Mutex.new
|
|
178
|
+
@map = WeakThreadKeyMap.new
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def [](context)
|
|
182
|
+
@mutex.synchronize do
|
|
183
|
+
@map[context] ||= Lease.new
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def clear
|
|
188
|
+
@mutex.synchronize do
|
|
189
|
+
@map.clear
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
module ExecutorHooks # :nodoc:
|
|
195
|
+
class << self
|
|
196
|
+
def run
|
|
197
|
+
# noop
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def complete(_)
|
|
201
|
+
ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
|
|
202
|
+
if (connection = pool.active_connection?)
|
|
203
|
+
transaction = connection.current_transaction
|
|
204
|
+
if transaction.closed? || !transaction.joinable?
|
|
205
|
+
pool.release_connection
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
class << self
|
|
214
|
+
def install_executor_hooks(executor = ActiveSupport::Executor)
|
|
215
|
+
executor.register_hook(ExecutorHooks)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
103
219
|
include MonitorMixin
|
|
104
|
-
|
|
220
|
+
prepend QueryCache::ConnectionPoolConfiguration
|
|
105
221
|
include ConnectionAdapters::AbstractPool
|
|
106
222
|
|
|
107
223
|
attr_accessor :automatic_reconnect, :checkout_timeout
|
|
108
|
-
attr_reader :db_config, :size, :reaper, :pool_config, :
|
|
224
|
+
attr_reader :db_config, :size, :reaper, :pool_config, :async_executor, :role, :shard
|
|
109
225
|
|
|
110
|
-
|
|
111
|
-
deprecate :connection_klass
|
|
112
|
-
delegate :schema_cache, :schema_cache=, to: :pool_config
|
|
226
|
+
delegate :schema_reflection, :server_version, to: :pool_config
|
|
113
227
|
|
|
114
228
|
# Creates a new ConnectionPool object. +pool_config+ is a PoolConfig
|
|
115
229
|
# object which describes database connection information (e.g. adapter,
|
|
@@ -122,7 +236,6 @@ module ActiveRecord
|
|
|
122
236
|
|
|
123
237
|
@pool_config = pool_config
|
|
124
238
|
@db_config = pool_config.db_config
|
|
125
|
-
@connection_class = pool_config.connection_class
|
|
126
239
|
@role = pool_config.role
|
|
127
240
|
@shard = pool_config.shard
|
|
128
241
|
|
|
@@ -138,9 +251,9 @@ module ActiveRecord
|
|
|
138
251
|
# then that +thread+ does indeed own that +conn+. However, an absence of such
|
|
139
252
|
# mapping does not mean that the +thread+ doesn't own the said connection. In
|
|
140
253
|
# that case +conn.owner+ attr should be consulted.
|
|
141
|
-
# Access and modification of <tt>@
|
|
254
|
+
# Access and modification of <tt>@leases</tt> does not require
|
|
142
255
|
# synchronization.
|
|
143
|
-
@
|
|
256
|
+
@leases = LeaseRegistry.new
|
|
144
257
|
|
|
145
258
|
@connections = []
|
|
146
259
|
@automatic_reconnect = true
|
|
@@ -153,73 +266,179 @@ module ActiveRecord
|
|
|
153
266
|
@threads_blocking_new_connections = 0
|
|
154
267
|
|
|
155
268
|
@available = ConnectionLeasingQueue.new self
|
|
156
|
-
|
|
157
|
-
@
|
|
269
|
+
@pinned_connection = nil
|
|
270
|
+
@pinned_connections_depth = 0
|
|
158
271
|
|
|
159
272
|
@async_executor = build_async_executor
|
|
160
273
|
|
|
161
|
-
|
|
274
|
+
@schema_cache = nil
|
|
162
275
|
|
|
163
276
|
@reaper = Reaper.new(self, db_config.reaping_frequency)
|
|
164
277
|
@reaper.run
|
|
165
278
|
end
|
|
166
279
|
|
|
167
|
-
def
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
280
|
+
def inspect # :nodoc:
|
|
281
|
+
name_field = " name=#{db_config.name.inspect}" unless db_config.name == "primary"
|
|
282
|
+
shard_field = " shard=#{@shard.inspect}" unless @shard == :default
|
|
283
|
+
|
|
284
|
+
"#<#{self.class.name} env_name=#{db_config.env_name.inspect}#{name_field} role=#{role.inspect}#{shard_field}>"
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def schema_cache
|
|
288
|
+
@schema_cache ||= BoundSchemaReflection.new(schema_reflection, self)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def schema_reflection=(schema_reflection)
|
|
292
|
+
pool_config.schema_reflection = schema_reflection
|
|
293
|
+
@schema_cache = nil
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def migration_context # :nodoc:
|
|
297
|
+
MigrationContext.new(migrations_paths, schema_migration, internal_metadata)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def migrations_paths # :nodoc:
|
|
301
|
+
db_config.migrations_paths || Migrator.migrations_paths
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def schema_migration # :nodoc:
|
|
305
|
+
SchemaMigration.new(self)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def internal_metadata # :nodoc:
|
|
309
|
+
InternalMetadata.new(self)
|
|
173
310
|
end
|
|
174
311
|
|
|
175
312
|
# Retrieve the connection associated with the current thread, or call
|
|
176
313
|
# #checkout to obtain one if necessary.
|
|
177
314
|
#
|
|
178
|
-
# #
|
|
315
|
+
# #lease_connection can be called any number of times; the connection is
|
|
179
316
|
# held in a cache keyed by a thread.
|
|
317
|
+
def lease_connection
|
|
318
|
+
lease = connection_lease
|
|
319
|
+
lease.connection ||= checkout
|
|
320
|
+
lease.sticky = true
|
|
321
|
+
lease.connection
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def permanent_lease? # :nodoc:
|
|
325
|
+
connection_lease.sticky.nil?
|
|
326
|
+
end
|
|
327
|
+
|
|
180
328
|
def connection
|
|
181
|
-
|
|
329
|
+
ActiveRecord.deprecator.warn(<<~MSG)
|
|
330
|
+
ActiveRecord::ConnectionAdapters::ConnectionPool#connection is deprecated
|
|
331
|
+
and will be removed in Rails 8.0. Use #lease_connection instead.
|
|
332
|
+
MSG
|
|
333
|
+
lease_connection
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def pin_connection!(lock_thread) # :nodoc:
|
|
337
|
+
@pinned_connection ||= (connection_lease&.connection || checkout)
|
|
338
|
+
@pinned_connections_depth += 1
|
|
339
|
+
|
|
340
|
+
# Any leased connection must be in @connections otherwise
|
|
341
|
+
# some methods like #connected? won't behave correctly
|
|
342
|
+
unless @connections.include?(@pinned_connection)
|
|
343
|
+
@connections << @pinned_connection
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
@pinned_connection.lock_thread = ActiveSupport::IsolatedExecutionState.context if lock_thread
|
|
347
|
+
@pinned_connection.pinned = true
|
|
348
|
+
@pinned_connection.verify! # eagerly validate the connection
|
|
349
|
+
@pinned_connection.begin_transaction joinable: false, _lazy: false
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def unpin_connection! # :nodoc:
|
|
353
|
+
raise "There isn't a pinned connection #{object_id}" unless @pinned_connection
|
|
354
|
+
|
|
355
|
+
clean = true
|
|
356
|
+
@pinned_connection.lock.synchronize do
|
|
357
|
+
@pinned_connections_depth -= 1
|
|
358
|
+
connection = @pinned_connection
|
|
359
|
+
@pinned_connection = nil if @pinned_connections_depth.zero?
|
|
360
|
+
|
|
361
|
+
if connection.transaction_open?
|
|
362
|
+
connection.rollback_transaction
|
|
363
|
+
else
|
|
364
|
+
# Something committed or rolled back the transaction
|
|
365
|
+
clean = false
|
|
366
|
+
connection.reset!
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
if @pinned_connection.nil?
|
|
370
|
+
connection.pinned = false
|
|
371
|
+
connection.steal!
|
|
372
|
+
connection.lock_thread = nil
|
|
373
|
+
checkin(connection)
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
clean
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def connection_class # :nodoc:
|
|
381
|
+
pool_config.connection_class
|
|
182
382
|
end
|
|
183
383
|
|
|
184
384
|
# Returns true if there is an open connection being used for the current thread.
|
|
185
385
|
#
|
|
186
386
|
# This method only works for connections that have been obtained through
|
|
187
|
-
# #
|
|
387
|
+
# #lease_connection or #with_connection methods. Connections obtained through
|
|
188
388
|
# #checkout will not be detected by #active_connection?
|
|
189
389
|
def active_connection?
|
|
190
|
-
|
|
390
|
+
connection_lease.connection
|
|
191
391
|
end
|
|
392
|
+
alias_method :active_connection, :active_connection? # :nodoc:
|
|
192
393
|
|
|
193
394
|
# Signal that the thread is finished with the current connection.
|
|
194
395
|
# #release_connection releases the connection-thread association
|
|
195
396
|
# and returns the connection to the pool.
|
|
196
397
|
#
|
|
197
398
|
# This method only works for connections that have been obtained through
|
|
198
|
-
# #
|
|
399
|
+
# #lease_connection or #with_connection methods, connections obtained through
|
|
199
400
|
# #checkout will not be automatically released.
|
|
200
|
-
def release_connection(
|
|
201
|
-
if conn =
|
|
401
|
+
def release_connection(existing_lease = nil)
|
|
402
|
+
if conn = connection_lease.release
|
|
202
403
|
checkin conn
|
|
404
|
+
return true
|
|
203
405
|
end
|
|
406
|
+
false
|
|
204
407
|
end
|
|
205
408
|
|
|
206
|
-
#
|
|
207
|
-
# already
|
|
208
|
-
#
|
|
209
|
-
#
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
409
|
+
# Yields a connection from the connection pool to the block. If no connection
|
|
410
|
+
# is already checked out by the current thread, a connection will be checked
|
|
411
|
+
# out from the pool, yielded to the block, and then returned to the pool when
|
|
412
|
+
# the block is finished. If a connection has already been checked out on the
|
|
413
|
+
# current thread, such as via #lease_connection or #with_connection, that existing
|
|
414
|
+
# connection will be the one yielded and it will not be returned to the pool
|
|
415
|
+
# automatically at the end of the block; it is expected that such an existing
|
|
416
|
+
# connection will be properly returned to the pool by the code that checked
|
|
417
|
+
# it out.
|
|
418
|
+
def with_connection(prevent_permanent_checkout: false)
|
|
419
|
+
lease = connection_lease
|
|
420
|
+
sticky_was = lease.sticky
|
|
421
|
+
lease.sticky = false if prevent_permanent_checkout
|
|
422
|
+
|
|
423
|
+
if lease.connection
|
|
424
|
+
begin
|
|
425
|
+
yield lease.connection
|
|
426
|
+
ensure
|
|
427
|
+
lease.sticky = sticky_was if prevent_permanent_checkout && !sticky_was
|
|
428
|
+
end
|
|
429
|
+
else
|
|
430
|
+
begin
|
|
431
|
+
yield lease.connection = checkout
|
|
432
|
+
ensure
|
|
433
|
+
lease.sticky = sticky_was if prevent_permanent_checkout && !sticky_was
|
|
434
|
+
release_connection(lease) unless lease.sticky
|
|
435
|
+
end
|
|
214
436
|
end
|
|
215
|
-
yield conn
|
|
216
|
-
ensure
|
|
217
|
-
release_connection if fresh_connection
|
|
218
437
|
end
|
|
219
438
|
|
|
220
439
|
# Returns true if a connection has already been opened.
|
|
221
440
|
def connected?
|
|
222
|
-
synchronize { @connections.any? }
|
|
441
|
+
synchronize { @connections.any?(&:connected?) }
|
|
223
442
|
end
|
|
224
443
|
|
|
225
444
|
# Returns an array containing the connections currently in the pool.
|
|
@@ -254,6 +473,7 @@ module ActiveRecord
|
|
|
254
473
|
conn.disconnect!
|
|
255
474
|
end
|
|
256
475
|
@connections = []
|
|
476
|
+
@leases.clear
|
|
257
477
|
@available.clear
|
|
258
478
|
end
|
|
259
479
|
end
|
|
@@ -280,7 +500,7 @@ module ActiveRecord
|
|
|
280
500
|
@connections.each do |conn|
|
|
281
501
|
conn.discard!
|
|
282
502
|
end
|
|
283
|
-
@connections = @available = @
|
|
503
|
+
@connections = @available = @leases = nil
|
|
284
504
|
end
|
|
285
505
|
end
|
|
286
506
|
|
|
@@ -338,7 +558,26 @@ module ActiveRecord
|
|
|
338
558
|
# Raises:
|
|
339
559
|
# - ActiveRecord::ConnectionTimeoutError no connection can be obtained from the pool.
|
|
340
560
|
def checkout(checkout_timeout = @checkout_timeout)
|
|
341
|
-
checkout_and_verify(acquire_connection(checkout_timeout))
|
|
561
|
+
return checkout_and_verify(acquire_connection(checkout_timeout)) unless @pinned_connection
|
|
562
|
+
|
|
563
|
+
@pinned_connection.lock.synchronize do
|
|
564
|
+
synchronize do
|
|
565
|
+
# The pinned connection may have been cleaned up before we synchronized, so check if it is still present
|
|
566
|
+
if @pinned_connection
|
|
567
|
+
@pinned_connection.verify!
|
|
568
|
+
|
|
569
|
+
# Any leased connection must be in @connections otherwise
|
|
570
|
+
# some methods like #connected? won't behave correctly
|
|
571
|
+
unless @connections.include?(@pinned_connection)
|
|
572
|
+
@connections << @pinned_connection
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
@pinned_connection
|
|
576
|
+
else
|
|
577
|
+
checkout_and_verify(acquire_connection(checkout_timeout))
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
end
|
|
342
581
|
end
|
|
343
582
|
|
|
344
583
|
# Check-in a database connection back into the pool, indicating that you
|
|
@@ -347,9 +586,11 @@ module ActiveRecord
|
|
|
347
586
|
# +conn+: an AbstractAdapter object, which was obtained by earlier by
|
|
348
587
|
# calling #checkout on this pool.
|
|
349
588
|
def checkin(conn)
|
|
589
|
+
return if @pinned_connection.equal?(conn)
|
|
590
|
+
|
|
350
591
|
conn.lock.synchronize do
|
|
351
592
|
synchronize do
|
|
352
|
-
|
|
593
|
+
connection_lease.clear(conn)
|
|
353
594
|
|
|
354
595
|
conn._run_checkin_callbacks do
|
|
355
596
|
conn.expire
|
|
@@ -448,8 +689,7 @@ module ActiveRecord
|
|
|
448
689
|
@available.num_waiting
|
|
449
690
|
end
|
|
450
691
|
|
|
451
|
-
#
|
|
452
|
-
# Example:
|
|
692
|
+
# Returns the connection pool's usage statistic.
|
|
453
693
|
#
|
|
454
694
|
# ActiveRecord::Base.connection_pool.stat # => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }
|
|
455
695
|
def stat
|
|
@@ -471,7 +711,19 @@ module ActiveRecord
|
|
|
471
711
|
Thread.pass
|
|
472
712
|
end
|
|
473
713
|
|
|
714
|
+
def new_connection # :nodoc:
|
|
715
|
+
connection = db_config.new_connection
|
|
716
|
+
connection.pool = self
|
|
717
|
+
connection
|
|
718
|
+
rescue ConnectionNotEstablished => ex
|
|
719
|
+
raise ex.set_pool(self)
|
|
720
|
+
end
|
|
721
|
+
|
|
474
722
|
private
|
|
723
|
+
def connection_lease
|
|
724
|
+
@leases[ActiveSupport::IsolatedExecutionState.context]
|
|
725
|
+
end
|
|
726
|
+
|
|
475
727
|
def build_async_executor
|
|
476
728
|
case ActiveRecord.async_query_executor
|
|
477
729
|
when :multi_thread_pool
|
|
@@ -500,19 +752,6 @@ module ActiveRecord
|
|
|
500
752
|
end
|
|
501
753
|
end
|
|
502
754
|
|
|
503
|
-
#--
|
|
504
|
-
# From the discussion on GitHub:
|
|
505
|
-
# https://github.com/rails/rails/pull/14938#commitcomment-6601951
|
|
506
|
-
# This hook-in method allows for easier monkey-patching fixes needed by
|
|
507
|
-
# JRuby users that use Fibers.
|
|
508
|
-
def connection_cache_key(thread)
|
|
509
|
-
thread
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
def current_thread
|
|
513
|
-
@lock_thread || Thread.current
|
|
514
|
-
end
|
|
515
|
-
|
|
516
755
|
# Take control of all existing connections so a "group" action such as
|
|
517
756
|
# reload/disconnect can be performed safely. It is no longer enough to
|
|
518
757
|
# wrap it in +synchronize+ because some pool's actions are allowed
|
|
@@ -526,17 +765,20 @@ module ActiveRecord
|
|
|
526
765
|
|
|
527
766
|
def attempt_to_checkout_all_existing_connections(raise_on_acquisition_timeout = true)
|
|
528
767
|
collected_conns = synchronize do
|
|
768
|
+
reap # No need to wait for dead owners
|
|
769
|
+
|
|
529
770
|
# account for our own connections
|
|
530
|
-
@connections.select { |conn| conn.owner ==
|
|
771
|
+
@connections.select { |conn| conn.owner == ActiveSupport::IsolatedExecutionState.context }
|
|
531
772
|
end
|
|
532
773
|
|
|
533
774
|
newly_checked_out = []
|
|
534
775
|
timeout_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (@checkout_timeout * 2)
|
|
535
776
|
|
|
536
|
-
@available.with_a_bias_for(
|
|
777
|
+
@available.with_a_bias_for(ActiveSupport::IsolatedExecutionState.context) do
|
|
537
778
|
loop do
|
|
538
779
|
synchronize do
|
|
539
780
|
return if collected_conns.size == @connections.size && @now_connecting == 0
|
|
781
|
+
|
|
540
782
|
remaining_timeout = timeout_time - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
541
783
|
remaining_timeout = 0 if remaining_timeout < 0
|
|
542
784
|
conn = checkout_for_exclusive_access(remaining_timeout)
|
|
@@ -580,14 +822,14 @@ module ActiveRecord
|
|
|
580
822
|
|
|
581
823
|
thread_report = []
|
|
582
824
|
@connections.each do |conn|
|
|
583
|
-
unless conn.owner ==
|
|
825
|
+
unless conn.owner == ActiveSupport::IsolatedExecutionState.context
|
|
584
826
|
thread_report << "#{conn} is owned by #{conn.owner}"
|
|
585
827
|
end
|
|
586
828
|
end
|
|
587
829
|
|
|
588
830
|
msg << " (#{thread_report.join(', ')})" if thread_report.any?
|
|
589
831
|
|
|
590
|
-
raise ExclusiveConnectionTimeoutError,
|
|
832
|
+
raise ExclusiveConnectionTimeoutError.new(msg, connection_pool: self)
|
|
591
833
|
end
|
|
592
834
|
|
|
593
835
|
def with_new_connections_blocked
|
|
@@ -641,22 +883,26 @@ module ActiveRecord
|
|
|
641
883
|
conn
|
|
642
884
|
else
|
|
643
885
|
reap
|
|
644
|
-
|
|
886
|
+
# Retry after reaping, which may return an available connection,
|
|
887
|
+
# remove an inactive connection, or both
|
|
888
|
+
if conn = @available.poll || try_to_checkout_new_connection
|
|
889
|
+
conn
|
|
890
|
+
else
|
|
891
|
+
@available.poll(checkout_timeout)
|
|
892
|
+
end
|
|
645
893
|
end
|
|
894
|
+
rescue ConnectionTimeoutError => ex
|
|
895
|
+
raise ex.set_pool(self)
|
|
646
896
|
end
|
|
647
897
|
|
|
648
898
|
#--
|
|
649
899
|
# if owner_thread param is omitted, this must be called in synchronize block
|
|
650
900
|
def remove_connection_from_thread_cache(conn, owner_thread = conn.owner)
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
alias_method :release, :remove_connection_from_thread_cache
|
|
654
|
-
|
|
655
|
-
def new_connection
|
|
656
|
-
Base.public_send(db_config.adapter_method, db_config.configuration_hash).tap do |conn|
|
|
657
|
-
conn.check_version
|
|
901
|
+
if owner_thread
|
|
902
|
+
@leases[owner_thread].clear(conn)
|
|
658
903
|
end
|
|
659
904
|
end
|
|
905
|
+
alias_method :release, :remove_connection_from_thread_cache
|
|
660
906
|
|
|
661
907
|
# If the pool is not at a <tt>@size</tt> limit, establish new connection. Connecting
|
|
662
908
|
# to the DB is done outside main synchronized section.
|
|
@@ -693,6 +939,12 @@ module ActiveRecord
|
|
|
693
939
|
def adopt_connection(conn)
|
|
694
940
|
conn.pool = self
|
|
695
941
|
@connections << conn
|
|
942
|
+
|
|
943
|
+
# We just created the first connection, it's time to load the schema
|
|
944
|
+
# cache if that wasn't eagerly done before
|
|
945
|
+
if @schema_cache.nil? && ActiveRecord.lazily_load_schema_cache
|
|
946
|
+
schema_cache.load!
|
|
947
|
+
end
|
|
696
948
|
end
|
|
697
949
|
|
|
698
950
|
def checkout_new_connection
|
|
@@ -702,10 +954,10 @@ module ActiveRecord
|
|
|
702
954
|
|
|
703
955
|
def checkout_and_verify(c)
|
|
704
956
|
c._run_checkout_callbacks do
|
|
705
|
-
c.
|
|
957
|
+
c.clean!
|
|
706
958
|
end
|
|
707
959
|
c
|
|
708
|
-
rescue
|
|
960
|
+
rescue Exception
|
|
709
961
|
remove c
|
|
710
962
|
c.disconnect!
|
|
711
963
|
raise
|