未验证 提交 e7a9f9de 编写于 作者: R Ryuta Kamizono 提交者: GitHub

Merge pull request #40212 from Shopify/active-record-exceptions-wrapping

Translate Mysql2 errors in Mysql2Adapter#quote_string (take 2)
* All connection adapters `execute` now raises `ActiveRecord::ConnectionNotEstablished` rather than
`ActiveRecord::InvalidStatement` when they encounter a connection error.
*Jean Boussier*
* `Mysql2Adapter#quote_string` now raises `ActiveRecord::ConnectionNotEstablished` rather than
`ActiveRecord::InvalidStatement` when it can't connect to the MySQL server.
*Jean Boussier*
* Add support for check constraints that are `NOT VALID` via `validate: false` (PostgreSQL-only). * Add support for check constraints that are `NOT VALID` via `validate: false` (PostgreSQL-only).
*Alex Robbin* *Alex Robbin*
......
...@@ -650,6 +650,12 @@ def extract_precision(sql_type) ...@@ -650,6 +650,12 @@ def extract_precision(sql_type)
def translate_exception(exception, message:, sql:, binds:) def translate_exception(exception, message:, sql:, binds:)
case error_number(exception) case error_number(exception)
when nil
if exception.message.match?(/MySQL client is not connected/i)
ConnectionNotEstablished.new(exception)
else
super
end
when ER_DB_CREATE_EXISTS when ER_DB_CREATE_EXISTS
DatabaseAlreadyExists.new(message, sql: sql, binds: binds) DatabaseAlreadyExists.new(message, sql: sql, binds: binds)
when ER_DUP_ENTRY when ER_DUP_ENTRY
......
...@@ -478,6 +478,12 @@ def translate_exception(exception, message:, sql:, binds:) ...@@ -478,6 +478,12 @@ def translate_exception(exception, message:, sql:, binds:)
return exception unless exception.respond_to?(:result) return exception unless exception.respond_to?(:result)
case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE) case exception.result.try(:error_field, PG::PG_DIAG_SQLSTATE)
when nil
if exception.message.match?(/connection is closed/i)
ConnectionNotEstablished.new(exception)
else
super
end
when UNIQUE_VIOLATION when UNIQUE_VIOLATION
RecordNotUnique.new(message, sql: sql, binds: binds) RecordNotUnique.new(message, sql: sql, binds: binds)
when FOREIGN_KEY_VIOLATION when FOREIGN_KEY_VIOLATION
......
...@@ -475,17 +475,18 @@ def copy_table_contents(from, to, columns, rename = {}) ...@@ -475,17 +475,18 @@ def copy_table_contents(from, to, columns, rename = {})
end end
def translate_exception(exception, message:, sql:, binds:) def translate_exception(exception, message:, sql:, binds:)
case exception.message
# SQLite 3.8.2 returns a newly formatted error message: # SQLite 3.8.2 returns a newly formatted error message:
# UNIQUE constraint failed: *table_name*.*column_name* # UNIQUE constraint failed: *table_name*.*column_name*
# Older versions of SQLite return: # Older versions of SQLite return:
# column *column_name* is not unique # column *column_name* is not unique
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/ if exception.message.match?(/(column(s)? .* (is|are) not unique|UNIQUE constraint failed: .*)/i)
RecordNotUnique.new(message, sql: sql, binds: binds) RecordNotUnique.new(message, sql: sql, binds: binds)
when /.* may not be NULL/, /NOT NULL constraint failed: .*/ elsif exception.message.match?(/(.* may not be NULL|NOT NULL constraint failed: .*)/i)
NotNullViolation.new(message, sql: sql, binds: binds) NotNullViolation.new(message, sql: sql, binds: binds)
when /FOREIGN KEY constraint failed/i elsif exception.message.match?(/FOREIGN KEY constraint failed/i)
InvalidForeignKey.new(message, sql: sql, binds: binds) InvalidForeignKey.new(message, sql: sql, binds: binds)
elsif exception.message.match?(/called on a closed database/i)
ConnectionNotEstablished.new(exception)
else else
super super
end end
......
...@@ -58,7 +58,7 @@ def test_successful_reconnection_after_timeout_with_verify ...@@ -58,7 +58,7 @@ def test_successful_reconnection_after_timeout_with_verify
def test_execute_after_disconnect def test_execute_after_disconnect
@connection.disconnect! @connection.disconnect!
error = assert_raise(ActiveRecord::StatementInvalid) do error = assert_raise(ActiveRecord::ConnectionNotEstablished) do
@connection.execute("SELECT 1") @connection.execute("SELECT 1")
end end
assert_kind_of Mysql2::Error, error.cause assert_kind_of Mysql2::Error, error.cause
...@@ -67,7 +67,7 @@ def test_execute_after_disconnect ...@@ -67,7 +67,7 @@ def test_execute_after_disconnect
def test_quote_after_disconnect def test_quote_after_disconnect
@connection.disconnect! @connection.disconnect!
assert_raise(ActiveRecord::StatementInvalid) do assert_raise(ActiveRecord::ConnectionNotEstablished) do
@connection.quote("string") @connection.quote("string")
end end
end end
......
...@@ -22,8 +22,10 @@ def setup ...@@ -22,8 +22,10 @@ def setup
test "can't execute statements while disconnected" do test "can't execute statements while disconnected" do
@connection.execute "SELECT count(*) from products" @connection.execute "SELECT count(*) from products"
@connection.disconnect! @connection.disconnect!
assert_raises(ActiveRecord::StatementInvalid) do assert_raises(ActiveRecord::ConnectionNotEstablished) do
@connection.execute "SELECT count(*) from products" silence_warnings do
@connection.execute "SELECT count(*) from products"
end
end end
end end
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册