mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
MySQL: Raise ActiveRecord::InvalidForeignKey for foreign-key constraint violations on delete
This commit is contained in:
parent
cfee9feee4
commit
59c3ed1b3f
3 changed files with 20 additions and 7 deletions
|
@ -619,6 +619,7 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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 @@ module ActiveRecord
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue