Skip to content

Commit 2b1c060

Browse files
committed
PG-1459 Improve how we collect username and datname
Improve collecting of username and datname fields by grabbing them earlier in utillity hook, when transaction state wasn't yet changed by actual hook processing and we still can do database access. If transaction was aborted by an error, then keep these fields empty.
1 parent b6ffd37 commit 2b1c060

5 files changed

Lines changed: 119 additions & 19 deletions

File tree

pg_stat_monitor.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
10181018
!IsA(parsetree, PrepareStmt) &&
10191019
!IsA(parsetree, DeallocateStmt))
10201020
{
1021-
pgsmEntry *entry;
10221021
char *query_text;
10231022
int location;
10241023
int query_len;
@@ -1030,6 +1029,7 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
10301029
BufferUsage bufusage_start = pgBufferUsage;
10311030
WalUsage walusage;
10321031
WalUsage walusage_start = pgWalUsage;
1032+
pgsmEntry *entry = pgsm_create_hash_entry(0, queryId, NULL);
10331033

10341034
if (getrusage(RUSAGE_SELF, &rusage_start) != 0)
10351035
elog(DEBUG1, "[pg_stat_monitor] pgsm_ProcessUtility: Failed to execute getrusage.");
@@ -1090,9 +1090,6 @@ pgsm_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
10901090
memset(&bufusage, 0, sizeof(BufferUsage));
10911091
BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
10921092

1093-
/* Create an entry for this query */
1094-
entry = pgsm_create_hash_entry(0, queryId, NULL);
1095-
10961093
location = pstmt->stmt_location;
10971094
query_len = pstmt->stmt_len;
10981095
query_text = (char *) CleanQuerytext(queryString, &location, &query_len);
@@ -1743,19 +1740,16 @@ pgsm_create_hash_entry(uint64 bucket_id, int64 queryid, PlanInfo *plan_info)
17431740
{
17441741
datname = get_database_name(entry->key.dbid);
17451742
username = GetUserNameFromId(entry->key.userid, true);
1746-
}
17471743

1748-
if (!datname)
1749-
datname = pnstrdup("<database name not available>", sizeof(entry->datname) - 1);
1744+
snprintf(entry->datname, sizeof(entry->datname), "%s", datname);
1745+
snprintf(entry->username, sizeof(entry->username), "%s", username);
17501746

1751-
if (!username)
1752-
username = pnstrdup("<user name not available>", sizeof(entry->username) - 1);
1747+
if (datname)
1748+
pfree(datname);
17531749

1754-
snprintf(entry->datname, sizeof(entry->datname), "%s", datname);
1755-
snprintf(entry->username, sizeof(entry->username), "%s", username);
1756-
1757-
pfree(datname);
1758-
pfree(username);
1750+
if (username)
1751+
pfree(username);
1752+
}
17591753

17601754
MemoryContextSwitchTo(oldctx);
17611755

regression/expected/application_name_unique.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ SELECT query,application_name FROM pg_stat_monitor ORDER BY query, application_n
2525
SELECT 1 AS num | naeem
2626
SELECT 1 AS num | psql
2727
SELECT pg_stat_monitor_reset() | pg_regress/application_name_unique
28-
SET application_name = 'naeem' | naeem
29-
SET application_name = 'psql' | psql
28+
SET application_name = 'naeem' | pg_regress/application_name_unique
29+
SET application_name = 'psql' | naeem
3030
(5 rows)
3131

3232
SELECT pg_stat_monitor_reset();

