activerecord 6.1.6 → 7.1.2
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +1627 -983
 - data/MIT-LICENSE +1 -1
 - data/README.rdoc +18 -18
 - data/lib/active_record/aggregations.rb +17 -14
 - data/lib/active_record/association_relation.rb +1 -11
 - data/lib/active_record/associations/association.rb +50 -19
 - data/lib/active_record/associations/association_scope.rb +17 -12
 - data/lib/active_record/associations/belongs_to_association.rb +28 -9
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
 - data/lib/active_record/associations/builder/association.rb +11 -5
 - data/lib/active_record/associations/builder/belongs_to.rb +40 -14
 - data/lib/active_record/associations/builder/collection_association.rb +10 -3
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
 - data/lib/active_record/associations/builder/has_many.rb +3 -2
 - data/lib/active_record/associations/builder/has_one.rb +2 -1
 - data/lib/active_record/associations/builder/singular_association.rb +6 -2
 - data/lib/active_record/associations/collection_association.rb +35 -31
 - data/lib/active_record/associations/collection_proxy.rb +30 -15
 - data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
 - data/lib/active_record/associations/foreign_association.rb +10 -3
 - data/lib/active_record/associations/has_many_association.rb +28 -18
 - data/lib/active_record/associations/has_many_through_association.rb +12 -7
 - data/lib/active_record/associations/has_one_association.rb +20 -10
 - data/lib/active_record/associations/has_one_through_association.rb +1 -1
 - data/lib/active_record/associations/join_dependency.rb +26 -16
 - data/lib/active_record/associations/preloader/association.rb +207 -52
 - data/lib/active_record/associations/preloader/batch.rb +48 -0
 - data/lib/active_record/associations/preloader/branch.rb +147 -0
 - data/lib/active_record/associations/preloader/through_association.rb +50 -14
 - data/lib/active_record/associations/preloader.rb +50 -121
 - data/lib/active_record/associations/singular_association.rb +9 -3
 - data/lib/active_record/associations/through_association.rb +25 -14
 - data/lib/active_record/associations.rb +439 -305
 - data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
 - data/lib/active_record/attribute_assignment.rb +1 -3
 - data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
 - data/lib/active_record/attribute_methods/dirty.rb +73 -22
 - data/lib/active_record/attribute_methods/primary_key.rb +78 -26
 - data/lib/active_record/attribute_methods/query.rb +31 -19
 - data/lib/active_record/attribute_methods/read.rb +25 -10
 - data/lib/active_record/attribute_methods/serialization.rb +194 -37
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
 - data/lib/active_record/attribute_methods/write.rb +10 -13
 - data/lib/active_record/attribute_methods.rb +121 -40
 - data/lib/active_record/attributes.rb +27 -38
 - data/lib/active_record/autosave_association.rb +61 -30
 - data/lib/active_record/base.rb +25 -2
 - data/lib/active_record/callbacks.rb +18 -34
 - 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 -34
 - data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
 - data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -138
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -149
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
 - data/lib/active_record/connection_adapters/column.rb +13 -0
 - data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
 - data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
 - data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
 - data/lib/active_record/connection_adapters/pool_config.rb +20 -11
 - data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
 - data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
 - data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
 - data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +394 -74
 - data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +509 -247
 - data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
 - data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
 - data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
 - data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
 - data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
 - 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 +254 -0
 - data/lib/active_record/connection_adapters.rb +9 -6
 - data/lib/active_record/connection_handling.rb +107 -136
 - data/lib/active_record/core.rb +202 -223
 - data/lib/active_record/counter_cache.rb +46 -25
 - data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
 - data/lib/active_record/database_configurations/database_config.rb +21 -12
 - data/lib/active_record/database_configurations/hash_config.rb +84 -16
 - data/lib/active_record/database_configurations/url_config.rb +18 -12
 - data/lib/active_record/database_configurations.rb +95 -59
 - data/lib/active_record/delegated_type.rb +61 -15
 - data/lib/active_record/deprecator.rb +7 -0
 - data/lib/active_record/destroy_association_async_job.rb +3 -1
 - data/lib/active_record/disable_joins_association_relation.rb +39 -0
 - data/lib/active_record/dynamic_matchers.rb +1 -1
 - data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
 - data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
 - data/lib/active_record/encryption/cipher.rb +53 -0
 - data/lib/active_record/encryption/config.rb +68 -0
 - data/lib/active_record/encryption/configurable.rb +60 -0
 - data/lib/active_record/encryption/context.rb +42 -0
 - data/lib/active_record/encryption/contexts.rb +76 -0
 - data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
 - data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
 - data/lib/active_record/encryption/encryptable_record.rb +224 -0
 - data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
 - data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
 - data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
 - data/lib/active_record/encryption/encryptor.rb +155 -0
 - data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
 - data/lib/active_record/encryption/errors.rb +15 -0
 - data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
 - data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
 - data/lib/active_record/encryption/key.rb +28 -0
 - data/lib/active_record/encryption/key_generator.rb +53 -0
 - data/lib/active_record/encryption/key_provider.rb +46 -0
 - data/lib/active_record/encryption/message.rb +33 -0
 - data/lib/active_record/encryption/message_serializer.rb +92 -0
 - data/lib/active_record/encryption/null_encryptor.rb +21 -0
 - data/lib/active_record/encryption/properties.rb +76 -0
 - data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
 - data/lib/active_record/encryption/scheme.rb +96 -0
 - data/lib/active_record/encryption.rb +56 -0
 - data/lib/active_record/enum.rb +154 -63
 - data/lib/active_record/errors.rb +171 -15
 - data/lib/active_record/explain.rb +23 -3
 - data/lib/active_record/explain_registry.rb +11 -6
 - data/lib/active_record/explain_subscriber.rb +1 -1
 - data/lib/active_record/fixture_set/file.rb +15 -1
 - 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 +70 -14
 - data/lib/active_record/fixture_set/table_rows.rb +4 -4
 - data/lib/active_record/fixtures.rb +131 -86
 - data/lib/active_record/future_result.rb +164 -0
 - data/lib/active_record/gem_version.rb +3 -3
 - data/lib/active_record/inheritance.rb +81 -29
 - data/lib/active_record/insert_all.rb +135 -22
 - data/lib/active_record/integration.rb +11 -10
 - data/lib/active_record/internal_metadata.rb +119 -33
 - data/lib/active_record/legacy_yaml_adapter.rb +2 -39
 - data/lib/active_record/locking/optimistic.rb +36 -21
 - data/lib/active_record/locking/pessimistic.rb +15 -6
 - data/lib/active_record/log_subscriber.rb +52 -19
 - data/lib/active_record/marshalling.rb +56 -0
 - data/lib/active_record/message_pack.rb +124 -0
 - data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
 - data/lib/active_record/middleware/database_selector.rb +23 -13
 - data/lib/active_record/middleware/shard_selector.rb +62 -0
 - data/lib/active_record/migration/command_recorder.rb +112 -14
 - data/lib/active_record/migration/compatibility.rb +221 -48
 - data/lib/active_record/migration/default_strategy.rb +23 -0
 - data/lib/active_record/migration/execution_strategy.rb +19 -0
 - data/lib/active_record/migration/join_table.rb +1 -1
 - data/lib/active_record/migration/pending_migration_connection.rb +21 -0
 - data/lib/active_record/migration.rb +358 -171
 - data/lib/active_record/model_schema.rb +120 -101
 - data/lib/active_record/nested_attributes.rb +37 -18
 - data/lib/active_record/no_touching.rb +3 -3
 - data/lib/active_record/normalization.rb +167 -0
 - data/lib/active_record/persistence.rb +405 -85
 - data/lib/active_record/promise.rb +84 -0
 - data/lib/active_record/query_cache.rb +3 -21
 - data/lib/active_record/query_logs.rb +174 -0
 - data/lib/active_record/query_logs_formatter.rb +41 -0
 - data/lib/active_record/querying.rb +29 -6
 - data/lib/active_record/railtie.rb +219 -43
 - data/lib/active_record/railties/controller_runtime.rb +13 -9
 - data/lib/active_record/railties/databases.rake +188 -252
 - data/lib/active_record/railties/job_runtime.rb +23 -0
 - data/lib/active_record/readonly_attributes.rb +41 -3
 - data/lib/active_record/reflection.rb +241 -80
 - data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
 - data/lib/active_record/relation/batches.rb +192 -63
 - data/lib/active_record/relation/calculations.rb +219 -90
 - data/lib/active_record/relation/delegation.rb +27 -13
 - data/lib/active_record/relation/finder_methods.rb +108 -51
 - data/lib/active_record/relation/merger.rb +22 -13
 - data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
 - data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
 - data/lib/active_record/relation/predicate_builder.rb +27 -20
 - data/lib/active_record/relation/query_attribute.rb +30 -12
 - data/lib/active_record/relation/query_methods.rb +654 -127
 - data/lib/active_record/relation/record_fetch_warning.rb +7 -9
 - data/lib/active_record/relation/spawn_methods.rb +20 -3
 - data/lib/active_record/relation/where_clause.rb +10 -19
 - data/lib/active_record/relation.rb +262 -120
 - data/lib/active_record/result.rb +37 -11
 - data/lib/active_record/runtime_registry.rb +18 -13
 - data/lib/active_record/sanitization.rb +65 -20
 - data/lib/active_record/schema.rb +36 -22
 - data/lib/active_record/schema_dumper.rb +73 -24
 - data/lib/active_record/schema_migration.rb +68 -33
 - data/lib/active_record/scoping/default.rb +72 -15
 - data/lib/active_record/scoping/named.rb +5 -13
 - data/lib/active_record/scoping.rb +65 -34
 - data/lib/active_record/secure_password.rb +60 -0
 - data/lib/active_record/secure_token.rb +21 -3
 - data/lib/active_record/serialization.rb +6 -1
 - data/lib/active_record/signed_id.rb +10 -8
 - data/lib/active_record/store.rb +16 -11
 - data/lib/active_record/suppressor.rb +13 -15
 - data/lib/active_record/table_metadata.rb +16 -3
 - data/lib/active_record/tasks/database_tasks.rb +225 -136
 - data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
 - data/lib/active_record/test_databases.rb +1 -1
 - data/lib/active_record/test_fixtures.rb +123 -99
 - data/lib/active_record/timestamp.rb +29 -18
 - data/lib/active_record/token_for.rb +113 -0
 - data/lib/active_record/touch_later.rb +11 -6
 - data/lib/active_record/transactions.rb +48 -27
 - data/lib/active_record/translation.rb +3 -3
 - data/lib/active_record/type/adapter_specific_registry.rb +32 -14
 - data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
 - data/lib/active_record/type/internal/timezone.rb +7 -2
 - data/lib/active_record/type/serialized.rb +9 -5
 - data/lib/active_record/type/time.rb +4 -0
 - data/lib/active_record/type/type_map.rb +17 -20
 - data/lib/active_record/type.rb +1 -2
 - data/lib/active_record/validations/absence.rb +1 -1
 - data/lib/active_record/validations/associated.rb +4 -4
 - 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 +51 -6
 - data/lib/active_record/validations.rb +8 -4
 - data/lib/active_record/version.rb +1 -1
 - data/lib/active_record.rb +335 -32
 - data/lib/arel/attributes/attribute.rb +0 -8
 - data/lib/arel/crud.rb +28 -22
 - data/lib/arel/delete_manager.rb +18 -4
 - data/lib/arel/errors.rb +10 -0
 - data/lib/arel/factory_methods.rb +4 -0
 - data/lib/arel/filter_predications.rb +9 -0
 - data/lib/arel/insert_manager.rb +2 -3
 - data/lib/arel/nodes/and.rb +4 -0
 - data/lib/arel/nodes/binary.rb +6 -1
 - data/lib/arel/nodes/bound_sql_literal.rb +61 -0
 - data/lib/arel/nodes/casted.rb +1 -1
 - data/lib/arel/nodes/cte.rb +36 -0
 - data/lib/arel/nodes/delete_statement.rb +12 -13
 - data/lib/arel/nodes/filter.rb +10 -0
 - data/lib/arel/nodes/fragments.rb +35 -0
 - data/lib/arel/nodes/function.rb +1 -0
 - data/lib/arel/nodes/homogeneous_in.rb +1 -9
 - data/lib/arel/nodes/insert_statement.rb +2 -2
 - data/lib/arel/nodes/leading_join.rb +8 -0
 - data/lib/arel/nodes/node.rb +111 -2
 - data/lib/arel/nodes/select_core.rb +2 -2
 - data/lib/arel/nodes/select_statement.rb +2 -2
 - data/lib/arel/nodes/sql_literal.rb +6 -0
 - data/lib/arel/nodes/table_alias.rb +4 -0
 - data/lib/arel/nodes/update_statement.rb +8 -3
 - data/lib/arel/nodes.rb +5 -0
 - data/lib/arel/predications.rb +13 -3
 - data/lib/arel/select_manager.rb +10 -4
 - data/lib/arel/table.rb +9 -6
 - data/lib/arel/tree_manager.rb +0 -12
 - data/lib/arel/update_manager.rb +18 -4
 - data/lib/arel/visitors/dot.rb +80 -90
 - data/lib/arel/visitors/mysql.rb +16 -3
 - data/lib/arel/visitors/postgresql.rb +0 -10
 - data/lib/arel/visitors/to_sql.rb +139 -19
 - data/lib/arel/visitors/visitor.rb +2 -2
 - data/lib/arel.rb +18 -3
 - data/lib/rails/generators/active_record/application_record/USAGE +8 -0
 - data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -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
 - data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
 - data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
 - data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
 - data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
 - data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
 - metadata +93 -13
 - data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
 - data/lib/active_record/null_relation.rb +0 -67
 
| 
         @@ -3,32 +3,40 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require "thread"
         
     | 
| 
       4 
4 
     | 
    
         
             
            require "concurrent/map"
         
     | 
| 
       5 
5 
     | 
    
         
             
            require "monitor"
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require "active_record/connection_adapters/abstract/connection_pool/queue"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "active_record/connection_adapters/abstract/connection_pool/reaper"
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       9 
11 
     | 
    
         
             
              module ConnectionAdapters
         
     | 
| 
       10 
12 
     | 
    
         
             
                module AbstractPool # :nodoc:
         
     | 
| 
       11 
     | 
    
         
            -
                  def get_schema_cache(connection)
         
     | 
| 
       12 
     | 
    
         
            -
                    self.schema_cache ||= SchemaCache.new(connection)
         
     | 
| 
       13 
     | 
    
         
            -
                    schema_cache.connection = connection
         
     | 
| 
       14 
     | 
    
         
            -
                    schema_cache
         
     | 
| 
       15 
     | 
    
         
            -
                  end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                  def set_schema_cache(cache)
         
     | 
| 
       18 
     | 
    
         
            -
                    self.schema_cache = cache
         
     | 
| 
       19 
     | 
    
         
            -
                  end
         
     | 
| 
       20 
13 
     | 
    
         
             
                end
         
     | 
| 
       21 
14 
     | 
    
         | 
| 
       22 
15 
     | 
    
         
             
                class NullPool # :nodoc:
         
     | 
| 
       23 
16 
     | 
    
         
             
                  include ConnectionAdapters::AbstractPool
         
     | 
| 
       24 
17 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
      
 18 
     | 
    
         
            +
                  class NullConfig # :nodoc:
         
     | 
| 
      
 19 
     | 
    
         
            +
                    def method_missing(*)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  NULL_CONFIG = NullConfig.new # :nodoc:
         
     | 
| 
       26 
24 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                  def  
     | 
| 
       28 
     | 
    
         
            -
                    nil
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def schema_reflection
         
     | 
| 
      
 26 
     | 
    
         
            +
                    SchemaReflection.new(nil)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def connection_class; end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def checkin(_); end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def remove(_); end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def async_executor; end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def db_config
         
     | 
| 
      
 34 
     | 
    
         
            +
                    NULL_CONFIG
         
     | 
| 
       29 
35 
     | 
    
         
             
                  end
         
     | 
| 
       30 
36 
     | 
    
         
             
                end
         
     | 
| 
       31 
37 
     | 
    
         | 
| 
      
 38 
     | 
    
         
            +
                # = Active Record Connection Pool
         
     | 
| 
      
 39 
     | 
    
         
            +
                #
         
     | 
| 
       32 
40 
     | 
    
         
             
                # Connection pool base class for managing Active Record database
         
     | 
| 
       33 
41 
     | 
    
         
             
                # connections.
         
     | 
| 
       34 
42 
     | 
    
         
             
                #
         
     | 
| 
         @@ -43,7 +51,7 @@ module ActiveRecord 
     | 
|
| 
       43 
51 
     | 
    
         
             
                # handle cases in which there are more threads than connections: if all
         
     | 
| 
       44 
52 
     | 
    
         
             
                # connections have been checked out, and a thread tries to checkout a
         
     | 
| 
       45 
53 
     | 
    
         
             
                # connection anyway, then ConnectionPool will wait until some other thread
         
     | 
| 
       46 
     | 
    
         
            -
                # has checked in a connection.
         
     | 
| 
      
 54 
     | 
    
         
            +
                # has checked in a connection, or the +checkout_timeout+ has expired.
         
     | 
| 
       47 
55 
     | 
    
         
             
                #
         
     | 
| 
       48 
56 
     | 
    
         
             
                # == Obtaining (checking out) a connection
         
     | 
| 
       49 
57 
     | 
    
         
             
                #
         
     | 
| 
         @@ -54,7 +62,7 @@ module ActiveRecord 
     | 
|
| 
       54 
62 
     | 
    
         
             
                #    as with Active Record 2.1 and
         
     | 
| 
       55 
63 
     | 
    
         
             
                #    earlier (pre-connection-pooling). Eventually, when you're done with
         
     | 
| 
       56 
64 
     | 
    
         
             
                #    the connection(s) and wish it to be returned to the pool, you call
         
     | 
| 
       57 
     | 
    
         
            -
                #    {ActiveRecord::Base.clear_active_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_active_connections!].
         
     | 
| 
      
 65 
     | 
    
         
            +
                #    {ActiveRecord::Base.connection_handler.clear_active_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_active_connections!].
         
     | 
| 
       58 
66 
     | 
    
         
             
                #    This will be the default behavior for Active Record when used in conjunction with
         
     | 
| 
       59 
67 
     | 
    
         
             
                #    Action Pack's request handling cycle.
         
     | 
| 
       60 
68 
     | 
    
         
             
                # 2. Manually check out a connection from the pool with
         
     | 
| 
         @@ -68,6 +76,12 @@ module ActiveRecord 
     | 
|
| 
       68 
76 
     | 
    
         
             
                # Connections in the pool are actually AbstractAdapter objects (or objects
         
     | 
| 
       69 
77 
     | 
    
         
             
                # compatible with AbstractAdapter's interface).
         
     | 
| 
       70 
78 
     | 
    
         
             
                #
         
     | 
| 
      
 79 
     | 
    
         
            +
                # While a thread has a connection checked out from the pool using one of the
         
     | 
| 
      
 80 
     | 
    
         
            +
                # above three methods, that connection will automatically be the one used
         
     | 
| 
      
 81 
     | 
    
         
            +
                # by ActiveRecord queries executing on that thread. It is not required to
         
     | 
| 
      
 82 
     | 
    
         
            +
                # explicitly pass the checked out connection to \Rails models or queries, for
         
     | 
| 
      
 83 
     | 
    
         
            +
                # example.
         
     | 
| 
      
 84 
     | 
    
         
            +
                #
         
     | 
| 
       71 
85 
     | 
    
         
             
                # == Options
         
     | 
| 
       72 
86 
     | 
    
         
             
                #
         
     | 
| 
       73 
87 
     | 
    
         
             
                # There are several connection-pooling-related options that you can add to
         
     | 
| 
         @@ -90,279 +104,14 @@ module ActiveRecord 
     | 
|
| 
       90 
104 
     | 
    
         
             
                # * private methods that require being called in a +synchronize+ blocks
         
     | 
| 
       91 
105 
     | 
    
         
             
                #   are now explicitly documented
         
     | 
| 
       92 
106 
     | 
    
         
             
                class ConnectionPool
         
     | 
| 
       93 
     | 
    
         
            -
                  # Threadsafe, fair, LIFO queue.  Meant to be used by ConnectionPool
         
     | 
| 
       94 
     | 
    
         
            -
                  # with which it shares a Monitor.
         
     | 
| 
       95 
     | 
    
         
            -
                  class Queue
         
     | 
| 
       96 
     | 
    
         
            -
                    def initialize(lock = Monitor.new)
         
     | 
| 
       97 
     | 
    
         
            -
                      @lock = lock
         
     | 
| 
       98 
     | 
    
         
            -
                      @cond = @lock.new_cond
         
     | 
| 
       99 
     | 
    
         
            -
                      @num_waiting = 0
         
     | 
| 
       100 
     | 
    
         
            -
                      @queue = []
         
     | 
| 
       101 
     | 
    
         
            -
                    end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
                    # Test if any threads are currently waiting on the queue.
         
     | 
| 
       104 
     | 
    
         
            -
                    def any_waiting?
         
     | 
| 
       105 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       106 
     | 
    
         
            -
                        @num_waiting > 0
         
     | 
| 
       107 
     | 
    
         
            -
                      end
         
     | 
| 
       108 
     | 
    
         
            -
                    end
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                    # Returns the number of threads currently waiting on this
         
     | 
| 
       111 
     | 
    
         
            -
                    # queue.
         
     | 
| 
       112 
     | 
    
         
            -
                    def num_waiting
         
     | 
| 
       113 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       114 
     | 
    
         
            -
                        @num_waiting
         
     | 
| 
       115 
     | 
    
         
            -
                      end
         
     | 
