Raise database error when table doesn't exist

Since 1944a7e74c, adding a foreign key or
check constraint to a non-existent table results in an unhelpful error:

    NoMethodError: undefined method `scan' for nil:NilClass

This restores the previous behaviour of raising the underlying error
from the database, which describes the actual problem.
This commit is contained in:
Eugene Kenny 2020-11-01 12:31:39 +00:00
parent afb9145a59
commit fcd40a443a
3 changed files with 25 additions and 4 deletions

View File

@ -89,7 +89,7 @@ module ActiveRecord
WHERE name = #{quote_table_name(table_name)} AND type = 'table'
SQL
table_sql.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
CheckConstraintDefinition.new(table_name, expression, name: name)
end
end

View File

@ -21,7 +21,7 @@ if ActiveRecord::Base.connection.supports_check_constraints?
end
teardown do
@connection.drop_table "trades", if_exists: true
@connection.drop_table "trades", if_exists: true rescue nil
end
def test_check_constraints
@ -56,6 +56,13 @@ if ActiveRecord::Base.connection.supports_check_constraints?
end
end
def test_add_check_constraint_with_non_existent_table_raises
e = assert_raises(ActiveRecord::StatementInvalid) do
@connection.add_check_constraint :refunds, "quantity > 0", name: "quantity_check"
end
assert_match(/refunds/, e.message)
end
def test_added_check_constraint_ensures_valid_values
@connection.add_check_constraint :trades, "quantity > 0", name: "quantity_check"

View File

@ -189,8 +189,8 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
end
teardown do
@connection.drop_table "astronauts", if_exists: true
@connection.drop_table "rockets", if_exists: true
@connection.drop_table "astronauts", if_exists: true rescue nil
@connection.drop_table "rockets", if_exists: true rescue nil
end
def test_foreign_keys
@ -308,6 +308,20 @@ if ActiveRecord::Base.connection.supports_foreign_keys?
assert_equal :nullify, fk.on_update
end
def test_add_foreign_key_with_non_existent_from_table_raises
e = assert_raises StatementInvalid do
@connection.add_foreign_key :missions, :rockets
end
assert_match(/missions/, e.message)
end
def test_add_foreign_key_with_non_existent_to_table_raises
e = assert_raises StatementInvalid do
@connection.add_foreign_key :missions, :rockets
end
assert_match(/missions/, e.message)
end
def test_foreign_key_exists
@connection.add_foreign_key :astronauts, :rockets