Index: doc/src/sgml/monitoring.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/monitoring.sgml,v
retrieving revision 1.27
diff -c -r1.27 monitoring.sgml
*** doc/src/sgml/monitoring.sgml	28 Dec 2004 19:08:58 -0000	1.27
--- doc/src/sgml/monitoring.sgml	3 May 2005 07:42:13 -0000
***************
*** 221,228 ****
       <row>
        <entry><structname>pg_stat_activity</></entry>
        <entry>One row per server process, showing process
!       <acronym>ID</>, database, user, current query, and the time at
!       which the current query began execution. The columns that report
        data on the current query are only available if the parameter
        <varname>stats_command_string</varname> has been turned on.
        Furthermore, these columns read as null unless the user examining
--- 221,230 ----
       <row>
        <entry><structname>pg_stat_activity</></entry>
        <entry>One row per server process, showing process
!       <acronym>ID</>, database, user, current query, the time at
!       which the current query began execution, the time at which
!       the current backend was started and the client address.
!       The columns that report
        data on the current query are only available if the parameter
        <varname>stats_command_string</varname> has been turned on.
        Furthermore, these columns read as null unless the user examining
***************
*** 569,574 ****
--- 571,608 ----
       </row>
  
       <row>
+       <entry><literal><function>pg_stat_get_backend_start</function>(<type>integer</type>)</literal></entry>
+       <entry><type>timestamp with time zone</type></entry>
+       <entry>
+        The time at which the given backend process was started
+        (null if the current user is not a superuser nor the same user
+        as that of the session being queried)
+       </entry>
+      </row>
+ 
+      <row>
+       <entry><literal><function>pg_stat_get_backend_client_addr</function>(<type>integer</type>)</literal></entry>
+       <entry><type>inet</type></entry>
+       <entry>
+        The IP adress of the client connected to the given backend. Null
+        if the connection is over a Unix domain socket. (also null if the
+        current user is not a superuser nor the same user as that of the
+        session being queried)
+       </entry>
+      </row>
+ 
+      <row>
+       <entry><literal><function>pg_stat_get_backend_client_port</function>(<type>integer</type>)</literal></entry>
+       <entry><type>integer</type></entry>
+       <entry>
+        The IP port number of the client connected to the given backend.
+        -1 if the connection is over a Unix domain socket. (null if the
+        current user is not a superuser nor the same user as that of the
+        session being queried)
+       </entry>
+      </row>
+ 
+      <row>
        <entry><literal><function>pg_stat_reset</function>()</literal></entry>
        <entry><type>boolean</type></entry>
        <entry>
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.11
diff -c -r1.11 system_views.sql
*** src/backend/catalog/system_views.sql	1 Jan 2005 20:44:14 -0000	1.11
--- src/backend/catalog/system_views.sql	3 May 2005 07:42:13 -0000
***************
*** 237,243 ****
              pg_stat_get_backend_userid(S.backendid) AS usesysid, 
              U.usename AS usename, 
              pg_stat_get_backend_activity(S.backendid) AS current_query, 
!             pg_stat_get_backend_activity_start(S.backendid) AS query_start 
      FROM pg_database D, 
              (SELECT pg_stat_get_backend_idset() AS backendid) AS S, 
              pg_shadow U 
--- 237,246 ----
              pg_stat_get_backend_userid(S.backendid) AS usesysid, 
              U.usename AS usename, 
              pg_stat_get_backend_activity(S.backendid) AS current_query, 
!             pg_stat_get_backend_activity_start(S.backendid) AS query_start,
!             pg_stat_get_backend_start(S.backendid) AS backend_start,
!             pg_stat_get_backend_client_addr(S.backendid) AS backend_client_addr,
!             pg_stat_get_backend_client_port(S.backendid) AS backend_client_port
      FROM pg_database D, 
              (SELECT pg_stat_get_backend_idset() AS backendid) AS S, 
              pg_shadow U 
Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/pgstat.c,v
retrieving revision 1.92
diff -c -r1.92 pgstat.c
*** src/backend/postmaster/pgstat.c	14 Apr 2005 20:32:42 -0000	1.92
--- src/backend/postmaster/pgstat.c	3 May 2005 07:42:14 -0000
***************
*** 1300,1305 ****
--- 1300,1306 ----
  	hdr->m_procpid = MyProcPid;
  	hdr->m_databaseid = MyDatabaseId;
  	hdr->m_userid = GetSessionUserId();
+ 	memcpy(&hdr->m_clientaddr, &MyProcPort->raddr, sizeof(hdr->m_clientaddr));
  }
  
  
***************
*** 2032,2039 ****
--- 2033,2043 ----
  	beentry->databaseid = msg->m_databaseid;
  	beentry->procpid = msg->m_procpid;
  	beentry->userid = msg->m_userid;
