Skip to content

Commit 1a248d8

Browse files
mtcmorrismetaskills
authored andcommitted
Handle using transactions and resetting isolation level correctly when READ_COMMITTED_SNAPSHOT is set to ON (#520)
1 parent 36dafe0 commit 1a248d8

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lib/active_record/connection_adapters/sqlserver/transaction.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ def sqlserver?
1414
def current_isolation_level
1515
return unless sqlserver?
1616
level = connection.user_options_isolation_level
17-
level.blank? ? 'READ COMMITTED' : level.upcase
17+
18+
# When READ_COMMITTED_SNAPSHOT is set to ON,
19+
# user_options_isolation_level will be equal to 'read committed
20+
# snapshot' which is not a valid isolation level
21+
if level.blank? || level == 'read committed snapshot'
22+
'READ COMMITTED'
23+
else
24+
level.upcase
25+
end
1826
end
1927

2028
end

test/cases/transaction_test_sqlserver.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,31 @@ class TransactionTestSQLServer < ActiveRecord::TestCase
5252
connection.user_options_isolation_level.must_match %r{read committed}i
5353
end
5454

55+
describe 'when READ_COMMITTED_SNAPSHOT is set' do
56+
before do
57+
connection.execute "ALTER DATABASE [#{connection.current_database}] SET ALLOW_SNAPSHOT_ISOLATION ON"
58+
connection.execute "ALTER DATABASE [#{connection.current_database}] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE"
59+
end
60+
61+
after do
62+
connection.execute "ALTER DATABASE [#{connection.current_database}] SET ALLOW_SNAPSHOT_ISOLATION OFF"
63+
connection.execute "ALTER DATABASE [#{connection.current_database}] SET READ_COMMITTED_SNAPSHOT OFF WITH ROLLBACK IMMEDIATE"
64+
end
65+
66+
it 'should use READ COMMITTED as an isolation level' do
67+
connection.user_options_isolation_level.must_match "read committed snapshot"
68+
69+
Ship.transaction(isolation: :serializable) do
70+
Ship.create! name: 'Black Pearl'
71+
end
72+
73+
# We're actually testing that the isolation level was correctly reset to
74+
# "READ COMMITTED", and that no exception was raised (it's reported back
75+
# by SQL Server as "read committed snapshot").
76+
connection.user_options_isolation_level.must_match "read committed snapshot"
77+
end
78+
end
79+
5580

5681
protected
5782

0 commit comments

Comments
 (0)