Skip to content

Commit 56a37d8

Browse files
authored
refactor(fixtures): Avoid disabling referential integrity (#362)
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 c02cf48 commit 56a37d8

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

lib/active_record/connection_adapters/cockroachdb/database_statements.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@ def insert_fixtures_set(fixture_set, tables_to_delete = [])
2424
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
2525
statements = table_deletes + fixture_inserts
2626

27-
disable_referential_integrity do
28-
execute_batch(statements, "Fixtures Load")
27+
begin # much faster without disabling referential integrity, worth trying.
28+
transaction(requires_new: true) do
29+
execute_batch(statements, "Fixtures Load")
30+
end
31+
rescue
32+
disable_referential_integrity do
33+
execute_batch(statements, "Fixtures Load")
34+
end
2935
end
3036
end
3137
end

lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ def check_all_foreign_keys_valid!
3636
def disable_referential_integrity
3737
foreign_keys = all_foreign_keys
3838

39-
foreign_keys.each do |foreign_key|
39+
statements = foreign_keys.map do |foreign_key|
4040
# We do not use the `#remove_foreign_key` method here because it
4141
# checks for foreign keys existance in the schema cache. This method
4242
# is performance critical and we know the foreign key exist.
4343
at = create_alter_table foreign_key.from_table
4444
at.drop_foreign_key foreign_key.name
4545

46-
execute schema_creation.accept(at)
46+
schema_creation.accept(at)
4747
end
48+
execute_batch(statements, "Disable referential integrity -> remove foreign keys")
4849

4950
yield
5051

@@ -66,11 +67,16 @@ def disable_referential_integrity
6667
# for every key. This method is performance critical for the test suite, hence
6768
# we use the `#all_foreign_keys` method that only make one query to the database.
6869
already_inserted_foreign_keys = all_foreign_keys
69-
foreign_keys.each do |foreign_key|
70+
statements = foreign_keys.map do |foreign_key|
7071
next if already_inserted_foreign_keys.any? { |fk| fk.from_table == foreign_key.from_table && fk.options[:name] == foreign_key.options[:name] }
7172

72-
add_foreign_key(foreign_key.from_table, foreign_key.to_table, **foreign_key.options)
73+
options = foreign_key_options(foreign_key.from_table, foreign_key.to_table, foreign_key.options)
74+
at = create_alter_table foreign_key.from_table
75+
at.add_foreign_key foreign_key.to_table, options
76+
77+
schema_creation.accept(at)
7378
end
79+
execute_batch(statements.compact, "Disable referential integrity -> add foreign keys")
7480
ensure
7581
ActiveRecord::Base.table_name_prefix = old_prefix
7682
ActiveRecord::Base.table_name_suffix = old_suffix

0 commit comments

Comments
 (0)