| 
       116 
     | 
    
         
            -
                    end
         
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                    # Add +element+ to the queue.  Never blocks.
         
     | 
| 
       119 
     | 
    
         
            -
                    def add(element)
         
     | 
| 
       120 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       121 
     | 
    
         
            -
                        @queue.push element
         
     | 
| 
       122 
     | 
    
         
            -
                        @cond.signal
         
     | 
| 
       123 
     | 
    
         
            -
                      end
         
     | 
| 
       124 
     | 
    
         
            -
                    end
         
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
                    # If +element+ is in the queue, remove and return it, or +nil+.
         
     | 
| 
       127 
     | 
    
         
            -
                    def delete(element)
         
     | 
| 
       128 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       129 
     | 
    
         
            -
                        @queue.delete(element)
         
     | 
| 
       130 
     | 
    
         
            -
                      end
         
     | 
| 
       131 
     | 
    
         
            -
                    end
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                    # Remove all elements from the queue.
         
     | 
| 
       134 
     | 
    
         
            -
                    def clear
         
     | 
| 
       135 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       136 
     | 
    
         
            -
                        @queue.clear
         
     | 
| 
       137 
     | 
    
         
            -
                      end
         
     | 
| 
       138 
     | 
    
         
            -
                    end
         
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                    # Remove the head of the queue.
         
     | 
| 
       141 
     | 
    
         
            -
                    #
         
     | 
| 
       142 
     | 
    
         
            -
                    # If +timeout+ is not given, remove and return the head of the
         
     | 
| 
       143 
     | 
    
         
            -
                    # queue if the number of available elements is strictly
         
     | 
| 
       144 
     | 
    
         
            -
                    # greater than the number of threads currently waiting (that
         
     | 
| 
       145 
     | 
    
         
            -
                    # is, don't jump ahead in line).  Otherwise, return +nil+.
         
     | 
| 
       146 
     | 
    
         
            -
                    #
         
     | 
| 
       147 
     | 
    
         
            -
                    # If +timeout+ is given, block if there is no element
         
     | 
| 
       148 
     | 
    
         
            -
                    # available, waiting up to +timeout+ seconds for an element to
         
     | 
| 
       149 
     | 
    
         
            -
                    # become available.
         
     | 
| 
       150 
     | 
    
         
            -
                    #
         
     | 
| 
       151 
     | 
    
         
            -
                    # Raises:
         
     | 
| 
       152 
     | 
    
         
            -
                    # - ActiveRecord::ConnectionTimeoutError if +timeout+ is given and no element
         
     | 
| 
       153 
     | 
    
         
            -
                    # becomes available within +timeout+ seconds,
         
     | 
| 
       154 
     | 
    
         
            -
                    def poll(timeout = nil)
         
     | 
| 
       155 
     | 
    
         
            -
                      synchronize { internal_poll(timeout) }
         
     | 
| 
       156 
     | 
    
         
            -
                    end
         
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
                    private
         
     | 
| 
       159 
     | 
    
         
            -
                      def internal_poll(timeout)
         
     | 
| 
       160 
     | 
    
         
            -
                        no_wait_poll || (timeout && wait_poll(timeout))
         
     | 
| 
       161 
     | 
    
         
            -
                      end
         
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
                      def synchronize(&block)
         
     | 
| 
       164 
     | 
    
         
            -
                        @lock.synchronize(&block)
         
     | 
| 
       165 
     | 
    
         
            -
                      end
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                      # Test if the queue currently contains any elements.
         
     | 
| 
       168 
     | 
    
         
            -
                      def any?
         
     | 
| 
       169 
     | 
    
         
            -
                        !@queue.empty?
         
     | 
| 
       170 
     | 
    
         
            -
                      end
         
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
                      # A thread can remove an element from the queue without
         
     | 
| 
       173 
     | 
    
         
            -
                      # waiting if and only if the number of currently available
         
     | 
| 
       174 
     | 
    
         
            -
                      # connections is strictly greater than the number of waiting
         
     | 
| 
       175 
     | 
    
         
            -
                      # threads.
         
     | 
| 
       176 
     | 
    
         
            -
                      def can_remove_no_wait?
         
     | 
| 
       177 
     | 
    
         
            -
                        @queue.size > @num_waiting
         
     | 
| 
       178 
     | 
    
         
            -
                      end
         
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
                      # Removes and returns the head of the queue if possible, or +nil+.
         
     | 
| 
       181 
     | 
    
         
            -
                      def remove
         
     | 
| 
       182 
     | 
    
         
            -
                        @queue.pop
         
     | 
| 
       183 
     | 
    
         
            -
                      end
         
     | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
                      # Remove and return the head of the queue if the number of
         
     | 
| 
       186 
     | 
    
         
            -
                      # available elements is strictly greater than the number of
         
     | 
| 
       187 
     | 
    
         
            -
                      # threads currently waiting.  Otherwise, return +nil+.
         
     | 
| 
       188 
     | 
    
         
            -
                      def no_wait_poll
         
     | 
| 
       189 
     | 
    
         
            -
                        remove if can_remove_no_wait?
         
     | 
| 
       190 
     | 
    
         
            -
                      end
         
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
                      # Waits on the queue up to +timeout+ seconds, then removes and
         
     | 
| 
       193 
     | 
    
         
            -
                      # returns the head of the queue.
         
     | 
| 
       194 
     | 
    
         
            -
                      def wait_poll(timeout)
         
     | 
| 
       195 
     | 
    
         
            -
                        @num_waiting += 1
         
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
                        t0 = Concurrent.monotonic_time
         
     | 
| 
       198 
     | 
    
         
            -
                        elapsed = 0
         
     | 
| 
       199 
     | 
    
         
            -
                        loop do
         
     | 
| 
       200 
     | 
    
         
            -
                          ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
         
     | 
| 
       201 
     | 
    
         
            -
                            @cond.wait(timeout - elapsed)
         
     | 
| 
       202 
     | 
    
         
            -
                          end
         
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
                          return remove if any?
         
     | 
| 
       205 
     | 
    
         
            -
             
     | 
| 
       206 
     | 
    
         
            -
                          elapsed = Concurrent.monotonic_time - t0
         
     | 
| 
       207 
     | 
    
         
            -
                          if elapsed >= timeout
         
     | 
| 
       208 
     | 
    
         
            -
                            msg = "could not obtain a connection from the pool within %0.3f seconds (waited %0.3f seconds); all pooled connections were in use" %
         
     | 
| 
       209 
     | 
    
         
            -
                              [timeout, elapsed]
         
     | 
| 
       210 
     | 
    
         
            -
                            raise ConnectionTimeoutError, msg
         
     | 
| 
       211 
     | 
    
         
            -
                          end
         
     | 
| 
       212 
     | 
    
         
            -
                        end
         
     | 
| 
       213 
     | 
    
         
            -
                      ensure
         
     | 
| 
       214 
     | 
    
         
            -
                        @num_waiting -= 1
         
     | 
| 
       215 
     | 
    
         
            -
                      end
         
     | 
| 
       216 
     | 
    
         
            -
                  end
         
     | 
| 
       217 
     | 
    
         
            -
             
     | 
| 
       218 
     | 
    
         
            -
                  # Adds the ability to turn a basic fair FIFO queue into one
         
     | 
| 
       219 
     | 
    
         
            -
                  # biased to some thread.
         
     | 
| 
       220 
     | 
    
         
            -
                  module BiasableQueue # :nodoc:
         
     | 
| 
       221 
     | 
    
         
            -
                    class BiasedConditionVariable # :nodoc:
         
     | 
| 
       222 
     | 
    
         
            -
                      # semantics of condition variables guarantee that +broadcast+, +broadcast_on_biased+,
         
     | 
| 
       223 
     | 
    
         
            -
                      # +signal+ and +wait+ methods are only called while holding a lock
         
     | 
| 
       224 
     | 
    
         
            -
                      def initialize(lock, other_cond, preferred_thread)
         
     | 
| 
       225 
     | 
    
         
            -
                        @real_cond = lock.new_cond
         
     | 
| 
       226 
     | 
    
         
            -
                        @other_cond = other_cond
         
     | 
| 
       227 
     | 
    
         
            -
                        @preferred_thread = preferred_thread
         
     | 
| 
       228 
     | 
    
         
            -
                        @num_waiting_on_real_cond = 0
         
     | 
| 
       229 
     | 
    
         
            -
                      end
         
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
                      def broadcast
         
     | 
| 
       232 
     | 
    
         
            -
                        broadcast_on_biased
         
     | 
| 
       233 
     | 
    
         
            -
                        @other_cond.broadcast
         
     | 
| 
       234 
     | 
    
         
            -
                      end
         
     | 
| 
       235 
     | 
    
         
            -
             
     | 
| 
       236 
     | 
    
         
            -
                      def broadcast_on_biased
         
     | 
| 
       237 
     | 
    
         
            -
                        @num_waiting_on_real_cond = 0
         
     | 
| 
       238 
     | 
    
         
            -
                        @real_cond.broadcast
         
     | 
| 
       239 
     | 
    
         
            -
                      end
         
     | 
| 
       240 
     | 
    
         
            -
             
     | 
| 
       241 
     | 
    
         
            -
                      def signal
         
     | 
| 
       242 
     | 
    
         
            -
                        if @num_waiting_on_real_cond > 0
         
     | 
| 
       243 
     | 
    
         
            -
                          @num_waiting_on_real_cond -= 1
         
     | 
| 
       244 
     | 
    
         
            -
                          @real_cond
         
     | 
| 
       245 
     | 
    
         
            -
                        else
         
     | 
| 
       246 
     | 
    
         
            -
                          @other_cond
         
     | 
| 
       247 
     | 
    
         
            -
                        end.signal
         
     | 
| 
       248 
     | 
    
         
            -
                      end
         
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
                      def wait(timeout)
         
     | 
| 
       251 
     | 
    
         
            -
                        if Thread.current == @preferred_thread
         
     | 
| 
       252 
     | 
    
         
            -
                          @num_waiting_on_real_cond += 1
         
     | 
| 
       253 
     | 
    
         
            -
                          @real_cond
         
     | 
| 
       254 
     | 
    
         
            -
                        else
         
     | 
| 
       255 
     | 
    
         
            -
                          @other_cond
         
     | 
| 
       256 
     | 
    
         
            -
                        end.wait(timeout)
         
     | 
| 
       257 
     | 
    
         
            -
                      end
         
     | 
| 
       258 
     | 
    
         
            -
                    end
         
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
     | 
    
         
            -
                    def with_a_bias_for(thread)
         
     | 
| 
       261 
     | 
    
         
            -
                      previous_cond = nil
         
     | 
| 
       262 
     | 
    
         
            -
                      new_cond      = nil
         
     | 
| 
       263 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       264 
     | 
    
         
            -
                        previous_cond = @cond
         
     | 
| 
       265 
     | 
    
         
            -
                        @cond = new_cond = BiasedConditionVariable.new(@lock, @cond, thread)
         
     | 
| 
       266 
     | 
    
         
            -
                      end
         
     | 
| 
       267 
     | 
    
         
            -
                      yield
         
     | 
| 
       268 
     | 
    
         
            -
                    ensure
         
     | 
| 
       269 
     | 
    
         
            -
                      synchronize do
         
     | 
| 
       270 
     | 
    
         
            -
                        @cond = previous_cond if previous_cond
         
     | 
| 
       271 
     | 
    
         
            -
                        new_cond.broadcast_on_biased if new_cond # wake up any remaining sleepers
         
     | 
| 
       272 
     | 
    
         
            -
                      end
         
     | 
| 
       273 
     | 
    
         
            -
                    end
         
     | 
| 
       274 
     | 
    
         
            -
                  end
         
     | 
| 
       275 
     | 
    
         
            -
             
     | 
| 
       276 
     | 
    
         
            -
                  # Connections must be leased while holding the main pool mutex. This is
         
     | 
| 
       277 
     | 
    
         
            -
                  # an internal subclass that also +.leases+ returned connections while
         
     | 
| 
       278 
     | 
    
         
            -
                  # still in queue's critical section (queue synchronizes with the same
         
     | 
| 
       279 
     | 
    
         
            -
                  # <tt>@lock</tt> as the main pool) so that a returned connection is already
         
     | 
| 
       280 
     | 
    
         
            -
                  # leased and there is no need to re-enter synchronized block.
         
     | 
| 
       281 
     | 
    
         
            -
                  class ConnectionLeasingQueue < Queue # :nodoc:
         
     | 
| 
       282 
     | 
    
         
            -
                    include BiasableQueue
         
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
                    private
         
     | 
| 
       285 
     | 
    
         
            -
                      def internal_poll(timeout)
         
     | 
| 
       286 
     | 
    
         
            -
                        conn = super
         
     | 
| 
       287 
     | 
    
         
            -
                        conn.lease if conn
         
     | 
| 
       288 
     | 
    
         
            -
                        conn
         
     | 
| 
       289 
     | 
    
         
            -
                      end
         
     | 
| 
       290 
     | 
    
         
            -
                  end
         
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
       292 
     | 
    
         
            -
                  # Every +frequency+ seconds, the reaper will call +reap+ and +flush+ on
         
     | 
| 
       293 
     | 
    
         
            -
                  # +pool+. A reaper instantiated with a zero frequency will never reap
         
     | 
| 
       294 
     | 
    
         
            -
                  # the connection pool.
         
     | 
| 
       295 
     | 
    
         
            -
                  #
         
     | 
| 
       296 
     | 
    
         
            -
                  # Configure the frequency by setting +reaping_frequency+ in your database
         
     | 
| 
       297 
     | 
    
         
            -
                  # yaml file (default 60 seconds).
         
     | 
| 
       298 
     | 
    
         
            -
                  class Reaper
         
     | 
| 
       299 
     | 
    
         
            -
                    attr_reader :pool, :frequency
         
     | 
| 
       300 
     | 
    
         
            -
             
     | 
| 
       301 
     | 
    
         
            -
                    def initialize(pool, frequency)
         
     | 
| 
       302 
     | 
    
         
            -
                      @pool      = pool
         
     | 
| 
       303 
     | 
    
         
            -
                      @frequency = frequency
         
     | 
| 
       304 
     | 
    
         
            -
                    end
         
     | 
| 
       305 
     | 
    
         
            -
             
     | 
| 
       306 
     | 
    
         
            -
                    @mutex = Mutex.new
         
     | 
| 
       307 
     | 
    
         
            -
                    @pools = {}
         
     | 
| 
       308 
     | 
    
         
            -
                    @threads = {}
         
     | 
| 
       309 
     | 
    
         
            -
             
     | 
| 
       310 
     | 
    
         
            -
                    class << self
         
     | 
| 
       311 
     | 
    
         
            -
                      def register_pool(pool, frequency) # :nodoc:
         
     | 
| 
       312 
     | 
    
         
            -
                        @mutex.synchronize do
         
     | 
| 
       313 
     | 
    
         
            -
                          unless @threads[frequency]&.alive?
         
     | 
| 
       314 
     | 
    
         
            -
                            @threads[frequency] = spawn_thread(frequency)
         
     | 
| 
       315 
     | 
    
         
            -
                          end
         
     | 
| 
       316 
     | 
    
         
            -
                          @pools[frequency] ||= []
         
     | 
| 
       317 
     | 
    
         
            -
                          @pools[frequency] << WeakRef.new(pool)
         
     | 
| 
       318 
     | 
    
         
            -
                        end
         
     | 
| 
       319 
     | 
    
         
            -
                      end
         
     | 
| 
       320 
     | 
    
         
            -
             
     | 
| 
       321 
     | 
    
         
            -
                      private
         
     | 
| 
       322 
     | 
    
         
            -
                        def spawn_thread(frequency)
         
     | 
| 
       323 
     | 
    
         
            -
                          Thread.new(frequency) do |t|
         
     | 
| 
       324 
     | 
    
         
            -
                            # Advise multi-threaded app servers to ignore this thread for
         
     | 
| 
       325 
     | 
    
         
            -
                            # the purposes of fork safety warnings
         
     | 
| 
       326 
     | 
    
         
            -
                            Thread.current.thread_variable_set(:fork_safe, true)
         
     | 
| 
       327 
     | 
    
         
            -
                            running = true
         
     | 
| 
       328 
     | 
    
         
            -
                            while running
         
     | 
| 
       329 
     | 
    
         
            -
                              sleep t
         
     | 
| 
       330 
     | 
    
         
            -
                              @mutex.synchronize do
         
     | 
| 
       331 
     | 
    
         
            -
                                @pools[frequency].select! do |pool|
         
     | 
| 
       332 
     | 
    
         
            -
                                  pool.weakref_alive? && !pool.discarded?
         
     | 
| 
       333 
     | 
    
         
            -
                                end
         
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
                                @pools[frequency].each do |p|
         
     | 
| 
       336 
     | 
    
         
            -
                                  p.reap
         
     | 
| 
       337 
     | 
    
         
            -
                                  p.flush
         
     | 
| 
       338 
     | 
    
         
            -
                                rescue WeakRef::RefError
         
     | 
| 
       339 
     | 
    
         
            -
                                end
         
     | 
| 
       340 
     | 
    
         
            -
             
     | 
| 
       341 
     | 
    
         
            -
                                if @pools[frequency].empty?
         
     | 
| 
       342 
     | 
    
         
            -
                                  @pools.delete(frequency)
         
     | 
| 
       343 
     | 
    
         
            -
                                  @threads.delete(frequency)
         
     | 
| 
       344 
     | 
    
         
            -
                                  running = false
         
     | 
| 
       345 
     | 
    
         
            -
                                end
         
     | 
| 
       346 
     | 
    
         
            -
                              end
         
     | 
| 
       347 
     | 
    
         
            -
                            end
         
     | 
| 
       348 
     | 
    
         
            -
                          end
         
     | 
| 
       349 
     | 
    
         
            -
                        end
         
     | 
| 
       350 
     | 
    
         
            -
                    end
         
     | 
| 
       351 
     | 
    
         
            -
             
     | 
| 
       352 
     | 
    
         
            -
                    def run
         
     | 
| 
       353 
     | 
    
         
            -
                      return unless frequency && frequency > 0
         
     | 
| 
       354 
     | 
    
         
            -
                      self.class.register_pool(pool, frequency)
         
     | 
| 
       355 
     | 
    
         
            -
                    end
         
     | 
| 
       356 
     | 
    
         
            -
                  end
         
     | 
| 
       357 
     | 
    
         
            -
             
     | 
| 
       358 
107 
     | 
    
         
             
                  include MonitorMixin
         
     | 
| 
       359 
108 
     | 
    
         
             
                  include QueryCache::ConnectionPoolConfiguration
         
     | 
| 
       360 
109 
     | 
    
         
             
                  include ConnectionAdapters::AbstractPool
         
     | 
| 
       361 
110 
     | 
    
         | 
| 
       362 
111 
     | 
    
         
             
                  attr_accessor :automatic_reconnect, :checkout_timeout
         
     | 
| 
       363 
     | 
    
         
            -
                  attr_reader :db_config, :size, :reaper, :pool_config, : 
     | 
| 
      
 112 
     | 
    
         
            +
                  attr_reader :db_config, :size, :reaper, :pool_config, :async_executor, :role, :shard
         
     | 
| 
       364 
113 
     | 
    
         | 
| 
       365 
     | 
    
         
            -
                  delegate : 
     | 
| 
      
 114 
     | 
    
         
            +
                  delegate :schema_reflection, :schema_reflection=, to: :pool_config
         
     | 
| 
       366 
115 
     | 
    
         | 
| 
       367 
116 
     | 
    
         
             
                  # Creates a new ConnectionPool object. +pool_config+ is a PoolConfig
         
     | 
| 
       368 
117 
     | 
    
         
             
                  # object which describes database connection information (e.g. adapter,
         
     | 
| 
         @@ -375,7 +124,8 @@ module ActiveRecord 
     | 
|
| 
       375 
124 
     | 
    
         | 
| 
       376 
125 
     | 
    
         
             
                    @pool_config = pool_config
         
     | 
| 
       377 
126 
     | 
    
         
             
                    @db_config = pool_config.db_config
         
     | 
| 
       378 
     | 
    
         
            -
                    @ 
     | 
| 
      
 127 
     | 
    
         
            +
                    @role = pool_config.role
         
     | 
| 
      
 128 
     | 
    
         
            +
                    @shard = pool_config.shard
         
     | 
| 
       379 
129 
     | 
    
         | 
| 
       380 
130 
     | 
    
         
             
                    @checkout_timeout = db_config.checkout_timeout
         
     | 
| 
       381 
131 
     | 
    
         
             
                    @idle_timeout = db_config.idle_timeout
         
     | 
| 
         @@ -407,16 +157,22 @@ module ActiveRecord 
     | 
|
| 
       407 
157 
     | 
    
         | 
| 
       408 
158 
     | 
    
         
             
                    @lock_thread = false
         
     | 
| 
       409 
159 
     | 
    
         | 
| 
      
 160 
     | 
    
         
            +
                    @async_executor = build_async_executor
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
       410 
162 
     | 
    
         
             
                    @reaper = Reaper.new(self, db_config.reaping_frequency)
         
     | 
| 
       411 
163 
     | 
    
         
             
                    @reaper.run
         
     | 
| 
       412 
164 
     | 
    
         
             
                  end
         
     | 
| 
       413 
165 
     | 
    
         | 
| 
       414 
166 
     | 
    
         
             
                  def lock_thread=(lock_thread)
         
     | 
| 
       415 
167 
     | 
    
         
             
                    if lock_thread
         
     | 
| 
       416 
     | 
    
         
            -
                      @lock_thread =  
     | 
| 
      
 168 
     | 
    
         
            +
                      @lock_thread = ActiveSupport::IsolatedExecutionState.context
         
     | 
