diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3440743a..3ebc86dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,9 +40,11 @@ jobs: fail-fast: false matrix: # https://www.cockroachlabs.com/docs/releases/release-support-policy - crdb: [v23.2, v24.1, v24.3] + crdb: [v24.3] ruby: ["3.4"] - name: Test (crdb=${{ matrix.crdb }} ruby=${{ matrix.ruby }}) + sql_cache: [15, 25, 35] + store: [20, 40, 60, 80] + name: "${{ matrix.sql_cache }}% SQL&Cache, ${{ matrix.store }}% Store" steps: - name: Set Up Actions uses: actions/checkout@v4 @@ -75,9 +77,8 @@ jobs: # Start a CockroachDB server and wait for it to become ready. rm -f "$urlfile" - rm -rf cockroach-data # Start CockroachDB. - cockroach start-single-node --max-sql-memory=25% --cache=25% --insecure --host=localhost --spatial-libs=./cockroach-$full_version.linux-amd64/lib --listening-url-file="$urlfile" >/dev/null 2>&1 & + cockroach start-single-node --insecure --max-sql-memory=${{ matrix.sql_cache }}% --cache=${{ matrix.sql_cache }}% --store=type=mem,size=${{ matrix.store }}% --host=localhost --spatial-libs=./cockroach-$full_version.linux-amd64/lib --listening-url-file="$urlfile" >/dev/null 2>&1 & # Ensure CockroachDB is stopped on script exit. # Wait until CockroachDB has started. for i in {0..3}; do diff --git a/lib/active_record/connection_adapters/cockroachdb/database_statements.rb b/lib/active_record/connection_adapters/cockroachdb/database_statements.rb index 56ce43ff..7f1011d3 100644 --- a/lib/active_record/connection_adapters/cockroachdb/database_statements.rb +++ b/lib/active_record/connection_adapters/cockroachdb/database_statements.rb @@ -24,8 +24,14 @@ def insert_fixtures_set(fixture_set, tables_to_delete = []) table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" } statements = table_deletes + fixture_inserts - disable_referential_integrity do - execute_batch(statements, "Fixtures Load") + begin # much faster without disabling referential integrity, worth trying. + transaction(requires_new: true) do + execute_batch(statements, "Fixtures Load") + end + rescue + disable_referential_integrity do + execute_batch(statements, "Fixtures Load") + end end end end diff --git a/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb b/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb index bdbf3852..fa4cb179 100644 --- a/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb +++ b/lib/active_record/connection_adapters/cockroachdb/referential_integrity.rb @@ -36,15 +36,16 @@ def check_all_foreign_keys_valid! def disable_referential_integrity foreign_keys = all_foreign_keys - foreign_keys.each do |foreign_key| + statements = foreign_keys.map do |foreign_key| # We do not use the `#remove_foreign_key` method here because it # checks for foreign keys existance in the schema cache. This method # is performance critical and we know the foreign key exist. at = create_alter_table foreign_key.from_table at.drop_foreign_key foreign_key.name - execute schema_creation.accept(at) + schema_creation.accept(at) end + execute_batch(statements, "Disable referential integrity -> remove foreign keys") yield @@ -66,11 +67,16 @@ def disable_referential_integrity # for every key. This method is performance critical for the test suite, hence # we use the `#all_foreign_keys` method that only make one query to the database. already_inserted_foreign_keys = all_foreign_keys - foreign_keys.each do |foreign_key| + statements = foreign_keys.map do |foreign_key| next if already_inserted_foreign_keys.any? { |fk| fk.from_table == foreign_key.from_table && fk.options[:name] == foreign_key.options[:name] } - add_foreign_key(foreign_key.from_table, foreign_key.to_table, **foreign_key.options) + options = foreign_key_options(foreign_key.from_table, foreign_key.to_table, foreign_key.options) + at = create_alter_table foreign_key.from_table + at.add_foreign_key foreign_key.to_table, options + + schema_creation.accept(at) end + execute_batch(statements.compact, "Disable referential integrity -> add foreign keys") ensure ActiveRecord::Base.table_name_prefix = old_prefix ActiveRecord::Base.table_name_suffix = old_suffix