diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 2253ca8..ca34aa8 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -531,7 +531,8 @@ CREATE VIEW pg_stat_activity AS S.xact_start, S.query_start, S.waiting, - S.current_query + S.state, + S.query FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U WHERE S.datid = D.oid AND S.usesysid = U.oid; diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 3b71232..c2d8080 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -2751,7 +2751,7 @@ autovac_report_activity(autovac_table *tab) /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); - pgstat_report_activity(activity); + pgstat_report_activity(STATE_RUNNING,activity); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 24582e3..86b2762 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2416,6 +2416,7 @@ pgstat_bestart(void) beentry->st_clientaddr = clientaddr; beentry->st_clienthostname[0] = '\0'; beentry->st_waiting = false; + beentry->st_state=-1; beentry->st_appname[0] = '\0'; beentry->st_activity[0] = '\0'; /* Also make sure the last byte in each string area is always 0 */ @@ -2479,7 +2480,7 @@ pgstat_beshutdown_hook(int code, Datum arg) * ---------- */ void -pgstat_report_activity(const char *cmd_str) +pgstat_report_activity(int state, const char *cmd_str) { volatile PgBackendStatus *beentry = MyBEEntry; TimestampTz start_timestamp; @@ -2496,9 +2497,6 @@ pgstat_report_activity(const char *cmd_str) */ start_timestamp = GetCurrentStatementStartTimestamp(); - len = strlen(cmd_str); - len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1); - /* * Update my status entry, following the protocol of bumping * st_changecount before and after. We use a volatile pointer here to @@ -2507,8 +2505,15 @@ pgstat_report_activity(const char *cmd_str) beentry->st_changecount++; beentry->st_activity_start_timestamp = start_timestamp; - memcpy((char *) beentry->st_activity, cmd_str, len); - beentry->st_activity[len] = '\0'; + beentry->st_state = state; + + if ( cmd_str != NULL ) + { + len = strlen(cmd_str); + len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1); + memcpy((char *) beentry->st_activity, cmd_str, len); + beentry->st_activity[len] = '\0'; + } beentry->st_changecount++; Assert((beentry->st_changecount & 1) == 0); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 976a832..4c1ce60 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -809,7 +809,7 @@ exec_simple_query(const char *query_string) */ debug_query_string = query_string; - pgstat_report_activity(query_string); + pgstat_report_activity(STATE_RUNNING,query_string); TRACE_POSTGRESQL_QUERY_START(query_string); @@ -1128,7 +1128,7 @@ exec_parse_message(const char *query_string, /* string to execute */ */ debug_query_string = query_string; - pgstat_report_activity(query_string); + pgstat_report_activity(STATE_RUNNING,query_string); set_ps_display("PARSE", false); @@ -1423,7 +1423,7 @@ exec_bind_message(StringInfo input_message) */ debug_query_string = psrc->query_string; - pgstat_report_activity(psrc->query_string); + pgstat_report_activity(STATE_RUNNING,psrc->query_string); set_ps_display("BIND", false); @@ -1826,7 +1826,7 @@ exec_execute_message(const char *portal_name, long max_rows) */ debug_query_string = sourceText; - pgstat_report_activity(sourceText); + pgstat_report_activity(STATE_RUNNING,sourceText); set_ps_display(portal->commandTag, false); @@ -3789,12 +3789,12 @@ PostgresMain(int argc, char *argv[], const char *username) if (IsAbortedTransactionBlockState()) { set_ps_display("idle in transaction (aborted)", false); - pgstat_report_activity(" in transaction (aborted)"); + pgstat_report_activity(STATE_IDLEINTRANSACTION_ABRT,NULL); } else if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction", false); - pgstat_report_activity(" in transaction"); + pgstat_report_activity(STATE_IDLEINTRANSACTION,NULL); } else { @@ -3802,7 +3802,7 @@ PostgresMain(int argc, char *argv[], const char *username) pgstat_report_stat(false); set_ps_display("idle", false); - pgstat_report_activity(""); + pgstat_report_activity(STATE_IDLE,NULL); } ReadyForQuery(whereToSendOutput); @@ -3922,7 +3922,8 @@ PostgresMain(int argc, char *argv[], const char *username) SetCurrentStatementStartTimestamp(); /* Report query to various monitoring facilities. */ - pgstat_report_activity(" function call"); +// pgstat_report_activity(" function call"); + pgstat_report_activity(STATE_FASTPATH,NULL); set_ps_display("", false); /* start an xact for this function invocation */ diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 7792b33..9f04b52 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -507,7 +507,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - tupdesc = CreateTemplateTupleDesc(12, false); + tupdesc = CreateTemplateTupleDesc(13, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); /* This should have been called 'pid'; can't change it. 2011-06-11 */ @@ -517,21 +517,23 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query", + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting", + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting", BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start", + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start", TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start", TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start", TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_addr", INETOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname", + TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_hostname", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port", + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_port", INT4OID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); @@ -584,8 +586,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ - Datum values[12]; - bool nulls[12]; + Datum values[13]; + bool nulls[13]; HeapTuple tuple; PgBackendStatus *beentry; SockAddr zero_clientaddr; @@ -610,8 +612,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++) nulls[i] = true; - nulls[4] = false; - values[4] = CStringGetTextDatum(""); + nulls[5] = false; + values[5] = CStringGetTextDatum(""); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); @@ -629,40 +631,67 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) /* Values only available to same user or superuser */ if (superuser() || beentry->st_userid == GetUserId()) { + if ( beentry->st_state == -1) + { + nulls[4] = true; + } + else + { + switch(beentry->st_state) + { + case STATE_IDLE: + values[4] = CStringGetTextDatum(""); + break; + case STATE_RUNNING: + values[4] = CStringGetTextDatum(""); + break; + case STATE_IDLEINTRANSACTION: + values[4] = CStringGetTextDatum(" in transaction"); + break; + case STATE_FASTPATH: + values[4] = CStringGetTextDatum(" function call"); + break; + case STATE_IDLEINTRANSACTION_ABRT: + values[4] = CStringGetTextDatum(" in transaction (aborted)"); + break; + } + } if (*(beentry->st_activity) == '\0') { - values[4] = CStringGetTextDatum(""); + + values[5] = CStringGetTextDatum(""); } else { - values[4] = CStringGetTextDatum(beentry->st_activity); + + values[5] = CStringGetTextDatum(beentry->st_activity); } - values[5] = BoolGetDatum(beentry->st_waiting); + values[6] = BoolGetDatum(beentry->st_waiting); if (beentry->st_xact_start_timestamp != 0) - values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp); + values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp); else - nulls[6] = true; + nulls[7] = true; if (beentry->st_activity_start_timestamp != 0) - values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp); + values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp); else - nulls[7] = true; + nulls[8] = true; if (beentry->st_proc_start_timestamp != 0) - values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp); + values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp); else - nulls[8] = true; + nulls[9] = 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[9] = true; nulls[10] = true; nulls[11] = true; + nulls[12] = true; } else { @@ -686,19 +715,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) if (ret == 0) { clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); - values[9] = DirectFunctionCall1(inet_in, + values[10] = DirectFunctionCall1(inet_in, CStringGetDatum(remote_host)); if (beentry->st_clienthostname) - values[10] = CStringGetTextDatum(beentry->st_clienthostname); + values[11] = CStringGetTextDatum(beentry->st_clienthostname); else - nulls[10] = true; - values[11] = Int32GetDatum(atoi(remote_port)); + nulls[11] = true; + values[12] = Int32GetDatum(atoi(remote_port)); } else { - nulls[9] = true; nulls[10] = true; nulls[11] = true; + nulls[12] = true; } } else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) @@ -709,30 +738,31 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) * connections we have no permissions to view, or with * errors. */ - nulls[9] = true; nulls[10] = true; - values[11] = DatumGetInt32(-1); + nulls[11] = true; + values[12] = DatumGetInt32(-1); } else { /* Unknown address type, should never happen */ - nulls[9] = true; nulls[10] = true; nulls[11] = true; + nulls[12] = true; } } } else { /* No permissions to view data about this session */ - values[4] = CStringGetTextDatum(""); - nulls[5] = true; + values[5] = CStringGetTextDatum(""); + nulls[4] = true; nulls[6] = true; nulls[7] = true; nulls[8] = true; nulls[9] = true; nulls[10] = true; nulls[11] = true; + nulls[12] = true; } tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); diff --git a/src/include/c.h b/src/include/c.h index 0391860..9d7c450 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -708,6 +708,11 @@ typedef NameData *Name; #define STATUS_EOF (-2) #define STATUS_FOUND (1) #define STATUS_WAITING (2) +#define STATE_IDLE (0) +#define STATE_RUNNING (1) +#define STATE_IDLEINTRANSACTION (2) +#define STATE_FASTPATH (3) +#define STATE_IDLEINTRANSACTION_ABRT (4) /* gettext domain name mangling */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 64b7a6a..e576436 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2548,7 +2548,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f DESCR("statistics: number of auto analyzes for a table"); DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 0 f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ )); DESCR("statistics: currently active backend IDs"); -DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ )); +DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ )); DESCR("statistics: information about currently active backends"); DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ )); DESCR("statistics: information about currently active replication"); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 7b2bd4e..e784087 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -632,6 +632,9 @@ typedef struct PgBackendStatus /* Is backend currently waiting on an lmgr lock? */ bool st_waiting; + /* current state integer */ + int st_state; + /* application name; MUST be null-terminated */ char *st_appname; @@ -715,7 +718,7 @@ extern void pgstat_report_recovery_conflict(int reason); extern void pgstat_initialize(void); extern void pgstat_bestart(void); -extern void pgstat_report_activity(const char *cmd_str); +extern void pgstat_report_activity(int state, const char *cmd_str); extern void pgstat_report_appname(const char *appname); extern void pgstat_report_xact_timestamp(TimestampTz tstamp); extern void pgstat_report_waiting(bool waiting);