| 
       417 
169 
     | 
    
         
             
                    else
         
     | 
| 
       418 
170 
     | 
    
         
             
                      @lock_thread = nil
         
     | 
| 
       419 
171 
     | 
    
         
             
                    end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                    if (active_connection = @thread_cached_conns[connection_cache_key(current_thread)])
         
     | 
| 
      
 174 
     | 
    
         
            +
                      active_connection.lock_thread = @lock_thread
         
     | 
| 
      
 175 
     | 
    
         
            +
                    end
         
     | 
| 
       420 
176 
     | 
    
         
             
                  end
         
     | 
| 
       421 
177 
     | 
    
         | 
| 
       422 
178 
     | 
    
         
             
                  # Retrieve the connection associated with the current thread, or call
         
     | 
| 
         @@ -428,6 +184,12 @@ module ActiveRecord 
     | 
|
| 
       428 
184 
     | 
    
         
             
                    @thread_cached_conns[connection_cache_key(current_thread)] ||= checkout
         
     | 
| 
       429 
185 
     | 
    
         
             
                  end
         
     | 
| 
       430 
186 
     | 
    
         | 
| 
      
 187 
     | 
    
         
            +
                  def connection_class # :nodoc:
         
     | 
| 
      
 188 
     | 
    
         
            +
                    pool_config.connection_class
         
     | 
| 
      
 189 
     | 
    
         
            +
                  end
         
     | 
| 
      
 190 
     | 
    
         
            +
                  alias :connection_klass :connection_class
         
     | 
| 
      
 191 
     | 
    
         
            +
                  deprecate :connection_klass, deprecator: ActiveRecord.deprecator
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
       431 
193 
     | 
    
         
             
                  # Returns true if there is an open connection being used for the current thread.
         
     | 
| 
       432 
194 
     | 
    
         
             
                  #
         
     | 
| 
       433 
195 
     | 
    
         
             
                  # This method only works for connections that have been obtained through
         
     | 
| 
         @@ -444,18 +206,23 @@ module ActiveRecord 
     | 
|
| 
       444 
206 
     | 
    
         
             
                  # This method only works for connections that have been obtained through
         
     | 
| 
       445 
207 
     | 
    
         
             
                  # #connection or #with_connection methods, connections obtained through
         
     | 
| 
       446 
208 
     | 
    
         
             
                  # #checkout will not be automatically released.
         
     | 
