<para>
Issuing <command>COMMIT</command> when not inside a transaction does
- no harm, but it will provoke a warning message.
+ no harm, but it will provoke a warning message. <command>COMMIT AND
+ CHAIN</command> when not inside a transaction is an error.
</para>
</refsect1>
<para>
Issuing <command>ROLLBACK</command> outside of a transaction
- block emits a warning and otherwise has no effect.
+ block emits a warning and otherwise has no effect. <command>ROLLBACK AND
+ CHAIN</command> outside of a transaction block is an error.
</para>
</refsect1>
break;
/*
- * In an implicit transaction block, commit, but issue a warning
+ * We are in an implicit transaction block. If AND CHAIN was
+ * specified, error. Otherwise commit, but issue a warning
* because there was no explicit BEGIN before this.
*/
case TBLOCK_IMPLICIT_INPROGRESS:
- ereport(WARNING,
- (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
- errmsg("there is no transaction in progress")));
+ if (chain)
+ ereport(ERROR,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ /* translator: %s represents an SQL statement name */
+ errmsg("%s can only be used in transaction blocks",
+ "COMMIT AND CHAIN")));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ errmsg("there is no transaction in progress")));
s->blockState = TBLOCK_END;
result = true;
break;
break;
/*
- * The user issued COMMIT when not inside a transaction. Issue a
- * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
+ * The user issued COMMIT when not inside a transaction. For
+ * COMMIT without CHAIN, issue a WARNING, staying in
+ * TBLOCK_STARTED state. The upcoming call to
* CommitTransactionCommand() will then close the transaction and
- * put us back into the default state.
+ * put us back into the default state. For COMMIT AND CHAIN,
+ * error.
*/
case TBLOCK_STARTED:
- ereport(WARNING,
- (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
- errmsg("there is no transaction in progress")));
+ if (chain)
+ ereport(ERROR,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ /* translator: %s represents an SQL statement name */
+ errmsg("%s can only be used in transaction blocks",
+ "COMMIT AND CHAIN")));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ errmsg("there is no transaction in progress")));
result = true;
break;
break;
/*
- * The user issued ABORT when not inside a transaction. Issue a
- * WARNING and go to abort state. The upcoming call to
- * CommitTransactionCommand() will then put us back into the
- * default state.
+ * The user issued ABORT when not inside a transaction. For
+ * ROLLBACK without CHAIN, issue a WARNING and go to abort state.
+ * The upcoming call to CommitTransactionCommand() will then put
+ * us back into the default state. For ROLLBACK AND CHAIN, error.
*
* We do the same thing with ABORT inside an implicit transaction,
* although in this case we might be rolling back actual database
*/
case TBLOCK_STARTED:
case TBLOCK_IMPLICIT_INPROGRESS:
- ereport(WARNING,
- (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
- errmsg("there is no transaction in progress")));
+ if (chain)
+ ereport(ERROR,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ /* translator: %s represents an SQL statement name */
+ errmsg("%s can only be used in transaction blocks",
+ "ROLLBACK AND CHAIN")));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
+ errmsg("there is no transaction in progress")));
s->blockState = TBLOCK_ABORT_PENDING;
break;
(1 row)
ROLLBACK;
+-- not allowed outside a transaction block
+COMMIT AND CHAIN; -- error
+ERROR: COMMIT AND CHAIN can only be used in transaction blocks
+ROLLBACK AND CHAIN; -- error
+ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
SELECT * FROM abc ORDER BY 1;
a
---
ERROR: RELEASE SAVEPOINT can only be used in transaction blocks
-- but this is OK, because the BEGIN converts it to a regular xact
SELECT 1\; BEGIN\; SAVEPOINT sp\; ROLLBACK TO SAVEPOINT sp\; COMMIT;
+-- Tests for AND CHAIN in implicit transaction blocks
+SET TRANSACTION READ WRITE\; COMMIT AND CHAIN; -- error
+ERROR: COMMIT AND CHAIN can only be used in transaction blocks
+SHOW transaction_read_only;
+ transaction_read_only
+-----------------------
+ off
+(1 row)
+
+SET TRANSACTION READ WRITE\; ROLLBACK AND CHAIN; -- error
+ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
+SHOW transaction_read_only;
+ transaction_read_only
+-----------------------
+ off
+(1 row)
+
+CREATE TABLE abc (a int);
+-- COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN
+INSERT INTO abc VALUES (7)\; COMMIT\; INSERT INTO abc VALUES (8)\; COMMIT AND CHAIN; -- 7 commit, 8 error
+WARNING: there is no transaction in progress
+ERROR: COMMIT AND CHAIN can only be used in transaction blocks
+INSERT INTO abc VALUES (9)\; ROLLBACK\; INSERT INTO abc VALUES (10)\; ROLLBACK AND CHAIN; -- 9 rollback, 10 error
+WARNING: there is no transaction in progress
+ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
+-- COMMIT/ROLLBACK AND CHAIN + COMMIT/ROLLBACK
+INSERT INTO abc VALUES (11)\; COMMIT AND CHAIN\; INSERT INTO abc VALUES (12)\; COMMIT; -- 11 error, 12 not reached
+ERROR: COMMIT AND CHAIN can only be used in transaction blocks
+INSERT INTO abc VALUES (13)\; ROLLBACK AND CHAIN\; INSERT INTO abc VALUES (14)\; ROLLBACK; -- 13 error, 14 not reached
+ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
+-- START TRANSACTION + COMMIT/ROLLBACK AND CHAIN
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (15)\; COMMIT AND CHAIN; -- 15 ok
+SHOW transaction_isolation; -- transaction is active at this point
+ transaction_isolation
+-----------------------
+ repeatable read
+(1 row)
+
+COMMIT;
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (16)\; ROLLBACK AND CHAIN; -- 16 ok
+SHOW transaction_isolation; -- transaction is active at this point
+ transaction_isolation
+-----------------------
+ repeatable read
+(1 row)
+
+ROLLBACK;
+-- START TRANSACTION + COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (17)\; COMMIT\; INSERT INTO abc VALUES (18)\; COMMIT AND CHAIN; -- 17 commit, 18 error
+ERROR: COMMIT AND CHAIN can only be used in transaction blocks
+SHOW transaction_isolation; -- out of transaction block
+ transaction_isolation
+-----------------------
+ read committed
+(1 row)
+
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (19)\; ROLLBACK\; INSERT INTO abc VALUES (20)\; ROLLBACK AND CHAIN; -- 19 rollback, 20 error
+ERROR: ROLLBACK AND CHAIN can only be used in transaction blocks
+SHOW transaction_isolation; -- out of transaction block
+ transaction_isolation
+-----------------------
+ read committed
+(1 row)
+
+SELECT * FROM abc ORDER BY 1;
+ a
+----
+ 7
+ 15
+ 17
+(3 rows)
+
+DROP TABLE abc;
-- Test for successful cleanup of an aborted transaction at session exit.
-- THIS MUST BE THE LAST TEST IN THIS FILE.
begin;
SHOW transaction_deferrable;
ROLLBACK;
+-- not allowed outside a transaction block
+COMMIT AND CHAIN; -- error
+ROLLBACK AND CHAIN; -- error
+
SELECT * FROM abc ORDER BY 1;
RESET default_transaction_read_only;
SELECT 1\; BEGIN\; SAVEPOINT sp\; ROLLBACK TO SAVEPOINT sp\; COMMIT;
+-- Tests for AND CHAIN in implicit transaction blocks
+
+SET TRANSACTION READ WRITE\; COMMIT AND CHAIN; -- error
+SHOW transaction_read_only;
+
+SET TRANSACTION READ WRITE\; ROLLBACK AND CHAIN; -- error
+SHOW transaction_read_only;
+
+CREATE TABLE abc (a int);
+
+-- COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN
+INSERT INTO abc VALUES (7)\; COMMIT\; INSERT INTO abc VALUES (8)\; COMMIT AND CHAIN; -- 7 commit, 8 error
+INSERT INTO abc VALUES (9)\; ROLLBACK\; INSERT INTO abc VALUES (10)\; ROLLBACK AND CHAIN; -- 9 rollback, 10 error
+
+-- COMMIT/ROLLBACK AND CHAIN + COMMIT/ROLLBACK
+INSERT INTO abc VALUES (11)\; COMMIT AND CHAIN\; INSERT INTO abc VALUES (12)\; COMMIT; -- 11 error, 12 not reached
+INSERT INTO abc VALUES (13)\; ROLLBACK AND CHAIN\; INSERT INTO abc VALUES (14)\; ROLLBACK; -- 13 error, 14 not reached
+
+-- START TRANSACTION + COMMIT/ROLLBACK AND CHAIN
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (15)\; COMMIT AND CHAIN; -- 15 ok
+SHOW transaction_isolation; -- transaction is active at this point
+COMMIT;
+
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (16)\; ROLLBACK AND CHAIN; -- 16 ok
+SHOW transaction_isolation; -- transaction is active at this point
+ROLLBACK;
+
+-- START TRANSACTION + COMMIT/ROLLBACK + COMMIT/ROLLBACK AND CHAIN
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (17)\; COMMIT\; INSERT INTO abc VALUES (18)\; COMMIT AND CHAIN; -- 17 commit, 18 error
+SHOW transaction_isolation; -- out of transaction block
+
+START TRANSACTION ISOLATION LEVEL REPEATABLE READ\; INSERT INTO abc VALUES (19)\; ROLLBACK\; INSERT INTO abc VALUES (20)\; ROLLBACK AND CHAIN; -- 19 rollback, 20 error
+SHOW transaction_isolation; -- out of transaction block
+
+SELECT * FROM abc ORDER BY 1;
+
+DROP TABLE abc;
+
+
-- Test for successful cleanup of an aborted transaction at session exit.
-- THIS MUST BE THE LAST TEST IN THIS FILE.