Skip to content

Commit 26f7e43

Browse files
committed
refactor(fixtures): Avoid disabling referential integrity
Avoid 87% of the `#disable_referential_integrity` calls made in fixture setup by just trying first without disabling and just disabling in case of failure. Also batch foreign keys removals and addition (for clarity only).
1 parent 2874f9f commit 26f7e43

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

lib/active_record/connection_adapters/cockroachdb/database_statements.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,17 @@ def insert_fixtures_set(fixture_set, tables_to_delete = [])
2323
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
2424
statements = table_deletes + fixture_inserts
2525

26-
with_multi_statements do
27-
disable_referential_integrity do
28-
execute_batch(statements, "Fixtures Load")
26+
begin # much faster without disabling referential integrity, worth trying.
27+
with_multi_statements do
28+
transaction(requires_new: true) do
29+
execute_batch(statements, "Fixtures Load")
30+
end
31+
end
32+
rescue
33+
with_multi_statements do
34+
disable_referential_integrity do
35+
execute_batch(statements, "Fixtures Load")
36+
end
2937
end
3038
end
3139
end

lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@ def all_foreign_keys_valid?
2222
def disable_referential_integrity
2323
foreign_keys = all_foreign_keys
2424

25-
foreign_keys.each do |foreign_key|
25+
statements = foreign_keys.map do |foreign_key|
2626
# We do not use the `#remove_foreign_key` method here because it
2727
# checks for foreign keys existance in the schema cache. This method
2828
# is performance critical and we know the foreign key exist.
2929
at = create_alter_table foreign_key.from_table
3030
at.drop_foreign_key foreign_key.name
3131

32-
execute schema_creation.accept(at)
32+
schema_creation.accept(at)
3333
end
34+
execute_batch(statements, "Disable referential integrity -> remove foreign keys")
3435

3536
yield
3637

@@ -52,11 +53,16 @@ def disable_referential_integrity
5253
# for every key. This method is performance critical for the test suite, hence
5354
# we use the `#all_foreign_keys` method that only make one query to the database.
5455
already_inserted_foreign_keys = all_foreign_keys
55-
foreign_keys.each do |foreign_key|
56+
statements = foreign_keys.map do |foreign_key|
5657
next if already_inserted_foreign_keys.any? { |fk| fk.from_table == foreign_key.from_table && fk.options[:name] == foreign_key.options[:name] }
5758

58-
add_foreign_key(foreign_key.from_table, foreign_key.to_table, **foreign_key.options)
59+
options = foreign_key_options(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
60+
at = create_alter_table foreign_key.from_table
61+
at.add_foreign_key foreign_key.to_table, options
62+
63+
schema_creation.accept(at)
5964
end
65+
execute_batch(statements.compact, "Disable referential integrity -> add foreign keys")
6066
ensure
6167
ActiveRecord::Base.table_name_prefix = old_prefix
6268
ActiveRecord::Base.table_name_suffix = old_suffix

0 commit comments

Comments
 (0)