diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql new file mode 100644 index 2253ca8..ca34aa8 *** a/src/backend/catalog/system_views.sql --- b/src/backend/catalog/system_views.sql *************** CREATE VIEW pg_stat_activity AS *** 531,537 **** S.xact_start, S.query_start, S.waiting, ! S.current_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; --- 531,538 ---- S.xact_start, S.query_start, S.waiting, ! 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 new file mode 100644 index 3b71232..c2d8080 *** a/src/backend/postmaster/autovacuum.c --- b/src/backend/postmaster/autovacuum.c *************** autovac_report_activity(autovac_table *t *** 2751,2757 **** /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); ! pgstat_report_activity(activity); } /* --- 2751,2757 ---- /* Set statement_timestamp() to current time for pg_stat_activity */ SetCurrentStatementStartTimestamp(); ! pgstat_report_activity(STATE_RUNNING,activity); } /* diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c new file mode 100644 index 24582e3..19812ba *** a/src/backend/postmaster/pgstat.c --- b/src/backend/postmaster/pgstat.c *************** pgstat_bestart(void) *** 2416,2421 **** --- 2416,2422 ---- 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 */ *************** pgstat_beshutdown_hook(int code, Datum a *** 2479,2485 **** * ---------- */ void ! pgstat_report_activity(const char *cmd_str) { volatile PgBackendStatus *beentry = MyBEEntry; TimestampTz start_timestamp; --- 2480,2486 ---- * ---------- */ void ! pgstat_report_activity(int state, const char *cmd_str) { volatile PgBackendStatus *beentry = MyBEEntry; TimestampTz start_timestamp; *************** pgstat_report_activity(const char *cmd_s *** 2496,2514 **** */ 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 * ensure the compiler doesn't try to get cute. */ ! 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_changecount++; Assert((beentry->st_changecount & 1) == 0); --- 2497,2519 ---- */ start_timestamp = GetCurrentStatementStartTimestamp(); /* * Update my status entry, following the protocol of bumping * st_changecount before and after. We use a volatile pointer here to * ensure the compiler doesn't try to get cute. */ ! beentry->st_changecount++; ! beentry->st_activity_start_timestamp = start_timestamp; ! 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 new file mode 100644 index 976a832..2b0c6cc *** a/src/backend/tcop/postgres.c --- b/src/backend/tcop/postgres.c *************** exec_simple_query(const char *query_stri *** 809,815 **** */ debug_query_string = query_string; ! pgstat_report_activity(query_string); TRACE_POSTGRESQL_QUERY_START(query_string); --- 809,815 ---- */ debug_query_string = query_string; ! pgstat_report_activity(STATE_RUNNING,query_string); TRACE_POSTGRESQL_QUERY_START(query_string); *************** exec_parse_message(const char *query_str *** 1128,1134 **** */ debug_query_string = query_string; ! pgstat_report_activity(query_string); set_ps_display("PARSE", false); --- 1128,1134 ---- */ debug_query_string = query_string; ! pgstat_report_activity(STATE_RUNNING,query_string); set_ps_display("PARSE", false); *************** exec_bind_message(StringInfo input_messa *** 1423,1429 **** */ debug_query_string = psrc->query_string; ! pgstat_report_activity(psrc->query_string); set_ps_display("BIND", false); --- 1423,1429 ---- */ debug_query_string = psrc->query_string; ! pgstat_report_activity(STATE_RUNNING,psrc->query_string); set_ps_display("BIND", false); *************** exec_execute_message(const char *portal_ *** 1826,1832 **** */ debug_query_string = sourceText; ! pgstat_report_activity(sourceText); set_ps_display(portal->commandTag, false); --- 1826,1832 ---- */ debug_query_string = sourceText; ! pgstat_report_activity(STATE_RUNNING,sourceText); set_ps_display(portal->commandTag, false); *************** PostgresMain(int argc, char *argv[], con *** 3789,3800 **** if (IsAbortedTransactionBlockState()) { set_ps_display("idle in transaction (aborted)", false); ! pgstat_report_activity(" in transaction (aborted)"); } else if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction", false); ! pgstat_report_activity(" in transaction"); } else { --- 3789,3800 ---- if (IsAbortedTransactionBlockState()) { set_ps_display("idle in transaction (aborted)", false); ! pgstat_report_activity(STATE_IDLEINTRANSACTION_ABRT,NULL); } else if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction", false); ! pgstat_report_activity(STATE_IDLEINTRANSACTION,NULL); } else { *************** PostgresMain(int argc, char *argv[], con *** 3802,3808 **** pgstat_report_stat(false); set_ps_display("idle", false); ! pgstat_report_activity(""); } ReadyForQuery(whereToSendOutput); --- 3802,3808 ---- pgstat_report_stat(false); set_ps_display("idle", false); ! pgstat_report_activity(STATE_IDLE,NULL); } ReadyForQuery(whereToSendOutput); *************** PostgresMain(int argc, char *argv[], con *** 3922,3928 **** SetCurrentStatementStartTimestamp(); /* Report query to various monitoring facilities. */ ! pgstat_report_activity(" function call"); set_ps_display("", false); /* start an xact for this function invocation */ --- 3922,3928 ---- SetCurrentStatementStartTimestamp(); /* Report query to various monitoring facilities. */ ! 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 new file mode 100644 index 7792b33..4df4f77 *** a/src/backend/utils/adt/pgstatfuncs.c --- b/src/backend/utils/adt/pgstatfuncs.c *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 507,513 **** oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); ! tupdesc = CreateTemplateTupleDesc(12, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); /* This should have been called 'pid'; can't change it. 2011-06-11 */ --- 507,513 ---- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); ! 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 */ *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 517,537 **** OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting", BOOLOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", INETOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port", INT4OID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); --- 517,539 ---- OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query", ! TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting", BOOLOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start", TIMESTAMPTZOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_addr", INETOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_hostname", TEXTOID, -1, 0); ! TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_port", INT4OID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 584,591 **** if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ ! Datum values[12]; ! bool nulls[12]; HeapTuple tuple; PgBackendStatus *beentry; SockAddr zero_clientaddr; --- 586,593 ---- if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ ! Datum values[13]; ! bool nulls[13]; HeapTuple tuple; PgBackendStatus *beentry; SockAddr zero_clientaddr; *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 610,617 **** for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++) nulls[i] = true; ! nulls[4] = false; ! values[4] = CStringGetTextDatum(""); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); --- 612,619 ---- for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++) nulls[i] = true; ! nulls[5] = false; ! values[5] = CStringGetTextDatum(""); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 629,668 **** /* Values only available to same user or superuser */ if (superuser() || beentry->st_userid == GetUserId()) { if (*(beentry->st_activity) == '\0') { ! values[4] = CStringGetTextDatum(""); } else { ! values[4] = CStringGetTextDatum(beentry->st_activity); } ! values[5] = BoolGetDatum(beentry->st_waiting); if (beentry->st_xact_start_timestamp != 0) ! values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp); else ! nulls[6] = true; if (beentry->st_activity_start_timestamp != 0) ! values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp); else ! nulls[7] = true; if (beentry->st_proc_start_timestamp != 0) ! values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp); else ! nulls[8] = 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; } else { --- 631,698 ---- /* 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("idle"); + break; + case STATE_RUNNING: + values[4] = CStringGetTextDatum("active"); + break; + case STATE_IDLEINTRANSACTION: + values[4] = CStringGetTextDatum("idle in transaction"); + break; + case STATE_FASTPATH: + values[4] = CStringGetTextDatum("fastpath function call"); + break; + case STATE_IDLEINTRANSACTION_ABRT: + values[4] = CStringGetTextDatum("idle in transaction (aborted)"); + break; + } + } if (*(beentry->st_activity) == '\0') { ! ! values[5] = CStringGetTextDatum(""); } else { ! ! values[5] = CStringGetTextDatum(beentry->st_activity); } ! values[6] = BoolGetDatum(beentry->st_waiting); if (beentry->st_xact_start_timestamp != 0) ! values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp); else ! nulls[7] = true; if (beentry->st_activity_start_timestamp != 0) ! values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp); else ! nulls[8] = true; if (beentry->st_proc_start_timestamp != 0) ! values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp); else ! 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[10] = true; nulls[11] = true; + nulls[12] = true; } else { *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 686,704 **** if (ret == 0) { clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); ! values[9] = DirectFunctionCall1(inet_in, CStringGetDatum(remote_host)); if (beentry->st_clienthostname) ! values[10] = CStringGetTextDatum(beentry->st_clienthostname); else ! nulls[10] = true; ! values[11] = Int32GetDatum(atoi(remote_port)); } else { - nulls[9] = true; nulls[10] = true; nulls[11] = true; } } else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) --- 716,734 ---- if (ret == 0) { clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); ! values[10] = DirectFunctionCall1(inet_in, CStringGetDatum(remote_host)); if (beentry->st_clienthostname) ! values[11] = CStringGetTextDatum(beentry->st_clienthostname); else ! nulls[11] = true; ! values[12] = Int32GetDatum(atoi(remote_port)); } else { nulls[10] = true; nulls[11] = true; + nulls[12] = true; } } else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 709,738 **** * connections we have no permissions to view, or with * errors. */ - nulls[9] = true; nulls[10] = true; ! values[11] = DatumGetInt32(-1); } else { /* Unknown address type, should never happen */ - nulls[9] = true; nulls[10] = true; nulls[11] = true; } } } else { /* No permissions to view data about this session */ ! values[4] = CStringGetTextDatum(""); ! nulls[5] = true; nulls[6] = true; nulls[7] = true; nulls[8] = true; nulls[9] = true; nulls[10] = true; nulls[11] = true; } tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); --- 739,769 ---- * connections we have no permissions to view, or with * errors. */ nulls[10] = true; ! nulls[11] = true; ! values[12] = DatumGetInt32(-1); } else { /* Unknown address type, should never happen */ nulls[10] = true; nulls[11] = true; + nulls[12] = true; } } } else { /* No permissions to view data about this session */ ! 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 new file mode 100644 index 0391860..9d7c450 *** a/src/include/c.h --- b/src/include/c.h *************** typedef NameData *Name; *** 708,713 **** --- 708,718 ---- #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 new file mode 100644 index 64b7a6a..e576436 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DATA(insert OID = 3057 ( pg_stat_get_aut *** 2548,2554 **** 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_ )); 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"); --- 2548,2554 ---- 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,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 new file mode 100644 index 7b2bd4e..e784087 *** a/src/include/pgstat.h --- b/src/include/pgstat.h *************** typedef struct PgBackendStatus *** 632,637 **** --- 632,640 ---- /* 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; *************** extern void pgstat_report_recovery_confl *** 715,721 **** extern void pgstat_initialize(void); extern void pgstat_bestart(void); ! extern void pgstat_report_activity(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); --- 718,724 ---- extern void pgstat_initialize(void); extern void pgstat_bestart(void); ! 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);