doc/src/sgml/config.sgml | 2 +-
doc/src/sgml/monitoring.sgml | 14 ++++
src/backend/access/heap/vacuumlazy.c | 2 +-
src/backend/access/nbtree/nbtsort.c | 2 +-
src/backend/catalog/system_views.sql | 1 +
src/backend/executor/execParallel.c | 16 +++-
src/backend/postmaster/autovacuum.c | 4 +-
src/backend/postmaster/pgstat.c | 8 +-
src/backend/replication/logical/worker.c | 6 +-
src/backend/replication/walsender.c | 6 +-
src/backend/tcop/postgres.c | 31 ++++----
src/backend/utils/adt/pgstatfuncs.c | 132 ++++++++++++++++++-------------
src/include/catalog/pg_proc.dat | 6 +-
src/include/pgstat.h | 15 +++-
src/test/modules/worker_spi/worker_spi.c | 8 +-
src/test/regress/expected/rules.out | 9 ++-
16 files changed, 169 insertions(+), 93 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 7a7177c550..d2b415629b 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -7230,7 +7230,7 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
Specifies the amount of memory reserved to store the text of the
currently executing command for each active session, for the
- pg_stat_activity.query field.
+ pg_stat_activity.query and individual_query fields.
If this value is specified without units, it is taken as bytes.
The default value is 1024 bytes.
This parameter can only be set at server start.
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 7dcddf478a..71782e9ffa 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -896,6 +896,20 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
+
+
+ individual_query text
+
+
+ Text of this backend's most recent individual query in case query contains multiple statements. If
+ state is active this field shows the
+ currently executing individual query. In all other states, it shows the last individual query
+ that was executed. By default the individual query text is truncated at 1024
+ bytes; this value can be changed via the parameter
+ .
+
+
+
backend_type text
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 1bbc4598f7..00efbf97cb 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -3489,7 +3489,7 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
/* Set debug_query_string for individual workers */
sharedquery = shm_toc_lookup(toc, PARALLEL_VACUUM_KEY_QUERY_TEXT, false);
debug_query_string = sharedquery;
- pgstat_report_activity(STATE_RUNNING, debug_query_string);
+ pgstat_report_activity(STATE_RUNNING, debug_query_string, 0, 0);
/*
* Open table. The lock mode is the same as the leader process. It's
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index efee86784b..81725bd0ac 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -1810,7 +1810,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
debug_query_string = sharedquery;
/* Report the query string from leader */
- pgstat_report_activity(STATE_RUNNING, debug_query_string);
+ pgstat_report_activity(STATE_RUNNING, debug_query_string, 0, 0);
/* Look up nbtree shared state */
btshared = shm_toc_lookup(toc, PARALLEL_KEY_BTREE_SHARED, false);
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8625cbeab6..a411f8b548 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -759,6 +759,7 @@ CREATE VIEW pg_stat_activity AS
S.backend_xid,
s.backend_xmin,
S.query,
+ S.individual_query,
S.backend_type
FROM pg_stat_get_activity(NULL) AS S
LEFT JOIN pg_database AS D ON (S.datid = D.oid)
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 382e78fb7f..e0587d57b4 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -65,6 +65,7 @@
#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xE000000000000008)
#define PARALLEL_KEY_JIT_INSTRUMENTATION UINT64CONST(0xE000000000000009)
#define PARALLEL_KEY_WAL_USAGE UINT64CONST(0xE00000000000000A)
+#define PARALLEL_KEY_INDIVIDUAL_QUERY UINT64CONST(0xE00000000000000B)
#define PARALLEL_TUPLE_QUEUE_SIZE 65536
@@ -601,6 +602,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
Size dsa_minsize = dsa_minimum_size();
char *query_string;
int query_len;
+ PgStat_IndividualQuery *individual_query;
/*
* Force any initplan outputs that we're going to pass to workers to be
@@ -638,6 +640,10 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
sizeof(FixedParallelExecutorState));
shm_toc_estimate_keys(&pcxt->estimator, 1);
+ /* Estimate space for individual query. */
+ shm_toc_estimate_chunk(&pcxt->estimator, sizeof(PgStat_IndividualQuery));
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+
/* Estimate space for query text. */
query_len = strlen(estate->es_sourceText);
shm_toc_estimate_chunk(&pcxt->estimator, query_len + 1);
@@ -732,6 +738,12 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
fpes->jit_flags = estate->es_jit_flags;
shm_toc_insert(pcxt->toc, PARALLEL_KEY_EXECUTOR_FIXED, fpes);
+ /* individual query stmt_len and stmt_location*/
+ individual_query = shm_toc_allocate(pcxt->toc, sizeof(PgStat_IndividualQuery));
+ individual_query->stmt_len = estate->es_plannedstmt->stmt_len;
+ individual_query->stmt_location = estate->es_plannedstmt->stmt_location;
+ shm_toc_insert(pcxt->toc, PARALLEL_KEY_INDIVIDUAL_QUERY, individual_query);
+
/* Store query string */
query_string = shm_toc_allocate(pcxt->toc, query_len + 1);
memcpy(query_string, estate->es_sourceText, query_len + 1);
@@ -1388,6 +1400,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
void *area_space;
dsa_area *area;
ParallelWorkerContext pwcxt;
+ PgStat_IndividualQuery *individual_query;
/* Get fixed-size state. */
fpes = shm_toc_lookup(toc, PARALLEL_KEY_EXECUTOR_FIXED, false);
@@ -1403,9 +1416,10 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
/* Setting debug_query_string for individual workers */
debug_query_string = queryDesc->sourceText;
+ individual_query = shm_toc_lookup(toc, PARALLEL_KEY_INDIVIDUAL_QUERY, false);
/* Report workers' query for monitoring purposes */
- pgstat_report_activity(STATE_RUNNING, debug_query_string);
+ pgstat_report_activity(STATE_RUNNING, debug_query_string, individual_query->stmt_location, individual_query->stmt_len);
/* Attach to the dynamic shared memory area. */
area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA, false);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 9c7d4b0c60..4c023b6d17 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3176,7 +3176,7 @@ autovac_report_activity(autovac_table *tab)
/* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp();
- pgstat_report_activity(STATE_RUNNING, activity);
+ pgstat_report_activity(STATE_RUNNING, activity, 0, 0);
}
/*
@@ -3215,7 +3215,7 @@ autovac_report_workitem(AutoVacuumWorkItem *workitem,
/* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp();
- pgstat_report_activity(STATE_RUNNING, activity);
+ pgstat_report_activity(STATE_RUNNING, activity, 0, 0);
}
/*
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 15f92b66c6..d313337e81 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3129,7 +3129,7 @@ pgstat_beshutdown_hook(int code, Datum arg)
* ----------
*/
void
-pgstat_report_activity(BackendState state, const char *cmd_str)
+pgstat_report_activity(BackendState state, const char *cmd_str, int stmt_location, int stmt_len)
{
volatile PgBackendStatus *beentry = MyBEEntry;
TimestampTz start_timestamp;
@@ -3156,6 +3156,8 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
beentry->st_state = STATE_DISABLED;
beentry->st_state_start_timestamp = 0;
beentry->st_activity_raw[0] = '\0';
+ beentry->stmt_location = 0;
+ beentry->stmt_len = 0;
beentry->st_activity_start_timestamp = 0;
/* st_xact_start_timestamp and wait_event_info are also disabled */
beentry->st_xact_start_timestamp = 0;
@@ -3178,7 +3180,11 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
* than computed every write.
*/
len = Min(strlen(cmd_str), pgstat_track_activity_query_size - 1);
+ /* Individual query */
+ beentry->stmt_location = stmt_location;
+ beentry->stmt_len = stmt_len;
}
+
current_timestamp = GetCurrentTimestamp();
/*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 2fcf2e61bc..a82616fb99 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -556,7 +556,7 @@ apply_handle_begin(StringInfo s)
in_remote_transaction = true;
- pgstat_report_activity(STATE_RUNNING, NULL);
+ pgstat_report_activity(STATE_RUNNING, NULL, 0, 0);
}
/*
@@ -600,7 +600,7 @@ apply_handle_commit(StringInfo s)
/* Process any tables that are being synchronized in parallel. */
process_syncing_tables(commit_data.end_lsn);
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
}
/*
@@ -1571,7 +1571,7 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
ALLOCSET_DEFAULT_SIZES);
/* mark as idle, before starting to loop */
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
for (;;)
{
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 5e2210dd7b..2fa3bb8839 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1601,7 +1601,7 @@ exec_replication_command(const char *cmd_string)
initStringInfo(&tmpbuf);
/* Report to pgstat that this process is running */
- pgstat_report_activity(STATE_RUNNING, NULL);
+ pgstat_report_activity(STATE_RUNNING, NULL, 0, 0);
switch (cmd_node->type)
{
@@ -1660,7 +1660,7 @@ exec_replication_command(const char *cmd_string)
(errmsg("cannot execute SQL commands in WAL sender for physical replication")));
/* Report to pgstat that this process is now idle */
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
/* Tell the caller that this wasn't a WalSender command. */
return false;
@@ -1679,7 +1679,7 @@ exec_replication_command(const char *cmd_string)
EndCommand(&qc, DestRemote, true);
/* Report to pgstat that this process is now idle */
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
return true;
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c9424f167c..4cffc5540c 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -991,14 +991,6 @@ exec_simple_query(const char *query_string)
bool use_implicit_block;
char msec_str[32];
- /*
- * Report query to various monitoring facilities.
- */
- debug_query_string = query_string;
-
- pgstat_report_activity(STATE_RUNNING, query_string);
-
- TRACE_POSTGRESQL_QUERY_START(query_string);
/*
* We use save_log_statement_stats so ShowUsage doesn't report incorrect
@@ -1076,6 +1068,15 @@ exec_simple_query(const char *query_string)
DestReceiver *receiver;
int16 format;
+ /*
+ * Report query to various monitoring facilities.
+ */
+ debug_query_string = query_string;
+
+ pgstat_report_activity(STATE_RUNNING, query_string, parsetree->stmt_location, parsetree->stmt_len);
+
+ TRACE_POSTGRESQL_QUERY_START(query_string);
+
/*
* Get the command name for use in status display (it also becomes the
* default completion tag, down inside PortalRun). Set ps_status and
@@ -1366,7 +1367,7 @@ exec_parse_message(const char *query_string, /* string to execute */
*/
debug_query_string = query_string;
- pgstat_report_activity(STATE_RUNNING, query_string);
+ pgstat_report_activity(STATE_RUNNING, query_string, 0, 0);
set_ps_display("PARSE");
@@ -1657,7 +1658,7 @@ exec_bind_message(StringInfo input_message)
*/
debug_query_string = psrc->query_string;
- pgstat_report_activity(STATE_RUNNING, psrc->query_string);
+ pgstat_report_activity(STATE_RUNNING, psrc->query_string, 0, 0);
set_ps_display("BIND");
@@ -2115,7 +2116,7 @@ exec_execute_message(const char *portal_name, long max_rows)
*/
debug_query_string = sourceText;
- pgstat_report_activity(STATE_RUNNING, sourceText);
+ pgstat_report_activity(STATE_RUNNING, sourceText, 0, 0);
set_ps_display(GetCommandTagName(portal->commandTag));
@@ -4196,7 +4197,7 @@ PostgresMain(int argc, char *argv[],
if (IsAbortedTransactionBlockState())
{
set_ps_display("idle in transaction (aborted)");
- pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
+ pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL, 0, 0);
/* Start the idle-in-transaction timer */
if (IdleInTransactionSessionTimeout > 0)
@@ -4209,7 +4210,7 @@ PostgresMain(int argc, char *argv[],
else if (IsTransactionOrTransactionBlock())
{
set_ps_display("idle in transaction");
- pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
+ pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL, 0, 0);
/* Start the idle-in-transaction timer */
if (IdleInTransactionSessionTimeout > 0)
@@ -4236,7 +4237,7 @@ PostgresMain(int argc, char *argv[],
pgstat_report_stat(false);
set_ps_display("idle");
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
}
ReadyForQuery(whereToSendOutput);
@@ -4384,7 +4385,7 @@ PostgresMain(int argc, char *argv[],
SetCurrentStatementStartTimestamp();
/* Report query to various monitoring facilities. */
- pgstat_report_activity(STATE_FASTPATH, NULL);
+ pgstat_report_activity(STATE_FASTPATH, NULL, 0, 0);
set_ps_display("");
/* start an xact for this function invocation */
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 95738a4e34..0700a227c6 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -567,7 +567,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
Datum
pg_stat_get_activity(PG_FUNCTION_ARGS)
{
-#define PG_STAT_GET_ACTIVITY_COLS 30
+#define PG_STAT_GET_ACTIVITY_COLS 31
int num_backends = pgstat_fetch_stat_numbackends();
int curr_backend;
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -631,6 +631,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[5] = false;
values[5] = CStringGetTextDatum("");
+ nulls[6] = false;
+ values[6] = CStringGetTextDatum("");
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
continue;
@@ -661,20 +663,21 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[3] = true;
if (TransactionIdIsValid(local_beentry->backend_xid))
- values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
+ values[16] = TransactionIdGetDatum(local_beentry->backend_xid);
else
- nulls[15] = true;
+ nulls[16] = true;
if (TransactionIdIsValid(local_beentry->backend_xmin))
- values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
+ values[17] = TransactionIdGetDatum(local_beentry->backend_xmin);
else
- nulls[16] = true;
+ nulls[17] = true;
/* Values only available to role member or pg_read_all_stats */
if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
{
SockAddr zero_clientaddr;
char *clipped_activity;
+ int individual_len;
switch (beentry->st_state)
{
@@ -703,10 +706,32 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
clipped_activity = pgstat_clip_activity(beentry->st_activity_raw);
values[5] = CStringGetTextDatum(clipped_activity);
+
+ if (clipped_activity[0] != '\0')
+ {
+ /* display individual query */
+ if ((beentry->stmt_len + beentry->stmt_location < pgstat_track_activity_query_size)
+ && (beentry->stmt_len + 1 != strlen(clipped_activity))
+ && (beentry->stmt_len + beentry->stmt_location != 0))
+ {
+ if (beentry->stmt_len == 0)
+ individual_len = strlen(clipped_activity) - beentry->stmt_location;
+ else
+ individual_len = beentry->stmt_len + 1;
+
+ clipped_activity[beentry->stmt_location + individual_len] = '\0';
+ values[6] = CStringGetTextDatum(clipped_activity + beentry->stmt_location);
+ } else {
+ nulls[6] = true;
+ }
+ } else {
+ nulls[6] = true;
+ }
+
pfree(clipped_activity);
/* leader_pid */
- nulls[29] = true;
+ nulls[30] = true;
proc = BackendPidGetProc(beentry->st_procpid);
@@ -743,20 +768,20 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
*/
if (leader && leader->pid != beentry->st_procpid)
{
- values[29] = Int32GetDatum(leader->pid);
- nulls[29] = false;
+ values[30] = Int32GetDatum(leader->pid);
+ nulls[30] = false;
}
}
if (wait_event_type)
- values[6] = CStringGetTextDatum(wait_event_type);
+ values[7] = CStringGetTextDatum(wait_event_type);
else
- nulls[6] = true;
+ nulls[7] = true;
if (wait_event)
- values[7] = CStringGetTextDatum(wait_event);
+ values[8] = CStringGetTextDatum(wait_event);
else
- nulls[7] = true;
+ nulls[8] = true;
/*
* Don't expose transaction time for walsenders; it confuses
@@ -765,33 +790,33 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
*/
if (beentry->st_xact_start_timestamp != 0 &&
beentry->st_backendType != B_WAL_SENDER)
- values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
+ values[9] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
else
- nulls[8] = true;
+ nulls[9] = true;
if (beentry->st_activity_start_timestamp != 0)
- values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
+ values[10] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
else
- nulls[9] = true;
+ nulls[10] = true;
if (beentry->st_proc_start_timestamp != 0)
- values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
+ values[11] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
else
- nulls[10] = true;
+ nulls[11] = true;
if (beentry->st_state_start_timestamp != 0)
- values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
+ values[12] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
else
- nulls[11] = true;
+ nulls[12] = true;
/* A zeroed client addr means we don't know */
memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
sizeof(zero_clientaddr)) == 0)
{
- nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
+ nulls[15] = true;
}
else
{
@@ -815,20 +840,20 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (ret == 0)
{
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
- values[12] = DirectFunctionCall1(inet_in,
+ values[13] = DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host));
if (beentry->st_clienthostname &&
beentry->st_clienthostname[0])
- values[13] = CStringGetTextDatum(beentry->st_clienthostname);
+ values[14] = CStringGetTextDatum(beentry->st_clienthostname);
else
- nulls[13] = true;
- values[14] = Int32GetDatum(atoi(remote_port));
+ nulls[14] = true;
+ values[15] = Int32GetDatum(atoi(remote_port));
}
else
{
- nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
+ nulls[15] = true;
}
}
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@@ -839,16 +864,16 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
* connections we have no permissions to view, or with
* errors.
*/
- nulls[12] = true;
nulls[13] = true;
- values[14] = Int32GetDatum(-1);
+ nulls[14] = true;
+ values[15] = Int32GetDatum(-1);
}
else
{
/* Unknown address type, should never happen */
- nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
+ nulls[15] = true;
}
}
/* Add backend type */
@@ -858,59 +883,59 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid);
if (bgw_type)
- values[17] = CStringGetTextDatum(bgw_type);
+ values[18] = CStringGetTextDatum(bgw_type);
else
- nulls[17] = true;
+ nulls[18] = true;
}
else
- values[17] =
+ values[18] =
CStringGetTextDatum(GetBackendTypeDesc(beentry->st_backendType));
/* SSL information */
if (beentry->st_ssl)
{
- values[18] = BoolGetDatum(true); /* ssl */
- values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
- values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
- values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
- values[22] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
+ values[19] = BoolGetDatum(true); /* ssl */
+ values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
+ values[21] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
+ values[22] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
+ values[23] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
if (beentry->st_sslstatus->ssl_client_dn[0])
- values[23] = CStringGetTextDatum(beentry->st_sslstatus->ssl_client_dn);
+ values[24] = CStringGetTextDatum(beentry->st_sslstatus->ssl_client_dn);
else
- nulls[23] = true;
+ nulls[24] = true;
if (beentry->st_sslstatus->ssl_client_serial[0])
- values[24] = DirectFunctionCall3(numeric_in,
+ values[25] = DirectFunctionCall3(numeric_in,
CStringGetDatum(beentry->st_sslstatus->ssl_client_serial),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
else
- nulls[24] = true;
+ nulls[25] = true;
if (beentry->st_sslstatus->ssl_issuer_dn[0])
- values[25] = CStringGetTextDatum(beentry->st_sslstatus->ssl_issuer_dn);
+ values[26] = CStringGetTextDatum(beentry->st_sslstatus->ssl_issuer_dn);
else
- nulls[25] = true;
+ nulls[26] = true;
}
else
{
- values[18] = BoolGetDatum(false); /* ssl */
- nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = nulls[24] = nulls[25] = true;
+ values[19] = BoolGetDatum(false); /* ssl */
+ nulls[20] = nulls[21] = nulls[22] = nulls[23] = nulls[24] = nulls[25] = nulls[26] = true;
}
/* GSSAPI information */
if (beentry->st_gss)
{
- values[26] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */
- values[27] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ);
- values[28] = BoolGetDatum(beentry->st_gssstatus->gss_enc); /* GSS Encryption in use */
+ values[27] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */
+ values[28] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ);
+ values[29] = BoolGetDatum(beentry->st_gssstatus->gss_enc); /* GSS Encryption in use */
}
else
{
- values[26] = BoolGetDatum(false); /* gss_auth */
- nulls[27] = true; /* No GSS principal */
- values[28] = BoolGetDatum(false); /* GSS Encryption not in
+ values[27] = BoolGetDatum(false); /* gss_auth */
+ nulls[28] = true; /* No GSS principal */
+ values[29] = BoolGetDatum(false); /* GSS Encryption not in
* use */
}
}
@@ -918,8 +943,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
{
/* No permissions to view data about this session */
values[5] = CStringGetTextDatum("");
+ values[6] = CStringGetTextDatum("");
nulls[4] = true;
- nulls[6] = true;
nulls[7] = true;
nulls[8] = true;
nulls[9] = true;
@@ -928,7 +953,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[12] = true;
nulls[13] = true;
nulls[14] = true;
- nulls[17] = true;
+ nulls[15] = true;
nulls[18] = true;
nulls[19] = true;
nulls[20] = true;
@@ -941,6 +966,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[27] = true;
nulls[28] = true;
nulls[29] = true;
+ nulls[30] = true;
}
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 082a11f270..a4451c1ef6 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5222,9 +5222,9 @@
proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
proretset => 't', provolatile => 's', proparallel => 'r',
prorettype => 'record', proargtypes => 'int4',
- proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool,int4}',
- proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
- proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}',
+ proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool,int4}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{pid,datid,pid,usesysid,application_name,state,query,individual_query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}',
prosrc => 'pg_stat_get_activity' },
{ oid => '3318',
descr => 'statistics: information about progress of backends running maintenance command',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 1387201382..df245aa042 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -118,6 +118,13 @@ typedef struct PgStat_TableCounts
PgStat_Counter t_blocks_hit;
} PgStat_TableCounts;
+/* Individual Query location and length*/
+typedef struct PgStat_IndividualQuery
+{
+ int stmt_location;
+ int stmt_len;
+} PgStat_IndividualQuery;
+
/* Possible targets for resetting cluster-wide shared values */
typedef enum PgStat_Shared_Reset_Target
{
@@ -1123,6 +1130,12 @@ typedef struct PgBackendStatus
*/
char *st_activity_raw;
+ /*
+ * Current individual command location and length
+ */
+ int stmt_location;
+ int stmt_len;
+
/*
* Command progress reporting. Any command which wishes can advertise
* that it is running by setting st_progress_command,
@@ -1314,7 +1327,7 @@ extern void pgstat_report_checksum_failure(void);
extern void pgstat_initialize(void);
extern void pgstat_bestart(void);
-extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_activity(BackendState state, const char *cmd_str, int stmt_location, int stmt_len);
extern void pgstat_report_tempfile(size_t filesize);
extern void pgstat_report_appname(const char *appname);
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 1c7b17c56f..c4d528f291 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -112,7 +112,7 @@ initialize_worker_spi(worktable *table)
StartTransactionCommand();
SPI_connect();
PushActiveSnapshot(GetTransactionSnapshot());
- pgstat_report_activity(STATE_RUNNING, "initializing worker_spi schema");
+ pgstat_report_activity(STATE_RUNNING, "initializing worker_spi schema", 0, 0);
/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
initStringInfo(&buf);
@@ -156,7 +156,7 @@ initialize_worker_spi(worktable *table)
SPI_finish();
PopActiveSnapshot();
CommitTransactionCommand();
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
}
void
@@ -262,7 +262,7 @@ worker_spi_main(Datum main_arg)
StartTransactionCommand();
SPI_connect();
PushActiveSnapshot(GetTransactionSnapshot());
- pgstat_report_activity(STATE_RUNNING, buf.data);
+ pgstat_report_activity(STATE_RUNNING, buf.data, 0, 0);
/* We can now execute queries via SPI */
ret = SPI_execute(buf.data, false, 0);
@@ -292,7 +292,7 @@ worker_spi_main(Datum main_arg)
PopActiveSnapshot();
CommitTransactionCommand();
pgstat_report_stat(false);
- pgstat_report_activity(STATE_IDLE, NULL);
+ pgstat_report_activity(STATE_IDLE, NULL, 0, 0);
}
proc_exit(1);
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 601734a6f1..5635e80811 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1751,8 +1751,9 @@ pg_stat_activity| SELECT s.datid,
s.backend_xid,
s.backend_xmin,
s.query,
+ s.individual_query,
s.backend_type
- FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
+ FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, individual_query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
LEFT JOIN pg_database d ON ((s.datid = d.oid)))
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1857,7 +1858,7 @@ pg_stat_gssapi| SELECT s.pid,
s.gss_auth AS gss_authenticated,
s.gss_princ AS principal,
s.gss_enc AS encrypted
- FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
+ FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, individual_query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
WHERE (s.client_port IS NOT NULL);
pg_stat_progress_analyze| SELECT s.pid,
s.datid,
@@ -2005,7 +2006,7 @@ pg_stat_replication| SELECT s.pid,
w.sync_priority,
w.sync_state,
w.reply_time
- FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
+ FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, individual_query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
pg_stat_slru| SELECT s.name,
@@ -2027,7 +2028,7 @@ pg_stat_ssl| SELECT s.pid,
s.ssl_client_dn AS client_dn,
s.ssl_client_serial AS client_serial,
s.ssl_issuer_dn AS issuer_dn
- FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
+ FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, individual_query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
WHERE (s.client_port IS NOT NULL);
pg_stat_subscription| SELECT su.oid AS subid,
su.subname,