Skip to content

Commit

Permalink
Improve detection of ActiveRecord::StatementTimeout with mysql2 adapter
Browse files Browse the repository at this point in the history
in the edge case when the query is terminated by MySQL server during filesort.
See https://bugs.mysql.com/bug.php?id=96537 for more details.
  • Loading branch information
kirs committed Aug 15, 2019
1 parent 8ab4fd1 commit c99c572
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
4 changes: 4 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
* Improve detection of ActiveRecord::StatementTimeout with mysql2 adapter in the edge case when the query is terminated during filesort.

*Kir Shatrov*

* Stop trying to read yaml file fixtures when loading Active Record fixtures.

*Gannon McGibbon*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ def extract_precision(sql_type)

# See https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html
ER_DB_CREATE_EXISTS = 1007
ER_FILSORT_ABORT = 1028
ER_DUP_ENTRY = 1062
ER_NOT_NULL_VIOLATION = 1048
ER_NO_REFERENCED_ROW = 1216
Expand Down Expand Up @@ -617,7 +618,7 @@ def translate_exception(exception, message:, sql:, binds:)
Deadlocked.new(message, sql: sql, binds: binds)
when ER_LOCK_WAIT_TIMEOUT
LockWaitTimeout.new(message, sql: sql, binds: binds)
when ER_QUERY_TIMEOUT
when ER_QUERY_TIMEOUT, ER_FILSORT_ABORT
StatementTimeout.new(message, sql: sql, binds: binds)
when ER_QUERY_INTERRUPTED
QueryCanceled.new(message, sql: sql, binds: binds)
Expand Down
15 changes: 15 additions & 0 deletions activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,21 @@ def test_read_timeout_exception
ActiveRecord::Base.establish_connection :arunit
end

def test_statement_timeout_error_codes
raw_conn = @conn.raw_connection
assert_raises(ActiveRecord::StatementTimeout) do
raw_conn.stub(:query, ->(_sql) { raise Mysql2::Error.new("fail", 50700, ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::ER_FILSORT_ABORT) }) {
@conn.execute("SELECT 1")
}
end

assert_raises(ActiveRecord::StatementTimeout) do
raw_conn.stub(:query, ->(_sql) { raise Mysql2::Error.new("fail", 50700, ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::ER_QUERY_TIMEOUT) }) {
@conn.execute("SELECT 1")
}
end
end

private
def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block)
super(@conn, "ex", definition, &block)
Expand Down

0 comments on commit c99c572

Please sign in to comment.