regression/expected/rollback.out

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
CREATE EXTENSION pg_stat_monitor;
2+
CREATE USER u WITH SUPERUSER;
3+
ERROR: role "u" already exists
4+
SET ROLE u;
5+
CREATE TABLE t (a int PRIMARY KEY) ;
6+
SELECT pg_stat_monitor_reset();
7+
pg_stat_monitor_reset
8+
-----------------------
9+
10+
(1 row)
11+
12+
BEGIN;
13+
INSERT INTO t VALUES (1);
14+
COMMIT;
15+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
16+
query | username | datname
17+
--------------------------------+----------+--------------------
18+
BEGIN | u | contrib_regression
19+
COMMIT | u | contrib_regression
20+
INSERT INTO t VALUES (1) | u | contrib_regression
21+
SELECT pg_stat_monitor_reset() | u | contrib_regression
22+
(4 rows)
23+
24+
SELECT pg_stat_monitor_reset();
25+
pg_stat_monitor_reset
26+
-----------------------
27+
28+
(1 row)
29+
30+
-- During manual rollback we will be able to get username and datname of the query that was rolled back.
31+
BEGIN;
32+
INSERT INTO t VALUES (2);
33+
ROLLBACK;
34+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
35+
query | username | datname
36+
--------------------------------+----------+--------------------
37+
BEGIN | u | contrib_regression
38+
INSERT INTO t VALUES (2) | u | contrib_regression
39+
ROLLBACK | u | contrib_regression
40+
SELECT pg_stat_monitor_reset() | u | contrib_regression
41+
(4 rows)
42+
43+
SELECT pg_stat_monitor_reset();
44+
pg_stat_monitor_reset
45+
-----------------------
46+
47+
(1 row)
48+
49+
-- If transaction is rolled back due an error, we won't be able to get username and datname of the query that was rolled back.
50+
BEGIN;
51+
INSERT INTO t VALUES (1);
52+
ERROR: duplicate key value violates unique constraint "t_pkey"
53+
DETAIL: Key (a)=(1) already exists.
54+
ROLLBACK;
55+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
56+
query | username | datname
57+
--------------------------------+----------+--------------------
58+
BEGIN | u | contrib_regression
59+
INSERT INTO t VALUES (1); | u | contrib_regression
60+
ROLLBACK | |
61+
SELECT pg_stat_monitor_reset() | u | contrib_regression
62+
(4 rows)
63+
64+
SELECT pg_stat_monitor_reset();
65+
pg_stat_monitor_reset
66+
-----------------------
67+
68+
(1 row)
69+
70+
DROP TABLE t;
71+
DROP EXTENSION pg_stat_monitor;

regression/expected/user.out

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ SELECT username, query FROM pg_stat_monitor ORDER BY username, query COLLATE "C"
3939
su | DROP OWNED BY u2
4040
su | DROP USER u2
4141
su | SELECT pg_stat_monitor_reset()
42-
su | SET ROLE su
42+
su | SET ROLE u1
4343
u1 | CREATE TABLE t1 (a int)
4444
u1 | SELECT * FROM t1
4545
u1 | SELECT pg_stat_monitor_reset();
46-
u1 | SET ROLE u1
46+
u1 | SET ROLE u2
4747
u2 | CREATE TABLE t2 (a int)
4848
u2 | DROP TABLE t2
4949
u2 | SELECT * FROM t2
50-
u2 | SET ROLE u2
50+
u2 | SET ROLE su
5151
(12 rows)
5252

5353
SELECT pg_stat_monitor_reset();

regression/sql/rollback.sql

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
CREATE EXTENSION pg_stat_monitor;
2+
3+
CREATE USER u WITH SUPERUSER;
4+
SET ROLE u;
5+
6+
7+
CREATE TABLE t (a int PRIMARY KEY) ;
8+
9+
SELECT pg_stat_monitor_reset();
10+
11+
BEGIN;
12+
INSERT INTO t VALUES (1);
13+
COMMIT;
14+
15+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
16+
SELECT pg_stat_monitor_reset();
17+
18+
-- During manual rollback we will be able to get username and datname of the query that was rolled back.
19+
BEGIN;
20+
INSERT INTO t VALUES (2);
21+
ROLLBACK;
22+
23+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
24+
SELECT pg_stat_monitor_reset();
25+
26+
-- If transaction is rolled back due an error, we won't be able to get username and datname of the query that was rolled back.
27+
BEGIN;
28+
INSERT INTO t VALUES (1);
29+
ROLLBACK;
30+
31+
SELECT query, username, datname FROM pg_stat_monitor ORDER BY query COLLATE "C";
32+
SELECT pg_stat_monitor_reset();
33+
34+
DROP TABLE t;
35+
DROP EXTENSION pg_stat_monitor;

0 commit comments

Comments
 (0)