activerecord 7.1.5.1 → 7.2.0.beta1
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 +515 -2445
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +9 -8
- data/lib/active_record/associations/belongs_to_association.rb +14 -7
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +6 -4
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +29 -28
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +33 -16
- data/lib/active_record/attribute_assignment.rb +1 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +4 -16
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -10
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +60 -71
- data/lib/active_record/attributes.rb +55 -42
- data/lib/active_record/autosave_association.rb +13 -32
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +248 -65
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +159 -74
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/transaction.rb +60 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +18 -46
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +32 -6
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +11 -5
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +5 -23
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -13
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -21
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +107 -75
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +12 -6
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +53 -37
- data/lib/active_record/counter_cache.rb +18 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +15 -4
- data/lib/active_record/database_configurations/hash_config.rb +38 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +24 -0
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +2 -2
- data/lib/active_record/encryption/encrypted_attribute_type.rb +22 -2
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption.rb +0 -2
- data/lib/active_record/enum.rb +10 -1
- data/lib/active_record/errors.rb +16 -11
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +8 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +7 -6
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +5 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +28 -68
- data/lib/active_record/nested_attributes.rb +13 -16
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +30 -352
- data/lib/active_record/query_cache.rb +18 -6
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +50 -62
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +41 -44
- data/lib/active_record/reflection.rb +90 -35
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +94 -61
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +196 -57
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +496 -72
- data/lib/active_record/result.rb +31 -44
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/signed_id.rb +11 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -70
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +81 -91
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +1 -1
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +68 -0
- data/lib/active_record/transactions.rb +43 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +14 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +149 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +29 -16
- data/lib/arel.rb +7 -3
- metadata +20 -15
@@ -1,9 +1,130 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/string/filters"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters
|
5
7
|
extend ActiveSupport::Autoload
|
6
8
|
|
9
|
+
@adapters = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Registers a custom database adapter.
|
13
|
+
#
|
14
|
+
# Can also be used to define aliases.
|
15
|
+
#
|
16
|
+
# == Example
|
17
|
+
#
|
18
|
+
# ActiveRecord::ConnectionAdapters.register("megadb", "MegaDB::ActiveRecordAdapter", "mega_db/active_record_adapter")
|
19
|
+
#
|
20
|
+
# ActiveRecord::ConnectionAdapters.register("mysql", "ActiveRecord::ConnectionAdapters::TrilogyAdapter", "active_record/connection_adapters/trilogy_adapter")
|
21
|
+
#
|
22
|
+
def register(name, class_name, path = class_name.underscore)
|
23
|
+
@adapters[name.to_s] = [class_name, path]
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolve(adapter_name) # :nodoc:
|
27
|
+
# Require the adapter itself and give useful feedback about
|
28
|
+
# 1. Missing adapter gems.
|
29
|
+
# 2. Incorrectly registered adapters.
|
30
|
+
# 3. Adapter gems' missing dependencies.
|
31
|
+
class_name, path_to_adapter = @adapters[adapter_name.to_s]
|
32
|
+
|
33
|
+
unless class_name
|
34
|
+
# To provide better error messages for adapters expecting the pre-7.2 adapter registration API, we attempt
|
35
|
+
# to load the adapter file from the old location which was required by convention, and then raise an error
|
36
|
+
# describing how to upgrade the adapter to the new API.
|
37
|
+
legacy_adapter_path = "active_record/connection_adapters/#{adapter_name}_adapter"
|
38
|
+
legacy_adapter_connection_method_name = "#{adapter_name}_connection".to_sym
|
39
|
+
|
40
|
+
begin
|
41
|
+
require legacy_adapter_path
|
42
|
+
# If we reach here it means we found the found a file that may be the legacy adapter and should raise.
|
43
|
+
if ActiveRecord::ConnectionHandling.method_defined?(legacy_adapter_connection_method_name)
|
44
|
+
# If we find the connection method then we care certain it is a legacy adapter.
|
45
|
+
deprecation_message = <<~MSG.squish
|
46
|
+
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
47
|
+
Rails 7.2 has changed the way Active Record database adapters are loaded. The adapter needs to be
|
48
|
+
updated to register itself rather than being loaded by convention.
|
49
|
+
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
50
|
+
be modified.
|
51
|
+
See:
|
52
|
+
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
53
|
+
MSG
|
54
|
+
|
55
|
+
exception_message = <<~MSG.squish
|
56
|
+
Database configuration specifies '#{adapter_name}' adapter but that adapter has not been registered.
|
57
|
+
Ensure that the adapter in the Gemfile is at the latest version. If it is, then the adapter may need to
|
58
|
+
be modified.
|
59
|
+
MSG
|
60
|
+
else
|
61
|
+
# If we do not find the connection method we are much less certain it is a legacy adapter. Even though the
|
62
|
+
# file exists in the location defined by convenntion, it does not necessarily mean that file is supposed
|
63
|
+
# to define the adapter the legacy way. So raise an error that explains both possibilities.
|
64
|
+
deprecation_message = <<~MSG.squish
|
65
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
66
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
67
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
68
|
+
adapter gem to your Gemfile if it's not in the list of available adapters.
|
69
|
+
Rails 7.2 has changed the way Active Record database adapters are loaded. Ensure that the adapter in
|
70
|
+
the Gemfile is at the latest version. If it is up to date, the adapter may need to be modified.
|
71
|
+
See:
|
72
|
+
https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html#method-c-register
|
73
|
+
MSG
|
74
|
+
|
75
|
+
exception_message = <<~MSG.squish
|
76
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
77
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
78
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
79
|
+
adapter gem to your Gemfile and that it is at its latest version. If it is up to date, the adapter may
|
80
|
+
need to be modified.
|
81
|
+
MSG
|
82
|
+
end
|
83
|
+
|
84
|
+
ActiveRecord.deprecator.warn(deprecation_message)
|
85
|
+
raise AdapterNotFound, exception_message
|
86
|
+
rescue LoadError => error
|
87
|
+
# The adapter was not found in the legacy location so fall through to the error handling for a missing adapter.
|
88
|
+
end
|
89
|
+
|
90
|
+
raise AdapterNotFound, <<~MSG.squish
|
91
|
+
Database configuration specifies nonexistent '#{adapter_name}' adapter.
|
92
|
+
Available adapters are: #{@adapters.keys.sort.join(", ")}.
|
93
|
+
Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary
|
94
|
+
adapter gem to your Gemfile if it's not in the list of available adapters.
|
95
|
+
MSG
|
96
|
+
end
|
97
|
+
|
98
|
+
unless Object.const_defined?(class_name)
|
99
|
+
begin
|
100
|
+
require path_to_adapter
|
101
|
+
rescue LoadError => error
|
102
|
+
# We couldn't require the adapter itself.
|
103
|
+
if error.path == path_to_adapter
|
104
|
+
# We can assume here that a non-builtin adapter was specified and the path
|
105
|
+
# registered by the adapter gem is incorrect.
|
106
|
+
raise LoadError, "Error loading the '#{adapter_name}' Active Record adapter. Ensure that the path registered by the adapter gem is correct. #{error.message}", error.backtrace
|
107
|
+
else
|
108
|
+
# Bubbled up from the adapter require. Prefix the exception message
|
109
|
+
# with some guidance about how to address it and reraise.
|
110
|
+
raise LoadError, "Error loading the '#{adapter_name}' Active Record adapter. Missing a gem it depends on? #{error.message}", error.backtrace
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
begin
|
116
|
+
Object.const_get(class_name)
|
117
|
+
rescue NameError => error
|
118
|
+
raise AdapterNotFound, "Could not load the #{class_name} Active Record adapter (#{error.message})."
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
register "sqlite3", "ActiveRecord::ConnectionAdapters::SQLite3Adapter", "active_record/connection_adapters/sqlite3_adapter"
|
124
|
+
register "mysql2", "ActiveRecord::ConnectionAdapters::Mysql2Adapter", "active_record/connection_adapters/mysql2_adapter"
|
125
|
+
register "trilogy", "ActiveRecord::ConnectionAdapters::TrilogyAdapter", "active_record/connection_adapters/trilogy_adapter"
|
126
|
+
register "postgresql", "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter", "active_record/connection_adapters/postgresql_adapter"
|
127
|
+
|
7
128
|
eager_autoload do
|
8
129
|
autoload :AbstractAdapter
|
9
130
|
end
|
@@ -243,22 +243,64 @@ module ActiveRecord
|
|
243
243
|
# Clears the query cache for all connections associated with the current thread.
|
244
244
|
def clear_query_caches_for_current_thread
|
245
245
|
connection_handler.each_connection_pool do |pool|
|
246
|
-
pool.
|
246
|
+
pool.clear_query_cache
|
247
247
|
end
|
248
248
|
end
|
249
249
|
|
250
250
|
# Returns the connection currently associated with the class. This can
|
251
251
|
# also be used to "borrow" the connection to do database work unrelated
|
252
252
|
# to any of the specific Active Records.
|
253
|
+
# The connection will remain leased for the entire duration of the request
|
254
|
+
# or job, or until +#release_connection+ is called.
|
255
|
+
def lease_connection
|
256
|
+
connection_pool.lease_connection
|
257
|
+
end
|
258
|
+
|
259
|
+
# Soft deprecated. Use +#with_connection+ or +#lease_connection+ instead.
|
253
260
|
def connection
|
254
|
-
|
261
|
+
pool = connection_pool
|
262
|
+
if pool.permanent_lease?
|
263
|
+
case ActiveRecord.permanent_connection_checkout
|
264
|
+
when :deprecated
|
265
|
+
ActiveRecord.deprecator.warn <<~MESSAGE
|
266
|
+
Called deprecated `ActiveRecord::Base.connection` method.
|
267
|
+
|
268
|
+
Either use `with_connection` or `lease_connection`.
|
269
|
+
MESSAGE
|
270
|
+
when :disallowed
|
271
|
+
raise ActiveRecordError, <<~MESSAGE
|
272
|
+
Called deprecated `ActiveRecord::Base.connection` method.
|
273
|
+
|
274
|
+
Either use `with_connection` or `lease_connection`.
|
275
|
+
MESSAGE
|
276
|
+
end
|
277
|
+
pool.lease_connection
|
278
|
+
else
|
279
|
+
pool.active_connection
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Return the currently leased connection into the pool
|
284
|
+
def release_connection
|
285
|
+
connection_pool.release_connection
|
286
|
+
end
|
287
|
+
|
288
|
+
# Checkouts a connection from the pool, yield it and then check it back in.
|
289
|
+
# If a connection was already leased via #lease_connection or a parent call to
|
290
|
+
# #with_connection, that same connection is yieled.
|
291
|
+
# If #lease_connection is called inside the block, the connection won't be checked
|
292
|
+
# back in.
|
293
|
+
# If #connection is called inside the block, the connection won't be checked back in
|
294
|
+
# unless the +prevent_permanent_checkout+ argument is set to +true+.
|
295
|
+
def with_connection(prevent_permanent_checkout: false, &block)
|
296
|
+
connection_pool.with_connection(prevent_permanent_checkout: prevent_permanent_checkout, &block)
|
255
297
|
end
|
256
298
|
|
257
299
|
attr_writer :connection_specification_name
|
258
300
|
|
259
301
|
# Returns the connection specification name from the current class or its parent.
|
260
302
|
def connection_specification_name
|
261
|
-
if
|
303
|
+
if @connection_specification_name.nil?
|
262
304
|
return self == Base ? Base.name : superclass.connection_specification_name
|
263
305
|
end
|
264
306
|
@connection_specification_name
|
@@ -279,8 +321,12 @@ module ActiveRecord
|
|
279
321
|
connection_pool.db_config
|
280
322
|
end
|
281
323
|
|
324
|
+
def adapter_class # :nodoc:
|
325
|
+
connection_pool.db_config.adapter_class
|
326
|
+
end
|
327
|
+
|
282
328
|
def connection_pool
|
283
|
-
connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard
|
329
|
+
connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard, strict: true)
|
284
330
|
end
|
285
331
|
|
286
332
|
def retrieve_connection
|
@@ -292,16 +338,9 @@ module ActiveRecord
|
|
292
338
|
connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
|
293
339
|
end
|
294
340
|
|
295
|
-
def remove_connection
|
296
|
-
if
|
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
|
341
|
+
def remove_connection
|
342
|
+
name = @connection_specification_name if defined?(@connection_specification_name)
|
303
343
|
|
304
|
-
name ||= @connection_specification_name if defined?(@connection_specification_name)
|
305
344
|
# if removing a connection that has a pool, we reset the
|
306
345
|
# connection_specification_name so it will use the parent
|
307
346
|
# pool.
|
@@ -312,39 +351,15 @@ module ActiveRecord
|
|
312
351
|
connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
|
313
352
|
end
|
314
353
|
|
315
|
-
def
|
316
|
-
|
317
|
-
end
|
318
|
-
|
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)
|
354
|
+
def schema_cache # :nodoc:
|
355
|
+
connection_pool.schema_cache
|
327
356
|
end
|
328
357
|
|
329
|
-
def
|
330
|
-
|
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)
|
358
|
+
def clear_cache! # :nodoc:
|
359
|
+
connection_pool.schema_cache.clear!
|
337
360
|
end
|
338
361
|
|
339
362
|
private
|
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
|
346
|
-
end
|
347
|
-
|
348
363
|
def resolve_config_for_connection(config_or_env)
|
349
364
|
raise "Anonymous class is not allowed." unless name
|
350
365
|
|
data/lib/active_record/core.rb
CHANGED
@@ -73,7 +73,7 @@ module ActiveRecord
|
|
73
73
|
end
|
74
74
|
self.configurations = {}
|
75
75
|
|
76
|
-
# Returns fully resolved ActiveRecord::DatabaseConfigurations object
|
76
|
+
# Returns a fully resolved ActiveRecord::DatabaseConfigurations object.
|
77
77
|
def self.configurations
|
78
78
|
@@configurations
|
79
79
|
end
|
@@ -102,6 +102,9 @@ module ActiveRecord
|
|
102
102
|
|
103
103
|
class_attribute :shard_selector, instance_accessor: false, default: nil
|
104
104
|
|
105
|
+
# Specifies the attributes that will be included in the output of the #inspect method
|
106
|
+
class_attribute :attributes_for_inspect, instance_accessor: false, default: [:id]
|
107
|
+
|
105
108
|
def self.application_record_class? # :nodoc:
|
106
109
|
if ActiveRecord.application_record_class
|
107
110
|
self == ActiveRecord.application_record_class
|
@@ -346,12 +349,12 @@ module ActiveRecord
|
|
346
349
|
|
347
350
|
# Returns a string like 'Post(id:integer, title:string, body:text)'
|
348
351
|
def inspect # :nodoc:
|
349
|
-
if self == Base
|
352
|
+
if self == Base
|
350
353
|
super
|
351
354
|
elsif abstract_class?
|
352
355
|
"#{super}(abstract)"
|
353
356
|
elsif !connected?
|
354
|
-
"#{super} (call '#{super}.
|
357
|
+
"#{super} (call '#{super}.lease_connection' to establish a connection)"
|
355
358
|
elsif table_exists?
|
356
359
|
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
|
357
360
|
"#{super}(#{attr_list})"
|
@@ -373,7 +376,7 @@ module ActiveRecord
|
|
373
376
|
TypeCaster::Map.new(self)
|
374
377
|
end
|
375
378
|
|
376
|
-
def cached_find_by_statement(key, &block) # :nodoc:
|
379
|
+
def cached_find_by_statement(connection, key, &block) # :nodoc:
|
377
380
|
cache = @find_by_statement_cache[connection.prepared_statements]
|
378
381
|
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
379
382
|
end
|
@@ -416,21 +419,23 @@ module ActiveRecord
|
|
416
419
|
end
|
417
420
|
|
418
421
|
def cached_find_by(keys, values)
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
422
|
+
with_connection do |connection|
|
423
|
+
statement = cached_find_by_statement(connection, keys) { |params|
|
424
|
+
wheres = keys.index_with do |key|
|
425
|
+
if key.is_a?(Array)
|
426
|
+
[key.map { params.bind }]
|
427
|
+
else
|
428
|
+
params.bind
|
429
|
+
end
|
425
430
|
end
|
426
|
-
|
427
|
-
|
428
|
-
}
|
431
|
+
where(wheres).limit(1)
|
432
|
+
}
|
429
433
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
+
begin
|
435
|
+
statement.execute(values.flatten, connection, allow_retry: true).first
|
436
|
+
rescue TypeError
|
437
|
+
raise ActiveRecord::StatementInvalid
|
438
|
+
end
|
434
439
|
end
|
435
440
|
end
|
436
441
|
end
|
@@ -450,7 +455,7 @@ module ActiveRecord
|
|
450
455
|
init_internals
|
451
456
|
initialize_internals_callback
|
452
457
|
|
453
|
-
|
458
|
+
super
|
454
459
|
|
455
460
|
yield self if block_given?
|
456
461
|
_run_initialize_callbacks
|
@@ -719,21 +724,14 @@ module ActiveRecord
|
|
719
724
|
self.class.connection_handler
|
720
725
|
end
|
721
726
|
|
722
|
-
# Returns the
|
727
|
+
# Returns the attributes specified by <tt>.attributes_for_inspect</tt> as a nicely formatted string.
|
723
728
|
def inspect
|
724
|
-
|
725
|
-
|
726
|
-
inspection = if defined?(@attributes) && @attributes
|
727
|
-
attribute_names.filter_map do |name|
|
728
|
-
if _has_attribute?(name)
|
729
|
-
"#{name}: #{attribute_for_inspect(name)}"
|
730
|
-
end
|
731
|
-
end.join(", ")
|
732
|
-
else
|
733
|
-
"not initialized"
|
734
|
-
end
|
729
|
+
inspect_with_attributes(attributes_for_inspect)
|
730
|
+
end
|
735
731
|
|
736
|
-
|
732
|
+
# Returns the full contents of the record as a nicely formatted string.
|
733
|
+
def full_inspect
|
734
|
+
inspect_with_attributes(attribute_names)
|
737
735
|
end
|
738
736
|
|
739
737
|
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
|
@@ -741,17 +739,17 @@ module ActiveRecord
|
|
741
739
|
def pretty_print(pp)
|
742
740
|
return super if custom_inspect_method_defined?
|
743
741
|
pp.object_address_group(self) do
|
744
|
-
if
|
745
|
-
attr_names =
|
742
|
+
if @attributes
|
743
|
+
attr_names = attributes_for_inspect.select { |name| _has_attribute?(name.to_s) }
|
746
744
|
pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
|
745
|
+
attr_name = attr_name.to_s
|
747
746
|
pp.breakable " "
|
748
747
|
pp.group(1) do
|
749
748
|
pp.text attr_name
|
750
749
|
pp.text ":"
|
751
750
|
pp.breakable
|
752
|
-
value =
|
753
|
-
|
754
|
-
pp.pp value
|
751
|
+
value = attribute_for_inspect(attr_name)
|
752
|
+
pp.text value
|
755
753
|
end
|
756
754
|
end
|
757
755
|
else
|
@@ -789,7 +787,6 @@ module ActiveRecord
|
|
789
787
|
@strict_loading_mode = :all
|
790
788
|
|
791
789
|
klass.define_attribute_methods
|
792
|
-
klass.generate_alias_attributes
|
793
790
|
end
|
794
791
|
|
795
792
|
def initialize_internals_callback
|
@@ -809,5 +806,24 @@ module ActiveRecord
|
|
809
806
|
def inspection_filter
|
810
807
|
self.class.inspection_filter
|
811
808
|
end
|
809
|
+
|
810
|
+
def inspect_with_attributes(attributes_to_list)
|
811
|
+
inspection = if @attributes
|
812
|
+
attributes_to_list.filter_map do |name|
|
813
|
+
name = name.to_s
|
814
|
+
if _has_attribute?(name)
|
815
|
+
"#{name}: #{attribute_for_inspect(name)}"
|
816
|
+
end
|
817
|
+
end.join(", ")
|
818
|
+
else
|
819
|
+
"not initialized"
|
820
|
+
end
|
821
|
+
|
822
|
+
"#<#{self.class} #{inspection}>"
|
823
|
+
end
|
824
|
+
|
825
|
+
def attributes_for_inspect
|
826
|
+
self.class.attributes_for_inspect == :all ? attribute_names : self.class.attributes_for_inspect
|
827
|
+
end
|
812
828
|
end
|
813
829
|
end
|
@@ -7,6 +7,7 @@ module ActiveRecord
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
class_attribute :_counter_cache_columns, instance_accessor: false, default: []
|
10
|
+
class_attribute :counter_cached_association_names, instance_writer: false, default: []
|
10
11
|
end
|
11
12
|
|
12
13
|
module ClassMethods
|
@@ -181,14 +182,26 @@ module ActiveRecord
|
|
181
182
|
def counter_cache_column?(name) # :nodoc:
|
182
183
|
_counter_cache_columns.include?(name)
|
183
184
|
end
|
185
|
+
|
186
|
+
def load_schema! # :nodoc:
|
187
|
+
super
|
188
|
+
|
189
|
+
association_names = _reflections.filter_map do |name, reflection|
|
190
|
+
next unless reflection.belongs_to? && reflection.counter_cache_column
|
191
|
+
|
192
|
+
name.to_sym
|
193
|
+
end
|
194
|
+
|
195
|
+
self.counter_cached_association_names |= association_names
|
196
|
+
end
|
184
197
|
end
|
185
198
|
|
186
199
|
private
|
187
200
|
def _create_record(attribute_names = self.attribute_names)
|
188
201
|
id = super
|
189
202
|
|
190
|
-
|
191
|
-
association.increment_counters
|
203
|
+
counter_cached_association_names.each do |association_name|
|
204
|
+
association(association_name).increment_counters
|
192
205
|
end
|
193
206
|
|
194
207
|
id
|
@@ -198,7 +211,9 @@ module ActiveRecord
|
|
198
211
|
affected_rows = super
|
199
212
|
|
200
213
|
if affected_rows > 0
|
201
|
-
|
214
|
+
counter_cached_association_names.each do |association_name|
|
215
|
+
association = association(association_name)
|
216
|
+
|
202
217
|
unless destroyed_by_association && _foreign_keys_equal?(destroyed_by_association.foreign_key, association.reflection.foreign_key)
|
203
218
|
association.decrement_counters
|
204
219
|
end
|
@@ -208,12 +223,6 @@ module ActiveRecord
|
|
208
223
|
affected_rows
|
209
224
|
end
|
210
225
|
|
211
|
-
def each_counter_cached_associations
|
212
|
-
_reflections.each do |name, reflection|
|
213
|
-
yield association(name.to_sym) if reflection.belongs_to? && reflection.counter_cache_column
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
226
|
def _foreign_keys_equal?(fkey1, fkey2)
|
218
227
|
fkey1 == fkey2 || Array(fkey1).map(&:to_sym) == Array(fkey2).map(&:to_sym)
|
219
228
|
end
|
@@ -25,8 +25,7 @@ module ActiveRecord
|
|
25
25
|
def initialize(url)
|
26
26
|
raise "Database URL cannot be empty" if url.blank?
|
27
27
|
@uri = uri_parser.parse(url)
|
28
|
-
@adapter =
|
29
|
-
@adapter = "postgresql" if @adapter == "postgres"
|
28
|
+
@adapter = resolved_adapter
|
30
29
|
|
31
30
|
if @uri.opaque
|
32
31
|
@uri.opaque, @query = @uri.opaque.split("?", 2)
|
@@ -46,7 +45,7 @@ module ActiveRecord
|
|
46
45
|
attr_reader :uri
|
47
46
|
|
48
47
|
def uri_parser
|
49
|
-
@uri_parser ||= URI::
|
48
|
+
@uri_parser ||= URI::Parser.new
|
50
49
|
end
|
51
50
|
|
52
51
|
# Converts the query parameters of the URI into a hash.
|
@@ -80,6 +79,12 @@ module ActiveRecord
|
|
80
79
|
end
|
81
80
|
end
|
82
81
|
|
82
|
+
def resolved_adapter
|
83
|
+
adapter = uri.scheme && @uri.scheme.tr("-", "_")
|
84
|
+
adapter = ActiveRecord.protocol_adapters[adapter] || adapter
|
85
|
+
adapter
|
86
|
+
end
|
87
|
+
|
83
88
|
# Returns name of the database.
|
84
89
|
def database_from_path
|
85
90
|
if @adapter == "sqlite3"
|
@@ -11,14 +11,21 @@ module ActiveRecord
|
|
11
11
|
def initialize(env_name, name)
|
12
12
|
@env_name = env_name
|
13
13
|
@name = name
|
14
|
+
@adapter_class = nil
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
|
17
|
+
def adapter_class
|
18
|
+
@adapter_class ||= ActiveRecord::ConnectionAdapters.resolve(adapter)
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
|
21
|
+
def new_connection
|
22
|
+
adapter_class.new(configuration_hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate!
|
26
|
+
adapter_class if adapter
|
27
|
+
|
28
|
+
true
|
22
29
|
end
|
23
30
|
|
24
31
|
def host
|
@@ -84,6 +91,10 @@ module ActiveRecord
|
|
84
91
|
def schema_cache_path
|
85
92
|
raise NotImplementedError
|
86
93
|
end
|
94
|
+
|
95
|
+
def use_metadata_table?
|
96
|
+
raise NotImplementedError
|
97
|
+
end
|
87
98
|
end
|
88
99
|
end
|
89
100
|
end
|