Skip to content

Commit

Permalink
Merge pull request rails#42691 from fatkodima/improve-mysql2-mismatch…
Browse files Browse the repository at this point in the history
…ed-fk-reporting

Improve mysql2 mismatched foreign keys reporting
  • Loading branch information
yahonda authored May 20, 2022
2 parents ecd878b + df5023a commit d3a2615
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -852,9 +852,12 @@ def build_statement_pool
end

def mismatched_foreign_key(message, sql:, binds:)
foreign_key_pat =
/Referencing column '(\w+)' and referenced/i =~ message ? $1 : '\w+'

match = %r/
(?:CREATE|ALTER)\s+TABLE\s*(?:`?\w+`?\.)?`?(?<table>\w+)`?.+?
FOREIGN\s+KEY\s*\(`?(?<foreign_key>\w+)`?\)\s*
FOREIGN\s+KEY\s*\(`?(?<foreign_key>#{foreign_key_pat})`?\)\s*
REFERENCES\s*(`?(?<target_table>\w+)`?)\s*\(`?(?<primary_key>\w+)`?\)
/xmi.match(sql)

Expand Down
27 changes: 27 additions & 0 deletions activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,33 @@ def test_errors_for_bigint_fks_on_integer_pk_table_in_alter_table
@conn.execute("ALTER TABLE engines DROP COLUMN old_car_id") rescue nil
end

def test_errors_for_multiple_fks_on_mismatched_types_for_pk_table_in_alter_table
skip "MariaDB does not return mismatched foreign key in error message" if @conn.mariadb?

begin
error = assert_raises(ActiveRecord::MismatchedForeignKey) do
# we should add matched foreign key first to properly test error parsing
@conn.add_reference :engines, :person, foreign_key: true

# table old_cars has primary key of integer
@conn.add_reference :engines, :old_car, foreign_key: true
end

assert_match(
%r/Column `old_car_id` on table `engines` does not match column `id` on `old_cars`, which has type `int(\(11\))?`\./,
error.message
)
assert_match(
%r/To resolve this issue, change the type of the `old_car_id` column on `engines` to be :integer\. \(For example `t.integer :old_car_id`\)\./,
error.message
)
assert_not_nil error.cause
ensure
@conn.remove_reference(:engines, :person)
@conn.remove_reference(:engines, :old_car)
end
end

def test_errors_for_bigint_fks_on_integer_pk_table_in_create_table
# table old_cars has primary key of integer

Expand Down

0 comments on commit d3a2615

Please sign in to comment.