From 8e3b4d9d40244c037bbc6e182ea3fabb9347d482 Mon Sep 17 00:00:00 2001 From: Noah Misch Date: Tue, 20 Oct 2015 00:37:22 -0400 Subject: [PATCH] Eschew "RESET statement_timeout" in tests. Instead, use transaction abort. Given an unlucky bout of latency, the timeout would cancel the RESET itself. Buildfarm members gharial, lapwing, mereswine, shearwater, and sungazer witness that. Back-patch to 9.1 (all supported versions). The query_canceled test still could timeout before entering its subtransaction; for whatever reason, that has yet to happen on the buildfarm. --- src/test/regress/expected/plpgsql.out | 43 +++++++++++++------ src/test/regress/expected/prepared_xacts.out | 6 ++- .../regress/expected/prepared_xacts_1.out | 6 ++- src/test/regress/sql/plpgsql.sql | 37 ++++++++++------ src/test/regress/sql/prepared_xacts.sql | 6 ++- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 141c9982f8..e30c579a2a 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -2020,7 +2020,7 @@ NOTICE: caught numeric_value_out_of_range or cardinality_violation (1 row) create temp table foo (f1 int); -create function blockme() returns int as $$ +create function subxact_rollback_semantics() returns int as $$ declare x int; begin x := 1; @@ -2028,28 +2028,20 @@ begin begin x := x + 1; insert into foo values(x); - -- we assume this will take longer than 2 seconds: - select count(*) into x from tenk1 a, tenk1 b, tenk1 c; + raise exception 'inner'; exception when others then - raise notice 'caught others?'; - return -1; - when query_canceled then - raise notice 'nyeah nyeah, can''t stop me'; x := x * 10; end; insert into foo values(x); return x; end$$ language plpgsql; -set statement_timeout to 2000; -select blockme(); -NOTICE: nyeah nyeah, can't stop me - blockme ---------- - 20 +select subxact_rollback_semantics(); + subxact_rollback_semantics +---------------------------- + 20 (1 row) -reset statement_timeout; select * from foo; f1 ---- @@ -2058,6 +2050,29 @@ select * from foo; (2 rows) drop table foo; +create function trap_timeout() returns void as $$ +begin + declare x int; + begin + -- we assume this will take longer than 2 seconds: + select count(*) into x from tenk1 a, tenk1 b, tenk1 c; + exception + when others then + raise notice 'caught others?'; + when query_canceled then + raise notice 'nyeah nyeah, can''t stop me'; + end; + -- Abort transaction to abandon the statement_timeout setting. Otherwise, + -- the next top-level statement would be vulnerable to the timeout. + raise exception 'end of function'; +end$$ language plpgsql; +begin; +set statement_timeout to 2000; +select trap_timeout(); +NOTICE: nyeah nyeah, can't stop me +ERROR: end of function +CONTEXT: PL/pgSQL function trap_timeout() line 15 at RAISE +rollback; -- Test for pass-by-ref values being stored in proper context create function test_variable_storage() returns text as $$ declare x text; diff --git a/src/test/regress/expected/prepared_xacts.out b/src/test/regress/expected/prepared_xacts.out index c0b08649e8..ef7034b588 100644 --- a/src/test/regress/expected/prepared_xacts.out +++ b/src/test/regress/expected/prepared_xacts.out @@ -194,10 +194,11 @@ SELECT gid FROM pg_prepared_xacts; (2 rows) -- pxtest3 should be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; ERROR: canceling statement due to statement timeout -reset statement_timeout; +rollback; -- Disconnect, we will continue testing in a different backend \c - -- There should still be two prepared transactions @@ -209,10 +210,11 @@ SELECT gid FROM pg_prepared_xacts; (2 rows) -- pxtest3 should still be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; ERROR: canceling statement due to statement timeout -reset statement_timeout; +rollback; -- Commit table creation COMMIT PREPARED 'regress-one'; \d pxtest2 diff --git a/src/test/regress/expected/prepared_xacts_1.out b/src/test/regress/expected/prepared_xacts_1.out index 898f278c11..5078bf6ba9 100644 --- a/src/test/regress/expected/prepared_xacts_1.out +++ b/src/test/regress/expected/prepared_xacts_1.out @@ -198,13 +198,14 @@ SELECT gid FROM pg_prepared_xacts; (0 rows) -- pxtest3 should be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; fff ----- (0 rows) -reset statement_timeout; +rollback; -- Disconnect, we will continue testing in a different backend \c - -- There should still be two prepared transactions @@ -214,13 +215,14 @@ SELECT gid FROM pg_prepared_xacts; (0 rows) -- pxtest3 should still be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; fff ----- (0 rows) -reset statement_timeout; +rollback; -- Commit table creation COMMIT PREPARED 'regress-one'; ERROR: prepared transaction with identifier "regress-one" does not exist diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index f883e7e0a2..7ffef895b6 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -1745,7 +1745,7 @@ select trap_matching_test(1); create temp table foo (f1 int); -create function blockme() returns int as $$ +create function subxact_rollback_semantics() returns int as $$ declare x int; begin x := 1; @@ -1753,29 +1753,40 @@ begin begin x := x + 1; insert into foo values(x); + raise exception 'inner'; + exception + when others then + x := x * 10; + end; + insert into foo values(x); + return x; +end$$ language plpgsql; + +select subxact_rollback_semantics(); +select * from foo; +drop table foo; + +create function trap_timeout() returns void as $$ +begin + declare x int; + begin -- we assume this will take longer than 2 seconds: select count(*) into x from tenk1 a, tenk1 b, tenk1 c; exception when others then raise notice 'caught others?'; - return -1; when query_canceled then raise notice 'nyeah nyeah, can''t stop me'; - x := x * 10; end; - insert into foo values(x); - return x; + -- Abort transaction to abandon the statement_timeout setting. Otherwise, + -- the next top-level statement would be vulnerable to the timeout. + raise exception 'end of function'; end$$ language plpgsql; +begin; set statement_timeout to 2000; - -select blockme(); - -reset statement_timeout; - -select * from foo; - -drop table foo; +select trap_timeout(); +rollback; -- Test for pass-by-ref values being stored in proper context create function test_variable_storage() returns text as $$ diff --git a/src/test/regress/sql/prepared_xacts.sql b/src/test/regress/sql/prepared_xacts.sql index 7902152775..dfb20a18e7 100644 --- a/src/test/regress/sql/prepared_xacts.sql +++ b/src/test/regress/sql/prepared_xacts.sql @@ -122,9 +122,10 @@ SELECT * FROM pxtest2; SELECT gid FROM pg_prepared_xacts; -- pxtest3 should be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; -reset statement_timeout; +rollback; -- Disconnect, we will continue testing in a different backend \c - @@ -133,9 +134,10 @@ reset statement_timeout; SELECT gid FROM pg_prepared_xacts; -- pxtest3 should still be locked because of the pending DROP +begin; set statement_timeout to 2000; SELECT * FROM pxtest3; -reset statement_timeout; +rollback; -- Commit table creation COMMIT PREPARED 'regress-one'; -- 2.40.0