Skip to content

Commit a4bbbbf

Browse files
committed
Assert TopTransactionContext existence instead of transaction state
If transaction was aborted for some reason there are still statements that allowed to execute. So intead of assertion for transaction state check if TopTransactionContext exists as it's supposed to be our parent context.
1 parent 948bc3d commit a4bbbbf

3 files changed

Lines changed: 69 additions & 3 deletions

File tree

regression/expected/rollback.out

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,53 @@ SELECT pg_stat_monitor_reset();
6666

6767
(1 row)
6868

69+
-- We still able to record ROLLBACK TO SAVEPOINT if subtransaction is aborted due an error.
70+
BEGIN;
71+
SAVEPOINT sp1;
72+
SELECT 1/0;
73+
ERROR: division by zero
74+
ROLLBACK TO SAVEPOINT sp1;
75+
INSERT INTO t VALUES (3);
76+
COMMIT;
77+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
78+
query | username | datname
79+
--------------------------------+----------+--------------------
80+
BEGIN | u | contrib_regression
81+
COMMIT | u | contrib_regression
82+
INSERT INTO t VALUES (3) | u | contrib_regression
83+
ROLLBACK TO SAVEPOINT sp1 | | contrib_regression
84+
SAVEPOINT sp1 | u | contrib_regression
85+
SELECT 1/0; | u | contrib_regression
86+
SELECT pg_stat_monitor_reset() | u | contrib_regression
87+
(7 rows)
88+
89+
SELECT pg_stat_monitor_reset();
90+
pg_stat_monitor_reset
91+
-----------------------
92+
93+
(1 row)
94+
95+
-- We are still able to record PREPARE TRANSACTION issued in an aborted transaction, it rolls it back.
96+
BEGIN;
97+
INSERT INTO t VALUES (1);
98+
ERROR: duplicate key value violates unique constraint "t_pkey"
99+
DETAIL: Key (a)=(1) already exists.
100+
PREPARE TRANSACTION 'pgsm_aborted_transaction';
101+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
102+
query | username | datname
103+
------------------------------------------------+----------+--------------------
104+
BEGIN | u | contrib_regression
105+
INSERT INTO t VALUES (1); | u | contrib_regression
106+
PREPARE TRANSACTION 'pgsm_aborted_transaction' | | contrib_regression
107+
SELECT pg_stat_monitor_reset() | u | contrib_regression
108+
(4 rows)
109+
110+
SELECT pg_stat_monitor_reset();
111+
pg_stat_monitor_reset
112+
-----------------------
113+
114+
(1 row)
115+
69116
DROP TABLE t;
70117
SET ROLE NONE;
71118
DROP USER u;

regression/sql/rollback.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ ROLLBACK;
2929
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
3030
SELECT pg_stat_monitor_reset();
3131

32+
-- We still able to record ROLLBACK TO SAVEPOINT if subtransaction is aborted due an error.
33+
BEGIN;
34+
SAVEPOINT sp1;
35+
SELECT 1/0;
36+
ROLLBACK TO SAVEPOINT sp1;
37+
INSERT INTO t VALUES (3);
38+
COMMIT;
39+
40+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
41+
SELECT pg_stat_monitor_reset();
42+
43+
-- We are still able to record PREPARE TRANSACTION issued in an aborted transaction, it rolls it back.
44+
BEGIN;
45+
INSERT INTO t VALUES (1);
46+
PREPARE TRANSACTION 'pgsm_aborted_transaction';
47+
48+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
49+
SELECT pg_stat_monitor_reset();
50+
3251
DROP TABLE t;
3352
SET ROLE NONE;
3453
DROP USER u;

src/pg_stat_monitor.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ pgsm_store_error(const char *query, const ErrorData *edata)
15881588
static MemoryContext
15891589
pgsm_memory_context(void)
15901590
{
1591-
Assert(IsTransactionState());
1591+
Assert(TopTransactionContext != NULL);
15921592

15931593
if (PgsmMemoryContext == NULL)
15941594
{
@@ -1597,8 +1597,8 @@ pgsm_memory_context(void)
15971597
* scenario. CurrentMemoryContext here is just a failsafe mechanism,
15981598
* it should never happen.
15991599
*/
1600-
MemoryContext parent = IsTransactionState() ? TopTransactionContext
1601-
: CurrentMemoryContext;
1600+
MemoryContext parent = TopTransactionContext != NULL
1601+
? TopTransactionContext : CurrentMemoryContext;
16021602

16031603
PgsmMemoryContext = AllocSetContextCreate(parent,
16041604
"pg_stat_monitor local store",

0 commit comments

Comments
 (0)