Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Conditionally Rollback a Transaction Using the PG Ruby Gem

I am currently taking a databases course and one of the lab questions has me stumped as to how to implement the above and indeed, if it was even possible. I have tried searching the docs but the transaction method defined is quite vague.

This is the first time I have tried to do any database manipulation WITHOUT the comfort blanket of Rails and so I am a little lost. I have managed to create a connection to my postgresql database and can execute statements, the final thing that I need to do is rollback a transaction based on a simple condition.

Allow me to show you the code:

require 'pg'
@conn = PG::Connection.open(:dbname => 'db_15_11_labs')
@conn.prepare('insert', 'INSERT INTO house (housenumber, street) VALUES ($1, $2) returning id')
@words = ["Foo", "Bar", "Bash", "Bang"]

def populate
  100.times.each_with_index do |i|
    # cycle through the @words array for street names, use i as house number
    ins = @conn.exec_prepared('insert', [i, "#{@words1[i % 4]} street"])
  end
end

Basically, the condition is that if the returned id (ins[0]['id']) is even, rollback the transaction. I figure that if ins[0]['id'] % 2 == 0 I need to throw some sort of exception but how do I do that and more importantly, how do I encode that information into the syntax given in the docs?

Thank you for your time.

EDIT 1

I have now managed to get the syntax that will allow for the conditions to be placed within the defined transaction as follows:

@conn.transaction do |conn|
    ins = @conn.exec_prepared('insert', [i, "#{@words1[i % 100]} street"])
end

and so this question really becomes more "how do I throw and catch an exception when ins[0]['id'] % 2 == 0

I have tried following a couple of simple tutorials on raising exceptions but doing the following:

throw :id_exception if (@ins[0]['id'].to_i % 2) == 0
    catch :id_exception do
    puts "caught :id_exception #{}"
end

inside the transaction results in an 'throw': uncaught throw :id_exception (ArgumentError)

like image 420
DazBaldwin Avatar asked Nov 18 '13 15:11

DazBaldwin


1 Answers

Transactions rollback automatically if an exception is raised inside the block. So you just need to create a little Exception class for yourself, raise one inside the block, and then arrange to rescue it so your program doesn't error-exit due to the raised exception.

Try something like this:

class MyLittleIdError < StandardError
end

begin
  @conn.transaction do |conn|
    ins = conn.exec_prepared('insert', [i, "#{@words1[i % 100]} street"])
    raise MyLittleIdError if (ins[0]['id'].to_i % 2) == 0
  end
rescue MyLittleIdError
  puts "aha! we have rolled back."
end
like image 161
cvkline Avatar answered Oct 14 '22 06:10

cvkline