activerecord 6.1.6 → 7.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1314 -975
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- 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 +2 -2
- data/lib/active_record/associations/collection_association.rb +19 -21
- data/lib/active_record/associations/collection_proxy.rb +10 -5
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +8 -5
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/preloader/association.rb +186 -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 +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +124 -95
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +49 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +57 -19
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +14 -15
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +8 -23
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +10 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +38 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -24
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +105 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -24
- data/lib/active_record/connection_adapters/mysql/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- 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/range.rb +1 -1
- 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 +51 -51
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +37 -19
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +208 -107
- data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +28 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +17 -15
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +96 -32
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +49 -55
- data/lib/active_record/core.rb +124 -134
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +15 -32
- data/lib/active_record/delegated_type.rb +53 -12
- data/lib/active_record/destroy_association_async_job.rb +1 -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/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +67 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +206 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -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 +160 -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 +42 -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 +90 -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 +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +50 -43
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +20 -23
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +10 -4
- data/lib/active_record/log_subscriber.rb +23 -7
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +18 -6
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +7 -7
- data/lib/active_record/migration/compatibility.rb +84 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +114 -83
- data/lib/active_record/model_schema.rb +58 -59
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +228 -60
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +16 -6
- data/lib/active_record/railtie.rb +136 -22
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +78 -136
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +73 -50
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +6 -6
- data/lib/active_record/relation/calculations.rb +43 -38
- data/lib/active_record/relation/delegation.rb +7 -7
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +276 -67
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +189 -88
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +17 -12
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +25 -19
- data/lib/active_record/schema_migration.rb +4 -4
- data/lib/active_record/scoping/default.rb +60 -13
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +3 -3
- data/lib/active_record/store.rb +7 -2
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +127 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -13
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +16 -9
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +217 -27
- 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/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- 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 +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- 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 +55 -11
@@ -30,32 +30,28 @@ module ActiveRecord
|
|
30
30
|
module Suppressor
|
31
31
|
extend ActiveSupport::Concern
|
32
32
|
|
33
|
+
class << self
|
34
|
+
def registry # :nodoc:
|
35
|
+
ActiveSupport::IsolatedExecutionState[:active_record_suppresor_registry] ||= {}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
33
39
|
module ClassMethods
|
34
40
|
def suppress(&block)
|
35
|
-
previous_state =
|
36
|
-
|
41
|
+
previous_state = Suppressor.registry[name]
|
42
|
+
Suppressor.registry[name] = true
|
37
43
|
yield
|
38
44
|
ensure
|
39
|
-
|
45
|
+
Suppressor.registry[name] = previous_state
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
43
49
|
def save(**) # :nodoc:
|
44
|
-
|
50
|
+
Suppressor.registry[self.class.name] ? true : super
|
45
51
|
end
|
46
52
|
|
47
53
|
def save!(**) # :nodoc:
|
48
|
-
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class SuppressorRegistry # :nodoc:
|
53
|
-
extend ActiveSupport::PerThreadRegistry
|
54
|
-
|
55
|
-
attr_reader :suppressed
|
56
|
-
|
57
|
-
def initialize
|
58
|
-
@suppressed = {}
|
54
|
+
Suppressor.registry[self.class.name] ? true : super
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
@@ -39,17 +39,23 @@ module ActiveRecord
|
|
39
39
|
##
|
40
40
|
# :singleton-method:
|
41
41
|
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
|
42
|
+
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
|
43
|
+
# Example:
|
44
|
+
# ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
|
45
|
+
# mysql2: ['--no-defaults', '--skip-add-drop-table'],
|
46
|
+
# postgres: '--no-tablespaces'
|
47
|
+
# }
|
42
48
|
mattr_accessor :structure_dump_flags, instance_accessor: false
|
43
49
|
|
44
50
|
##
|
45
51
|
# :singleton-method:
|
46
52
|
# Extra flags passed to database CLI tool when calling db:schema:load
|
53
|
+
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
|
47
54
|
mattr_accessor :structure_load_flags, instance_accessor: false
|
48
55
|
|
49
56
|
extend self
|
50
57
|
|
51
|
-
attr_writer :
|
52
|
-
deprecate :current_config=
|
58
|
+
attr_writer :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
|
53
59
|
attr_accessor :database_configuration
|
54
60
|
|
55
61
|
LOCAL_HOSTS = ["127.0.0.1", "localhost"]
|
@@ -103,11 +109,6 @@ module ActiveRecord
|
|
103
109
|
@env ||= Rails.env
|
104
110
|
end
|
105
111
|
|
106
|
-
def spec
|
107
|
-
@spec ||= "primary"
|
108
|
-
end
|
109
|
-
deprecate spec: "please use name instead"
|
110
|
-
|
111
112
|
def name
|
112
113
|
@name ||= "primary"
|
113
114
|
end
|
@@ -116,18 +117,6 @@ module ActiveRecord
|
|
116
117
|
@seed_loader ||= Rails.application
|
117
118
|
end
|
118
119
|
|
119
|
-
def current_config(options = {})
|
120
|
-
if options.has_key?(:config)
|
121
|
-
@current_config = options[:config]
|
122
|
-
else
|
123
|
-
env_name = options[:env] || env
|
124
|
-
name = options[:spec] || "primary"
|
125
|
-
|
126
|
-
@current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
|
127
|
-
end
|
128
|
-
end
|
129
|
-
deprecate :current_config
|
130
|
-
|
131
120
|
def create(configuration, *arguments)
|
132
121
|
db_config = resolve_configuration(configuration)
|
133
122
|
database_adapter_for(db_config, *arguments).create
|
@@ -154,7 +143,7 @@ module ActiveRecord
|
|
154
143
|
begin
|
155
144
|
Rails.application.config.load_database_yaml
|
156
145
|
rescue
|
157
|
-
unless ActiveRecord
|
146
|
+
unless ActiveRecord.suppress_multiple_database_warning
|
158
147
|
$stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
|
159
148
|
end
|
160
149
|
|
@@ -171,12 +160,14 @@ module ActiveRecord
|
|
171
160
|
return if database_configs.count == 1
|
172
161
|
|
173
162
|
database_configs.each do |db_config|
|
163
|
+
next unless db_config.database_tasks?
|
164
|
+
|
174
165
|
yield db_config.name
|
175
166
|
end
|
176
167
|
end
|
177
168
|
|
178
169
|
def raise_for_multi_db(environment = env, command:)
|
179
|
-
db_configs =
|
170
|
+
db_configs = configs_for(env_name: environment)
|
180
171
|
|
181
172
|
if db_configs.count > 1
|
182
173
|
dbs_list = []
|
@@ -194,6 +185,40 @@ module ActiveRecord
|
|
194
185
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
195
186
|
end
|
196
187
|
|
188
|
+
def prepare_all
|
189
|
+
seed = false
|
190
|
+
|
191
|
+
each_current_configuration(env) do |db_config|
|
192
|
+
ActiveRecord::Base.establish_connection(db_config)
|
193
|
+
|
194
|
+
begin
|
195
|
+
# Skipped when no database
|
196
|
+
migrate
|
197
|
+
|
198
|
+
if ActiveRecord.dump_schema_after_migration
|
199
|
+
dump_schema(db_config, ActiveRecord.schema_format)
|
200
|
+
end
|
201
|
+
rescue ActiveRecord::NoDatabaseError
|
202
|
+
create(db_config)
|
203
|
+
|
204
|
+
if File.exist?(schema_dump_path(db_config))
|
205
|
+
load_schema(
|
206
|
+
db_config,
|
207
|
+
ActiveRecord.schema_format,
|
208
|
+
nil
|
209
|
+
)
|
210
|
+
else
|
211
|
+
migrate
|
212
|
+
end
|
213
|
+
|
214
|
+
seed = true
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
ActiveRecord::Base.establish_connection
|
219
|
+
load_seed if seed
|
220
|
+
end
|
221
|
+
|
197
222
|
def drop(configuration, *arguments)
|
198
223
|
db_config = resolve_configuration(configuration)
|
199
224
|
database_adapter_for(db_config, *arguments).drop
|
@@ -223,19 +248,25 @@ module ActiveRecord
|
|
223
248
|
private :truncate_tables
|
224
249
|
|
225
250
|
def truncate_all(environment = env)
|
226
|
-
|
251
|
+
configs_for(env_name: environment).each do |db_config|
|
227
252
|
truncate_tables(db_config)
|
228
253
|
end
|
229
254
|
end
|
230
255
|
|
231
|
-
def migrate
|
256
|
+
def migrate(version = nil)
|
232
257
|
check_target_version
|
233
258
|
|
234
259
|
scope = ENV["SCOPE"]
|
235
260
|
verbose_was, Migration.verbose = Migration.verbose, verbose?
|
236
261
|
|
237
262
|
Base.connection.migration_context.migrate(target_version) do |migration|
|
238
|
-
|
263
|
+
if version.blank?
|
264
|
+
scope.blank? || scope == migration.scope
|
265
|
+
else
|
266
|
+
migration.version == version
|
267
|
+
end
|
268
|
+
end.tap do |migrations_ran|
|
269
|
+
Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
|
239
270
|
end
|
240
271
|
|
241
272
|
ActiveRecord::Base.clear_cache!
|
@@ -243,6 +274,23 @@ module ActiveRecord
|
|
243
274
|
Migration.verbose = verbose_was
|
244
275
|
end
|
245
276
|
|
277
|
+
def db_configs_with_versions(db_configs) # :nodoc:
|
278
|
+
db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
|
279
|
+
|
280
|
+
db_configs.each do |db_config|
|
281
|
+
ActiveRecord::Base.establish_connection(db_config)
|
282
|
+
versions_to_run = ActiveRecord::Base.connection.migration_context.pending_migration_versions
|
283
|
+
target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
|
284
|
+
|
285
|
+
versions_to_run.each do |version|
|
286
|
+
next if target_version && target_version != version
|
287
|
+
db_configs_with_versions[version] << db_config
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
db_configs_with_versions
|
292
|
+
end
|
293
|
+
|
246
294
|
def migrate_status
|
247
295
|
unless ActiveRecord::Base.connection.schema_migration.table_exists?
|
248
296
|
Kernel.abort "Schema migrations table does not exist yet."
|
@@ -269,7 +317,7 @@ module ActiveRecord
|
|
269
317
|
end
|
270
318
|
|
271
319
|
def charset_current(env_name = env, db_name = name)
|
272
|
-
db_config =
|
320
|
+
db_config = configs_for(env_name: env_name, name: db_name)
|
273
321
|
charset(db_config)
|
274
322
|
end
|
275
323
|
|
@@ -279,7 +327,7 @@ module ActiveRecord
|
|
279
327
|
end
|
280
328
|
|
281
329
|
def collation_current(env_name = env, db_name = name)
|
282
|
-
db_config =
|
330
|
+
db_config = configs_for(env_name: env_name, name: db_name)
|
283
331
|
collation(db_config)
|
284
332
|
end
|
285
333
|
|
@@ -305,17 +353,20 @@ module ActiveRecord
|
|
305
353
|
def structure_dump(configuration, *arguments)
|
306
354
|
db_config = resolve_configuration(configuration)
|
307
355
|
filename = arguments.delete_at(0)
|
308
|
-
|
356
|
+
flags = structure_dump_flags_for(db_config.adapter)
|
357
|
+
database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
|
309
358
|
end
|
310
359
|
|
311
360
|
def structure_load(configuration, *arguments)
|
312
361
|
db_config = resolve_configuration(configuration)
|
313
362
|
filename = arguments.delete_at(0)
|
314
|
-
|
363
|
+
flags = structure_load_flags_for(db_config.adapter)
|
364
|
+
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
|
315
365
|
end
|
316
366
|
|
317
|
-
def load_schema(db_config, format = ActiveRecord
|
318
|
-
file ||=
|
367
|
+
def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
|
368
|
+
file ||= schema_dump_path(db_config, format)
|
369
|
+
return unless file
|
319
370
|
|
320
371
|
verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
|
321
372
|
check_schema_file(file)
|
@@ -336,18 +387,12 @@ module ActiveRecord
|
|
336
387
|
Migration.verbose = verbose_was
|
337
388
|
end
|
338
389
|
|
339
|
-
def schema_up_to_date?(configuration, format = ActiveRecord
|
390
|
+
def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
|
340
391
|
db_config = resolve_configuration(configuration)
|
341
392
|
|
342
|
-
|
343
|
-
ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 7.0.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
|
344
|
-
end
|
345
|
-
|
346
|
-
name ||= db_config.name
|
393
|
+
file ||= schema_dump_path(db_config)
|
347
394
|
|
348
|
-
file
|
349
|
-
|
350
|
-
return true unless File.exist?(file)
|
395
|
+
return true unless file && File.exist?(file)
|
351
396
|
|
352
397
|
ActiveRecord::Base.establish_connection(db_config)
|
353
398
|
|
@@ -357,10 +402,10 @@ module ActiveRecord
|
|
357
402
|
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
|
358
403
|
end
|
359
404
|
|
360
|
-
def reconstruct_from_schema(db_config, format = ActiveRecord
|
361
|
-
file ||=
|
405
|
+
def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
|
406
|
+
file ||= schema_dump_path(db_config, format)
|
362
407
|
|
363
|
-
check_schema_file(file)
|
408
|
+
check_schema_file(file) if file
|
364
409
|
|
365
410
|
ActiveRecord::Base.establish_connection(db_config)
|
366
411
|
|
@@ -375,9 +420,11 @@ module ActiveRecord
|
|
375
420
|
load_schema(db_config, format, file)
|
376
421
|
end
|
377
422
|
|
378
|
-
def dump_schema(db_config, format = ActiveRecord
|
423
|
+
def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
|
379
424
|
require "active_record/schema_dumper"
|
380
|
-
filename =
|
425
|
+
filename = schema_dump_path(db_config, format)
|
426
|
+
return unless filename
|
427
|
+
|
381
428
|
connection = ActiveRecord::Base.connection
|
382
429
|
|
383
430
|
FileUtils.mkdir_p(db_dir)
|
@@ -397,11 +444,7 @@ module ActiveRecord
|
|
397
444
|
end
|
398
445
|
end
|
399
446
|
|
400
|
-
def
|
401
|
-
File.join(db_dir, schema_file_type(format))
|
402
|
-
end
|
403
|
-
|
404
|
-
def schema_file_type(format = ActiveRecord::Base.schema_format)
|
447
|
+
def schema_file_type(format = ActiveRecord.schema_format)
|
405
448
|
case format
|
406
449
|
when :ruby
|
407
450
|
"schema.rb"
|
@@ -409,15 +452,19 @@ module ActiveRecord
|
|
409
452
|
"structure.sql"
|
410
453
|
end
|
411
454
|
end
|
455
|
+
deprecate :schema_file_type
|
412
456
|
|
413
|
-
def
|
414
|
-
|
415
|
-
|
457
|
+
def schema_dump_path(db_config, format = ActiveRecord.schema_format)
|
458
|
+
return ENV["SCHEMA"] if ENV["SCHEMA"]
|
459
|
+
|
460
|
+
filename = db_config.schema_dump(format)
|
461
|
+
return unless filename
|
462
|
+
|
463
|
+
if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
|
464
|
+
filename
|
416
465
|
else
|
417
|
-
|
466
|
+
File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
418
467
|
end
|
419
|
-
|
420
|
-
ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
421
468
|
end
|
422
469
|
|
423
470
|
def cache_dump_filename(db_config_name, schema_cache_path: nil)
|
@@ -430,7 +477,7 @@ module ActiveRecord
|
|
430
477
|
schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
431
478
|
end
|
432
479
|
|
433
|
-
def load_schema_current(format = ActiveRecord
|
480
|
+
def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
|
434
481
|
each_current_configuration(environment) do |db_config|
|
435
482
|
load_schema(db_config, format, file)
|
436
483
|
end
|
@@ -468,6 +515,10 @@ module ActiveRecord
|
|
468
515
|
end
|
469
516
|
|
470
517
|
private
|
518
|
+
def configs_for(**options)
|
519
|
+
Base.configurations.configs_for(**options)
|
520
|
+
end
|
521
|
+
|
471
522
|
def resolve_configuration(configuration)
|
472
523
|
Base.configurations.resolve(configuration)
|
473
524
|
end
|
@@ -488,7 +539,7 @@ module ActiveRecord
|
|
488
539
|
end
|
489
540
|
|
490
541
|
def class_for_adapter(adapter)
|
491
|
-
_key, task = @tasks.
|
542
|
+
_key, task = @tasks.reverse_each.detect { |pattern, _task| adapter[pattern] }
|
492
543
|
unless task
|
493
544
|
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
494
545
|
end
|
@@ -500,7 +551,7 @@ module ActiveRecord
|
|
500
551
|
environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
|
501
552
|
|
502
553
|
environments.each do |env|
|
503
|
-
|
554
|
+
configs_for(env_name: env).each do |db_config|
|
504
555
|
next if name && name != db_config.name
|
505
556
|
|
506
557
|
yield db_config
|
@@ -509,7 +560,7 @@ module ActiveRecord
|
|
509
560
|
end
|
510
561
|
|
511
562
|
def each_local_configuration
|
512
|
-
|
563
|
+
configs_for.each do |db_config|
|
513
564
|
next unless db_config.database
|
514
565
|
|
515
566
|
if local_database?(db_config)
|
@@ -526,7 +577,23 @@ module ActiveRecord
|
|
526
577
|
end
|
527
578
|
|
528
579
|
def schema_sha1(file)
|
529
|
-
Digest::SHA1.hexdigest(File.read(file))
|
580
|
+
OpenSSL::Digest::SHA1.hexdigest(File.read(file))
|
581
|
+
end
|
582
|
+
|
583
|
+
def structure_dump_flags_for(adapter)
|
584
|
+
if structure_dump_flags.is_a?(Hash)
|
585
|
+
structure_dump_flags[adapter.to_sym]
|
586
|
+
else
|
587
|
+
structure_dump_flags
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
def structure_load_flags_for(adapter)
|
592
|
+
if structure_load_flags.is_a?(Hash)
|
593
|
+
structure_load_flags[adapter.to_sym]
|
594
|
+
else
|
595
|
+
structure_load_flags
|
596
|
+
end
|
530
597
|
end
|
531
598
|
end
|
532
599
|
end
|
@@ -94,7 +94,7 @@ module ActiveRecord
|
|
94
94
|
sslcapath: "--ssl-capath",
|
95
95
|
sslcipher: "--ssl-cipher",
|
96
96
|
sslkey: "--ssl-key"
|
97
|
-
}.
|
97
|
+
}.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
|
98
98
|
|
99
99
|
args
|
100
100
|
end
|
@@ -47,20 +47,21 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def structure_dump(filename, extra_flags)
|
50
|
-
set_psql_env
|
51
|
-
|
52
50
|
search_path = \
|
53
|
-
case ActiveRecord
|
51
|
+
case ActiveRecord.dump_schemas
|
54
52
|
when :schema_search_path
|
55
53
|
configuration_hash[:schema_search_path]
|
56
54
|
when :all
|
57
55
|
nil
|
58
56
|
when String
|
59
|
-
ActiveRecord
|
57
|
+
ActiveRecord.dump_schemas
|
60
58
|
end
|
61
59
|
|
62
|
-
args = ["--schema-only", "--no-privileges", "--no-owner"
|
60
|
+
args = ["--schema-only", "--no-privileges", "--no-owner"]
|
61
|
+
args.concat(["--file", filename])
|
62
|
+
|
63
63
|
args.concat(Array(extra_flags)) if extra_flags
|
64
|
+
|
64
65
|
unless search_path.blank?
|
65
66
|
args += search_path.split(",").map do |part|
|
66
67
|
"--schema=#{part.strip}"
|
@@ -79,8 +80,7 @@ module ActiveRecord
|
|
79
80
|
end
|
80
81
|
|
81
82
|
def structure_load(filename, extra_flags)
|
82
|
-
|
83
|
-
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
|
83
|
+
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL, "--file", filename]
|
84
84
|
args.concat(Array(extra_flags)) if extra_flags
|
85
85
|
args << db_config.database
|
86
86
|
run_cmd("psql", args, "loading")
|
@@ -100,15 +100,21 @@ module ActiveRecord
|
|
100
100
|
)
|
101
101
|
end
|
102
102
|
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
103
|
+
def psql_env
|
104
|
+
{}.tap do |env|
|
105
|
+
env["PGHOST"] = db_config.host if db_config.host
|
106
|
+
env["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
|
107
|
+
env["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
|
108
|
+
env["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
|
109
|
+
env["PGSSLMODE"] = configuration_hash[:sslmode].to_s if configuration_hash[:sslmode]
|
110
|
+
env["PGSSLCERT"] = configuration_hash[:sslcert].to_s if configuration_hash[:sslcert]
|
111
|
+
env["PGSSLKEY"] = configuration_hash[:sslkey].to_s if configuration_hash[:sslkey]
|
112
|
+
env["PGSSLROOTCERT"] = configuration_hash[:sslrootcert].to_s if configuration_hash[:sslrootcert]
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
116
|
def run_cmd(cmd, args, action)
|
111
|
-
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
117
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(psql_env, cmd, *args)
|
112
118
|
end
|
113
119
|
|
114
120
|
def run_cmd_error(cmd, args, action)
|
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
15
15
|
db_config._database = "#{db_config.database}-#{i}"
|
16
16
|
|
17
|
-
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord
|
17
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord.schema_format, nil)
|
18
18
|
end
|
19
19
|
ensure
|
20
20
|
ActiveRecord::Base.establish_connection
|
@@ -86,6 +86,9 @@ module ActiveRecord
|
|
86
86
|
include methods
|
87
87
|
end
|
88
88
|
|
89
|
+
# Prevents automatically wrapping each specified test in a transaction,
|
90
|
+
# to allow application logic transactions to be tested in a top-level
|
91
|
+
# (non-nested) context.
|
89
92
|
def uses_transaction(*methods)
|
90
93
|
@uses_transaction = [] unless defined?(@uses_transaction)
|
91
94
|
@uses_transaction.concat methods.map(&:to_s)
|
@@ -134,7 +137,7 @@ module ActiveRecord
|
|
134
137
|
@connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
|
135
138
|
spec_name = payload[:spec_name] if payload.key?(:spec_name)
|
136
139
|
shard = payload[:shard] if payload.key?(:shard)
|
137
|
-
setup_shared_connection_pool
|
140
|
+
setup_shared_connection_pool if ActiveRecord.legacy_connection_handling
|
138
141
|
|
139
142
|
if spec_name
|
140
143
|
begin
|
@@ -143,10 +146,14 @@ module ActiveRecord
|
|
143
146
|
connection = nil
|
144
147
|
end
|
145
148
|
|
146
|
-
if connection
|
147
|
-
|
148
|
-
|
149
|
-
|
149
|
+
if connection
|
150
|
+
setup_shared_connection_pool unless ActiveRecord.legacy_connection_handling
|
151
|
+
|
152
|
+
if !@fixture_connections.include?(connection)
|
153
|
+
connection.begin_transaction joinable: false, _lazy: false
|
154
|
+
connection.pool.lock_thread = true if lock_threads
|
155
|
+
@fixture_connections << connection
|
156
|
+
end
|
150
157
|
end
|
151
158
|
end
|
152
159
|
end
|
@@ -193,8 +200,8 @@ module ActiveRecord
|
|
193
200
|
# need to share a connection pool so that the reading connection
|
194
201
|
# can see data in the open transaction on the writing connection.
|
195
202
|
def setup_shared_connection_pool
|
196
|
-
if ActiveRecord
|
197
|
-
writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord
|
203
|
+
if ActiveRecord.legacy_connection_handling
|
204
|
+
writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord.writing_role]
|
198
205
|
|
199
206
|
ActiveRecord::Base.connection_handlers.values.each do |handler|
|
200
207
|
if handler != writing_handler
|
@@ -221,7 +228,7 @@ module ActiveRecord
|
|
221
228
|
handler.connection_pool_names.each do |name|
|
222
229
|
pool_manager = handler.send(:owner_to_pool_manager)[name]
|
223
230
|
pool_manager.shard_names.each do |shard_name|
|
224
|
-
writing_pool_config = pool_manager.get_pool_config(ActiveRecord
|
231
|
+
writing_pool_config = pool_manager.get_pool_config(ActiveRecord.writing_role, shard_name)
|
225
232
|
@saved_pool_configs[name][shard_name] ||= {}
|
226
233
|
pool_manager.role_names.each do |role|
|
227
234
|
next unless pool_config = pool_manager.get_pool_config(role, shard_name)
|
@@ -236,7 +243,7 @@ module ActiveRecord
|
|
236
243
|
end
|
237
244
|
|
238
245
|
def teardown_shared_connection_pool
|
239
|
-
if ActiveRecord
|
246
|
+
if ActiveRecord.legacy_connection_handling
|
240
247
|
@legacy_saved_pool_configs.each_pair do |handler, names|
|
241
248
|
names.each_pair do |name, shards|
|
242
249
|
shards.each_pair do |shard_name, pool_config|
|
@@ -75,7 +75,7 @@ module ActiveRecord
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def current_time_from_proper_timezone
|
78
|
-
default_timezone == :utc ? Time.now.utc : Time.now
|
78
|
+
ActiveRecord.default_timezone == :utc ? Time.now.utc : Time.now
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
@@ -127,7 +127,7 @@ module ActiveRecord
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def should_record_timestamps?
|
130
|
-
record_timestamps && (!
|
130
|
+
record_timestamps && (!partial_updates? || has_changes_to_save?)
|
131
131
|
end
|
132
132
|
|
133
133
|
def timestamp_attributes_for_create_in_model
|
@@ -148,8 +148,7 @@ module ActiveRecord
|
|
148
148
|
|
149
149
|
def max_updated_column_timestamp
|
150
150
|
timestamp_attributes_for_update_in_model
|
151
|
-
.
|
152
|
-
.compact
|
151
|
+
.filter_map { |attr| self[attr]&.to_time }
|
153
152
|
.max
|
154
153
|
end
|
155
154
|
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
# See ActiveRecord::Transactions::ClassMethods for documentation.
|
5
5
|
module Transactions
|
6
6
|
extend ActiveSupport::Concern
|
7
|
-
|
7
|
+
# :nodoc:
|
8
8
|
ACTIONS = [:create, :destroy, :update]
|
9
9
|
|
10
10
|
included do
|
@@ -290,19 +290,19 @@ module ActiveRecord
|
|
290
290
|
self.class.transaction(**options, &block)
|
291
291
|
end
|
292
292
|
|
293
|
-
def destroy
|
293
|
+
def destroy # :nodoc:
|
294
294
|
with_transaction_returning_status { super }
|
295
295
|
end
|
296
296
|
|
297
|
-
def save(**)
|
297
|
+
def save(**) # :nodoc:
|
298
298
|
with_transaction_returning_status { super }
|
299
299
|
end
|
300
300
|
|
301
|
-
def save!(**)
|
301
|
+
def save!(**) # :nodoc:
|
302
302
|
with_transaction_returning_status { super }
|
303
303
|
end
|
304
304
|
|
305
|
-
def touch(*, **)
|
305
|
+
def touch(*, **) # :nodoc:
|
306
306
|
with_transaction_returning_status { super }
|
307
307
|
end
|
308
308
|
|
@@ -314,8 +314,8 @@ module ActiveRecord
|
|
314
314
|
#
|
315
315
|
# Ensure that it is not called if the object was never persisted (failed create),
|
316
316
|
# but call it after the commit of a destroyed object.
|
317
|
-
def committed!(should_run_callbacks: true)
|
318
|
-
|
317
|
+
def committed!(should_run_callbacks: true) # :nodoc:
|
318
|
+
@_start_transaction_state = nil
|
319
319
|
if should_run_callbacks
|
320
320
|
@_committed_already_called = true
|
321
321
|
_run_commit_callbacks
|
@@ -326,7 +326,7 @@ module ActiveRecord
|
|
326
326
|
|
327
327
|
# Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
|
328
328
|
# state should be rolled back to the beginning or just to the last savepoint.
|
329
|
-
def rolledback!(force_restore_state: false, should_run_callbacks: true)
|
329
|
+
def rolledback!(force_restore_state: false, should_run_callbacks: true) # :nodoc:
|
330
330
|
if should_run_callbacks
|
331
331
|
_run_rollback_callbacks
|
332
332
|
end
|
@@ -389,12 +389,7 @@ module ActiveRecord
|
|
389
389
|
def clear_transaction_record_state
|
390
390
|
return unless @_start_transaction_state
|
391
391
|
@_start_transaction_state[:level] -= 1
|
392
|
-
|
393
|
-
end
|
394
|
-
|
395
|
-
# Force to clear the transaction record state.
|
396
|
-
def force_clear_transaction_record_state
|
397
|
-
@_start_transaction_state = nil
|
392
|
+
@_start_transaction_state = nil if @_start_transaction_state[:level] < 1
|
398
393
|
end
|
399
394
|
|
400
395
|
# Restore the new record state and id of a record that was previously saved by a call to save_record_state.
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
include ActiveModel::Translation
|
6
6
|
|
7
7
|
# Set the lookup ancestors for ActiveModel.
|
8
|
-
def lookup_ancestors
|
8
|
+
def lookup_ancestors # :nodoc:
|
9
9
|
klass = self
|
10
10
|
classes = [klass]
|
11
11
|
return classes if klass == ActiveRecord::Base
|
@@ -16,8 +16,8 @@ module ActiveRecord
|
|
16
16
|
classes
|
17
17
|
end
|
18
18
|
|
19
|
-
# Set the i18n scope to
|
20
|
-
def i18n_scope
|
19
|
+
# Set the i18n scope to override ActiveModel.
|
20
|
+
def i18n_scope # :nodoc:
|
21
21
|
:activerecord
|
22
22
|
end
|
23
23
|
end
|