Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions lib/pg/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -306,22 +306,19 @@ class << self
# and a +COMMIT+ at the end of the block, or
# +ROLLBACK+ if any exception occurs.
def transaction
rollback = false
exec "BEGIN"
yield(self)
rescue PG::RollbackTransaction
rollback = true
cancel if transaction_status == PG::PQTRANS_ACTIVE
block
exec "ROLLBACK"
rescue Exception
rollback = true
cancel if transaction_status == PG::PQTRANS_ACTIVE
block
exec "ROLLBACK"
rescue PG::RollbackTransaction => error
rescue Exception => error
raise
ensure
exec "COMMIT" unless rollback
if error || Thread.current.status == "aborting"
cancel if transaction_status == PG::PQTRANS_ACTIVE
block
exec("ROLLBACK")
else
exec("COMMIT")
end
end

### Returns an array of Hashes with connection defaults. See ::conndefaults
Expand Down
35 changes: 35 additions & 0 deletions spec/pg/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,41 @@
end
expect( res ).to eq( "transaction result" )
end

context "when current thread gets halted in the middle of the running transaction" do

it "rollbacks the transaction" do
# abort the per-example transaction so we can test our own
@conn.exec('ROLLBACK')
@conn.exec("CREATE TABLE pie ( flavor TEXT )")

begin
q = Thread::Queue.new
thread = Thread.new do
conn = $pg_server.connect
conn.transaction do
conn.exec("INSERT INTO pie VALUES ('rhubarb'), ('cherry'), ('schizophrenia')")
q << 1
# emulate some load that keeps the transaction open
sleep 2
end
ensure
conn&.close
end
# Wait for the thread to reach the testing point
q.pop
# Terminate the thread ungracefully and wait it to die
thread.exit
thread.join

res = @conn.exec("SELECT * FROM pie")
expect(res.ntuples).to eq(0)
ensure
thread.exit
@conn.exec("DROP TABLE pie")
end
end
end
end

describe "large objects" do
Expand Down
Loading