+ 	beentry->start_sec = 
+ 		GetCurrentAbsoluteTimeUsec(&beentry->start_usec);
  	beentry->activity_start_sec = 0;
  	beentry->activity_start_usec = 0;
+ 	memcpy(&beentry->clientaddr, &msg->m_clientaddr, sizeof(beentry->clientaddr));
  	MemSet(beentry->activity, 0, PGSTAT_ACTIVITY_SIZE);
  
  	/*
Index: src/backend/utils/adt/network.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/network.c,v
retrieving revision 1.54
diff -c -r1.54 network.c
*** src/backend/utils/adt/network.c	8 Oct 2004 01:10:31 -0000	1.54
--- src/backend/utils/adt/network.c	3 May 2005 07:42:16 -0000
***************
*** 65,71 ****
  }
  
  /* Common input routine */
! static inet *
  network_in(char *src, int type)
  {
  	int			bits;
--- 65,71 ----
  }
  
  /* Common input routine */
! inet *
  network_in(char *src, int type)
  {
  	int			bits;
Index: src/backend/utils/adt/pgstatfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pgstatfuncs.c,v
retrieving revision 1.20
diff -c -r1.20 pgstatfuncs.c
*** src/backend/utils/adt/pgstatfuncs.c	31 Dec 2004 22:01:22 -0000	1.20
--- src/backend/utils/adt/pgstatfuncs.c	3 May 2005 07:42:16 -0000
***************
*** 22,27 ****
--- 22,30 ----
  #include "nodes/execnodes.h"
  #include "pgstat.h"
  #include "utils/hsearch.h"
+ #include "utils/inet.h"
+ #include "utils/builtins.h"
+ #include "libpq/ip.h"
  
  /* bogus ... these externs should be in a header file */
  extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
***************
*** 41,46 ****
--- 44,52 ----
  extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
+ extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
+ extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
+ extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
  
  extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
***************
*** 357,362 ****
--- 363,477 ----
  	PG_RETURN_TIMESTAMPTZ(result);
  }
  
+ Datum
+ pg_stat_get_backend_start(PG_FUNCTION_ARGS)
+ {
+ 	PgStat_StatBeEntry *beentry;
+ 	int32       beid;
+ 	AbsoluteTime sec;
+ 	int         usec;
+ 	TimestampTz result;
+ 
+ 	beid = PG_GETARG_INT32(0);
+ 
+ 	if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
+ 		PG_RETURN_NULL();
+ 
+ 	if (!superuser() && beentry->userid != GetUserId())
+ 		PG_RETURN_NULL();
+ 
+ 	sec = beentry->start_sec;
+ 	usec = beentry->start_usec;
+ 
+ 	if (sec == 0 && usec == 0)
+ 		PG_RETURN_NULL();
+ 
+ 	result = AbsoluteTimeUsecToTimestampTz(sec, usec);
+ 
+ 	PG_RETURN_TIMESTAMPTZ(result);
+ }
+ 
+ 
+ Datum
+ pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
+ {
+ 	PgStat_StatBeEntry *beentry;
+ 	int32       beid;
+ 	char		remote_host[NI_MAXHOST];
+ 	int			ret;
+ 
+ 	beid = PG_GETARG_INT32(0);
+ 
+ 	if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
+ 		PG_RETURN_NULL();
+ 
+ 	if (!superuser() && beentry->userid != GetUserId())
+ 		PG_RETURN_NULL();
+ 
+ 	switch (beentry->clientaddr.addr.ss_family)
+ 	{
+ 		case AF_INET:
+ #ifdef HAVE_IPV6
+ 		case AF_INET6:
+ #endif
+ 			break;
+ 		default:
+ 			PG_RETURN_NULL();
+ 	}
+ 
+ 	remote_host[0] = '\0';
+ 
+ 	ret = getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
+ 						  remote_host, sizeof(remote_host),
+ 						  NULL, 0,
+ 						  NI_NUMERICHOST | NI_NUMERICSERV);
+ 	if (ret)
+ 		PG_RETURN_NULL();
+ 
+ 	PG_RETURN_INET_P(network_in(remote_host, 0));
+ }
+ 
+ Datum
+ pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
+ {
+ 	PgStat_StatBeEntry *beentry;
+ 	int32       beid;
+ 	char		remote_port[NI_MAXSERV];
+ 	int			ret;
+ 
+ 	beid = PG_GETARG_INT32(0);
+ 
+ 	if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
+ 		PG_RETURN_NULL();
+ 
+ 	if (!superuser() && beentry->userid != GetUserId())
+ 		PG_RETURN_NULL();
+ 
+ 	switch (beentry->clientaddr.addr.ss_family)
+ 	{
+ 		case AF_INET:
+ #ifdef HAVE_IPV6
+ 		case AF_INET6:
+ #endif
+ 			break;
+ 		case AF_UNIX:
+ 			PG_RETURN_INT32(-1);
+ 		default:
+ 			PG_RETURN_NULL();
+ 	}
+ 
+ 	remote_port[0] = '\0';
+ 
+ 	ret = getnameinfo_all(&beentry->clientaddr.addr,beentry->clientaddr.salen,
+ 						  NULL, 0,
+ 						  remote_port, sizeof(remote_port),
+ 						  NI_NUMERICHOST | NI_NUMERICSERV);
+ 	if (ret)
+ 		PG_RETURN_NULL();
+ 
+ 	PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
+ }
+ 
  
  Datum
  pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
