mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-12 04:16:50 +02:00
7063c46fc1
results due to syncscan patch, when shared_buffers is small enough. Per buildfarm reports and some local testing with shared_buffers set to the lowest value considered by initdb.
334 lines
7.9 KiB
PL/PgSQL
334 lines
7.9 KiB
PL/PgSQL
--
|
|
-- 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;
|
|
|
|
|
|
BEGIN;
|
|
|
|
CREATE TABLE disappear (a int4);
|
|
|
|
DELETE FROM aggtest;
|
|
|
|
-- should be empty
|
|
SELECT * FROM aggtest;
|
|
|
|
ABORT;
|
|
|
|
-- should not exist
|
|
SELECT oid FROM pg_class WHERE relname = 'disappear';
|
|
|
|
-- should have members again
|
|
SELECT * FROM aggtest;
|
|
|
|
|
|
-- 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
|
|
INSERT INTO writetest VALUES (1); -- fail
|
|
SELECT * FROM writetest; -- ok
|
|
DELETE FROM temptest; -- ok
|
|
UPDATE temptest SET a = 0 FROM writetest WHERE temptest.a = 1 AND writetest.a = temptest.a; -- ok
|
|
PREPARE test AS UPDATE writetest SET a = 0; -- ok
|
|
EXECUTE test; -- fail
|
|
SELECT * FROM writetest, temptest; -- ok
|
|
CREATE TABLE test AS SELECT * FROM writetest; -- fail
|
|
|
|
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 SAVEPOINT one;
|
|
RELEASE SAVEPOINT one;
|
|
SAVEPOINT two;
|
|
CREATE TABLE baz (a int);
|
|
RELEASE SAVEPOINT two;
|
|
drop TABLE foobar;
|
|
CREATE TABLE barbaz (a int);
|
|
COMMIT;
|
|
-- should exist: barbaz, baz, foo
|
|
SELECT * FROM foo; -- should be empty
|
|
SELECT * FROM bar; -- shouldn't exist
|
|
SELECT * FROM barbaz; -- should be empty
|
|
SELECT * FROM baz; -- should be empty
|
|
|
|
-- inserts
|
|
BEGIN;
|
|
INSERT INTO foo VALUES (1);
|
|
SAVEPOINT one;
|
|
INSERT into bar VALUES (1);
|
|
ROLLBACK TO one;
|
|
RELEASE SAVEPOINT one;
|
|
SAVEPOINT two;
|
|
INSERT into barbaz VALUES (1);
|
|
RELEASE two;
|
|
SAVEPOINT three;
|
|
SAVEPOINT four;
|
|
INSERT INTO foo VALUES (2);
|
|
RELEASE SAVEPOINT four;
|
|
ROLLBACK TO SAVEPOINT three;
|
|
RELEASE SAVEPOINT three;
|
|
INSERT INTO foo VALUES (3);
|
|
COMMIT;
|
|
SELECT * FROM foo; -- should have 1 and 3
|
|
SELECT * FROM barbaz; -- should have 1
|
|
|
|
-- test whole-tree commit
|
|
BEGIN;
|
|
SAVEPOINT one;
|
|
SELECT foo;
|
|
ROLLBACK TO SAVEPOINT one;
|
|
RELEASE SAVEPOINT 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 SAVEPOINT five;
|
|
COMMIT;
|
|
COMMIT; -- should not be in a transaction block
|
|
SELECT * FROM savepoints;
|
|
|
|
-- test whole-tree rollback
|
|
BEGIN;
|
|
SAVEPOINT one;
|
|
DELETE FROM savepoints WHERE a=1;
|
|
RELEASE SAVEPOINT 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
|
|
|
|
SELECT * FROM savepoints;
|
|
|
|
-- test whole-tree commit on an aborted subtransaction
|
|
BEGIN;
|
|
INSERT INTO savepoints VALUES (4);
|
|
SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (5);
|
|
SELECT foo;
|
|
COMMIT;
|
|
SELECT * FROM savepoints;
|
|
|
|
BEGIN;
|
|
INSERT INTO savepoints VALUES (6);
|
|
SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (7);
|
|
RELEASE SAVEPOINT 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;
|
|
-- 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;
|
|
|
|
BEGIN;
|
|
INSERT INTO savepoints VALUES (9);
|
|
SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (10);
|
|
ROLLBACK TO SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (11);
|
|
COMMIT;
|
|
SELECT a FROM savepoints WHERE a in (9, 10, 11);
|
|
-- 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;
|
|
|
|
BEGIN;
|
|
INSERT INTO savepoints VALUES (12);
|
|
SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (13);
|
|
SAVEPOINT two;
|
|
INSERT INTO savepoints VALUES (14);
|
|
ROLLBACK TO SAVEPOINT 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;
|
|
|
|
BEGIN;
|
|
INSERT INTO savepoints VALUES (18);
|
|
SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (19);
|
|
SAVEPOINT two;
|
|
INSERT INTO savepoints VALUES (20);
|
|
ROLLBACK TO SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (21);
|
|
ROLLBACK TO SAVEPOINT one;
|
|
INSERT INTO savepoints VALUES (22);
|
|
COMMIT;
|
|
SELECT a FROM savepoints WHERE a BETWEEN 18 AND 22;
|
|
|
|
DROP TABLE savepoints;
|
|
|
|
-- only in a transaction block:
|
|
SAVEPOINT one;
|
|
ROLLBACK TO SAVEPOINT one;
|
|
RELEASE SAVEPOINT one;
|
|
|
|
-- Only "rollback to" allowed in aborted state
|
|
BEGIN;
|
|
SAVEPOINT one;
|
|
SELECT 0/0;
|
|
SAVEPOINT two; -- ignored till the end of ...
|
|
RELEASE SAVEPOINT one; -- ignored till the end of ...
|
|
ROLLBACK TO SAVEPOINT one;
|
|
SELECT 1;
|
|
COMMIT;
|
|
SELECT 1; -- this should work
|
|
|
|
-- check non-transactional behavior of cursors
|
|
BEGIN;
|
|
DECLARE c CURSOR FOR SELECT unique2 FROM tenk1 ORDER BY unique2;
|
|
SAVEPOINT one;
|
|
FETCH 10 FROM c;
|
|
ROLLBACK TO SAVEPOINT one;
|
|
FETCH 10 FROM c;
|
|
RELEASE SAVEPOINT one;
|
|
FETCH 10 FROM c;
|
|
CLOSE c;
|
|
DECLARE c CURSOR FOR SELECT unique2/0 FROM tenk1 ORDER BY unique2;
|
|
SAVEPOINT two;
|
|
FETCH 10 FROM c;
|
|
ROLLBACK TO SAVEPOINT two;
|
|
-- c is now dead to the world ...
|
|
FETCH 10 FROM c;
|
|
ROLLBACK TO SAVEPOINT two;
|
|
RELEASE SAVEPOINT two;
|
|
FETCH 10 FROM c;
|
|
COMMIT;
|
|
|
|
--
|
|
-- Check that "stable" functions are really stable. They should not be
|
|
-- able to see the partial results of the calling query. (Ideally we would
|
|
-- also check that they don't see commits of concurrent transactions, but
|
|
-- that's a mite hard to do within the limitations of pg_regress.)
|
|
--
|
|
select * from xacttest;
|
|
|
|
create or replace function max_xacttest() returns smallint language sql as
|
|
'select max(a) from xacttest' stable;
|
|
|
|
begin;
|
|
update xacttest set a = max_xacttest() + 10 where a > 0;
|
|
select * from xacttest;
|
|
rollback;
|
|
|
|
-- But a volatile function can see the partial results of the calling query
|
|
create or replace function max_xacttest() returns smallint language sql as
|
|
'select max(a) from xacttest' volatile;
|
|
|
|
begin;
|
|
update xacttest set a = max_xacttest() + 10 where a > 0;
|
|
select * from xacttest;
|
|
rollback;
|
|
|
|
-- Now the same test with plpgsql (since it depends on SPI which is different)
|
|
create or replace function max_xacttest() returns smallint language plpgsql as
|
|
'begin return max(a) from xacttest; end' stable;
|
|
|
|
begin;
|
|
update xacttest set a = max_xacttest() + 10 where a > 0;
|
|
select * from xacttest;
|
|
rollback;
|
|
|
|
create or replace function max_xacttest() returns smallint language plpgsql as
|
|
'begin return max(a) from xacttest; end' volatile;
|
|
|
|
begin;
|
|
update xacttest set a = max_xacttest() + 10 where a > 0;
|
|
select * from xacttest;
|
|
rollback;
|
|
|
|
|
|
-- test case for problems with dropping an open relation during abort
|
|
BEGIN;
|
|
savepoint x;
|
|
CREATE TABLE koju (a INT UNIQUE);
|
|
INSERT INTO koju VALUES (1);
|
|
INSERT INTO koju VALUES (1);
|
|
rollback to x;
|
|
|
|
CREATE TABLE koju (a INT UNIQUE);
|
|
INSERT INTO koju VALUES (1);
|
|
INSERT INTO koju VALUES (1);
|
|
ROLLBACK;
|
|
|
|
DROP TABLE foo;
|
|
DROP TABLE baz;
|
|
DROP TABLE barbaz;
|
|
|
|
-- verify that cursors created during an aborted subtransaction are
|
|
-- closed, but that we do not rollback the effect of any FETCHs
|
|
-- performed in the aborted subtransaction
|
|
begin;
|
|
|
|
savepoint x;
|
|
create table abc (a int);
|
|
insert into abc values (5);
|
|
insert into abc values (10);
|
|
declare foo cursor for select * from abc;
|
|
fetch from foo;
|
|
rollback to x;
|
|
|
|
-- should fail
|
|
fetch from foo;
|
|
commit;
|
|
|
|
begin;
|
|
|
|
create table abc (a int);
|
|
insert into abc values (5);
|
|
insert into abc values (10);
|
|
insert into abc values (15);
|
|
declare foo cursor for select * from abc;
|
|
|
|
fetch from foo;
|
|
|
|
savepoint x;
|
|
fetch from foo;
|
|
rollback to x;
|
|
|
|
fetch from foo;
|
|
|
|
abort;
|
|
|
|
-- tests for the "tid" type
|
|
SELECT '(3, 3)'::tid = '(3, 4)'::tid;
|
|
SELECT '(3, 3)'::tid = '(3, 3)'::tid;
|
|
SELECT '(3, 3)'::tid <> '(3, 3)'::tid;
|
|
SELECT '(3, 3)'::tid <> '(3, 4)'::tid;
|