Skip to content

Commit

Permalink
Translate ORA-00060 into ActiveRecord::Deadlocked error
Browse files Browse the repository at this point in the history
This PR translates `ORA-00060` into `ActiveRecord::Deadlocked` error.

Added an `ORA-00060` reproduction test case equivalent to
activerecord/test/cases/adapters/mysql2/transaction_test.rb.
https://github.com/rails/rails/blob/8f2490b57f488ed60fc6e0a201ccd5e66811ab51/activerecord/test/cases/adapters/mysql2/transaction_test.rb#L36-L61

The following is a reproduce testing log.

```console
% bundle exec rspec ./spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb:575
(snip)

  1) OracleEnhancedAdapter Transaction Raises Deadlocked when a deadlock
  is encountered
     Failure/Error:
              expect {
                barrier = Concurrent::CyclicBarrier.new(2)

                t1 = TestPost.create(title: "one")
                t2 = TestPost.create(title: "two")

                thread = Thread.new do
                  TestPost.transaction do
                    t1.lock!
                    barrier.wait

       expected ActiveRecord::Deadlocked, got
       #<ActiveRecord::StatementInvalid: OCIError: ORA-00060: deadlock
       detected while waiting for resource: UPDATE "TEST_POSTS" SET
       "TITLE" = :a1 WHERE "TEST_POSTS"."ID" = :a2> with backtrace:
```

And this commit resolves `Java::JavaSql::SQLException` exception.
`Java::JavaSql::SQLException` is not `NativeException`.

https://travis-ci.org/rsim/oracle-enhanced/jobs/301301765

It seems to be a potential issue caused by not passing test
`OracleEnhanced::JDBCConnection#error_code` in rails/activerecord tests.
  • Loading branch information
koic committed Nov 15, 2017
1 parent f6b49a8 commit dd7bc78
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
Expand Up @@ -460,6 +460,8 @@ def error_code(exception)
case exception
when NativeException
exception.cause.getErrorCode
when Java::JavaSql::SQLException
exception.getErrorCode
else
nil
end
Expand Down
Expand Up @@ -672,6 +672,8 @@ def translate_exception(exception, message) #:nodoc:
case @connection.error_code(exception)
when 1
RecordNotUnique.new(message)
when 60
Deadlocked.new(message)
when 900, 904, 942, 955, 1418, 2289, 17008
ActiveRecord::StatementInvalid.new(message)
when 1400
Expand Down
Expand Up @@ -561,4 +561,50 @@ class ::TestPost < ActiveRecord::Base

end

describe "Transaction" do
before(:all) do
schema_define do
create_table :test_posts do |t|
t.string :title
end
end
class ::TestPost < ActiveRecord::Base
end
end

it "Raises Deadlocked when a deadlock is encountered" do
expect {
barrier = Concurrent::CyclicBarrier.new(2)

t1 = TestPost.create(title: "one")
t2 = TestPost.create(title: "two")

thread = Thread.new do
TestPost.transaction do
t1.lock!
barrier.wait
t2.update_attributes(title: "one")
end
end

begin
TestPost.transaction do
t2.lock!
barrier.wait
t1.update_attributes(title: "two")
end
ensure
thread.join
end
}.to raise_error(ActiveRecord::Deadlocked)
end
end

after(:all) do
schema_define do
drop_table :test_posts
end
Object.send(:remove_const, "TestPost") rescue nil
ActiveRecord::Base.clear_cache!
end
end

0 comments on commit dd7bc78

Please sign in to comment.