activerecord 7.2.4 → 8.1.4
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 +1013 -878
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/association.rb +69 -27
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +7 -3
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency.rb +3 -2
- data/lib/active_record/associations/preloader/association.rb +3 -3
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +18 -5
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attributes.rb +3 -0
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/base.rb +1 -2
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +429 -93
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +148 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +124 -34
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +129 -63
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +132 -65
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -66
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +79 -61
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +156 -68
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +15 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +104 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +41 -66
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +15 -18
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +25 -2
- data/lib/active_record/core.rb +33 -17
- data/lib/active_record/counter_cache.rb +35 -8
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +74 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +8 -8
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +28 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +33 -30
- data/lib/active_record/errors.rb +33 -9
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +15 -9
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +31 -29
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +56 -13
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +48 -42
- data/lib/active_record/model_schema.rb +40 -15
- data/lib/active_record/nested_attributes.rb +14 -12
- data/lib/active_record/persistence.rb +163 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +100 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +35 -30
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -38
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +54 -22
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +60 -43
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +73 -43
- data/lib/active_record/relation/merger.rb +12 -10
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +23 -8
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +200 -96
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +2 -9
- data/lib/active_record/relation.rb +127 -87
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +17 -10
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/signed_id.rb +44 -16
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +53 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -58
- data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +52 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +56 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +85 -50
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +6 -11
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +7 -2
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/dot.rb +0 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +4 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +15 -12
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
|
@@ -45,7 +45,7 @@ module ActiveRecord
|
|
|
45
45
|
# Example:
|
|
46
46
|
# ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
|
|
47
47
|
# mysql2: ['--no-defaults', '--skip-add-drop-table'],
|
|
48
|
-
#
|
|
48
|
+
# postgresql: '--no-tablespaces'
|
|
49
49
|
# }
|
|
50
50
|
mattr_accessor :structure_dump_flags, instance_accessor: false
|
|
51
51
|
|
|
@@ -66,7 +66,7 @@ module ActiveRecord
|
|
|
66
66
|
return if ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
|
|
67
67
|
|
|
68
68
|
configs_for(env_name: environment).each do |db_config|
|
|
69
|
-
check_current_protected_environment!(db_config)
|
|
69
|
+
database_adapter_for(db_config).check_current_protected_environment!(db_config, migration_class)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -147,8 +147,6 @@ module ActiveRecord
|
|
|
147
147
|
return if database_configs.count == 1
|
|
148
148
|
|
|
149
149
|
database_configs.each do |db_config|
|
|
150
|
-
next unless db_config.database_tasks?
|
|
151
|
-
|
|
152
150
|
yield db_config.name
|
|
153
151
|
end
|
|
154
152
|
end
|
|
@@ -178,22 +176,9 @@ module ActiveRecord
|
|
|
178
176
|
dump_db_configs = []
|
|
179
177
|
|
|
180
178
|
each_current_configuration(env) do |db_config|
|
|
181
|
-
|
|
182
|
-
begin
|
|
183
|
-
database_initialized = migration_connection_pool.schema_migration.table_exists?
|
|
184
|
-
rescue ActiveRecord::NoDatabaseError
|
|
185
|
-
create(db_config)
|
|
186
|
-
retry
|
|
187
|
-
end
|
|
179
|
+
database_initialized = initialize_database(db_config)
|
|
188
180
|
|
|
189
|
-
|
|
190
|
-
if File.exist?(schema_dump_path(db_config))
|
|
191
|
-
load_schema(db_config, ActiveRecord.schema_format, nil)
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
seed = true
|
|
195
|
-
end
|
|
196
|
-
end
|
|
181
|
+
seed = true if database_initialized && db_config.seeds?
|
|
197
182
|
end
|
|
198
183
|
|
|
199
184
|
each_current_environment(env) do |environment|
|
|
@@ -253,12 +238,33 @@ module ActiveRecord
|
|
|
253
238
|
end
|
|
254
239
|
end
|
|
255
240
|
|
|
256
|
-
def
|
|
241
|
+
def migrate_all
|
|
242
|
+
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
|
243
|
+
db_configs.each { |db_config| initialize_database(db_config) }
|
|
244
|
+
|
|
245
|
+
if db_configs.size == 1 && db_configs.first.primary?
|
|
246
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate(skip_initialize: true)
|
|
247
|
+
else
|
|
248
|
+
mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
|
|
249
|
+
|
|
250
|
+
mapped_versions.sort.each do |version, db_configs|
|
|
251
|
+
db_configs.each do |db_config|
|
|
252
|
+
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(db_config) do
|
|
253
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate(version, skip_initialize: true)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def migrate(version = nil, skip_initialize: false)
|
|
257
261
|
scope = ENV["SCOPE"]
|
|
258
262
|
verbose_was, Migration.verbose = Migration.verbose, verbose?
|
|
259
263
|
|
|
260
264
|
check_target_version
|
|
261
265
|
|
|
266
|
+
initialize_database(migration_connection_pool.db_config) unless skip_initialize
|
|
267
|
+
|
|
262
268
|
migration_connection_pool.migration_context.migrate(target_version) do |migration|
|
|
263
269
|
if version.blank?
|
|
264
270
|
scope.blank? || scope == migration.scope
|
|
@@ -365,7 +371,8 @@ module ActiveRecord
|
|
|
365
371
|
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
|
|
366
372
|
end
|
|
367
373
|
|
|
368
|
-
def load_schema(db_config, format =
|
|
374
|
+
def load_schema(db_config, format = db_config.schema_format, file = nil) # :nodoc:
|
|
375
|
+
format = format.to_sym
|
|
369
376
|
file ||= schema_dump_path(db_config, format)
|
|
370
377
|
return unless file
|
|
371
378
|
|
|
@@ -386,7 +393,7 @@ module ActiveRecord
|
|
|
386
393
|
Migration.verbose = verbose_was
|
|
387
394
|
end
|
|
388
395
|
|
|
389
|
-
def schema_up_to_date?(configuration,
|
|
396
|
+
def schema_up_to_date?(configuration, _ = nil, file = nil)
|
|
390
397
|
db_config = resolve_configuration(configuration)
|
|
391
398
|
|
|
392
399
|
file ||= schema_dump_path(db_config)
|
|
@@ -402,49 +409,66 @@ module ActiveRecord
|
|
|
402
409
|
end
|
|
403
410
|
end
|
|
404
411
|
|
|
405
|
-
def reconstruct_from_schema(db_config,
|
|
406
|
-
file ||= schema_dump_path(db_config,
|
|
412
|
+
def reconstruct_from_schema(db_config, file = nil) # :nodoc:
|
|
413
|
+
file ||= schema_dump_path(db_config, db_config.schema_format)
|
|
407
414
|
|
|
408
415
|
check_schema_file(file) if file
|
|
409
416
|
|
|
410
417
|
with_temporary_pool(db_config, clobber: true) do
|
|
411
|
-
if schema_up_to_date?(db_config,
|
|
418
|
+
if schema_up_to_date?(db_config, nil, file)
|
|
412
419
|
truncate_tables(db_config) unless ENV["SKIP_TEST_DATABASE_TRUNCATE"]
|
|
413
420
|
else
|
|
414
421
|
purge(db_config)
|
|
415
|
-
load_schema(db_config,
|
|
422
|
+
load_schema(db_config, db_config.schema_format, file)
|
|
416
423
|
end
|
|
417
424
|
rescue ActiveRecord::NoDatabaseError
|
|
418
425
|
create(db_config)
|
|
419
|
-
load_schema(db_config,
|
|
426
|
+
load_schema(db_config, db_config.schema_format, file)
|
|
420
427
|
end
|
|
421
428
|
end
|
|
422
429
|
|
|
423
|
-
def
|
|
430
|
+
def dump_all
|
|
431
|
+
seen_schemas = []
|
|
432
|
+
|
|
433
|
+
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
|
434
|
+
schema_path = schema_dump_path(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
435
|
+
|
|
436
|
+
next if seen_schemas.include?(schema_path)
|
|
437
|
+
|
|
438
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
|
|
439
|
+
seen_schemas << schema_path
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
def dump_schema(db_config, format = db_config.schema_format) # :nodoc:
|
|
424
444
|
return unless db_config.schema_dump
|
|
425
445
|
|
|
426
446
|
require "active_record/schema_dumper"
|
|
427
447
|
filename = schema_dump_path(db_config, format)
|
|
428
448
|
return unless filename
|
|
429
449
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
450
|
+
with_temporary_pool(db_config) do |pool|
|
|
451
|
+
FileUtils.mkdir_p(db_dir)
|
|
452
|
+
case format.to_sym
|
|
453
|
+
when :ruby
|
|
454
|
+
File.open(filename, "w:utf-8") do |file|
|
|
455
|
+
ActiveRecord::SchemaDumper.dump(pool, file)
|
|
456
|
+
end
|
|
457
|
+
when :sql
|
|
458
|
+
structure_dump(db_config, filename)
|
|
459
|
+
if pool.schema_migration.table_exists?
|
|
460
|
+
File.open(filename, "a") do |f|
|
|
461
|
+
pool.with_connection do |connection|
|
|
462
|
+
f.puts connection.dump_schema_versions
|
|
463
|
+
end
|
|
464
|
+
f.print "\n"
|
|
465
|
+
end
|
|
442
466
|
end
|
|
443
467
|
end
|
|
444
468
|
end
|
|
445
469
|
end
|
|
446
470
|
|
|
447
|
-
def schema_dump_path(db_config, format =
|
|
471
|
+
def schema_dump_path(db_config, format = db_config.schema_format)
|
|
448
472
|
return ENV["SCHEMA"] if ENV["SCHEMA"]
|
|
449
473
|
|
|
450
474
|
filename = db_config.schema_dump(format)
|
|
@@ -457,32 +481,16 @@ module ActiveRecord
|
|
|
457
481
|
end
|
|
458
482
|
end
|
|
459
483
|
|
|
460
|
-
def cache_dump_filename(
|
|
461
|
-
|
|
462
|
-
schema_cache_path ||
|
|
463
|
-
|
|
464
|
-
schema_cache_env ||
|
|
465
|
-
db_config_or_name.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
|
|
466
|
-
else
|
|
467
|
-
ActiveRecord.deprecator.warn(<<~MSG.squish)
|
|
468
|
-
Passing a database name to `cache_dump_filename` is deprecated and will be removed in Rails 8.0. Pass a
|
|
469
|
-
`ActiveRecord::DatabaseConfigurations::DatabaseConfig` object instead.
|
|
470
|
-
MSG
|
|
471
|
-
|
|
472
|
-
filename = if ActiveRecord::Base.configurations.primary?(db_config_or_name)
|
|
473
|
-
"schema_cache.yml"
|
|
474
|
-
else
|
|
475
|
-
"#{db_config_or_name}_schema_cache.yml"
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
schema_cache_path || schema_cache_env || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
|
479
|
-
end
|
|
484
|
+
def cache_dump_filename(db_config, schema_cache_path: nil)
|
|
485
|
+
schema_cache_path ||
|
|
486
|
+
db_config.schema_cache_path ||
|
|
487
|
+
db_config.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
|
|
480
488
|
end
|
|
481
489
|
|
|
482
|
-
def load_schema_current(format =
|
|
490
|
+
def load_schema_current(format = nil, file = nil, environment = env)
|
|
483
491
|
each_current_configuration(environment) do |db_config|
|
|
484
492
|
with_temporary_connection(db_config) do
|
|
485
|
-
load_schema(db_config, format, file)
|
|
493
|
+
load_schema(db_config, format || db_config.schema_format, file)
|
|
486
494
|
end
|
|
487
495
|
end
|
|
488
496
|
end
|
|
@@ -547,17 +555,6 @@ module ActiveRecord
|
|
|
547
555
|
end
|
|
548
556
|
|
|
549
557
|
private
|
|
550
|
-
def schema_cache_env
|
|
551
|
-
if ENV["SCHEMA_CACHE"]
|
|
552
|
-
ActiveRecord.deprecator.warn(<<~MSG.squish)
|
|
553
|
-
Setting `ENV["SCHEMA_CACHE"]` is deprecated and will be removed in Rails 8.0.
|
|
554
|
-
Configure the `:schema_cache_path` in the database configuration instead.
|
|
555
|
-
MSG
|
|
556
|
-
|
|
557
|
-
nil
|
|
558
|
-
end
|
|
559
|
-
end
|
|
560
|
-
|
|
561
558
|
def with_temporary_pool(db_config, clobber: false)
|
|
562
559
|
original_db_config = migration_class.connection_db_config
|
|
563
560
|
pool = migration_class.connection_handler.establish_connection(db_config, clobber: clobber)
|
|
@@ -651,20 +648,23 @@ module ActiveRecord
|
|
|
651
648
|
end
|
|
652
649
|
end
|
|
653
650
|
|
|
654
|
-
def
|
|
655
|
-
with_temporary_pool(db_config) do
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
|
|
651
|
+
def initialize_database(db_config)
|
|
652
|
+
with_temporary_pool(db_config) do
|
|
653
|
+
begin
|
|
654
|
+
database_already_initialized = migration_connection_pool.schema_migration.table_exists?
|
|
655
|
+
rescue ActiveRecord::NoDatabaseError
|
|
656
|
+
create(db_config)
|
|
657
|
+
retry
|
|
662
658
|
end
|
|
663
659
|
|
|
664
|
-
|
|
665
|
-
|
|
660
|
+
unless database_already_initialized
|
|
661
|
+
schema_dump_path = schema_dump_path(db_config)
|
|
662
|
+
if schema_dump_path && File.exist?(schema_dump_path)
|
|
663
|
+
load_schema(db_config)
|
|
664
|
+
end
|
|
666
665
|
end
|
|
667
|
-
|
|
666
|
+
|
|
667
|
+
!database_already_initialized
|
|
668
668
|
end
|
|
669
669
|
end
|
|
670
670
|
end
|
|
@@ -2,18 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Tasks # :nodoc:
|
|
5
|
-
class MySQLDatabaseTasks # :nodoc:
|
|
6
|
-
ER_DB_CREATE_EXISTS = 1007
|
|
7
|
-
|
|
8
|
-
def self.using_database_configurations?
|
|
9
|
-
true
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def initialize(db_config)
|
|
13
|
-
@db_config = db_config
|
|
14
|
-
@configuration_hash = db_config.configuration_hash
|
|
15
|
-
end
|
|
16
|
-
|
|
5
|
+
class MySQLDatabaseTasks < AbstractTasks # :nodoc:
|
|
17
6
|
def create
|
|
18
7
|
establish_connection(configuration_hash_without_database)
|
|
19
8
|
connection.create_database(db_config.database, creation_options)
|
|
@@ -35,10 +24,6 @@ module ActiveRecord
|
|
|
35
24
|
connection.charset
|
|
36
25
|
end
|
|
37
26
|
|
|
38
|
-
def collation
|
|
39
|
-
connection.collation
|
|
40
|
-
end
|
|
41
|
-
|
|
42
27
|
def structure_dump(filename, extra_flags)
|
|
43
28
|
args = prepare_command_options
|
|
44
29
|
args.concat(["--result-file", "#{filename}"])
|
|
@@ -55,7 +40,7 @@ module ActiveRecord
|
|
|
55
40
|
args.concat([db_config.database.to_s])
|
|
56
41
|
args.unshift(*extra_flags) if extra_flags
|
|
57
42
|
|
|
58
|
-
run_cmd("mysqldump", args
|
|
43
|
+
run_cmd("mysqldump", *args)
|
|
59
44
|
end
|
|
60
45
|
|
|
61
46
|
def structure_load(filename, extra_flags)
|
|
@@ -64,24 +49,10 @@ module ActiveRecord
|
|
|
64
49
|
args.concat(["--database", db_config.database.to_s])
|
|
65
50
|
args.unshift(*extra_flags) if extra_flags
|
|
66
51
|
|
|
67
|
-
run_cmd("mysql", args
|
|
52
|
+
run_cmd("mysql", *args)
|
|
68
53
|
end
|
|
69
54
|
|
|
70
55
|
private
|
|
71
|
-
attr_reader :db_config, :configuration_hash
|
|
72
|
-
|
|
73
|
-
def connection
|
|
74
|
-
ActiveRecord::Base.lease_connection
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def establish_connection(config = db_config)
|
|
78
|
-
ActiveRecord::Base.establish_connection(config)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def configuration_hash_without_database
|
|
82
|
-
configuration_hash.merge(database: nil)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
56
|
def creation_options
|
|
86
57
|
Hash.new.tap do |options|
|
|
87
58
|
options[:charset] = configuration_hash[:encoding] if configuration_hash.include?(:encoding)
|
|
@@ -90,32 +61,7 @@ module ActiveRecord
|
|
|
90
61
|
end
|
|
91
62
|
|
|
92
63
|
def prepare_command_options
|
|
93
|
-
|
|
94
|
-
host: "--host",
|
|
95
|
-
port: "--port",
|
|
96
|
-
socket: "--socket",
|
|
97
|
-
username: "--user",
|
|
98
|
-
password: "--password",
|
|
99
|
-
encoding: "--default-character-set",
|
|
100
|
-
sslca: "--ssl-ca",
|
|
101
|
-
sslcert: "--ssl-cert",
|
|
102
|
-
sslcapath: "--ssl-capath",
|
|
103
|
-
sslcipher: "--ssl-cipher",
|
|
104
|
-
sslkey: "--ssl-key",
|
|
105
|
-
ssl_mode: "--ssl-mode"
|
|
106
|
-
}.filter_map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }
|
|
107
|
-
|
|
108
|
-
args
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def run_cmd(cmd, args, action)
|
|
112
|
-
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def run_cmd_error(cmd, args, action)
|
|
116
|
-
msg = +"failed to execute: `#{cmd}`\n"
|
|
117
|
-
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
|
118
|
-
msg
|
|
64
|
+
db_config.adapter_class.cli_args(configuration_hash)
|
|
119
65
|
end
|
|
120
66
|
end
|
|
121
67
|
end
|
|
@@ -4,20 +4,11 @@ require "tempfile"
|
|
|
4
4
|
|
|
5
5
|
module ActiveRecord
|
|
6
6
|
module Tasks # :nodoc:
|
|
7
|
-
class PostgreSQLDatabaseTasks # :nodoc:
|
|
7
|
+
class PostgreSQLDatabaseTasks < AbstractTasks # :nodoc:
|
|
8
8
|
DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
|
|
9
9
|
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1"
|
|
10
10
|
SQL_COMMENT_BEGIN = "--"
|
|
11
11
|
|
|
12
|
-
def self.using_database_configurations?
|
|
13
|
-
true
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def initialize(db_config)
|
|
17
|
-
@db_config = db_config
|
|
18
|
-
@configuration_hash = db_config.configuration_hash
|
|
19
|
-
end
|
|
20
|
-
|
|
21
12
|
def create(connection_already_established = false)
|
|
22
13
|
establish_connection(public_schema_config) unless connection_already_established
|
|
23
14
|
connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
|
|
@@ -29,14 +20,6 @@ module ActiveRecord
|
|
|
29
20
|
connection.drop_database(db_config.database)
|
|
30
21
|
end
|
|
31
22
|
|
|
32
|
-
def charset
|
|
33
|
-
connection.encoding
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def collation
|
|
37
|
-
connection.collation
|
|
38
|
-
end
|
|
39
|
-
|
|
40
23
|
def purge
|
|
41
24
|
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
|
42
25
|
drop
|
|
@@ -72,29 +55,20 @@ module ActiveRecord
|
|
|
72
55
|
end
|
|
73
56
|
|
|
74
57
|
args << db_config.database
|
|
75
|
-
run_cmd("pg_dump", args
|
|
58
|
+
run_cmd("pg_dump", *args)
|
|
76
59
|
remove_sql_header_comments(filename)
|
|
77
60
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
|
78
61
|
end
|
|
79
62
|
|
|
80
63
|
def structure_load(filename, extra_flags)
|
|
81
|
-
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL
|
|
64
|
+
args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--output", File::NULL]
|
|
82
65
|
args.concat(Array(extra_flags)) if extra_flags
|
|
66
|
+
args.concat(["--file", filename])
|
|
83
67
|
args << db_config.database
|
|
84
|
-
run_cmd("psql", args
|
|
68
|
+
run_cmd("psql", *args)
|
|
85
69
|
end
|
|
86
70
|
|
|
87
71
|
private
|
|
88
|
-
attr_reader :db_config, :configuration_hash
|
|
89
|
-
|
|
90
|
-
def connection
|
|
91
|
-
ActiveRecord::Base.lease_connection
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def establish_connection(config = db_config)
|
|
95
|
-
ActiveRecord::Base.establish_connection(config)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
72
|
def encoding
|
|
99
73
|
configuration_hash[:encoding] || DEFAULT_ENCODING
|
|
100
74
|
end
|
|
@@ -116,15 +90,8 @@ module ActiveRecord
|
|
|
116
90
|
end
|
|
117
91
|
end
|
|
118
92
|
|
|
119
|
-
def run_cmd(cmd, args,
|
|
120
|
-
fail run_cmd_error(cmd, args
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def run_cmd_error(cmd, args, action)
|
|
124
|
-
msg = +"failed to execute:\n"
|
|
125
|
-
msg << "#{cmd} #{args.join(' ')}\n\n"
|
|
126
|
-
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
|
127
|
-
msg
|
|
93
|
+
def run_cmd(cmd, *args, **opts)
|
|
94
|
+
fail run_cmd_error(cmd, args) unless Kernel.system(psql_env, cmd, *args, **opts)
|
|
128
95
|
end
|
|
129
96
|
|
|
130
97
|
def remove_sql_header_comments(filename)
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Tasks # :nodoc:
|
|
5
|
-
class SQLiteDatabaseTasks # :nodoc:
|
|
6
|
-
def self.using_database_configurations?
|
|
7
|
-
true
|
|
8
|
-
end
|
|
9
|
-
|
|
5
|
+
class SQLiteDatabaseTasks < AbstractTasks # :nodoc:
|
|
10
6
|
def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
|
|
11
7
|
@db_config = db_config
|
|
12
8
|
@root = root
|
|
@@ -37,10 +33,6 @@ module ActiveRecord
|
|
|
37
33
|
connection.reconnect!
|
|
38
34
|
end
|
|
39
35
|
|
|
40
|
-
def charset
|
|
41
|
-
connection.encoding
|
|
42
|
-
end
|
|
43
|
-
|
|
44
36
|
def structure_dump(filename, extra_flags)
|
|
45
37
|
args = []
|
|
46
38
|
args.concat(Array(extra_flags)) if extra_flags
|
|
@@ -50,11 +42,12 @@ module ActiveRecord
|
|
|
50
42
|
if ignore_tables.any?
|
|
51
43
|
ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
|
|
52
44
|
condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
|
|
53
|
-
args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
|
|
45
|
+
args << "SELECT sql || ';' FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
|
|
54
46
|
else
|
|
55
|
-
args << ".schema"
|
|
47
|
+
args << ".schema --nosys"
|
|
56
48
|
end
|
|
57
|
-
|
|
49
|
+
|
|
50
|
+
run_cmd("sqlite3", *args, out: filename)
|
|
58
51
|
end
|
|
59
52
|
|
|
60
53
|
def structure_load(filename, extra_flags)
|
|
@@ -62,28 +55,23 @@ module ActiveRecord
|
|
|
62
55
|
`sqlite3 #{flags} #{db_config.database} < "#{filename}"`
|
|
63
56
|
end
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
def check_current_protected_environment!(db_config, migration_class)
|
|
59
|
+
super
|
|
60
|
+
rescue ActiveRecord::StatementInvalid => e
|
|
61
|
+
case e.cause
|
|
62
|
+
when SQLite3::ReadOnlyException
|
|
63
|
+
else
|
|
64
|
+
raise e
|
|
70
65
|
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
attr_reader :root
|
|
71
70
|
|
|
72
71
|
def establish_connection(config = db_config)
|
|
73
72
|
ActiveRecord::Base.establish_connection(config)
|
|
74
73
|
connection.connect!
|
|
75
74
|
end
|
|
76
|
-
|
|
77
|
-
def run_cmd(cmd, args, out)
|
|
78
|
-
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def run_cmd_error(cmd, args)
|
|
82
|
-
msg = +"failed to execute:\n"
|
|
83
|
-
msg << "#{cmd} #{args.join(' ')}\n\n"
|
|
84
|
-
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
|
85
|
-
msg
|
|
86
|
-
end
|
|
87
75
|
end
|
|
88
76
|
end
|
|
89
77
|
end
|
|
@@ -4,17 +4,31 @@ require "active_support/testing/parallelization"
|
|
|
4
4
|
|
|
5
5
|
module ActiveRecord
|
|
6
6
|
module TestDatabases # :nodoc:
|
|
7
|
+
ActiveSupport::Testing::Parallelization.before_fork_hook do
|
|
8
|
+
if ActiveSupport.parallelize_test_databases
|
|
9
|
+
ActiveRecord::Base.connection_handler.clear_all_connections!
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
|
|
8
|
-
|
|
14
|
+
if ActiveSupport.parallelize_test_databases
|
|
15
|
+
create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook do
|
|
20
|
+
ActiveRecord::Base.connection_handler.each_connection_pool.each(&:discard!)
|
|
9
21
|
end
|
|
10
22
|
|
|
11
23
|
def self.create_and_load_schema(i, env_name:)
|
|
12
24
|
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
|
13
25
|
|
|
14
|
-
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
|
15
|
-
db_config._database = "#{db_config.database}
|
|
26
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name, include_hidden: true).each do |db_config|
|
|
27
|
+
db_config._database = "#{db_config.database}_#{i}"
|
|
16
28
|
|
|
17
|
-
|
|
29
|
+
if db_config.database_tasks?
|
|
30
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, nil)
|
|
31
|
+
end
|
|
18
32
|
end
|
|
19
33
|
ensure
|
|
20
34
|
ActiveRecord::Base.establish_connection
|