Created
July 22, 2021 18:55
-
-
Save JoshCheek/780e839513ebdcf3cd0419a414d1f602 to your computer and use it in GitHub Desktop.
Using PostgreSQL's savepoints to recover from errors while inside a transaction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# these are Ruby 3's endless methods | |
require 'pg' | |
db = PG.connect | |
def db.exec_params(...) = super.map { |h| h.transform_keys &:intern } | |
def db.exec(...) = super.map { |h| h.transform_keys &:intern } | |
# transactions methods | |
def db.begin() = exec('begin') | |
def db.save(name) = exec("savepoint #{name}") | |
def db.rollback_to(name) = exec("rollback to #{name}") | |
def db.select() = exec("select * from omgs") | |
def db.insert(*vals) = exec_params(<<~SQL, vals) | |
insert into omgs (val) | |
values #{vals.map.with_index(1) { |_, i| "($#{i})" }.join(", ")} | |
returning * | |
SQL | |
# A transaction with a table and 3 rows | |
db.begin | |
db.exec 'create table omgs(val integer)' | |
db.insert 11, 22 | |
db.save 'has_1122' | |
# We can rollback the inserted data while still leaving the transaction open | |
db.insert 33, 44 | |
db.select # => [{:val=>"11"}, {:val=>"22"}, {:val=>"33"}, {:val=>"44"}] | |
db.rollback_to 'has_1122' | |
db.select # => [{:val=>"11"}, {:val=>"22"}] | |
# Errors will prevent us from running new commands | |
# becuase "current transaction is aborted" | |
db.insert 55, 66 | |
db.select # => [{:val=>"11"}, {:val=>"22"}, {:val=>"55"}, {:val=>"66"}] | |
db.exec 'omg!' rescue $! # => #<PG::SyntaxError: ERROR: syntax error at or near "omg"\nLINE 1: omg!\n ^\n> | |
db.select rescue $! # => #<PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block\n> | |
# But we can rollback to that last savepoint and then try again | |
db.rollback_to 'has_1122' | |
db.select # => [{:val=>"11"}, {:val=>"22"}] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment