简体   繁体   English

如何使用 PG Ruby Gem 有条件地回滚事务

[英]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.这是我第一次尝试在没有 Rails 舒适毯的情况下进行任何数据库操作,所以我有点迷茫。 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.我已经成功地创建了一个到我的 postgresql 数据库的连接并且可以执行语句,我需要做的最后一件事是根据一个简单的条件回滚一个事务。

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.基本上,条件是如果返回的 id ( ins[0]['id'] ) 是偶数,则回滚事务。 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 ?我认为如果ins[0]['id'] % 2 == 0我需要抛出某种异常,但我该怎么做,更重要的是,我如何将该信息编码到文档中给出的语法中?

Thank you for your time.谢谢你的时间。

EDIT 1编辑 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所以这个问题真的变得更加“当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)交易内部导致'throw': uncaught throw :id_exception (ArgumentError)

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.所以你只需要为自己创建一个小的 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

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.这是我第一次尝试在没有Rails舒适性的情况下进行任何数据库操作,因此我有些失落。 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.我已经设法建立了到我的Postgresql数据库的连接并且可以执行语句,我要做的最后一件事是基于简单条件回滚事务。

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.基本上,条件是如果返回的id( ins[0]['id'] )为偶数,则回滚该事务。 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 ?我认为如果ins[0]['id'] % 2 == 0我需要抛出某种异常,但是我该怎么做,更重要的是,如何将该信息编码为docs中给出的语法?

Thank you for your time.感谢您的时间。

EDIT 1编辑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所以这个问题实际上变得更加“当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)事务内部导致'throw': uncaught throw :id_exception (ArgumentError)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM