/* * call-seq: * conn.transaction { |conn| ... } -> nil * * Executes a +BEGIN+ at the start of the block, * and a +COMMIT+ at the end of the block, or * +ROLLBACK+ if any exception occurs. */ static VALUE pgconn_transaction(VALUE self) { PGconn *conn = get_pgconn(self); PGresult *result; VALUE rb_pgresult; int status; if (rb_block_given_p()) { result = PQexec(conn, "BEGIN"); rb_pgresult = new_pgresult(result, conn); pgresult_check(self, rb_pgresult); rb_protect(rb_yield, self, &status); if(status == 0) { result = PQexec(conn, "COMMIT"); rb_pgresult = new_pgresult(result, conn); pgresult_check(self, rb_pgresult); } else { /* exception occurred, ROLLBACK and re-raise */ result = PQexec(conn, "ROLLBACK"); rb_pgresult = new_pgresult(result, conn); pgresult_check(self, rb_pgresult); rb_jump_tag(status); } } else { /* no block supplied? */ rb_raise(rb_eArgError, "Must supply block for PGconn#transaction"); } return Qnil; }