lib/pg_conn.rb in pg_conn-0.15.0 vs lib/pg_conn.rb in pg_conn-0.15.1

- old
+ new

@@ -65,11 +65,14 @@ # The transaction timestamp of the most recent SQL statement executed by # #exec or #transaction block attr_reader :timestamp - # PG::Error object if the last statement failed; otherwise nil + # PG::Error object of the first failed statement in the transaction; + # otherwise nil. It is cleared at the beginning of a transaction so be sure + # to save it before you run any cleanup code that may initiate new + # transactions attr_reader :error # Tuple of error message, lineno, and charno of the error object where each # element defaults to nil if not found def err @@ -605,28 +608,21 @@ # error state and if you're also using subtransactions the whole # transaction stack has collapsed # # TODO: Make sure the transaction stack is emptied on postgres errors def exec(sql, commit: true, fail: true, silent: false) - begin - transaction(commit: commit) { execute(sql, fail: fail, silent: silent) } - rescue PG::Error - raise if fail - cancel_transaction - return nil - end + transaction(commit: commit) { execute(sql, fail: fail, silent: silent) } end # Like #exec but returns true/false depending on if the command succeeded. - # There is not corresponding #exeucte? method because any failure rolls + # There is not a corresponding #execute? method because any failure rolls # back the whole transaction stack. TODO: Check which exceptions that # should be captured def exec?(sql, commit: true, silent: true) begin exec(sql, commit: commit, fail: true, silent: silent) rescue PG::Error - cancel_transaction return false end return true end @@ -641,10 +637,11 @@ def execute(sql, fail: true, silent: false) if @pg_connection begin pg_exec(sql, silent: silent)&.cmd_tuples rescue PG::Error + cancel_transaction raise if fail return nil end else pg_exec(sql, silent: silent) @@ -670,23 +667,30 @@ # TODO: Move to TransactionMethods def commit() if transaction? - pop_transaction + pop_transaction(fail: false) else pg_exec("commit") end end def rollback() raise Rollback end - # True if a transaction is in progress. Note that this requires all - # transactions to be started using PgConn's transaction methods; - # transactions started using raw SQL are not registered + # True if a transaction is in progress + # + # Note that this requires all transactions to be started using PgConn's + # transaction methods; transactions started using raw SQL are not + # registered def transaction?() !@savepoints.nil? end + # True if a database transaction is in progress + def database_transaction? + pg_exec("select transaction_timestamp() != statement_timestamp()", fail: false) + end + # Returns number of transaction or savepoint levels def transactions() @savepoints ? 1 + @savepoints.size : 0 end def push_transaction if transaction? @@ -694,15 +698,16 @@ @savepoints.push savepoint pg_exec("savepoint #{savepoint}") else @savepoints = [] pg_exec("begin") + @error = @err = nil @timestamp = pg_exec("select current_timestamp").values[0][0] if @pg_connection end end - def pop_transaction(commit: true, fail: true) + def pop_transaction(commit: true, fail: true, exception: true) if transaction? if savepoint = @savepoints.pop if !commit pg_exec("rollback to savepoint #{savepoint}") pg_exec("release savepoint #{savepoint}") @@ -726,12 +731,14 @@ # progress, the method always succeeds def cancel_transaction begin pg_exec("rollback") rescue PG::Error + ; end @savepoints = nil + true end # Start a transaction. If called with a block, the block is executed within # a transaction that is auto-committed if the commit option is true (the # default). #transaction returns the result of the block or nil if no block @@ -746,17 +753,18 @@ result = nil begin push_transaction result = yield rescue PgConn::Rollback - pop_transaction(commit: false) + pop_transaction(commit: false, fail: false) return nil rescue PG::Error + cancel_transaction @savepoints = nil raise end - pop_transaction(commit: commit) + pop_transaction(commit: commit, fail: false) result else push_transaction nil end @@ -810,11 +818,10 @@ # though # # TODO: Fix silent by not handling exceptions def pg_exec(arg, silent: false) if @pg_connection - @error = @err = nil begin last_stmt = nil # To make the current SQL statement visible to the rescue clause. FIXME Not used? if arg.is_a?(String) return nil if arg == "" last_stmt = arg @@ -824,12 +831,14 @@ return nil if stmts.empty? # stmts.unshift("set on_error_exit stop") last_stmt = stmts.last @pg_connection.exec(stmts.join(";\n")) end - rescue PG::Error => ex - @error = ex + if @error.nil? + @error = ex + @err = nil + end if !silent # FIXME Why do we handle this? $stderr.puts arg $stderr.puts $stderr.puts ex.message $stderr.flush