activerecord 6.1.7 → 7.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2030 -1020
- 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 +51 -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 +39 -35
- 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/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -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 +446 -306
- 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 +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- 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 -46
- 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 +113 -597
- 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 +78 -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 +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- 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/cidr.rb +6 -0
- 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 +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- 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 +296 -104
- 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 +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -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 +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- 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 +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -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 +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -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 +147 -86
- data/lib/active_record/future_result.rb +174 -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 +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +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 +233 -46
- 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 +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- 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 +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- 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 +248 -81
- 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 +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- 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 +10 -7
- 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 +670 -129
- 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 +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -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 +10 -10
- 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 +251 -140
- 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 +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- 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 +5 -13
- 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 +141 -20
- 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 +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
+
# = Active Record Connection Handling
|
4
5
|
module ConnectionHandling
|
5
6
|
RAILS_ENV = -> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
|
6
7
|
DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }
|
@@ -38,26 +39,25 @@ module ActiveRecord
|
|
38
39
|
# )
|
39
40
|
#
|
40
41
|
# In case {ActiveRecord::Base.configurations}[rdoc-ref:Core.configurations]
|
41
|
-
# is set (Rails automatically loads the contents of config/database.yml into it),
|
42
|
+
# is set (\Rails automatically loads the contents of config/database.yml into it),
|
42
43
|
# a symbol can also be given as argument, representing a key in the
|
43
44
|
# configuration hash:
|
44
45
|
#
|
45
46
|
# ActiveRecord::Base.establish_connection(:production)
|
46
47
|
#
|
47
|
-
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
|
48
|
+
# The exceptions AdapterNotSpecified, AdapterNotFound, and +ArgumentError+
|
48
49
|
# may be returned on an error.
|
49
50
|
def establish_connection(config_or_env = nil)
|
50
51
|
config_or_env ||= DEFAULT_ENV.call.to_sym
|
51
|
-
db_config
|
52
|
-
connection_handler.establish_connection(db_config, owner_name:
|
52
|
+
db_config = resolve_config_for_connection(config_or_env)
|
53
|
+
connection_handler.establish_connection(db_config, owner_name: self, role: current_role, shard: current_shard)
|
53
54
|
end
|
54
55
|
|
55
56
|
# Connects a model to the databases specified. The +database+ keyword
|
56
57
|
# takes a hash consisting of a +role+ and a +database_key+.
|
57
58
|
#
|
58
|
-
# This will
|
59
|
-
#
|
60
|
-
# establishes a connection to that config.
|
59
|
+
# This will look up the database config using the +database_key+ and
|
60
|
+
# establish a connection to that config.
|
61
61
|
#
|
62
62
|
# class AnimalsModel < ApplicationRecord
|
63
63
|
# self.abstract_class = true
|
@@ -66,7 +66,7 @@ module ActiveRecord
|
|
66
66
|
# end
|
67
67
|
#
|
68
68
|
# +connects_to+ also supports horizontal sharding. The horizontal sharding API
|
69
|
-
#
|
69
|
+
# supports read replicas as well. You can connect a model to a list of shards like this:
|
70
70
|
#
|
71
71
|
# class AnimalsModel < ApplicationRecord
|
72
72
|
# self.abstract_class = true
|
@@ -87,28 +87,25 @@ module ActiveRecord
|
|
87
87
|
|
88
88
|
connections = []
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
handler = lookup_connection_handler(role.to_sym)
|
93
|
-
|
94
|
-
self.connection_class = true
|
95
|
-
connections << handler.establish_connection(db_config, owner_name: owner_name, role: role)
|
90
|
+
if shards.empty?
|
91
|
+
shards[:default] = database
|
96
92
|
end
|
97
93
|
|
94
|
+
self.default_shard = shards.keys.first
|
95
|
+
|
98
96
|
shards.each do |shard, database_keys|
|
99
97
|
database_keys.each do |role, database_key|
|
100
|
-
db_config
|
101
|
-
handler = lookup_connection_handler(role.to_sym)
|
98
|
+
db_config = resolve_config_for_connection(database_key)
|
102
99
|
|
103
100
|
self.connection_class = true
|
104
|
-
connections <<
|
101
|
+
connections << connection_handler.establish_connection(db_config, owner_name: self, role: role, shard: shard.to_sym)
|
105
102
|
end
|
106
103
|
end
|
107
104
|
|
108
105
|
connections
|
109
106
|
end
|
110
107
|
|
111
|
-
# Connects to a role (
|
108
|
+
# Connects to a role (e.g. writing, reading, or a custom role) and/or
|
112
109
|
# shard for the duration of the block. At the end of the block the
|
113
110
|
# connection will be returned to the original role / shard.
|
114
111
|
#
|
@@ -134,48 +131,20 @@ module ActiveRecord
|
|
134
131
|
# ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
|
135
132
|
# Dog.first # finds first Dog record stored on the shard one replica
|
136
133
|
# end
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
if legacy_connection_handling
|
141
|
-
if self != Base
|
142
|
-
raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
|
143
|
-
end
|
144
|
-
else
|
145
|
-
if self != Base && !abstract_class
|
146
|
-
raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
|
147
|
-
end
|
148
|
-
|
149
|
-
if name != connection_specification_name && !primary_class?
|
150
|
-
raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
|
151
|
-
end
|
134
|
+
def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
|
135
|
+
if self != Base && !abstract_class
|
136
|
+
raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
|
152
137
|
end
|
153
138
|
|
154
|
-
if
|
155
|
-
raise
|
156
|
-
|
157
|
-
ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails 7.0.0 without replacement.")
|
158
|
-
|
159
|
-
if database.is_a?(Hash)
|
160
|
-
role, database = database.first
|
161
|
-
role = role.to_sym
|
162
|
-
end
|
163
|
-
|
164
|
-
db_config, owner_name = resolve_config_for_connection(database)
|
165
|
-
handler = lookup_connection_handler(role)
|
166
|
-
|
167
|
-
handler.establish_connection(db_config, owner_name: owner_name, role: role)
|
168
|
-
|
169
|
-
with_handler(role, &blk)
|
170
|
-
elsif role || shard
|
171
|
-
unless role
|
172
|
-
raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
|
173
|
-
end
|
139
|
+
if !connection_class? && !primary_class?
|
140
|
+
raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
|
141
|
+
end
|
174
142
|
|
175
|
-
|
176
|
-
else
|
143
|
+
unless role || shard
|
177
144
|
raise ArgumentError, "must provide a `shard` and/or `role`."
|
178
145
|
end
|
146
|
+
|
147
|
+
with_role_and_shard(role, shard, prevent_writes, &blk)
|
179
148
|
end
|
180
149
|
|
181
150
|
# Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
|
@@ -194,17 +163,13 @@ module ActiveRecord
|
|
194
163
|
def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
|
195
164
|
classes = classes.flatten
|
196
165
|
|
197
|
-
if legacy_connection_handling
|
198
|
-
raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
|
199
|
-
end
|
200
|
-
|
201
166
|
if self != Base || classes.include?(Base)
|
202
167
|
raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
|
203
168
|
end
|
204
169
|
|
205
|
-
prevent_writes = true if role == reading_role
|
170
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
206
171
|
|
207
|
-
|
172
|
+
append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes)
|
208
173
|
yield
|
209
174
|
ensure
|
210
175
|
connected_to_stack.pop
|
@@ -218,13 +183,28 @@ module ActiveRecord
|
|
218
183
|
# It is not recommended to use this method in a request since it
|
219
184
|
# does not yield to a block like +connected_to+.
|
220
185
|
def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
|
221
|
-
if
|
222
|
-
raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
|
223
|
-
end
|
186
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
224
187
|
|
225
|
-
|
188
|
+
append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
|
189
|
+
end
|
190
|
+
|
191
|
+
# Prohibit swapping shards while inside of the passed block.
|
192
|
+
#
|
193
|
+
# In some cases you may want to be able to swap shards but not allow a
|
194
|
+
# nested call to connected_to or connected_to_many to swap again. This
|
195
|
+
# is useful in cases you're using sharding to provide per-request
|
196
|
+
# database isolation.
|
197
|
+
def prohibit_shard_swapping(enabled = true)
|
198
|
+
prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
|
199
|
+
ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled
|
200
|
+
yield
|
201
|
+
ensure
|
202
|
+
ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value
|
203
|
+
end
|
226
204
|
|
227
|
-
|
205
|
+
# Determine whether or not shard swapping is currently prohibited
|
206
|
+
def shard_swapping_prohibited?
|
207
|
+
ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
|
228
208
|
end
|
229
209
|
|
230
210
|
# Prevent writing to the database regardless of role.
|
@@ -239,40 +219,31 @@ module ActiveRecord
|
|
239
219
|
# See +READ_QUERY+ for the queries that are blocked by this
|
240
220
|
# method.
|
241
221
|
def while_preventing_writes(enabled = true, &block)
|
242
|
-
|
243
|
-
connection_handler.while_preventing_writes(enabled, &block)
|
244
|
-
else
|
245
|
-
connected_to(role: current_role, prevent_writes: enabled, &block)
|
246
|
-
end
|
222
|
+
connected_to(role: current_role, prevent_writes: enabled, &block)
|
247
223
|
end
|
248
224
|
|
249
|
-
# Returns true if role is the current connected role
|
225
|
+
# Returns true if role is the current connected role and/or
|
226
|
+
# current connected shard. If no shard is passed, the default will be
|
227
|
+
# used.
|
250
228
|
#
|
251
229
|
# ActiveRecord::Base.connected_to(role: :writing) do
|
252
230
|
# ActiveRecord::Base.connected_to?(role: :writing) #=> true
|
253
231
|
# ActiveRecord::Base.connected_to?(role: :reading) #=> false
|
254
232
|
# end
|
233
|
+
#
|
234
|
+
# ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one) do
|
235
|
+
# ActiveRecord::Base.connected_to?(role: :reading, shard: :shard_one) #=> true
|
236
|
+
# ActiveRecord::Base.connected_to?(role: :reading, shard: :default) #=> false
|
237
|
+
# ActiveRecord::Base.connected_to?(role: :writing, shard: :shard_one) #=> true
|
238
|
+
# end
|
255
239
|
def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
|
256
240
|
current_role == role.to_sym && current_shard == shard.to_sym
|
257
241
|
end
|
258
242
|
|
259
|
-
def lookup_connection_handler(handler_key) # :nodoc:
|
260
|
-
if ActiveRecord::Base.legacy_connection_handling
|
261
|
-
handler_key ||= ActiveRecord::Base.writing_role
|
262
|
-
connection_handlers[handler_key] ||= ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
263
|
-
else
|
264
|
-
ActiveRecord::Base.connection_handler
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
243
|
# Clears the query cache for all connections associated with the current thread.
|
269
244
|
def clear_query_caches_for_current_thread
|
270
|
-
|
271
|
-
|
272
|
-
clear_on_handler(handler)
|
273
|
-
end
|
274
|
-
else
|
275
|
-
clear_on_handler(ActiveRecord::Base.connection_handler)
|
245
|
+
connection_handler.each_connection_pool do |pool|
|
246
|
+
pool.connection.clear_query_cache if pool.active_connection?
|
276
247
|
end
|
277
248
|
end
|
278
249
|
|
@@ -285,7 +256,7 @@ module ActiveRecord
|
|
285
256
|
|
286
257
|
attr_writer :connection_specification_name
|
287
258
|
|
288
|
-
#
|
259
|
+
# Returns the connection specification name from the current class or its parent.
|
289
260
|
def connection_specification_name
|
290
261
|
if !defined?(@connection_specification_name) || @connection_specification_name.nil?
|
291
262
|
return self == Base ? Base.name : superclass.connection_specification_name
|
@@ -294,25 +265,14 @@ module ActiveRecord
|
|
294
265
|
end
|
295
266
|
|
296
267
|
def primary_class? # :nodoc:
|
297
|
-
self == Base ||
|
298
|
-
end
|
299
|
-
|
300
|
-
# Returns the configuration of the associated connection as a hash:
|
301
|
-
#
|
302
|
-
# ActiveRecord::Base.connection_config
|
303
|
-
# # => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}
|
304
|
-
#
|
305
|
-
# Please use only for reading.
|
306
|
-
def connection_config
|
307
|
-
connection_pool.db_config.configuration_hash
|
268
|
+
self == Base || application_record_class?
|
308
269
|
end
|
309
|
-
deprecate connection_config: "Use connection_db_config instead"
|
310
270
|
|
311
271
|
# Returns the db_config object from the associated connection:
|
312
272
|
#
|
313
273
|
# ActiveRecord::Base.connection_db_config
|
314
274
|
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
|
315
|
-
# @name="primary", @config={pool: 5, timeout: 5000, database: "
|
275
|
+
# @name="primary", @config={pool: 5, timeout: 5000, database: "storage/development.sqlite3", adapter: "sqlite3"}>
|
316
276
|
#
|
317
277
|
# Use only for reading.
|
318
278
|
def connection_db_config
|
@@ -333,6 +293,14 @@ module ActiveRecord
|
|
333
293
|
end
|
334
294
|
|
335
295
|
def remove_connection(name = nil)
|
296
|
+
if name
|
297
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
298
|
+
The name argument for `#remove_connection` is deprecated without replacement
|
299
|
+
and will be removed in Rails 7.2. `#remove_connection` should always be called
|
300
|
+
on the connection class directly, which makes the name argument obsolete.
|
301
|
+
MSG
|
302
|
+
end
|
303
|
+
|
336
304
|
name ||= @connection_specification_name if defined?(@connection_specification_name)
|
337
305
|
# if removing a connection that has a pool, we reset the
|
338
306
|
# connection_specification_name so it will use the parent
|
@@ -348,58 +316,61 @@ module ActiveRecord
|
|
348
316
|
connection.schema_cache.clear!
|
349
317
|
end
|
350
318
|
|
351
|
-
|
352
|
-
|
319
|
+
def clear_active_connections!(role = nil)
|
320
|
+
deprecation_for_delegation(__method__)
|
321
|
+
connection_handler.clear_active_connections!(role)
|
322
|
+
end
|
323
|
+
|
324
|
+
def clear_reloadable_connections!(role = nil)
|
325
|
+
deprecation_for_delegation(__method__)
|
326
|
+
connection_handler.clear_reloadable_connections!(role)
|
327
|
+
end
|
328
|
+
|
329
|
+
def clear_all_connections!(role = nil)
|
330
|
+
deprecation_for_delegation(__method__)
|
331
|
+
connection_handler.clear_all_connections!(role)
|
332
|
+
end
|
333
|
+
|
334
|
+
def flush_idle_connections!(role = nil)
|
335
|
+
deprecation_for_delegation(__method__)
|
336
|
+
connection_handler.flush_idle_connections!(role)
|
337
|
+
end
|
353
338
|
|
354
339
|
private
|
355
|
-
def
|
356
|
-
|
357
|
-
|
358
|
-
|
340
|
+
def deprecation_for_delegation(method)
|
341
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
342
|
+
Calling `ActiveRecord::Base.#{method} is deprecated. Please
|
343
|
+
call the method directly on the connection handler; for
|
344
|
+
example: `ActiveRecord::Base.connection_handler.#{method}`.
|
345
|
+
MSG
|
359
346
|
end
|
360
347
|
|
361
348
|
def resolve_config_for_connection(config_or_env)
|
362
349
|
raise "Anonymous class is not allowed." unless name
|
363
350
|
|
364
|
-
|
365
|
-
self.connection_specification_name =
|
351
|
+
connection_name = primary_class? ? Base.name : name
|
352
|
+
self.connection_specification_name = connection_name
|
366
353
|
|
367
|
-
|
368
|
-
[db_config, self]
|
369
|
-
end
|
370
|
-
|
371
|
-
def with_handler(handler_key, &blk)
|
372
|
-
handler = lookup_connection_handler(handler_key)
|
373
|
-
swap_connection_handler(handler, &blk)
|
354
|
+
Base.configurations.resolve(config_or_env)
|
374
355
|
end
|
375
356
|
|
376
357
|
def with_role_and_shard(role, shard, prevent_writes)
|
377
|
-
prevent_writes = true if role == reading_role
|
378
|
-
|
379
|
-
if ActiveRecord::Base.legacy_connection_handling
|
380
|
-
with_handler(role.to_sym) do
|
381
|
-
connection_handler.while_preventing_writes(prevent_writes) do
|
382
|
-
self.connected_to_stack << { shard: shard, klasses: [self] }
|
383
|
-
yield
|
384
|
-
end
|
385
|
-
end
|
386
|
-
else
|
387
|
-
self.connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self] }
|
388
|
-
return_value = yield
|
389
|
-
return_value.load if return_value.is_a? ActiveRecord::Relation
|
390
|
-
return_value
|
391
|
-
end
|
392
|
-
ensure
|
393
|
-
self.connected_to_stack.pop
|
394
|
-
end
|
358
|
+
prevent_writes = true if role == ActiveRecord.reading_role
|
395
359
|
|
396
|
-
|
397
|
-
old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler
|
360
|
+
append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
|
398
361
|
return_value = yield
|
399
362
|
return_value.load if return_value.is_a? ActiveRecord::Relation
|
400
363
|
return_value
|
401
364
|
ensure
|
402
|
-
|
365
|
+
self.connected_to_stack.pop
|
366
|
+
end
|
367
|
+
|
368
|
+
def append_to_connected_to_stack(entry)
|
369
|
+
if shard_swapping_prohibited? && entry[:shard].present?
|
370
|
+
raise ArgumentError, "cannot swap `shard` while shard swapping is prohibited."
|
371
|
+
end
|
372
|
+
|
373
|
+
connected_to_stack << entry
|
403
374
|
end
|
404
375
|
end
|
405
376
|
end
|