-- -- TRANSACTIONS -- BEGIN; SELECT * INTO TABLE xacttest FROM aggtest; INSERT INTO xacttest (a, b) VALUES (777, 777.777); END; -- should retrieve one value-- SELECT a FROM xacttest WHERE a > 100; a ----- 777 (1 row) BEGIN; CREATE TABLE disappear (a int4); DELETE FROM aggtest; -- should be empty SELECT * FROM aggtest; a | b ---+--- (0 rows) ABORT; -- should not exist SELECT oid FROM pg_class WHERE relname = 'disappear'; oid ----- (0 rows) -- should have members again SELECT * FROM aggtest; a | b -----+--------- 56 | 7.8 100 | 99.097 0 | 0.09561 42 | 324.78 (4 rows) -- Read-only tests CREATE TABLE writetest (a int); CREATE TEMPORARY TABLE temptest (a int); SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; DROP TABLE writetest; -- fail ERROR: transaction is read-only INSERT INTO writetest VALUES (1); -- fail ERROR: transaction is read-only SELECT * FROM writetest; -- ok a --- (0 rows) DELETE FROM temptest; -- ok UPDATE temptest SET a = 0 WHERE a = 1 AND writetest.a = temptest.a; -- ok PREPARE test AS UPDATE writetest SET a = 0; -- ok EXECUTE test; -- fail ERROR: transaction is read-only SELECT * FROM writetest, temptest; -- ok a | a ---+--- (0 rows) CREATE TABLE test AS SELECT * FROM writetest; -- fail ERROR: transaction is read-only START TRANSACTION READ WRITE; DROP TABLE writetest; -- ok COMMIT; -- Subtransactions, basic tests -- create & drop tables SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE; CREATE TABLE foobar (a int); BEGIN; CREATE TABLE foo (a int); SAVEPOINT one; DROP TABLE foo; CREATE TABLE bar (a int); ROLLBACK TO one; RELEASE one; SAVEPOINT two; CREATE TABLE baz (a int); RELEASE two; drop TABLE foobar; CREATE TABLE barbaz (a int); COMMIT; -- should exist: barbaz, baz, foo SELECT * FROM foo; -- should be empty a --- (0 rows) SELECT * FROM bar; -- shouldn't exist ERROR: relation "bar" does not exist SELECT * FROM barbaz; -- should be empty a --- (0 rows) SELECT * FROM baz; -- should be empty a --- (0 rows) -- inserts BEGIN; INSERT INTO foo VALUES (1); SAVEPOINT one; INSERT into bar VALUES (1); ERROR: relation "bar" does not exist ROLLBACK TO one; RELEASE one; SAVEPOINT two; INSERT into barbaz VALUES (1); RELEASE two; SAVEPOINT three; SAVEPOINT four; INSERT INTO foo VALUES (2); RELEASE four; ROLLBACK TO three; RELEASE three; INSERT INTO foo VALUES (3); COMMIT; SELECT * FROM foo; -- should have 1 and 3 a --- 1 3 (2 rows) SELECT * FROM barbaz; -- should have 1 a --- 1 (1 row) -- test whole-tree commit BEGIN; SAVEPOINT one; SELECT foo; ERROR: column "foo" does not exist ROLLBACK TO one; RELEASE one; SAVEPOINT two; CREATE TABLE savepoints (a int); SAVEPOINT three; INSERT INTO savepoints VALUES (1); SAVEPOINT four; INSERT INTO savepoints VALUES (2); SAVEPOINT five; INSERT INTO savepoints VALUES (3); ROLLBACK TO five; COMMIT; COMMIT; -- should not be in a transaction block WARNING: there is no transaction in progress SELECT * FROM savepoints; a --- 1 2 (2 rows) -- test whole-tree rollback BEGIN; SAVEPOINT one; DELETE FROM savepoints WHERE a=1; RELEASE one; SAVEPOINT two; DELETE FROM savepoints WHERE a=1; SAVEPOINT three; DELETE FROM savepoints WHERE a=2; ROLLBACK; COMMIT; -- should not be in a transaction block WARNING: there is no transaction in progress SELECT * FROM savepoints; a --- 1 2 (2 rows) -- test whole-tree commit on an aborted subtransaction BEGIN; INSERT INTO savepoints VALUES (4); SAVEPOINT one; INSERT INTO savepoints VALUES (5); SELECT foo; ERROR: column "foo" does not exist COMMIT; SELECT * FROM savepoints; a --- 1 2 (2 rows) BEGIN; INSERT INTO savepoints VALUES (6); SAVEPOINT one; INSERT INTO savepoints VALUES (7); RELEASE one; INSERT INTO savepoints VALUES (8); COMMIT; -- rows 6 and 8 should have been created by the same xact SELECT a.xmin = b.xmin FROM savepoints a, savepoints b WHERE a.a=6 AND b.a=8; ?column? ---------- t (1 row) -- rows 6 and 7 should have been created by different xacts SELECT a.xmin = b.xmin FROM savepoints a, savepoints b WHERE a.a=6 AND b.a=7; ?column? ---------- f (1 row) BEGIN; INSERT INTO savepoints VALUES (9); SAVEPOINT one; INSERT INTO savepoints VALUES (10); ROLLBACK TO one; INSERT INTO savepoints VALUES (11); COMMIT; SELECT a FROM savepoints WHERE a in (9, 10, 11); a ---- 9 11 (2 rows) -- rows 9 and 11 should have been created by different xacts SELECT a.xmin = b.xmin FROM savepoints a, savepoints b WHERE a.a=9 AND b.a=11; ?column? ---------- f (1 row) BEGIN; INSERT INTO savepoints VALUES (12); SAVEPOINT one; INSERT INTO savepoints VALUES (13); SAVEPOINT two; INSERT INTO savepoints VALUES (14); ROLLBACK TO one; INSERT INTO savepoints VALUES (15); SAVEPOINT two; INSERT INTO savepoints VALUES (16); SAVEPOINT three; INSERT INTO savepoints VALUES (17); COMMIT; SELECT a FROM savepoints WHERE a BETWEEN 12 AND 17; a ---- 12 15 16 17 (4 rows) BEGIN; INSERT INTO savepoints VALUES (18); SAVEPOINT one; INSERT INTO savepoints VALUES (19); SAVEPOINT two; INSERT INTO savepoints VALUES (20); ROLLBACK TO one; INSERT INTO savepoints VALUES (21); ROLLBACK TO one; INSERT INTO savepoints VALUES (22); COMMIT; SELECT a FROM savepoints WHERE a BETWEEN 18 AND 22; a ---- 18 22 (2 rows) DROP TABLE savepoints; -- only in a transaction block: SAVEPOINT one; ERROR: SAVEPOINT may only be used in transaction blocks ROLLBACK TO one; ERROR: ROLLBACK TO may only be used in transaction blocks RELEASE one; ERROR: RELEASE may only be used in transaction blocks -- Only "rollback to" allowed in aborted state BEGIN; SAVEPOINT one; SELECT 0/0; ERROR: division by zero SAVEPOINT two; -- ignored till the end of ... ERROR: current transaction is aborted, commands ignored until end of transaction block RELEASE one; -- ignored till the end of ... ERROR: current transaction is aborted, commands ignored until end of transaction block ROLLBACK TO one; SELECT 1; ?column? ---------- 1 (1 row) COMMIT; SELECT 1; -- this should work ?column? ---------- 1 (1 row) -- check non-transactional behavior of cursors BEGIN; DECLARE c CURSOR FOR SELECT unique2 FROM tenk1; SAVEPOINT one; FETCH 10 FROM c; unique2 --------- 0 1 2 3 4 5 6 7 8 9 (10 rows) ROLLBACK TO one; FETCH 10 FROM c; unique2 --------- 10 11 12 13 14 15 16 17 18 19 (10 rows) RELEASE one; FETCH 10 FROM c; unique2 --------- 20 21 22 23 24 25 26 27 28 29 (10 rows) CLOSE c; DECLARE c CURSOR FOR SELECT unique2/0 FROM tenk1; SAVEPOINT two; FETCH 10 FROM c; ERROR: division by zero ROLLBACK TO two; -- c is now dead to the world ... FETCH 10 FROM c; ERROR: portal "c" cannot be run ROLLBACK TO two; RELEASE two; FETCH 10 FROM c; ERROR: portal "c" cannot be run COMMIT; DROP TABLE foo; DROP TABLE baz; DROP TABLE barbaz;