提交 59c3ed1b 编写于 作者: G George Claghorn

MySQL: Raise ActiveRecord::InvalidForeignKey for foreign-key constraint violations on delete

上级 cfee9fee
......@@ -619,6 +619,7 @@ def extract_precision(sql_type)
ER_DUP_ENTRY = 1062
ER_NOT_NULL_VIOLATION = 1048
ER_DO_NOT_HAVE_DEFAULT = 1364
ER_ROW_IS_REFERENCED_2 = 1451
ER_NO_REFERENCED_ROW_2 = 1452
ER_DATA_TOO_LONG = 1406
ER_OUT_OF_RANGE = 1264
......@@ -633,7 +634,7 @@ def translate_exception(exception, message)
case error_number(exception)
when ER_DUP_ENTRY
RecordNotUnique.new(message)
when ER_NO_REFERENCED_ROW_2
when ER_ROW_IS_REFERENCED_2, ER_NO_REFERENCED_ROW_2
InvalidForeignKey.new(message)
when ER_CANNOT_ADD_FOREIGN
mismatched_foreign_key(message)
......
......@@ -111,7 +111,8 @@ class WrappedDatabaseException < StatementInvalid
class RecordNotUnique < WrappedDatabaseException
end
# Raised when a record cannot be inserted or updated because it references a non-existent record.
# Raised when a record cannot be inserted or updated because it references a non-existent record,
# or when a record cannot be deleted because a parent record references it.
class InvalidForeignKey < WrappedDatabaseException
end
......
......@@ -304,6 +304,8 @@ def test_supports_multi_insert_is_deprecated
class AdapterForeignKeyTest < ActiveRecord::TestCase
self.use_transactional_tests = false
fixtures :fk_test_has_pk
def setup
@connection = ActiveRecord::Base.connection
end
......@@ -322,7 +324,7 @@ def test_foreign_key_violations_are_translated_to_specific_exception_with_valida
assert_not_nil error.cause
end
def test_foreign_key_violations_are_translated_to_specific_exception
def test_foreign_key_violations_on_insert_are_translated_to_specific_exception
error = assert_raises(ActiveRecord::InvalidForeignKey) do
insert_into_fk_test_has_fk
end
......@@ -330,6 +332,16 @@ def test_foreign_key_violations_are_translated_to_specific_exception
assert_not_nil error.cause
end
def test_foreign_key_violations_on_delete_are_translated_to_specific_exception
insert_into_fk_test_has_fk fk_id: 1
error = assert_raises(ActiveRecord::InvalidForeignKey) do
@connection.execute "DELETE FROM fk_test_has_pk WHERE pk_id = 1"
end
assert_not_nil error.cause
end
def test_disable_referential_integrity
assert_nothing_raised do
@connection.disable_referential_integrity do
......@@ -342,14 +354,13 @@ def test_disable_referential_integrity
end
private
def insert_into_fk_test_has_fk
def insert_into_fk_test_has_fk(fk_id: 0)
# Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
if @connection.prefetch_primary_key?
id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
@connection.execute "INSERT INTO fk_test_has_fk (id,fk_id) VALUES (#{id_value},0)"
@connection.execute "INSERT INTO fk_test_has_fk (id,fk_id) VALUES (#{id_value},#{fk_id})"
else
@connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
@connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (#{fk_id})"
end
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册