Index: src/include/pgstat.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/pgstat.h,v
retrieving revision 1.27
diff -c -r1.27 pgstat.h
*** src/include/pgstat.h	1 Jan 2005 05:43:08 -0000	1.27
--- src/include/pgstat.h	3 May 2005 07:42:16 -0000
***************
*** 14,20 ****
  #include "utils/hsearch.h"
  #include "utils/nabstime.h"
  #include "utils/rel.h"
! 
  
  /* ----------
   * The types of backend/postmaster -> collector messages
--- 14,20 ----
  #include "utils/hsearch.h"
  #include "utils/nabstime.h"
  #include "utils/rel.h"
! #include "libpq/pqcomm.h"
  
  /* ----------
   * The types of backend/postmaster -> collector messages
***************
*** 54,59 ****
--- 54,60 ----
  	int			m_procpid;
  	Oid			m_databaseid;
  	AclId		m_userid;
+ 	SockAddr    m_clientaddr;
  } PgStat_MsgHdr;
  
  /* ----------
***************
*** 231,238 ****
--- 232,242 ----
  	Oid			databaseid;
  	Oid			userid;
  	int			procpid;
+ 	AbsoluteTime start_sec;
+ 	int         start_usec;
  	AbsoluteTime activity_start_sec;
  	int			activity_start_usec;
+ 	SockAddr    clientaddr;
  	char		activity[PGSTAT_ACTIVITY_SIZE];
  } PgStat_StatBeEntry;
  
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.360
diff -c -r1.360 pg_proc.h
*** src/include/catalog/pg_proc.h	30 Apr 2005 20:31:38 -0000	1.360
--- src/include/catalog/pg_proc.h	3 May 2005 07:42:17 -0000
***************
*** 2822,2827 ****
--- 2822,2833 ----
  DESCR("Statistics: Current query of backend");
  DATA(insert OID = 2094 (  pg_stat_get_backend_activity_start PGNSP PGUID 12 f f t f s 1 1184 "23" _null_ _null_ _null_  pg_stat_get_backend_activity_start - _null_));
  DESCR("Statistics: Start time for current query of backend");
+ DATA(insert OID = 1391 ( pg_stat_get_backend_start PGNSP PGUID 12 f f t f s 1 1184 "23" _null_ _null_ _null_ pg_stat_get_backend_start - _null_));
+ DESCR("Statistics: Start time for current backend session");
+ DATA(insert OID = 1392 ( pg_stat_get_backend_client_addr PGNSP PGUID 12 f f t f s 1 869 "23" _null_ _null_ _null_ pg_stat_get_backend_client_addr - _null_));
+ DESCR("Statistics: Address of client connected to backend");
+ DATA(insert OID = 1393 ( pg_stat_get_backend_client_port PGNSP PGUID 12 f f t f s 1 23 "23" _null_ _null_ _null_ pg_stat_get_backend_client_port - _null_));
+ DESCR("Statistics: Port of client connected to backend");
  DATA(insert OID = 1941 (  pg_stat_get_db_numbackends	PGNSP PGUID 12 f f t f s 1 23 "26" _null_ _null_ _null_	pg_stat_get_db_numbackends - _null_ ));
  DESCR("Statistics: Number of backends in database");
  DATA(insert OID = 1942 (  pg_stat_get_db_xact_commit	PGNSP PGUID 12 f f t f s 1 20 "26" _null_ _null_ _null_	pg_stat_get_db_xact_commit - _null_ ));
Index: src/include/utils/inet.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/inet.h,v
retrieving revision 1.20
diff -c -r1.20 inet.h
*** src/include/utils/inet.h	31 Dec 2004 22:03:46 -0000	1.20
--- src/include/utils/inet.h	3 May 2005 07:42:17 -0000
***************
*** 60,65 ****
--- 60,67 ----
  	unsigned char f;
  } macaddr;
  
+ extern inet *network_in(char *src, int type);
+ 
  /*
   * fmgr interface macros
   */
