pg_stat_activity_state_query.v2.patch

application/octet-stream

Filename: pg_stat_activity_state_query.v2.patch
Type: application/octet-stream
Part: 0
Message: Re: IDLE in transaction introspection

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v2
File+
src/backend/catalog/system_views.sql 0 0
src/backend/postmaster/autovacuum.c 0 0
src/backend/postmaster/pgstat.c 0 0
src/backend/tcop/postgres.c 0 0
src/backend/utils/adt/pgstatfuncs.c 0 0
src/include/catalog/pg_proc.h 0 0
src/include/c.h 0 0
src/include/pgstat.h 0 0
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("<IDLE> in transaction (aborted)");
  			}
  			else if (IsTransactionOrTransactionBlock())
  			{
  				set_ps_display("idle in transaction", false);
! 				pgstat_report_activity("<IDLE> 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("<IDLE>");
  			}
  
  			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("<FASTPATH> function call");
  				set_ps_display("<FASTPATH>", 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("<FASTPATH>", 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("<backend information not available>");
  
  			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("<backend information not available>");
  
  			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("<command string not enabled>");
  			}
  			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("<command string not enabled>");
  			}
  			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("<insufficient privilege>");
! 			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("<insufficient privilege>");
! 			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);