activerecord 7.2.2.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +564 -753
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/belongs_to_association.rb +18 -2
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- 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 +10 -8
- data/lib/active_record/associations/collection_proxy.rb +22 -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/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- 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 +17 -4
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attribute_methods.rb +24 -19
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +91 -39
- data/lib/active_record/base.rb +3 -4
- data/lib/active_record/coders/json.rb +14 -5
- 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 +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +458 -117
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +136 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +44 -11
- 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 +37 -36
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -29
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +175 -87
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +77 -58
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -9
- 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 +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -45
- 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/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 +28 -45
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +69 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +140 -64
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -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 +13 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +112 -42
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +2 -19
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +37 -10
- data/lib/active_record/core.rb +61 -25
- data/lib/active_record/counter_cache.rb +34 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- 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 +9 -9
- data/lib/active_record/encryption/encrypted_attribute_type.rb +12 -3
- data/lib/active_record/encryption/encryptor.rb +49 -28
- 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 +46 -42
- data/lib/active_record/errors.rb +36 -12
- 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 +73 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +13 -9
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +12 -7
- 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 +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +44 -11
- 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 +50 -43
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +104 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +12 -12
- data/lib/active_record/railtie.rb +37 -32
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -37
- 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 +53 -21
- 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 +80 -63
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +54 -37
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -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 +22 -7
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +156 -95
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +122 -80
- 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_dumper.rb +47 -22
- 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/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +47 -18
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -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 +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- 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 +39 -16
- 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 +15 -2
- data/lib/active_record/type/serialized.rb +11 -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 +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -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/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/table.rb +3 -7
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +6 -22
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +17 -17
- 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)
|
|
@@ -107,16 +78,6 @@ module ActiveRecord
|
|
|
107
78
|
|
|
108
79
|
args
|
|
109
80
|
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
|
|
119
|
-
end
|
|
120
81
|
end
|
|
121
82
|
end
|
|
122
83
|
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)
|
|
@@ -132,6 +99,13 @@ module ActiveRecord
|
|
|
132
99
|
tempfile = Tempfile.open("uncommented_structure.sql")
|
|
133
100
|
begin
|
|
134
101
|
File.foreach(filename) do |line|
|
|
102
|
+
next if line.start_with?("\\restrict ")
|
|
103
|
+
|
|
104
|
+
if line.start_with?("\\unrestrict ")
|
|
105
|
+
removing_comments = true
|
|
106
|
+
next
|
|
107
|
+
end
|
|
108
|
+
|
|
135
109
|
unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
|
|
136
110
|
tempfile << line
|
|
137
111
|
removing_comments = false
|
|
@@ -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,27 @@ 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
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
def self.create_and_load_schema(i, env_name:)
|
|
12
20
|
old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
|
|
13
21
|
|
|
14
|
-
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
|
|
15
|
-
db_config._database = "#{db_config.database}
|
|
22
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env_name, include_hidden: true).each do |db_config|
|
|
23
|
+
db_config._database = "#{db_config.database}_#{i}"
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
if db_config.database_tasks?
|
|
26
|
+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, nil)
|
|
27
|
+
end
|
|
18
28
|
end
|
|
19
29
|
ensure
|
|
20
30
|
ActiveRecord::Base.establish_connection
|
|
@@ -36,11 +36,26 @@ module ActiveRecord
|
|
|
36
36
|
class_attribute :pre_loaded_fixtures, default: false
|
|
37
37
|
class_attribute :lock_threads, default: true
|
|
38
38
|
class_attribute :fixture_sets, default: {}
|
|
39
|
+
class_attribute :database_transactions_config, default: {}
|
|
39
40
|
|
|
40
41
|
ActiveSupport.run_load_hooks(:active_record_fixtures, self)
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
module ClassMethods
|
|
45
|
+
# Do not use transactional tests for the given database. This overrides
|
|
46
|
+
# the default setting as defined by `use_transactional_tests`, which
|
|
47
|
+
# applies to all database connection pools not explicitly configured here.
|
|
48
|
+
def skip_transactional_tests_for_database(database_name)
|
|
49
|
+
use_transactional_tests_for_database(database_name, false)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Enable or disable transactions per database. This overrides the default
|
|
53
|
+
# setting as defined by `use_transactional_tests`, which applies to all
|
|
54
|
+
# database connection pools not explicitly configured here.
|
|
55
|
+
def use_transactional_tests_for_database(database_name, enabled = true)
|
|
56
|
+
self.database_transactions_config = database_transactions_config.merge(database_name => enabled)
|
|
57
|
+
end
|
|
58
|
+
|
|
44
59
|
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
|
45
60
|
#
|
|
46
61
|
# Examples:
|
|
@@ -106,7 +121,8 @@ module ActiveRecord
|
|
|
106
121
|
|
|
107
122
|
private
|
|
108
123
|
def run_in_transaction?
|
|
109
|
-
|
|
124
|
+
has_explicit_config = database_transactions_config.any? { |_, enabled| enabled }
|
|
125
|
+
(use_transactional_tests || has_explicit_config) &&
|
|
110
126
|
!self.class.uses_transaction?(name)
|
|
111
127
|
end
|
|
112
128
|
|
|
@@ -137,12 +153,15 @@ module ActiveRecord
|
|
|
137
153
|
invalidate_already_loaded_fixtures
|
|
138
154
|
@loaded_fixtures = load_fixtures(config)
|
|
139
155
|
end
|
|
156
|
+
setup_asynchronous_queries_session
|
|
140
157
|
|
|
141
158
|
# Instantiate fixtures for every test if requested.
|
|
142
159
|
instantiate_fixtures if use_instantiated_fixtures
|
|
143
160
|
end
|
|
144
161
|
|
|
145
162
|
def teardown_fixtures
|
|
163
|
+
teardown_asynchronous_queries_session
|
|
164
|
+
|
|
146
165
|
# Rollback changes if a transaction is active.
|
|
147
166
|
if run_in_transaction?
|
|
148
167
|
teardown_transactional_fixtures
|
|
@@ -154,15 +173,31 @@ module ActiveRecord
|
|
|
154
173
|
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
|
155
174
|
end
|
|
156
175
|
|
|
176
|
+
def setup_asynchronous_queries_session
|
|
177
|
+
@_async_queries_session = ActiveRecord::Base.asynchronous_queries_tracker.start_session
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def teardown_asynchronous_queries_session
|
|
181
|
+
ActiveRecord::Base.asynchronous_queries_tracker.finalize_session(true) if @_async_queries_session
|
|
182
|
+
end
|
|
183
|
+
|
|
157
184
|
def invalidate_already_loaded_fixtures
|
|
158
185
|
@@already_loaded_fixtures.clear
|
|
159
186
|
end
|
|
160
187
|
|
|
188
|
+
def transactional_tests_for_pool?(pool)
|
|
189
|
+
database_transactions_config.fetch(pool.db_config.name.to_sym, use_transactional_tests)
|
|
190
|
+
end
|
|
191
|
+
|
|
161
192
|
def setup_transactional_fixtures
|
|
162
193
|
setup_shared_connection_pool
|
|
163
194
|
|
|
164
195
|
# Begin transactions for connections already established
|
|
165
196
|
@fixture_connection_pools = ActiveRecord::Base.connection_handler.connection_pool_list(:writing)
|
|
197
|
+
|
|
198
|
+
# Filter to pools that want to use transactions
|
|
199
|
+
@fixture_connection_pools.select! { |pool| transactional_tests_for_pool?(pool) }
|
|
200
|
+
|
|
166
201
|
@fixture_connection_pools.each do |pool|
|
|
167
202
|
pool.pin_connection!(lock_threads)
|
|
168
203
|
pool.lease_connection
|
|
@@ -178,7 +213,8 @@ module ActiveRecord
|
|
|
178
213
|
if pool
|
|
179
214
|
setup_shared_connection_pool
|
|
180
215
|
|
|
181
|
-
|
|
216
|
+
# Don't begin a transaction if we've already done so, or are not using them for this pool
|
|
217
|
+
if !@fixture_connection_pools.include?(pool) && transactional_tests_for_pool?(pool)
|
|
182
218
|
pool.pin_connection!(lock_threads)
|
|
183
219
|
pool.lease_connection
|
|
184
220
|
@fixture_connection_pools << pool
|
|
@@ -190,6 +226,7 @@ module ActiveRecord
|
|
|
190
226
|
|
|
191
227
|
def teardown_transactional_fixtures
|
|
192
228
|
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
|
229
|
+
|
|
193
230
|
unless @fixture_connection_pools.map(&:unpin_connection!).all?
|
|
194
231
|
# Something caused the transaction to be committed or rolled back
|
|
195
232
|
# We can no longer trust the database is in a clean state.
|