Repository: incubator-hawq Updated Branches: refs/heads/master 27022e561 -> cb80c3331
HAWQ-1015. Add feature test for transactions with new test framework Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/cb80c333 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/cb80c333 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/cb80c333 Branch: refs/heads/master Commit: cb80c333176e38a29eba618b70440b12f1b4ab33 Parents: 27022e5 Author: ivan <iw...@pivotal.io> Authored: Mon Aug 29 11:01:31 2016 +0800 Committer: ivan <iw...@pivotal.io> Committed: Tue Aug 30 09:46:28 2016 +0800 ---------------------------------------------------------------------- .../feature/transactions/ans/transactions.ans | 558 +++++++++++++++++++ .../feature/transactions/sql/transactions.sql | 342 ++++++++++++ .../feature/transactions/test_transactions.cpp | 19 + 3 files changed, 919 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/cb80c333/src/test/feature/transactions/ans/transactions.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/transactions/ans/transactions.ans b/src/test/feature/transactions/ans/transactions.ans new file mode 100755 index 0000000..35669f4 --- /dev/null +++ b/src/test/feature/transactions/ans/transactions.ans @@ -0,0 +1,558 @@ +-- +-- TRANSACTIONS +-- +CREATE TABLE aggtest ( + a int2, + b float4 +); +CREATE TABLE +INSERT INTO aggtest VALUES (56, 7.8), (100, 99.097), (0, 0.09561), (42, 324.78); +INSERT 0 4 +BEGIN; +BEGIN +SELECT * + INTO TABLE xacttest + FROM aggtest; +SELECT 4 +INSERT INTO xacttest (a, b) VALUES (777, 777.777); +INSERT 0 1 +END; +COMMIT +-- should retrieve one value-- +SELECT a FROM xacttest WHERE a > 100; + a +----- + 777 +(1 row) + +BEGIN; +BEGIN +CREATE TABLE disappear (a int4); +CREATE TABLE +TRUNCATE aggtest; +TRUNCATE TABLE +-- should be empty +SELECT * FROM aggtest; + a | b +---+--- +(0 rows) + +ABORT; +ROLLBACK +-- 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) + +drop table aggtest; +DROP TABLE +-- Read-only tests +CREATE TABLE writetest (a int); +CREATE TABLE +CREATE TEMPORARY TABLE temptest (a int); +CREATE TABLE +SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; +SET +DROP TABLE writetest; -- fail +psql:/tmp/TestTransaction_BasicTest.sql:56: ERROR: transaction is read-only +INSERT INTO writetest VALUES (1); -- fail +psql:/tmp/TestTransaction_BasicTest.sql:57: ERROR: transaction is read-only +SELECT * FROM writetest; -- ok + a +--- +(0 rows) + +-- DELETE FROM temptest; -- ok +-- UPDATE temptest SET a = 0 FROM writetest WHERE temptest.a = 1 AND writetest.a = temptest.a; -- ok +-- PREPARE test AS INSERT INTO writetest VALUES (1); -- ok +-- EXECUTE test; -- fail +SELECT * FROM writetest, temptest; -- ok + a | a +---+--- +(0 rows) + +CREATE TABLE test AS SELECT * FROM writetest; -- fail +psql:/tmp/TestTransaction_BasicTest.sql:64: ERROR: transaction is read-only +START TRANSACTION READ WRITE; +START TRANSACTION +DROP TABLE writetest; -- ok +DROP TABLE +COMMIT; +COMMIT +-- Subtransactions, basic tests +-- create & drop tables +SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE; +SET +CREATE TABLE foobar (a int); +CREATE TABLE +BEGIN; +BEGIN + CREATE TABLE foo (a int); +CREATE TABLE + SAVEPOINT one; +SAVEPOINT + DROP TABLE foo; +DROP TABLE + CREATE TABLE bar (a int); +CREATE TABLE + ROLLBACK TO SAVEPOINT one; +ROLLBACK + RELEASE SAVEPOINT one; +RELEASE + SAVEPOINT two; +SAVEPOINT + CREATE TABLE baz (a int); +CREATE TABLE + RELEASE SAVEPOINT two; +RELEASE + drop TABLE foobar; +DROP TABLE + CREATE TABLE barbaz (a int); +CREATE TABLE +COMMIT; +COMMIT +-- should exist: barbaz, baz, foo +SELECT * FROM foo; -- should be empty + a +--- +(0 rows) + +SELECT * FROM bar; -- shouldn't exist +psql:/tmp/TestTransaction_BasicTest.sql:89: ERROR: relation "bar" does not exist +LINE 1: SELECT * FROM bar; + ^ +SELECT * FROM barbaz; -- should be empty + a +--- +(0 rows) + +SELECT * FROM baz; -- should be empty + a +--- +(0 rows) + +-- inserts +BEGIN; +BEGIN + INSERT INTO foo VALUES (1); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT into bar VALUES (1); +psql:/tmp/TestTransaction_BasicTest.sql:97: ERROR: relation "bar" does not exist + ROLLBACK TO one; +ROLLBACK + RELEASE SAVEPOINT one; +RELEASE + SAVEPOINT two; +SAVEPOINT + INSERT into barbaz VALUES (1); +INSERT 0 1 + RELEASE two; +RELEASE + SAVEPOINT three; +SAVEPOINT + SAVEPOINT four; +SAVEPOINT + INSERT INTO foo VALUES (2); +INSERT 0 1 + RELEASE SAVEPOINT four; +RELEASE + ROLLBACK TO SAVEPOINT three; +ROLLBACK + RELEASE SAVEPOINT three; +RELEASE + INSERT INTO foo VALUES (3); +INSERT 0 1 +COMMIT; +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; +BEGIN + SAVEPOINT one; +SAVEPOINT + SELECT foo; +psql:/tmp/TestTransaction_BasicTest.sql:117: ERROR: column "foo" does not exist +LINE 1: SELECT foo; + ^ + ROLLBACK TO SAVEPOINT one; +ROLLBACK + RELEASE SAVEPOINT one; +RELEASE + SAVEPOINT two; +SAVEPOINT + CREATE TABLE savepoints (a int); +CREATE TABLE + SAVEPOINT three; +SAVEPOINT + INSERT INTO savepoints VALUES (1); +INSERT 0 1 + SAVEPOINT four; +SAVEPOINT + INSERT INTO savepoints VALUES (2); +INSERT 0 1 + SAVEPOINT five; +SAVEPOINT + INSERT INTO savepoints VALUES (3); +INSERT 0 1 + ROLLBACK TO SAVEPOINT five; +ROLLBACK +COMMIT; +COMMIT +COMMIT; -- should not be in a transaction block +psql:/tmp/TestTransaction_BasicTest.sql:130: WARNING: there is no transaction in progress +COMMIT +SELECT * FROM savepoints; + a +--- + 1 + 2 +(2 rows) + +-- test whole-tree rollback +BEGIN; +BEGIN + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (23); +INSERT 0 1 + RELEASE SAVEPOINT one; +RELEASE + SAVEPOINT two; +SAVEPOINT + INSERT INTO savepoints VALUES (24); +INSERT 0 1 + SAVEPOINT three; +SAVEPOINT + INSERT INTO savepoints VALUES (25); +INSERT 0 1 +ROLLBACK; +ROLLBACK +COMMIT; -- should not be in a transaction block +psql:/tmp/TestTransaction_BasicTest.sql:143: WARNING: there is no transaction in progress +COMMIT + +SELECT * FROM savepoints ORDER BY 1; + a +--- + 1 + 2 +(2 rows) + +-- test whole-tree commit on an aborted subtransaction +BEGIN; +BEGIN + INSERT INTO savepoints VALUES (4); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (5); +INSERT 0 1 + SELECT foo; +psql:/tmp/TestTransaction_BasicTest.sql:152: ERROR: column "foo" does not exist +LINE 1: SELECT foo; + ^ +COMMIT; +ROLLBACK +SELECT * FROM savepoints ORDER BY 1; + a +--- + 1 + 2 +(2 rows) + +BEGIN; +BEGIN + INSERT INTO savepoints VALUES (6); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (7); +INSERT 0 1 + RELEASE SAVEPOINT one; +RELEASE + INSERT INTO savepoints VALUES (8); +INSERT 0 1 +COMMIT; +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; +BEGIN + INSERT INTO savepoints VALUES (9); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (10); +INSERT 0 1 + ROLLBACK TO SAVEPOINT one; +ROLLBACK + INSERT INTO savepoints VALUES (11); +INSERT 0 1 +COMMIT; +COMMIT +SELECT a FROM savepoints WHERE a in (9, 10, 11) ORDER BY 1; + 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; +BEGIN; +BEGIN + INSERT INTO savepoints VALUES (12); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (13); +INSERT 0 1 + SAVEPOINT two; +SAVEPOINT + INSERT INTO savepoints VALUES (14); +INSERT 0 1 + ROLLBACK TO SAVEPOINT one; +ROLLBACK + INSERT INTO savepoints VALUES (15); +INSERT 0 1 + SAVEPOINT two; +SAVEPOINT + INSERT INTO savepoints VALUES (16); +INSERT 0 1 + SAVEPOINT three; +SAVEPOINT + INSERT INTO savepoints VALUES (17); +INSERT 0 1 +COMMIT; +COMMIT +SELECT a FROM savepoints WHERE a BETWEEN 12 AND 17 ORDER BY 1; + a +---- + 12 + 15 + 16 + 17 +(4 rows) + +BEGIN; +BEGIN + INSERT INTO savepoints VALUES (18); +INSERT 0 1 + SAVEPOINT one; +SAVEPOINT + INSERT INTO savepoints VALUES (19); +INSERT 0 1 + SAVEPOINT two; +SAVEPOINT + INSERT INTO savepoints VALUES (20); +INSERT 0 1 + ROLLBACK TO SAVEPOINT one; +ROLLBACK + INSERT INTO savepoints VALUES (21); +INSERT 0 1 + ROLLBACK TO SAVEPOINT one; +ROLLBACK + INSERT INTO savepoints VALUES (22); +INSERT 0 1 +COMMIT; +COMMIT +SELECT a FROM savepoints WHERE a BETWEEN 18 AND 22 ORDER BY 1; + a +---- + 18 + 22 +(2 rows) + +DROP TABLE savepoints; +DROP TABLE +-- only in a transaction block: +SAVEPOINT one; +psql:/tmp/TestTransaction_BasicTest.sql:210: ERROR: SAVEPOINT may only be used in transaction blocks +ROLLBACK TO SAVEPOINT one; +psql:/tmp/TestTransaction_BasicTest.sql:211: ERROR: ROLLBACK TO SAVEPOINT may only be used in transaction blocks +RELEASE SAVEPOINT one; +psql:/tmp/TestTransaction_BasicTest.sql:212: ERROR: RELEASE SAVEPOINT may only be used in transaction blocks +-- Only "rollback to" allowed in aborted state +BEGIN; +BEGIN + SAVEPOINT one; +SAVEPOINT + SELECT 0/0; +psql:/tmp/TestTransaction_BasicTest.sql:217: ERROR: division by zero + SAVEPOINT two; -- ignored till the end of ... +psql:/tmp/TestTransaction_BasicTest.sql:218: ERROR: current transaction is aborted, commands ignored until end of transaction block + RELEASE SAVEPOINT one; -- ignored till the end of ... +psql:/tmp/TestTransaction_BasicTest.sql:219: ERROR: current transaction is aborted, commands ignored until end of transaction block + ROLLBACK TO SAVEPOINT one; +ROLLBACK + SELECT 1; + ?column? +---------- + 1 +(1 row) + +COMMIT; +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 ORDER BY 1; +-- 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 1; +-- 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; + a | b +-----+--------- + 56 | 7.8 + 100 | 99.097 + 0 | 0.09561 + 42 | 324.78 + 777 | 777.777 +(5 rows) + +-- 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 +DROP TABLE baz; +DROP TABLE +DROP TABLE barbaz; +DROP TABLE +-- 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; + ?column? +---------- + f +(1 row) + +SELECT '(3, 3)'::tid = '(3, 3)'::tid; + ?column? +---------- + t +(1 row) + +SELECT '(3, 3)'::tid <> '(3, 3)'::tid; + ?column? +---------- + f +(1 row) + +SELECT '(3, 3)'::tid <> '(3, 4)'::tid; + ?column? +---------- + t +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/cb80c333/src/test/feature/transactions/sql/transactions.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/transactions/sql/transactions.sql b/src/test/feature/transactions/sql/transactions.sql new file mode 100644 index 0000000..45ded0d --- /dev/null +++ b/src/test/feature/transactions/sql/transactions.sql @@ -0,0 +1,342 @@ +-- +-- TRANSACTIONS +-- + +CREATE TABLE aggtest ( + a int2, + b float4 +); + +INSERT INTO aggtest VALUES (56, 7.8), (100, 99.097), (0, 0.09561), (42, 324.78); + +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); + +TRUNCATE 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; + +drop table 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 INSERT INTO writetest VALUES (1); -- 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; + INSERT INTO savepoints VALUES (23); + RELEASE SAVEPOINT one; + SAVEPOINT two; + INSERT INTO savepoints VALUES (24); + SAVEPOINT three; + INSERT INTO savepoints VALUES (25); +ROLLBACK; +COMMIT; -- should not be in a transaction block + +SELECT * FROM savepoints ORDER BY 1; + +-- 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 ORDER BY 1; + +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) ORDER BY 1; +-- 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 ORDER BY 1; + +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 ORDER BY 1; + +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 1; +-- 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 1; +-- 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; http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/cb80c333/src/test/feature/transactions/test_transactions.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/transactions/test_transactions.cpp b/src/test/feature/transactions/test_transactions.cpp new file mode 100644 index 0000000..c3254da --- /dev/null +++ b/src/test/feature/transactions/test_transactions.cpp @@ -0,0 +1,19 @@ +#include "gtest/gtest.h" + +#include "lib/sql_util.h" + +using std::string; + +class TestTransaction: public ::testing::Test +{ + public: + TestTransaction() { } + ~TestTransaction() {} +}; + +TEST_F(TestTransaction, BasicTest) +{ + hawq::test::SQLUtility util; + util.execSQLFile("transactions/sql/transactions.sql", + "transactions/ans/transactions.ans"); +}