| 
       447 
     | 
    
         
            -
                  def release_connection(owner_thread =  
     | 
| 
      
 209 
     | 
    
         
            +
                  def release_connection(owner_thread = ActiveSupport::IsolatedExecutionState.context)
         
     | 
| 
       448 
210 
     | 
    
         
             
                    if conn = @thread_cached_conns.delete(connection_cache_key(owner_thread))
         
     | 
| 
       449 
211 
     | 
    
         
             
                      checkin conn
         
     | 
| 
       450 
212 
     | 
    
         
             
                    end
         
     | 
| 
       451 
213 
     | 
    
         
             
                  end
         
     | 
| 
       452 
214 
     | 
    
         | 
| 
       453 
     | 
    
         
            -
                  #  
     | 
| 
       454 
     | 
    
         
            -
                  # already  
     | 
| 
       455 
     | 
    
         
            -
                  #  
     | 
| 
       456 
     | 
    
         
            -
                  #  
     | 
| 
      
 215 
     | 
    
         
            +
                  # Yields a connection from the connection pool to the block. If no connection
         
     | 
| 
      
 216 
     | 
    
         
            +
                  # is already checked out by the current thread, a connection will be checked
         
     | 
| 
      
 217 
     | 
    
         
            +
                  # out from the pool, yielded to the block, and then returned to the pool when
         
     | 
| 
      
 218 
     | 
    
         
            +
                  # the block is finished. If a connection has already been checked out on the
         
     | 
| 
      
 219 
     | 
    
         
            +
                  # current thread, such as via #connection or #with_connection, that existing
         
     | 
| 
      
 220 
     | 
    
         
            +
                  # connection will be the one yielded and it will not be returned to the pool
         
     | 
| 
      
 221 
     | 
    
         
            +
                  # automatically at the end of the block; it is expected that such an existing
         
     | 
| 
      
 222 
     | 
    
         
            +
                  # connection will be properly returned to the pool by the code that checked
         
     | 
| 
      
 223 
     | 
    
         
            +
                  # it out.
         
     | 
| 
       457 
224 
     | 
    
         
             
                  def with_connection
         
     | 
| 
       458 
     | 
    
         
            -
                    unless conn = @thread_cached_conns[connection_cache_key( 
     | 
| 
      
 225 
     | 
    
         
            +
                    unless conn = @thread_cached_conns[connection_cache_key(ActiveSupport::IsolatedExecutionState.context)]
         
     | 
| 
       459 
226 
     | 
    
         
             
                      conn = connection
         
     | 
| 
       460 
227 
     | 
    
         
             
                      fresh_connection = true
         
     | 
| 
       461 
228 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -585,7 +352,9 @@ module ActiveRecord 
     | 
|
| 
       585 
352 
     | 
    
         
             
                  # Raises:
         
     | 
| 
       586 
353 
     | 
    
         
             
                  # - ActiveRecord::ConnectionTimeoutError no connection can be obtained from the pool.
         
     | 
| 
       587 
354 
     | 
    
         
             
                  def checkout(checkout_timeout = @checkout_timeout)
         
     | 
| 
       588 
     | 
    
         
            -
                    checkout_and_verify(acquire_connection(checkout_timeout))
         
     | 
| 
      
 355 
     | 
    
         
            +
                    connection = checkout_and_verify(acquire_connection(checkout_timeout))
         
     | 
| 
      
 356 
     | 
    
         
            +
                    connection.lock_thread = @lock_thread
         
     | 
| 
      
 357 
     | 
    
         
            +
                    connection
         
     | 
| 
       589 
358 
     | 
    
         
             
                  end
         
     | 
| 
       590 
359 
     | 
    
         | 
| 
       591 
360 
     | 
    
         
             
                  # Check-in a database connection back into the pool, indicating that you
         
     | 
| 
         @@ -602,6 +371,7 @@ module ActiveRecord 
     | 
|
| 
       602 
371 
     | 
    
         
             
                          conn.expire
         
     | 
| 
       603 
372 
     | 
    
         
             
                        end
         
     | 
| 
       604 
373 
     | 
    
         | 
| 
      
 374 
     | 
    
         
            +
                        conn.lock_thread = nil
         
     | 
| 
       605 
375 
     | 
    
         
             
                        @available.add conn
         
     | 
| 
       606 
376 
     | 
    
         
             
                      end
         
     | 
| 
       607 
377 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -713,7 +483,28 @@ module ActiveRecord 
     | 
|
| 
       713 
483 
     | 
    
         
             
                    end
         
     | 
| 
       714 
484 
     | 
    
         
             
                  end
         
     | 
| 
       715 
485 
     | 
    
         | 
| 
      
 486 
     | 
    
         
            +
                  def schedule_query(future_result) # :nodoc:
         
     | 
| 
      
 487 
     | 
    
         
            +
                    @async_executor.post { future_result.execute_or_skip }
         
     | 
| 
      
 488 
     | 
    
         
            +
                    Thread.pass
         
     | 
| 
      
 489 
     | 
    
         
            +
                  end
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
       716 
491 
     | 
    
         
             
                  private
         
     | 
| 
      
 492 
     | 
    
         
            +
                    def build_async_executor
         
     | 
| 
      
 493 
     | 
    
         
            +
                      case ActiveRecord.async_query_executor
         
     | 
| 
      
 494 
     | 
    
         
            +
                      when :multi_thread_pool
         
     | 
| 
      
 495 
     | 
    
         
            +
                        if @db_config.max_threads > 0
         
     | 
| 
      
 496 
     | 
    
         
            +
                          Concurrent::ThreadPoolExecutor.new(
         
     | 
| 
      
 497 
     | 
    
         
            +
                            min_threads: @db_config.min_threads,
         
     | 
| 
      
 498 
     | 
    
         
            +
                            max_threads: @db_config.max_threads,
         
     | 
| 
      
 499 
     | 
    
         
            +
                            max_queue: @db_config.max_queue,
         
     | 
| 
      
 500 
     | 
    
         
            +
                            fallback_policy: :caller_runs
         
     | 
| 
      
 501 
     | 
    
         
            +
                          )
         
     | 
| 
      
 502 
     | 
    
         
            +
                        end
         
     | 
| 
      
 503 
     | 
    
         
            +
                      when :global_thread_pool
         
     | 
| 
      
 504 
     | 
    
         
            +
                        ActiveRecord.global_thread_pool_async_query_executor
         
     | 
| 
      
 505 
     | 
    
         
            +
                      end
         
     | 
| 
      
 506 
     | 
    
         
            +
                    end
         
     | 
| 
      
 507 
     | 
    
         
            +
             
     | 
| 
       717 
508 
     | 
    
         
             
                    #--
         
     | 
| 
       718 
509 
     | 
    
         
             
                    # this is unfortunately not concurrent
         
     | 
| 
       719 
510 
     | 
    
         
             
                    def bulk_make_new_connections(num_new_conns_needed)
         
     | 
| 
         @@ -736,7 +527,7 @@ module ActiveRecord 
     | 
|
| 
       736 
527 
     | 
    
         
             
                    end
         
     | 
| 
       737 
528 
     | 
    
         | 
| 
       738 
529 
     | 
    
         
             
                    def current_thread
         
     | 
| 
       739 
     | 
    
         
            -
                      @lock_thread ||  
     | 
| 
      
 530 
     | 
    
         
            +
                      @lock_thread || ActiveSupport::IsolatedExecutionState.context
         
     | 
| 
       740 
531 
     | 
    
         
             
                    end
         
     | 
| 
       741 
532 
     | 
    
         | 
| 
       742 
533 
     | 
    
         
             
                    # Take control of all existing connections so a "group" action such as
         
     | 
| 
         @@ -753,17 +544,17 @@ module ActiveRecord 
     | 
|
| 
       753 
544 
     | 
    
         
             
                    def attempt_to_checkout_all_existing_connections(raise_on_acquisition_timeout = true)
         
     | 
| 
       754 
545 
     | 
    
         
             
                      collected_conns = synchronize do
         
     | 
| 
       755 
546 
     | 
    
         
             
                        # account for our own connections
         
     | 
| 
       756 
     | 
    
         
            -
                        @connections.select { |conn| conn.owner ==  
     | 
| 
      
 547 
     | 
    
         
            +
                        @connections.select { |conn| conn.owner == ActiveSupport::IsolatedExecutionState.context }
         
     | 
| 
       757 
548 
     | 
    
         
             
                      end
         
     | 
| 
       758 
549 
     | 
    
         | 
| 
       759 
550 
     | 
    
         
             
                      newly_checked_out = []
         
     | 
| 
       760 
     | 
    
         
            -
                      timeout_time      =  
     | 
| 
      
 551 
     | 
    
         
            +
                      timeout_time      = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (@checkout_timeout * 2)
         
     | 
| 
       761 
552 
     | 
    
         | 
| 
       762 
     | 
    
         
            -
                      @available.with_a_bias_for( 
     | 
| 
      
 553 
     | 
    
         
            +
                      @available.with_a_bias_for(ActiveSupport::IsolatedExecutionState.context) do
         
     | 
| 
       763 
554 
     | 
    
         
             
                        loop do
         
     | 
| 
       764 
555 
     | 
    
         
             
                          synchronize do
         
     | 
| 
       765 
556 
     | 
    
         
             
                            return if collected_conns.size == @connections.size && @now_connecting == 0
         
     | 
| 
       766 
     | 
    
         
            -
                            remaining_timeout = timeout_time -  
     | 
| 
      
 557 
     | 
    
         
            +
                            remaining_timeout = timeout_time - Process.clock_gettime(Process::CLOCK_MONOTONIC)
         
     | 
| 
       767 
558 
     | 
    
         
             
                            remaining_timeout = 0 if remaining_timeout < 0
         
     | 
| 
       768 
559 
     | 
    
         
             
                            conn = checkout_for_exclusive_access(remaining_timeout)
         
     | 
| 
       769 
560 
     | 
    
         
             
                            collected_conns   << conn
         
     | 
| 
         @@ -806,7 +597,7 @@ module ActiveRecord 
     | 
|
| 
       806 
597 
     | 
    
         | 
| 
       807 
598 
     | 
    
         
             
                      thread_report = []
         
     | 
| 
       808 
599 
     | 
    
         
             
                      @connections.each do |conn|
         
     | 
| 
       809 
     | 
    
         
            -
                        unless conn.owner ==  
     | 
| 
      
 600 
     | 
    
         
            +
                        unless conn.owner == ActiveSupport::IsolatedExecutionState.context
         
     | 
| 
       810 
601 
     | 
    
         
             
                          thread_report << "#{conn} is owned by #{conn.owner}"
         
     | 
| 
       811 
602 
     | 
    
         
             
                        end
         
     | 
| 
       812 
603 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -879,9 +670,12 @@ module ActiveRecord 
     | 
|
| 
       879 
670 
     | 
    
         
             
                    alias_method :release, :remove_connection_from_thread_cache
         
     | 
| 
       880 
671 
     | 
    
         | 
| 
       881 
672 
     | 
    
         
             
                    def new_connection
         
     | 
| 
       882 
     | 
    
         
            -
                      Base.public_send(db_config.adapter_method, db_config.configuration_hash) 
     | 
| 
       883 
     | 
    
         
            -
             
     | 
| 
       884 
     | 
    
         
            -
                       
     | 
| 
      
 673 
     | 
    
         
            +
                      connection = Base.public_send(db_config.adapter_method, db_config.configuration_hash)
         
     | 
| 
      
 674 
     | 
    
         
            +
                      connection.pool = self
         
     | 
| 
      
 675 
     | 
    
         
            +
                      connection.check_version
         
     | 
| 
      
 676 
     | 
    
         
            +
                      connection
         
     | 
| 
      
 677 
     | 
    
         
            +
                    rescue ConnectionNotEstablished => ex
         
     | 
| 
      
 678 
     | 
    
         
            +
                      raise ex.set_pool(self)
         
     | 
| 
       885 
679 
     | 
    
         
             
                    end
         
     | 
| 
       886 
680 
     | 
    
         | 
| 
       887 
681 
     | 
    
         
             
                    # If the pool is not at a <tt>@size</tt> limit, establish new connection. Connecting
         
     | 
| 
         @@ -928,302 +722,14 @@ module ActiveRecord 
     | 
|
| 
       928 
722 
     | 
    
         | 
| 
       929 
723 
     | 
    
         
             
                    def checkout_and_verify(c)
         
     | 
| 
       930 
724 
     | 
    
         
             
                      c._run_checkout_callbacks do
         
     | 
| 
       931 
     | 
    
         
            -
                        c. 
     | 
| 
      
 725 
     | 
    
         
            +
                        c.clean!
         
     | 
| 
       932 
726 
     | 
    
         
             
                      end
         
     | 
| 
       933 
727 
     | 
    
         
             
                      c
         
     | 
| 
       934 
     | 
    
         
            -
                    rescue
         
     | 
| 
      
 728 
     | 
    
         
            +
                    rescue Exception
         
     | 
| 
       935 
729 
     | 
    
         
             
                      remove c
         
     | 
| 
       936 
730 
     | 
    
         
             
                      c.disconnect!
         
     | 
| 
       937 
731 
     | 
    
         
             
                      raise
         
     | 
| 
       938 
732 
     | 
    
         
             
                    end
         
     | 
| 
       939 
733 
     | 
    
         
             
                end
         
     | 
| 
       940 
     | 
    
         
            -
             
     | 
| 
       941 
     | 
    
         
            -
                # ConnectionHandler is a collection of ConnectionPool objects. It is used
         
     | 
| 
       942 
     | 
    
         
            -
                # for keeping separate connection pools that connect to different databases.
         
     | 
| 
       943 
     | 
    
         
            -
                #
         
     | 
| 
       944 
     | 
    
         
            -
                # For example, suppose that you have 5 models, with the following hierarchy:
         
     | 
| 
       945 
     | 
    
         
            -
                #
         
     | 
| 
       946 
     | 
    
         
            -
                #   class Author < ActiveRecord::Base
         
     | 
| 
       947 
     | 
    
         
            -
                #   end
         
     | 
| 
       948 
     | 
    
         
            -
                #
         
     | 
| 
       949 
     | 
    
         
            -
                #   class BankAccount < ActiveRecord::Base
         
     | 
| 
       950 
     | 
    
         
            -
                #   end
         
     | 
| 
       951 
     | 
    
         
            -
                #
         
     | 
| 
       952 
     | 
    
         
            -
                #   class Book < ActiveRecord::Base
         
     | 
| 
       953 
     | 
    
         
            -
                #     establish_connection :library_db
         
     | 
| 
       954 
     | 
    
         
            -
                #   end
         
     | 
| 
       955 
     | 
    
         
            -
                #
         
     | 
| 
       956 
     | 
    
         
            -
                #   class ScaryBook < Book
         
     | 
| 
       957 
     | 
    
         
            -
                #   end
         
     | 
| 
       958 
     | 
    
         
            -
                #
         
     | 
| 
       959 
     | 
    
         
            -
                #   class GoodBook < Book
         
     | 
| 
       960 
     | 
    
         
            -
                #   end
         
     | 
| 
       961 
     | 
    
         
            -
                #
         
     | 
| 
       962 
     | 
    
         
            -
                # And a database.yml that looked like this:
         
     | 
| 
       963 
     | 
    
         
            -
                #
         
     | 
| 
       964 
     | 
    
         
            -
                #   development:
         
     | 
| 
       965 
     | 
    
         
            -
                #     database: my_application
         
     | 
| 
       966 
     | 
    
         
            -
                #     host: localhost
         
     | 
| 
       967 
     | 
    
         
            -
                #
         
     | 
| 
       968 
     | 
    
         
            -
                #   library_db:
         
     | 
| 
       969 
     | 
    
         
            -
                #     database: library
         
     | 
| 
       970 
     | 
    
         
            -
                #     host: some.library.org
         
     | 
| 
       971 
     | 
    
         
            -
                #
         
     | 
| 
       972 
     | 
    
         
            -
                # Your primary database in the development environment is "my_application"
         
     | 
| 
       973 
     | 
    
         
            -
                # but the Book model connects to a separate database called "library_db"
         
     | 
| 
       974 
     | 
    
         
            -
                # (this can even be a database on a different machine).
         
     | 
| 
       975 
     | 
    
         
            -
                #
         
     | 
| 
       976 
     | 
    
         
            -
                # Book, ScaryBook and GoodBook will all use the same connection pool to
         
     | 
| 
       977 
     | 
    
         
            -
                # "library_db" while Author, BankAccount, and any other models you create
         
     | 
| 
       978 
     | 
    
         
            -
                # will use the default connection pool to "my_application".
         
     | 
| 
       979 
     | 
    
         
            -
                #
         
     | 
| 
       980 
     | 
    
         
            -
                # The various connection pools are managed by a single instance of
         
     | 
| 
       981 
     | 
    
         
            -
                # ConnectionHandler accessible via ActiveRecord::Base.connection_handler.
         
     | 
| 
       982 
     | 
    
         
            -
                # All Active Record models use this handler to determine the connection pool that they
         
     | 
| 
       983 
     | 
    
         
            -
                # should use.
         
     | 
| 
       984 
     | 
    
         
            -
                #
         
     | 
| 
       985 
     | 
    
         
            -
                # The ConnectionHandler class is not coupled with the Active models, as it has no knowledge
         
     | 
| 
       986 
     | 
    
         
            -
                # about the model. The model needs to pass a connection specification name to the handler,
         
     | 
| 
       987 
     | 
    
         
            -
                # in order to look up the correct connection pool.
         
     | 
| 
       988 
     | 
    
         
            -
                class ConnectionHandler
         
     | 
| 
       989 
     | 
    
         
            -
                  FINALIZER = lambda { |_| ActiveSupport::ForkTracker.check! }
         
     | 
| 
       990 
     | 
    
         
            -
                  private_constant :FINALIZER
         
     | 
| 
       991 
     | 
    
         
            -
             
     | 
| 
       992 
     | 
    
         
            -
                  def initialize
         
     | 
| 
       993 
     | 
    
         
            -
                    # These caches are keyed by pool_config.connection_specification_name (PoolConfig#connection_specification_name).
         
     | 
| 
       994 
     | 
    
         
            -
                    @owner_to_pool_manager = Concurrent::Map.new(initial_capacity: 2)
         
     | 
| 
       995 
     | 
    
         
            -
             
     | 
| 
       996 
     | 
    
         
            -
                    # Backup finalizer: if the forked child skipped Kernel#fork the early discard has not occurred
         
     | 
| 
       997 
     | 
    
         
            -
                    ObjectSpace.define_finalizer self, FINALIZER
         
     | 
| 
       998 
     | 
    
         
            -
                  end
         
     | 
| 
       999 
     | 
    
         
            -
             
     | 
| 
       1000 
     | 
    
         
            -
                  def prevent_writes # :nodoc:
         
     | 
| 
       1001 
     | 
    
         
            -
                    Thread.current[:prevent_writes]
         
     | 
| 
       1002 
     | 
    
         
            -
                  end
         
     | 
| 
       1003 
     | 
    
         
            -
             
     | 
| 
       1004 
     | 
    
         
            -
                  def prevent_writes=(prevent_writes) # :nodoc:
         
     | 
| 
       1005 
     | 
    
         
            -
                    Thread.current[:prevent_writes] = prevent_writes
         
     | 
| 
       1006 
     | 
    
         
            -
                  end
         
     | 
| 
       1007 
     | 
    
         
            -
             
     | 
| 
       1008 
     | 
    
         
            -
                  # Prevent writing to the database regardless of role.
         
     | 
| 
       1009 
     | 
    
         
            -
                  #
         
     | 
| 
       1010 
     | 
    
         
            -
                  # In some cases you may want to prevent writes to the database
         
     | 
| 
       1011 
     | 
    
         
            -
                  # even if you are on a database that can write. `while_preventing_writes`
         
     | 
| 
       1012 
     | 
    
         
            -
                  # will prevent writes to the database for the duration of the block.
         
     | 
| 
       1013 
     | 
    
         
            -
                  #
         
     | 
| 
       1014 
     | 
    
         
            -
                  # This method does not provide the same protection as a readonly
         
     | 
| 
       1015 
     | 
    
         
            -
                  # user and is meant to be a safeguard against accidental writes.
         
     | 
| 
       1016 
     | 
    
         
            -
                  #
         
     | 
| 
       1017 
     | 
    
         
            -
                  # See `READ_QUERY` for the queries that are blocked by this
         
     | 
| 
       1018 
     | 
    
         
            -
                  # method.
         
     | 
| 
       1019 
     | 
    
         
            -
                  def while_preventing_writes(enabled = true)
         
     | 
| 
       1020 
     | 
    
         
            -
                    unless ActiveRecord::Base.legacy_connection_handling
         
     | 
| 
       1021 
     | 
    
         
            -
                      raise NotImplementedError, "`while_preventing_writes` is only available on the connection_handler with legacy_connection_handling"
         
     | 
| 
       1022 
     | 
    
         
            -
                    end
         
     | 
| 
       1023 
     | 
    
         
            -
             
     | 
| 
       1024 
     | 
    
         
            -
                    original, self.prevent_writes = self.prevent_writes, enabled
         
     | 
| 
       1025 
     | 
    
         
            -
                    yield
         
     | 
| 
       1026 
     | 
    
         
            -
                  ensure
         
     | 
| 
       1027 
     | 
    
         
            -
                    self.prevent_writes = original
         
     | 
| 
       1028 
     | 
    
         
            -
                  end
         
     | 
| 
       1029 
     | 
    
         
            -
             
     | 
| 
       1030 
     | 
    
         
            -
                  def connection_pool_names # :nodoc:
         
     | 
| 
       1031 
     | 
    
         
            -
                    owner_to_pool_manager.keys
         
     | 
| 
       1032 
     | 
    
         
            -
                  end
         
     | 
| 
       1033 
     | 
    
         
            -
             
     | 
| 
       1034 
     | 
    
         
            -
                  def all_connection_pools
         
     | 
| 
       1035 
     | 
    
         
            -
                    owner_to_pool_manager.values.flat_map { |m| m.pool_configs.map(&:pool) }
         
     | 
| 
       1036 
     | 
    
         
            -
                  end
         
     | 
| 
       1037 
     | 
    
         
            -
             
     | 
| 
       1038 
     | 
    
         
            -
                  def connection_pool_list(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1039 
     | 
    
         
            -
                    owner_to_pool_manager.values.flat_map { |m| m.pool_configs(role).map(&:pool) }
         
     | 
| 
       1040 
     | 
    
         
            -
                  end
         
     | 
| 
       1041 
     | 
    
         
            -
                  alias :connection_pools :connection_pool_list
         
     | 
| 
       1042 
     | 
    
         
            -
             
     | 
| 
       1043 
     | 
    
         
            -
                  def establish_connection(config, owner_name: Base, role: ActiveRecord::Base.current_role, shard: Base.current_shard)
         
     | 
| 
       1044 
     | 
    
         
            -
                    owner_name = config.to_s if config.is_a?(Symbol)
         
     | 
| 
       1045 
     | 
    
         
            -
             
     | 
| 
       1046 
     | 
    
         
            -
                    pool_config = resolve_pool_config(config, owner_name)
         
     | 
| 
       1047 
     | 
    
         
            -
                    db_config = pool_config.db_config
         
     | 
| 
       1048 
     | 
    
         
            -
             
     | 
| 
       1049 
     | 
    
         
            -
                    # Protects the connection named `ActiveRecord::Base` from being removed
         
     | 
| 
       1050 
     | 
    
         
            -
                    # if the user calls `establish_connection :primary`.
         
     | 
| 
       1051 
     | 
    
         
            -
                    if owner_to_pool_manager.key?(pool_config.connection_specification_name)
         
     | 
| 
       1052 
     | 
    
         
            -
                      remove_connection_pool(pool_config.connection_specification_name, role: role, shard: shard)
         
     | 
| 
       1053 
     | 
    
         
            -
                    end
         
     | 
| 
       1054 
     | 
    
         
            -
             
     | 
| 
       1055 
     | 
    
         
            -
                    message_bus = ActiveSupport::Notifications.instrumenter
         
     | 
| 
       1056 
     | 
    
         
            -
                    payload = {}
         
     | 
| 
       1057 
     | 
    
         
            -
                    if pool_config
         
     | 
| 
       1058 
     | 
    
         
            -
                      payload[:spec_name] = pool_config.connection_specification_name
         
     | 
| 
       1059 
     | 
    
         
            -
                      payload[:shard] = shard
         
     | 
| 
       1060 
     | 
    
         
            -
                      payload[:config] = db_config.configuration_hash
         
     | 
| 
       1061 
     | 
    
         
            -
                    end
         
     | 
| 
       1062 
     | 
    
         
            -
             
     | 
| 
       1063 
     | 
    
         
            -
                    if ActiveRecord::Base.legacy_connection_handling
         
     | 
| 
       1064 
     | 
    
         
            -
                      owner_to_pool_manager[pool_config.connection_specification_name] ||= LegacyPoolManager.new
         
     | 
| 
       1065 
     | 
    
         
            -
                    else
         
     | 
| 
       1066 
     | 
    
         
            -
                      owner_to_pool_manager[pool_config.connection_specification_name] ||= PoolManager.new
         
     | 
| 
       1067 
     | 
    
         
            -
                    end
         
     | 
| 
       1068 
     | 
    
         
            -
                    pool_manager = get_pool_manager(pool_config.connection_specification_name)
         
     | 
| 
       1069 
     | 
    
         
            -
                    pool_manager.set_pool_config(role, shard, pool_config)
         
     | 
| 
       1070 
     | 
    
         
            -
             
     | 
| 
       1071 
     | 
    
         
            -
                    message_bus.instrument("!connection.active_record", payload) do
         
     | 
| 
       1072 
     | 
    
         
            -
                      pool_config.pool
         
     | 
| 
       1073 
     | 
    
         
            -
                    end
         
     | 
| 
       1074 
     | 
    
         
            -
                  end
         
     | 
| 
       1075 
     | 
    
         
            -
             
     | 
| 
       1076 
     | 
    
         
            -
                  # Returns true if there are any active connections among the connection
         
     | 
| 
       1077 
     | 
    
         
            -
                  # pools that the ConnectionHandler is managing.
         
     | 
| 
       1078 
     | 
    
         
            -
                  def active_connections?(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1079 
     | 
    
         
            -
                    connection_pool_list(role).any?(&:active_connection?)
         
     | 
| 
       1080 
     | 
    
         
            -
                  end
         
     | 
| 
       1081 
     | 
    
         
            -
             
     | 
| 
       1082 
     | 
    
         
            -
                  # Returns any connections in use by the current thread back to the pool,
         
     | 
| 
       1083 
     | 
    
         
            -
                  # and also returns connections to the pool cached by threads that are no
         
     | 
| 
       1084 
     | 
    
         
            -
                  # longer alive.
         
     | 
| 
       1085 
     | 
    
         
            -
                  def clear_active_connections!(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1086 
     | 
    
         
            -
                    connection_pool_list(role).each(&:release_connection)
         
     | 
| 
       1087 
     | 
    
         
            -
                  end
         
     | 
| 
       1088 
     | 
    
         
            -
             
     | 
| 
       1089 
     | 
    
         
            -
                  # Clears the cache which maps classes.
         
     | 
| 
       1090 
     | 
    
         
            -
                  #
         
     | 
| 
       1091 
     | 
    
         
            -
                  # See ConnectionPool#clear_reloadable_connections! for details.
         
     | 
| 
       1092 
     | 
    
         
            -
                  def clear_reloadable_connections!(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1093 
     | 
    
         
            -
                    connection_pool_list(role).each(&:clear_reloadable_connections!)
         
     | 
| 
       1094 
     | 
    
         
            -
                  end
         
     | 
| 
       1095 
     | 
    
         
            -
             
     | 
| 
       1096 
     | 
    
         
            -
                  def clear_all_connections!(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1097 
     | 
    
         
            -
                    connection_pool_list(role).each(&:disconnect!)
         
     | 
| 
       1098 
     | 
    
         
            -
                  end
         
     | 
| 
       1099 
     | 
    
         
            -
             
     | 
| 
       1100 
     | 
    
         
            -
                  # Disconnects all currently idle connections.
         
     | 
| 
       1101 
     | 
    
         
            -
                  #
         
     | 
| 
       1102 
     | 
    
         
            -
                  # See ConnectionPool#flush! for details.
         
     | 
| 
       1103 
     | 
    
         
            -
                  def flush_idle_connections!(role = ActiveRecord::Base.current_role)
         
     | 
| 
       1104 
     | 
    
         
            -
                    connection_pool_list(role).each(&:flush!)
         
     | 
| 
       1105 
     | 
    
         
            -
                  end
         
     | 
| 
       1106 
     | 
    
         
            -
             
     | 
| 
       1107 
     | 
    
         
            -
                  # Locate the connection of the nearest super class. This can be an
         
     | 
| 
       1108 
     | 
    
         
            -
                  # active or defined connection: if it is the latter, it will be
         
     | 
| 
       1109 
     | 
    
         
            -
                  # opened and set as the active connection for the class it was defined
         
     | 
| 
       1110 
     | 
    
         
            -
                  # for (not necessarily the current class).
         
     | 
| 
       1111 
     | 
    
         
            -
                  def retrieve_connection(spec_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) # :nodoc:
         
     | 
| 
       1112 
     | 
    
         
            -
                    pool = retrieve_connection_pool(spec_name, role: role, shard: shard)
         
     | 
| 
       1113 
     | 
    
         
            -
             
     | 
| 
       1114 
     | 
    
         
            -
                    unless pool
         
     | 
| 
       1115 
     | 
    
         
            -
                      if shard != ActiveRecord::Base.default_shard
         
     | 
| 
       1116 
     | 
    
         
            -
                        message = "No connection pool for '#{spec_name}' found for the '#{shard}' shard."
         
     | 
| 
       1117 
     | 
    
         
            -
                      elsif ActiveRecord::Base.connection_handler != ActiveRecord::Base.default_connection_handler
         
     | 
| 
       1118 
     | 
    
         
            -
                        message = "No connection pool for '#{spec_name}' found for the '#{ActiveRecord::Base.current_role}' role."
         
     | 
| 
       1119 
     | 
    
         
            -
                      elsif role != ActiveRecord::Base.default_role
         
     | 
| 
       1120 
     | 
    
         
            -
                        message = "No connection pool for '#{spec_name}' found for the '#{role}' role."
         
     | 
| 
       1121 
     | 
    
         
            -
                      else
         
     | 
| 
       1122 
     | 
    
         
            -
                        message = "No connection pool for '#{spec_name}' found."
         
     | 
| 
       1123 
     | 
    
         
            -
                      end
         
     | 
| 
       1124 
     | 
    
         
            -
             
     | 
| 
       1125 
     | 
    
         
            -
                      raise ConnectionNotEstablished, message
         
     | 
| 
       1126 
     | 
    
         
            -
                    end
         
     | 
| 
       1127 
     | 
    
         
            -
             
     | 
| 
       1128 
     | 
    
         
            -
                    pool.connection
         
     | 
| 
       1129 
     | 
    
         
            -
                  end
         
     | 
| 
       1130 
     | 
    
         
            -
             
     | 
| 
       1131 
     | 
    
         
            -
                  # Returns true if a connection that's accessible to this class has
         
     | 
| 
       1132 
     | 
    
         
            -
                  # already been opened.
         
     | 
| 
       1133 
     | 
    
         
            -
                  def connected?(spec_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
         
     | 
| 
       1134 
     | 
    
         
            -
                    pool = retrieve_connection_pool(spec_name, role: role, shard: shard)
         
     | 
| 
       1135 
     | 
    
         
            -
                    pool && pool.connected?
         
     | 
| 
       1136 
     | 
    
         
            -
                  end
         
     | 
| 
       1137 
     | 
    
         
            -
             
     | 
| 
       1138 
     | 
    
         
            -
                  # Remove the connection for this class. This will close the active
         
     | 
| 
       1139 
     | 
    
         
            -
                  # connection and the defined connection (if they exist). The result
         
     | 
| 
       1140 
     | 
    
         
            -
                  # can be used as an argument for #establish_connection, for easily
         
     | 
| 
       1141 
     | 
    
         
            -
                  # re-establishing the connection.
         
     | 
| 
       1142 
     | 
    
         
            -
                  def remove_connection(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
         
     | 
| 
       1143 
     | 
    
         
            -
                    remove_connection_pool(owner, role: role, shard: shard)&.configuration_hash
         
     | 
| 
       1144 
     | 
    
         
            -
                  end
         
     | 
| 
       1145 
     | 
    
         
            -
                  deprecate remove_connection: "Use #remove_connection_pool, which now returns a DatabaseConfig object instead of a Hash"
         
     | 
| 
       1146 
     | 
    
         
            -
             
     | 
| 
       1147 
     | 
    
         
            -
                  def remove_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
         
     | 
| 
       1148 
     | 
    
         
            -
                    if pool_manager = get_pool_manager(owner)
         
     | 
| 
       1149 
     | 
    
         
            -
                      pool_config = pool_manager.remove_pool_config(role, shard)
         
     | 
| 
       1150 
     | 
    
         
            -
             
     | 
| 
       1151 
     | 
    
         
            -
                      if pool_config
         
     | 
| 
       1152 
     | 
    
         
            -
                        pool_config.disconnect!
         
     | 
| 
       1153 
     | 
    
         
            -
                        pool_config.db_config
         
     | 
| 
       1154 
     | 
    
         
            -
                      end
         
     | 
| 
       1155 
     | 
    
         
            -
                    end
         
     | 
| 
       1156 
     | 
    
         
            -
                  end
         
     | 
| 
       1157 
     | 
    
         
            -
             
     | 
| 
       1158 
     | 
    
         
            -
                  # Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool_manager.
         
     | 
| 
       1159 
     | 
    
         
            -
                  # This makes retrieving the connection pool O(1) once the process is warm.
         
     | 
| 
       1160 
     | 
    
         
            -
                  # When a connection is established or removed, we invalidate the cache.
         
     | 
| 
       1161 
     | 
    
         
            -
                  def retrieve_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
         
     | 
| 
       1162 
     | 
    
         
            -
                    pool_config = get_pool_manager(owner)&.get_pool_config(role, shard)
         
     | 
| 
       1163 
     | 
    
         
            -
                    pool_config&.pool
         
     | 
| 
       1164 
     | 
    
         
            -
                  end
         
     | 
| 
       1165 
     | 
    
         
            -
             
     | 
| 
       1166 
     | 
    
         
            -
                  private
         
     | 
| 
       1167 
     | 
    
         
            -
                    attr_reader :owner_to_pool_manager
         
     | 
| 
       1168 
     | 
    
         
            -
             
     | 
| 
       1169 
     | 
    
         
            -
                    # Returns the pool manager for an owner.
         
     | 
| 
       1170 
     | 
    
         
            -
                    #
         
     | 
| 
       1171 
     | 
    
         
            -
                    # Using `"primary"` to look up the pool manager for `ActiveRecord::Base` is
         
     | 
| 
       1172 
     | 
    
         
            -
                    # deprecated in favor of looking it up by `"ActiveRecord::Base"`.
         
     | 
| 
       1173 
     | 
    
         
            -
                    #
         
     | 
| 
       1174 
     | 
    
         
            -
                    # During the deprecation period, if `"primary"` is passed, the pool manager
         
     | 
| 
       1175 
     | 
    
         
            -
                    # for `ActiveRecord::Base` will still be returned.
         
     | 
| 
       1176 
     | 
    
         
            -
                    def get_pool_manager(owner)
         
     | 
| 
       1177 
     | 
    
         
            -
                      return owner_to_pool_manager[owner] if owner_to_pool_manager.key?(owner)
         
     | 
| 
       1178 
     | 
    
         
            -
             
     | 
| 
       1179 
     | 
    
         
            -
                      if owner == "primary"
         
     | 
| 
       1180 
     | 
    
         
            -
                        ActiveSupport::Deprecation.warn("Using `\"primary\"` as a `connection_specification_name` is deprecated and will be removed in Rails 7.0.0. Please use `ActiveRecord::Base`.")
         
     | 
| 
       1181 
     | 
    
         
            -
                        owner_to_pool_manager[Base.name]
         
     | 
| 
       1182 
     | 
    
         
            -
                      end
         
     | 
| 
       1183 
     | 
    
         
            -
                    end
         
     | 
| 
       1184 
     | 
    
         
            -
             
     | 
| 
       1185 
     | 
    
         
            -
                    # Returns an instance of PoolConfig for a given adapter.
         
     | 
| 
       1186 
     | 
    
         
            -
                    # Accepts a hash one layer deep that contains all connection information.
         
     | 
| 
       1187 
     | 
    
         
            -
                    #
         
     | 
| 
       1188 
     | 
    
         
            -
                    # == Example
         
     | 
| 
       1189 
     | 
    
         
            -
                    #
         
     | 
| 
       1190 
     | 
    
         
            -
                    #   config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } }
         
     | 
| 
       1191 
     | 
    
         
            -
                    #   pool_config = Base.configurations.resolve_pool_config(:production)
         
     | 
| 
       1192 
     | 
    
         
            -
                    #   pool_config.db_config.configuration_hash
         
     | 
| 
       1193 
     | 
    
         
            -
                    #   # => { host: "localhost", database: "foo", adapter: "sqlite3" }
         
     | 
| 
       1194 
     | 
    
         
            -
                    #
         
     | 
| 
       1195 
     | 
    
         
            -
                    def resolve_pool_config(config, owner_name)
         
     | 
| 
       1196 
     | 
    
         
            -
                      db_config = Base.configurations.resolve(config)
         
     | 
| 
       1197 
     | 
    
         
            -
             
     | 
| 
       1198 
     | 
    
         
            -
                      raise(AdapterNotSpecified, "database configuration does not specify adapter") unless db_config.adapter
         
     | 
| 
       1199 
     | 
    
         
            -
             
     | 
| 
       1200 
     | 
    
         
            -
                      # Require the adapter itself and give useful feedback about
         
     | 
| 
       1201 
     | 
    
         
            -
                      #   1. Missing adapter gems and
         
     | 
| 
       1202 
     | 
    
         
            -
                      #   2. Adapter gems' missing dependencies.
         
     | 
| 
       1203 
     | 
    
         
            -
                      path_to_adapter = "active_record/connection_adapters/#{db_config.adapter}_adapter"
         
     | 
| 
       1204 
     | 
    
         
            -
                      begin
         
     | 
| 
       1205 
     | 
    
         
            -
                        require path_to_adapter
         
     | 
| 
       1206 
     | 
    
         
            -
                      rescue LoadError => e
         
     | 
| 
       1207 
     | 
    
         
            -
                        # We couldn't require the adapter itself. Raise an exception that
         
     | 
| 
       1208 
     | 
    
         
            -
                        # points out config typos and missing gems.
         
     | 
| 
       1209 
     | 
    
         
            -
                        if e.path == path_to_adapter
         
     | 
| 
       1210 
     | 
    
         
            -
                          # We can assume that a non-builtin adapter was specified, so it's
         
     | 
| 
       1211 
     | 
    
         
            -
                          # either misspelled or missing from Gemfile.
         
     | 
| 
       1212 
     | 
    
         
            -
                          raise LoadError, "Could not load the '#{db_config.adapter}' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
         
     | 
| 
       1213 
     | 
    
         
            -
             
     | 
| 
       1214 
     | 
    
         
            -
                          # Bubbled up from the adapter require. Prefix the exception message
         
     | 
| 
       1215 
     | 
    
         
            -
                          # with some guidance about how to address it and reraise.
         
     | 
| 
       1216 
     | 
    
         
            -
                        else
         
     | 
| 
       1217 
     | 
    
         
            -
                          raise LoadError, "Error loading the '#{db_config.adapter}' Active Record adapter. Missing a gem it depends on? #{e.message}", e.backtrace
         
     | 
| 
       1218 
     | 
    
         
            -
                        end
         
     | 
| 
       1219 
     | 
    
         
            -
                      end
         
     | 
| 
       1220 
     | 
    
         
            -
             
     | 
| 
       1221 
     | 
    
         
            -
                      unless ActiveRecord::Base.respond_to?(db_config.adapter_method)
         
     | 
| 
       1222 
     | 
    
         
            -
                        raise AdapterNotFound, "database configuration specifies nonexistent #{db_config.adapter} adapter"
         
     | 
| 
       1223 
     | 
    
         
            -
                      end
         
     | 
| 
       1224 
     | 
    
         
            -
             
     | 
| 
       1225 
     | 
    
         
            -
                      ConnectionAdapters::PoolConfig.new(owner_name, db_config)
         
     | 
| 
       1226 
     | 
    
         
            -
                    end
         
     | 
| 
       1227 
     | 
    
         
            -
                end
         
     | 
| 
       1228 
734 
     | 
    
         
             
              end
         
     | 
| 
       1229 
735 
     | 
    
         
             
            end
         
     |