diff --git a/contrib/test_decoding/expected/permissions.out b/contrib/test_decoding/expected/permissions.out
new file mode 100644
index 212fd1d..538ebdc
*** a/contrib/test_decoding/expected/permissions.out
--- b/contrib/test_decoding/expected/permissions.out
*************** SET synchronous_commit = on;
*** 4,9 ****
--- 4,16 ----
  CREATE ROLE lr_normal;
  CREATE ROLE lr_superuser SUPERUSER;
  CREATE ROLE lr_replication REPLICATION;
+ GRANT EXECUTE ON FUNCTION pg_create_physical_replication_slot(name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_drop_replication_slot(name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_create_logical_replication_slot(name,name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_get_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_peek_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_get_binary_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_peek_binary_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
  CREATE TABLE lr_test(data text);
  -- superuser can control replication
  SET ROLE lr_superuser;
*************** RESET ROLE;
*** 54,66 ****
  -- plain user *can't* can control replication
  SET ROLE lr_normal;
  SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
! ERROR:  must be superuser or replication role to use replication slots
  INSERT INTO lr_test VALUES('lr_superuser_init');
  ERROR:  permission denied for relation lr_test
  SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
! ERROR:  must be superuser or replication role to use replication slots
  SELECT pg_drop_replication_slot('regression_slot');
! ERROR:  must be superuser or replication role to use replication slots
  RESET ROLE;
  -- replication users can drop superuser created slots
  SET ROLE lr_superuser;
--- 61,73 ----
  -- plain user *can't* can control replication
  SET ROLE lr_normal;
  SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
! ERROR:  permission denied for function pg_create_logical_replication_slot
  INSERT INTO lr_test VALUES('lr_superuser_init');
  ERROR:  permission denied for relation lr_test
  SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
! ERROR:  permission denied for function pg_logical_slot_get_changes
  SELECT pg_drop_replication_slot('regression_slot');
! ERROR:  permission denied for function pg_drop_replication_slot
  RESET ROLE;
  -- replication users can drop superuser created slots
  SET ROLE lr_superuser;
*************** SELECT 'init' FROM pg_create_logical_rep
*** 90,96 ****
  RESET ROLE;
  SET ROLE lr_normal;
  SELECT pg_drop_replication_slot('regression_slot');
! ERROR:  must be superuser or replication role to use replication slots
  RESET ROLE;
  -- all users can see existing slots
  SET ROLE lr_superuser;
--- 97,103 ----
  RESET ROLE;
  SET ROLE lr_normal;
  SELECT pg_drop_replication_slot('regression_slot');
! ERROR:  permission denied for function pg_drop_replication_slot
  RESET ROLE;
  -- all users can see existing slots
  SET ROLE lr_superuser;
*************** SELECT pg_drop_replication_slot('regress
*** 126,130 ****
--- 133,139 ----
  
  DROP ROLE lr_normal;
  DROP ROLE lr_superuser;
+ SET client_min_messages TO 'warning';
+ DROP OWNED BY lr_replication CASCADE;
  DROP ROLE lr_replication;
  DROP TABLE lr_test;
diff --git a/contrib/test_decoding/sql/permissions.sql b/contrib/test_decoding/sql/permissions.sql
new file mode 100644
index 8680c55..2c02d14
*** a/contrib/test_decoding/sql/permissions.sql
--- b/contrib/test_decoding/sql/permissions.sql
*************** SET synchronous_commit = on;
*** 5,10 ****
--- 5,17 ----
  CREATE ROLE lr_normal;
  CREATE ROLE lr_superuser SUPERUSER;
  CREATE ROLE lr_replication REPLICATION;
+ GRANT EXECUTE ON FUNCTION pg_create_physical_replication_slot(name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_drop_replication_slot(name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_create_logical_replication_slot(name,name) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_get_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_peek_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_get_binary_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
+ GRANT EXECUTE ON FUNCTION pg_logical_slot_peek_binary_changes(name, pg_lsn, int, VARIADIC options text[]) TO lr_replication;
  CREATE TABLE lr_test(data text);
  
  -- superuser can control replication
*************** SELECT pg_drop_replication_slot('regress
*** 65,69 ****
--- 72,78 ----
  
  DROP ROLE lr_normal;
  DROP ROLE lr_superuser;
+ SET client_min_messages TO 'warning';
+ DROP OWNED BY lr_replication CASCADE;
  DROP ROLE lr_replication;
  DROP TABLE lr_test;
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
new file mode 100644
index 2179bf7..c9d9f3d
*** a/src/backend/access/transam/xlogfuncs.c
--- b/src/backend/access/transam/xlogfuncs.c
*************** pg_start_backup(PG_FUNCTION_ARGS)
*** 54,64 ****
  
  	backupidstr = text_to_cstring(backupid);
  
- 	if (!superuser() && !has_rolreplication(GetUserId()))
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 		   errmsg("must be superuser or replication role to run a backup")));
- 
  	startpoint = do_pg_start_backup(backupidstr, fast, NULL, NULL);
  
  	PG_RETURN_LSN(startpoint);
--- 54,59 ----
*************** pg_stop_backup(PG_FUNCTION_ARGS)
*** 82,92 ****
  {
  	XLogRecPtr	stoppoint;
  
- 	if (!superuser() && !has_rolreplication(GetUserId()))
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 		 (errmsg("must be superuser or replication role to run a backup"))));
- 
  	stoppoint = do_pg_stop_backup(NULL, true, NULL);
  
  	PG_RETURN_LSN(stoppoint);
--- 77,82 ----
*************** pg_switch_xlog(PG_FUNCTION_ARGS)
*** 100,110 ****
  {
  	XLogRecPtr	switchpoint;
  
- 	if (!superuser())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 			 (errmsg("must be superuser to switch transaction log files"))));
- 
  	if (RecoveryInProgress())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
--- 90,95 ----
*************** pg_create_restore_point(PG_FUNCTION_ARGS
*** 129,139 ****
  	char	   *restore_name_str;
  	XLogRecPtr	restorepoint;
  
- 	if (!superuser())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser to create a restore point"))));
- 
  	if (RecoveryInProgress())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
--- 114,119 ----
*************** pg_xlogfile_name(PG_FUNCTION_ARGS)
*** 338,348 ****
  Datum
  pg_xlog_replay_pause(PG_FUNCTION_ARGS)
  {
- 	if (!superuser())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser to control recovery"))));
- 
  	if (!RecoveryInProgress())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
--- 318,323 ----
*************** pg_xlog_replay_pause(PG_FUNCTION_ARGS)
*** 360,370 ****
  Datum
  pg_xlog_replay_resume(PG_FUNCTION_ARGS)
  {
- 	if (!superuser())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser to control recovery"))));
- 
  	if (!RecoveryInProgress())
  		ereport(ERROR,
  				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
--- 335,340 ----
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
new file mode 100644
index 2800f73..a6f9674
*** a/src/backend/catalog/system_views.sql
--- b/src/backend/catalog/system_views.sql
*************** CREATE VIEW pg_stat_activity AS
*** 623,628 ****
--- 623,652 ----
      WHERE S.datid = D.oid AND
              S.usesysid = U.oid;
  
+ CREATE VIEW pg_stat_activity_all AS
+     SELECT
+             S.datid AS datid,
+             D.datname AS datname,
+             S.pid,
+             S.usesysid,
+             U.rolname AS usename,
+             S.application_name,
+             S.client_addr,
+             S.client_hostname,
+             S.client_port,
+             S.backend_start,
+             S.xact_start,
+             S.query_start,
+             S.state_change,
+             S.waiting,
+             S.state,
+             S.backend_xid,
+             s.backend_xmin,
+             S.query
+     FROM pg_database D, pg_stat_get_activity_all(NULL) AS S, pg_authid U
+     WHERE S.datid = D.oid AND
+             S.usesysid = U.oid;
+ 
  CREATE VIEW pg_stat_replication AS
      SELECT
              S.pid,
*************** CREATE VIEW pg_stat_replication AS
*** 646,651 ****
--- 670,698 ----
      WHERE S.usesysid = U.oid AND
              S.pid = W.pid;
  
+ CREATE VIEW pg_stat_replication_all AS
+     SELECT
+             S.pid,
+             S.usesysid,
+             U.rolname AS usename,
+             S.application_name,
+             S.client_addr,
+             S.client_hostname,
+             S.client_port,
+             S.backend_start,
+             S.backend_xmin,
+             W.state,
+             W.sent_location,
+             W.write_location,
+             W.flush_location,
+             W.replay_location,
+             W.sync_priority,
+             W.sync_state
+     FROM pg_stat_get_activity_all(NULL) AS S, pg_authid U,
+             pg_stat_get_wal_senders_all() AS W
+     WHERE S.usesysid = U.oid AND
+             S.pid = W.pid;
+ 
  CREATE VIEW pg_replication_slots AS
      SELECT
              L.slot_name,
*************** RETURNS interval
*** 897,899 ****
--- 944,967 ----
  LANGUAGE INTERNAL
  STRICT IMMUTABLE
  AS 'make_interval';
+ 
+ -- Revoke privileges for functions that should not be available to
+ -- all users.  Administrators are allowed to change this later, if
+ -- they wish.
+ REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_switch_xlog() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_rotate_logfile() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_signal_backend(int, int) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_stat_get_activity_all(integer) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_stat_get_wal_senders_all() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_xlog_replay_pause() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_xlog_replay_resume() FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_create_physical_replication_slot(name) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_create_logical_replication_slot(name, name) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_drop_replication_slot(name) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_logical_slot_get_changes(name, pg_lsn, int, VARIADIC options text[]) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_logical_slot_peek_changes(name, pg_lsn, int, VARIADIC options text[]) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_logical_slot_get_binary_changes(name, pg_lsn, int, VARIADIC options text[]) FROM public;
+ REVOKE EXECUTE ON FUNCTION pg_logical_slot_peek_binary_changes(name, pg_lsn, int, VARIADIC options text[]) FROM public;
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
new file mode 100644
index 3be5263..2995bfa
*** a/src/backend/replication/logical/logicalfuncs.c
--- b/src/backend/replication/logical/logicalfuncs.c
*************** XLogRead(char *buf, TimeLineID tli, XLog
*** 202,216 ****
  	}
  }
  
- static void
- check_permissions(void)
- {
- 	if (!superuser() && !has_rolreplication(GetUserId()))
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser or replication role to use replication slots"))));
- }
- 
  /*
   * read_page callback for logical decoding contexts.
   *
--- 202,207 ----
*************** pg_logical_slot_get_changes_guts(Functio
*** 324,331 ****
  	if (get_call_result_type(fcinfo, NULL, &p->tupdesc) != TYPEFUNC_COMPOSITE)
  		elog(ERROR, "return type must be a row type");
  
- 	check_permissions();
- 
  	CheckLogicalDecodingRequirements();
  
  	arr = PG_GETARG_ARRAYTYPE_P(3);
--- 315,320 ----
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
new file mode 100644
index f31925d..c879977
*** a/src/backend/replication/slotfuncs.c
--- b/src/backend/replication/slotfuncs.c
***************
*** 23,37 ****
  #include "utils/builtins.h"
  #include "utils/pg_lsn.h"
  
- static void
- check_permissions(void)
- {
- 	if (!superuser() && !has_rolreplication(GetUserId()))
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser or replication role to use replication slots"))));
- }
- 
  /*
   * SQL function for creating a new physical (streaming replication)
   * replication slot.
--- 23,28 ----
*************** pg_create_physical_replication_slot(PG_F
*** 51,58 ****
  	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  		elog(ERROR, "return type must be a row type");
  
- 	check_permissions();
- 
  	CheckSlotRequirements();
  
  	/* acquire replication slot, this will check for conflicting names */
--- 42,47 ----
*************** pg_create_logical_replication_slot(PG_FU
*** 94,101 ****
  	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  		elog(ERROR, "return type must be a row type");
  
- 	check_permissions();
- 
  	CheckLogicalDecodingRequirements();
  
  	/*
--- 83,88 ----
*************** pg_drop_replication_slot(PG_FUNCTION_ARG
*** 143,150 ****
  {
  	Name		name = PG_GETARG_NAME(0);
  
- 	check_permissions();
- 
  	CheckSlotRequirements();
  
  	ReplicationSlotDrop(NameStr(*name));
--- 130,135 ----
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
new file mode 100644
index da9ee7b..67472db
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
*************** static XLogRecPtr WalSndWaitForWal(XLogR
*** 217,222 ****
--- 217,223 ----
  
  static void XLogRead(char *buf, XLogRecPtr startptr, Size count);
  
+ static void populate_pg_stat_get_wal_senders(TupleDesc tupdesc, Tuplestorestate *tupstore, bool filter);
  
  /* Initialize walsender process before entering the main command loop */
  void
*************** WalSndGetStateString(WalSndState state)
*** 2717,2738 ****
  	return "UNKNOWN";
  }
  
  
  /*
   * Returns activity of walsenders, including pids and xlog locations sent to
!  * standby servers.
   */
  Datum
  pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
  {
- #define PG_STAT_GET_WAL_SENDERS_COLS	8
  	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
  	TupleDesc	tupdesc;
  	Tuplestorestate *tupstore;
  	MemoryContext per_query_ctx;
  	MemoryContext oldcontext;
- 	WalSnd	   *sync_standby;
- 	int			i;
  
  	/* check to see if caller supports us returning a tuplestore */
  	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
--- 2718,2738 ----
  	return "UNKNOWN";
  }
  
+ #define PG_STAT_GET_WAL_SENDERS_COLS	8
  
  /*
   * Returns activity of walsenders, including pids and xlog locations sent to
!  * standby servers.  Note that this version filters out the results unless the
!  * caller is a superuser.
   */
  Datum
  pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
  {
  	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
  	TupleDesc	tupdesc;
  	Tuplestorestate *tupstore;
  	MemoryContext per_query_ctx;
  	MemoryContext oldcontext;
  
  	/* check to see if caller supports us returning a tuplestore */
  	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
*************** pg_stat_get_wal_senders(PG_FUNCTION_ARGS
*** 2760,2765 ****
--- 2760,2832 ----
  	MemoryContextSwitchTo(oldcontext);
  
  	/*
+ 	 * Populate the tuplestore.
+ 	 *
+ 	 * For non-superusers, we ask that the results be filtered.
+ 	 */
+ 	populate_pg_stat_get_wal_senders(tupdesc, tupstore, !superuser());
+ 
+ 	/* clean up and return the tuplestore */
+ 	tuplestore_donestoring(tupstore);
+ 
+ 	return (Datum) 0;
+ }
+ 
+ /*
+  * Returns activity of walsenders, including pids and xlog locations sent to
+  * standby servers.  Note that this version does NOT filter out the results,
+  * therefore the permissions must be managed at the GRANT level.
+  */
+ Datum
+ pg_stat_get_wal_senders_all(PG_FUNCTION_ARGS)
+ {
+ 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ 	TupleDesc	tupdesc;
+ 	Tuplestorestate *tupstore;
+ 	MemoryContext per_query_ctx;
+ 	MemoryContext oldcontext;
+ 
+ 	/* check to see if caller supports us returning a tuplestore */
+ 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("set-valued function called in context that cannot accept a set")));
+ 	if (!(rsinfo->allowedModes & SFRM_Materialize))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("materialize mode required, but it is not " \
+ 						"allowed in this context")));
+ 
+ 	/* Build a tuple descriptor for our result type */
+ 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ 		elog(ERROR, "return type must be a row type");
+ 
+ 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+ 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
+ 
+ 	tupstore = tuplestore_begin_heap(true, false, work_mem);
+ 	rsinfo->returnMode = SFRM_Materialize;
+ 	rsinfo->setResult = tupstore;
+ 	rsinfo->setDesc = tupdesc;
+ 
+ 	MemoryContextSwitchTo(oldcontext);
+ 
+ 	/* Populate the tuplestore */
+ 	populate_pg_stat_get_wal_senders(tupdesc, tupstore, false);
+ 
+ 	/* clean up and return the tuplestore */
+ 	tuplestore_donestoring(tupstore);
+ 
+ 	return (Datum) 0;
+ }
+ 
+ static void
+ populate_pg_stat_get_wal_senders(TupleDesc tupdesc, Tuplestorestate *tupstore, bool filter)
+ {
+ 	WalSnd	   *sync_standby;
+ 	int			i;
+ 
+ 	/*
  	 * Get the currently active synchronous standby.
  	 */
  	LWLockAcquire(SyncRepLock, LW_SHARED);
*************** pg_stat_get_wal_senders(PG_FUNCTION_ARGS
*** 2794,2804 ****
  		memset(nulls, 0, sizeof(nulls));
  		values[0] = Int32GetDatum(walsnd->pid);
  
! 		if (!superuser())
  		{
  			/*
! 			 * Only superusers can see details. Other users only get the pid
! 			 * value to know it's a walsender, but no details.
  			 */
  			MemSet(&nulls[1], true, PG_STAT_GET_WAL_SENDERS_COLS - 1);
  		}
--- 2861,2871 ----
  		memset(nulls, 0, sizeof(nulls));
  		values[0] = Int32GetDatum(walsnd->pid);
  
! 		if (filter)
  		{
  			/*
! 			 * When asked to filter record results, set all the rest of the
! 			 * columns to NULL.
  			 */
  			MemSet(&nulls[1], true, PG_STAT_GET_WAL_SENDERS_COLS - 1);
  		}
*************** pg_stat_get_wal_senders(PG_FUNCTION_ARGS
*** 2843,2852 ****
  		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
  	}
  
! 	/* clean up and return the tuplestore */
! 	tuplestore_donestoring(tupstore);
! 
! 	return (Datum) 0;
  }
  
  /*
--- 2910,2916 ----
  		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
  	}
  
! 	return;
  }
  
  /*
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
new file mode 100644
index 61d609f..0204da6
*** a/src/backend/utils/adt/misc.c
--- b/src/backend/utils/adt/misc.c
*************** current_query(PG_FUNCTION_ARGS)
*** 76,86 ****
  }
  
  /*
!  * Send a signal to another backend.
   *
!  * The signal is delivered if the user is either a superuser or the same
!  * role as the backend being signaled. For "dangerous" signals, an explicit
!  * check for superuser needs to be done prior to calling this function.
   *
   * Returns 0 on success, 1 on general failure, 2 on normal permission error
   * and 3 if the caller needs to be a superuser.
--- 76,94 ----
  }
  
  /*
!  * Internal helper function for sending a signal to another backend.
   *
!  * The signal is delivered if the user is a superuser.  If the other backend
!  * is owned by a superuser role, then the calling user must be a superuser.
!  *
!  * When perm_check is passed in as true, then the user must be a member of
!  * the role which owns the backend being signaled.  For "dangerous" signals,
!  * an explicit check for superuser needs to be done prior to calling this
!  * function.
!  *
!  * When perm_check is passwd in as false, then no check of role membership is
!  * performed as the GRANT system is expected to have been used to manage access
!  * to calling the function which called us.
   *
   * Returns 0 on success, 1 on general failure, 2 on normal permission error
   * and 3 if the caller needs to be a superuser.
*************** current_query(PG_FUNCTION_ARGS)
*** 94,100 ****
  #define SIGNAL_BACKEND_NOPERMISSION 2
  #define SIGNAL_BACKEND_NOSUPERUSER 3
  static int
! pg_signal_backend(int pid, int sig)
  {
  	PGPROC	   *proc = BackendPidGetProc(pid);
  
--- 102,108 ----
  #define SIGNAL_BACKEND_NOPERMISSION 2
  #define SIGNAL_BACKEND_NOSUPERUSER 3
  static int
! pg_signal_backend_helper(int pid, int sig, bool perm_check)
  {
  	PGPROC	   *proc = BackendPidGetProc(pid);
  
*************** pg_signal_backend(int pid, int sig)
*** 122,128 ****
  		return SIGNAL_BACKEND_NOSUPERUSER;
  
  	/* Users can signal backends they have role membership in. */
! 	if (!has_privs_of_role(GetUserId(), proc->roleId))
  		return SIGNAL_BACKEND_NOPERMISSION;
  
  	/*
--- 130,136 ----
  		return SIGNAL_BACKEND_NOSUPERUSER;
  
  	/* Users can signal backends they have role membership in. */
! 	if (perm_check && !has_privs_of_role(GetUserId(), proc->roleId))
  		return SIGNAL_BACKEND_NOPERMISSION;
  
  	/*
*************** pg_signal_backend(int pid, int sig)
*** 150,155 ****
--- 158,198 ----
  }
  
  /*
+  * Signal a backend process.  Permissions for this are managed by the GRANT
+  * system and therefore we do not do any extra permissions checks through
+  * this path.
+  *
+  * Note that only superusers can signal superuser-owned processes.
+  */
+ Datum
+ pg_signal_backend(PG_FUNCTION_ARGS)
+ {
+ 	int			backend = PG_GETARG_INT32(0);
+ 	int			signal = PG_GETARG_INT32(1);
+ 	int			r;
+ 
+ 	/*
+ 	 * We only allow "safe" signals to be used through this, unless the user
+ 	 * is a superuser.
+ 	 */
+ 	if (!superuser() && signal != SIGINT && signal != SIGTERM)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 (errmsg("must be a superuser to send signals other than SIGINT and SIGTERM"))));
+ 
+ 	r = pg_signal_backend_helper(backend, signal, false);
+ 
+ 	if (r == SIGNAL_BACKEND_NOSUPERUSER)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 (errmsg("must be a superuser to cancel superuser query"))));
+ 
+ 	Assert (r != SIGNAL_BACKEND_NOPERMISSION);
+ 
+ 	PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
+ }
+ 
+ /*
   * Signal to cancel a backend process.  This is allowed if you are a member of
   * the role whose process is being canceled.
   *
*************** pg_signal_backend(int pid, int sig)
*** 158,164 ****
  Datum
  pg_cancel_backend(PG_FUNCTION_ARGS)
  {
! 	int			r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
  
  	if (r == SIGNAL_BACKEND_NOSUPERUSER)
  		ereport(ERROR,
--- 201,207 ----
  Datum
  pg_cancel_backend(PG_FUNCTION_ARGS)
  {
! 	int			r = pg_signal_backend_helper(PG_GETARG_INT32(0), SIGINT, true);
  
  	if (r == SIGNAL_BACKEND_NOSUPERUSER)
  		ereport(ERROR,
*************** pg_cancel_backend(PG_FUNCTION_ARGS)
*** 182,188 ****
  Datum
  pg_terminate_backend(PG_FUNCTION_ARGS)
  {
! 	int			r = pg_signal_backend(PG_GETARG_INT32(0), SIGTERM);
  
  	if (r == SIGNAL_BACKEND_NOSUPERUSER)
  		ereport(ERROR,
--- 225,231 ----
  Datum
  pg_terminate_backend(PG_FUNCTION_ARGS)
  {
! 	int			r = pg_signal_backend_helper(PG_GETARG_INT32(0), SIGTERM, true);
  
  	if (r == SIGNAL_BACKEND_NOSUPERUSER)
  		ereport(ERROR,
*************** pg_reload_conf(PG_FUNCTION_ARGS)
*** 225,235 ****
  Datum
  pg_rotate_logfile(PG_FUNCTION_ARGS)
  {
- 	if (!superuser())
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- 				 (errmsg("must be superuser to rotate log files"))));
- 
  	if (!Logging_collector)
  	{
  		ereport(WARNING,
--- 268,273 ----
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
new file mode 100644
index 78adb2d..fa27386
*** a/src/backend/utils/adt/pgstatfuncs.c
--- b/src/backend/utils/adt/pgstatfuncs.c
*************** extern Datum pg_stat_get_function_self_t
*** 53,58 ****
--- 53,59 ----
  
  extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
+ extern Datum pg_stat_get_activity_all(PG_FUNCTION_ARGS);
  extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
  extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
*************** extern Datum pg_stat_reset_single_functi
*** 126,131 ****
--- 127,134 ----
  /* Global bgwriter statistics, from bgwriter.c */
  extern PgStat_MsgBgWriter bgwriterStats;
  
+ static void populate_pg_stat_get_activity(TupleDesc tupdesc, Tuplestorestate *tupstore, int pid, Oid calling_user);
+ 
  Datum
  pg_stat_get_numscans(PG_FUNCTION_ARGS)
  {
*************** pg_stat_get_backend_idset(PG_FUNCTION_AR
*** 524,648 ****
  	}
  }
  
  Datum
  pg_stat_get_activity(PG_FUNCTION_ARGS)
  {
! 	FuncCallContext *funcctx;
  
! 	if (SRF_IS_FIRSTCALL())
! 	{
! 		MemoryContext oldcontext;
! 		TupleDesc	tupdesc;
  
! 		funcctx = SRF_FIRSTCALL_INIT();
  
! 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
  
! 		tupdesc = CreateTemplateTupleDesc(16, false);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
! 						   OIDOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid",
! 						   INT4OID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid",
! 						   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, "state_change",
! 						   TIMESTAMPTZOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_addr",
! 						   INETOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_hostname",
! 						   TEXTOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 14, "client_port",
! 						   INT4OID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 15, "backend_xid",
! 						   XIDOID, -1, 0);
! 		TupleDescInitEntry(tupdesc, (AttrNumber) 16, "backend_xmin",
! 						   XIDOID, -1, 0);
  
! 		funcctx->tuple_desc = BlessTupleDesc(tupdesc);
  
! 		funcctx->user_fctx = palloc0(sizeof(int));
! 		if (PG_ARGISNULL(0))
! 		{
! 			/* Get all backends */
! 			funcctx->max_calls = pgstat_fetch_stat_numbackends();
! 		}
! 		else
! 		{
! 			/*
! 			 * Get one backend - locate by pid.
! 			 *
! 			 * We lookup the backend early, so we can return zero rows if it
! 			 * doesn't exist, instead of returning a single row full of NULLs.
! 			 */
! 			int			pid = PG_GETARG_INT32(0);
! 			int			i;
! 			int			n = pgstat_fetch_stat_numbackends();
  
! 			for (i = 1; i <= n; i++)
! 			{
! 				PgBackendStatus *be = pgstat_fetch_stat_beentry(i);
  
! 				if (be)
! 				{
! 					if (be->st_procpid == pid)
! 					{
! 						*(int *) (funcctx->user_fctx) = i;
! 						break;
! 					}
! 				}
! 			}
  
! 			if (*(int *) (funcctx->user_fctx) == 0)
! 				/* Pid not found, return zero rows */
! 				funcctx->max_calls = 0;
! 			else
! 				funcctx->max_calls = 1;
! 		}
  
! 		MemoryContextSwitchTo(oldcontext);
! 	}
  
! 	/* stuff done on every call of the function */
! 	funcctx = SRF_PERCALL_SETUP();
  
! 	if (funcctx->call_cntr < funcctx->max_calls)
  	{
  		/* for each row */
  		Datum		values[16];
  		bool		nulls[16];
- 		HeapTuple	tuple;
  		LocalPgBackendStatus *local_beentry;
  		PgBackendStatus *beentry;
  
  		MemSet(values, 0, sizeof(values));
  		MemSet(nulls, 0, sizeof(nulls));
  
! 		if (*(int *) (funcctx->user_fctx) > 0)
! 		{
! 			/* Get specific pid slot */
! 			local_beentry = pgstat_fetch_stat_local_beentry(*(int *) (funcctx->user_fctx));
! 			beentry = &local_beentry->backendStatus;
! 		}
! 		else
  		{
! 			/* Get the next one in the list */
! 			local_beentry = pgstat_fetch_stat_local_beentry(funcctx->call_cntr + 1);	/* 1-based index */
! 			beentry = &local_beentry->backendStatus;
  		}
  		if (!beentry)
  		{
  			int			i;
--- 527,672 ----
  	}
  }
  
+ /*
+  * Returns activity of other backends.  Note that this version filters out
+  * the results unless the caller is a member of the role of the backend being
+  * examined.
+  */
  Datum
  pg_stat_get_activity(PG_FUNCTION_ARGS)
  {
! 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
! 	TupleDesc   tupdesc;
! 	Tuplestorestate *tupstore;
! 	MemoryContext per_query_ctx;
! 	MemoryContext oldcontext;
  
! 	/* check to see if caller supports us returning a tuplestore */
! 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("set-valued function called in context that cannot accept a set")));
! 	if (!(rsinfo->allowedModes & SFRM_Materialize))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("materialize mode required, but it is not " \
! 						"allowed in this context")));
  
! 	/* Build a tuple descriptor for our result type */
! 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
! 		elog(ERROR, "return type must be a row type");
  
! 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
! 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
  
! 	tupstore = tuplestore_begin_heap(true, false, work_mem);
! 	rsinfo->returnMode = SFRM_Materialize;
! 	rsinfo->setResult = tupstore;
! 	rsinfo->setDesc = tupdesc;
  
! 	MemoryContextSwitchTo(oldcontext);
  
! 	/*
! 	 * Populate the tuplestore.
! 	 *
! 	 * For this path, we pass in the current GetUserId() result and have the
! 	 * populate function filter the results based on that.
! 	 */
! 	populate_pg_stat_get_activity(tupdesc, tupstore, PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0), GetUserId());
  
! 	/* clean up and return the tuplestore */
! 	tuplestore_donestoring(tupstore);
  
! 	return (Datum) 0;
! }
  
! /*
!  * Returns activity of other backends.  Note that this version does NOT
!  * filter the results and therefore the permissions at the SQL level must
!  * be REVOKE'd from public.
!  */
! Datum
! pg_stat_get_activity_all(PG_FUNCTION_ARGS)
! {
! 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
! 	TupleDesc   tupdesc;
! 	Tuplestorestate *tupstore;
! 	MemoryContext per_query_ctx;
! 	MemoryContext oldcontext;
  
! 	/* check to see if caller supports us returning a tuplestore */
! 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("set-valued function called in context that cannot accept a set")));
! 	if (!(rsinfo->allowedModes & SFRM_Materialize))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 				 errmsg("materialize mode required, but it is not " \
! 						"allowed in this context")));
  
! 	/* Build a tuple descriptor for our result type */
! 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
! 		elog(ERROR, "return type must be a row type");
  
! 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
! 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
! 
! 	tupstore = tuplestore_begin_heap(true, false, work_mem);
! 	rsinfo->returnMode = SFRM_Materialize;
! 	rsinfo->setResult = tupstore;
! 	rsinfo->setDesc = tupdesc;
! 
! 	MemoryContextSwitchTo(oldcontext);
! 
! 	/*
! 	 * Populate the tuplestore.
! 	 *
! 	 * For this path, we pass in the current GetUserId() result and have the
! 	 * populate function filter the results based on that.
! 	 */
! 	populate_pg_stat_get_activity(tupdesc, tupstore, PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0), InvalidOid);
! 
! 	/* clean up and return the tuplestore */
! 	tuplestore_donestoring(tupstore);
! 
! 	return (Datum) 0;
! }
! 
! static void
! populate_pg_stat_get_activity(TupleDesc tupdesc, Tuplestorestate *tupstore, int pid, Oid calling_user)
! {
! 	int num_backends = pgstat_fetch_stat_numbackends();
! 	int curr_backend;
! 
! 	/* 1-based index */
! 	for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
  	{
  		/* for each row */
  		Datum		values[16];
  		bool		nulls[16];
  		LocalPgBackendStatus *local_beentry;
  		PgBackendStatus *beentry;
  
  		MemSet(values, 0, sizeof(values));
  		MemSet(nulls, 0, sizeof(nulls));
  
! 		if (pid != -1)
  		{
! 			/* Skip any which are not the one we're looking for. */
! 			PgBackendStatus *be = pgstat_fetch_stat_beentry(curr_backend);
! 
! 			if (!be || be->st_procpid != pid)
! 				continue;
! 
  		}
+ 
+ 		/* Get the next one in the list */
+ 		local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
+ 		if (!local_beentry)
+ 			continue;
+ 
+ 		beentry = &local_beentry->backendStatus;
  		if (!beentry)
  		{
  			int			i;
*************** pg_stat_get_activity(PG_FUNCTION_ARGS)
*** 653,660 ****
  			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));
  		}
  
  		/* Values available to all callers */
--- 677,684 ----
  			nulls[5] = false;
  			values[5] = CStringGetTextDatum("<backend information not available>");
  
! 			tuplestore_putvalues(tupstore, tupdesc, values, nulls);
! 			continue;
  		}
  
  		/* Values available to all callers */
*************** pg_stat_get_activity(PG_FUNCTION_ARGS)
*** 677,683 ****
  			nulls[15] = true;
  
  		/* Values only available to role member */
! 		if (has_privs_of_role(GetUserId(), beentry->st_userid))
  		{
  			SockAddr	zero_clientaddr;
  
--- 701,708 ----
  			nulls[15] = true;
  
  		/* Values only available to role member */
! 		if (calling_user == InvalidOid ||
! 			has_privs_of_role(calling_user, beentry->st_userid))
  		{
  			SockAddr	zero_clientaddr;
  
*************** pg_stat_get_activity(PG_FUNCTION_ARGS)
*** 812,826 ****
  			nulls[13] = true;
  		}
  
! 		tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
  
! 		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
! 	}
! 	else
! 	{
! 		/* nothing left */
! 		SRF_RETURN_DONE(funcctx);
  	}
  }
  
  
--- 837,850 ----
  			nulls[13] = true;
  		}
  
! 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
  
! 		/* If only a single backend was requested, and we found it, break. */
! 		if (pid != -1)
! 			break;
  	}
+ 
+ 	return;
  }
  
  
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
new file mode 100644
index 7da5c41..c20f6c3
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** selectDumpableNamespace(NamespaceInfo *n
*** 1234,1245 ****
--- 1234,1255 ----
  	 * If specific tables are being dumped, do not dump any complete
  	 * namespaces. If specific namespaces are being dumped, dump just those
  	 * namespaces. Otherwise, dump all non-system namespaces.
+ 	 *
+ 	 * Note that we do consider dumping ACLs of functions in pg_catalog,
+ 	 * so mark that as a dumpable namespace, but further mark it as the
+ 	 * catalog namespace.
  	 */
+ 
+ 	/* Will be set when we may be dumping catalog ACLs, see below. */
+ 	nsinfo->catalog = false;
+ 
  	if (table_include_oids.head != NULL)
  		nsinfo->dobj.dump = false;
  	else if (schema_include_oids.head != NULL)
  		nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
  												   nsinfo->dobj.catId.oid);
+ 	else if (strncmp(nsinfo->dobj.name, "pg_catalog", 10) == 0)
+ 		nsinfo->dobj.dump = nsinfo->catalog = true;
  	else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
  			 strcmp(nsinfo->dobj.name, "information_schema") == 0)
  		nsinfo->dobj.dump = false;
*************** selectDumpableTable(TableInfo *tbinfo)
*** 1264,1276 ****
  {
  	/*
  	 * If specific tables are being dumped, dump just those tables; else, dump
! 	 * according to the parent namespace's dump flag.
  	 */
  	if (table_include_oids.head != NULL)
  		tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
  												   tbinfo->dobj.catId.oid);
  	else
! 		tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
  
  	/*
  	 * In any case, a table can be excluded by an exclusion switch
--- 1274,1288 ----
  {
  	/*
  	 * If specific tables are being dumped, dump just those tables; else, dump
! 	 * according to the parent namespace's dump flag, except we never dump
! 	 * catalog tables.
  	 */
  	if (table_include_oids.head != NULL)
  		tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
  												   tbinfo->dobj.catId.oid);
  	else
! 		tbinfo->dobj.dump = tbinfo->dobj.namespace->catalog ? false :
! 								tbinfo->dobj.namespace->dobj.dump;
  
  	/*
  	 * In any case, a table can be excluded by an exclusion switch
*************** selectDumpableTable(TableInfo *tbinfo)
*** 1297,1302 ****
--- 1309,1321 ----
  static void
  selectDumpableType(TypeInfo *tyinfo)
  {
+ 	/* Skip types in the catalog. */
+ 	if (tyinfo->dobj.namespace->catalog)
+ 	{
+ 		tyinfo->dobj.dump = false;
+ 		return;
+ 	}
+ 
  	/* skip complex types, except for standalone composite types */
  	if (OidIsValid(tyinfo->typrelid) &&
  		tyinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
*************** selectDumpableType(TypeInfo *tyinfo)
*** 1347,1353 ****
  static void
  selectDumpableDefaultACL(DumpOptions *dopt, DefaultACLInfo *dinfo)
  {
! 	if (dinfo->dobj.namespace)
  		dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
  	else
  		dinfo->dobj.dump = dopt->include_everything;
--- 1366,1372 ----
  static void
  selectDumpableDefaultACL(DumpOptions *dopt, DefaultACLInfo *dinfo)
  {
! 	if (dinfo->dobj.namespace && !dinfo->dobj.namespace->catalog)
  		dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
  	else
  		dinfo->dobj.dump = dopt->include_everything;
*************** selectDumpableObject(DumpableObject *dob
*** 1402,1410 ****
  	/*
  	 * Default policy is to dump if parent namespace is dumpable, or always
  	 * for non-namespace-associated items.
  	 */
! 	if (dobj->namespace)
  		dobj->dump = dobj->namespace->dobj.dump;
  	else
  		dobj->dump = true;
  }
--- 1421,1433 ----
  	/*
  	 * Default policy is to dump if parent namespace is dumpable, or always
  	 * for non-namespace-associated items.
+ 	 *
+ 	 * For the catalog, however, we only consider functions currently.
  	 */
! 	if (dobj->namespace && !dobj->namespace->catalog)
  		dobj->dump = dobj->namespace->dobj.dump;
+ 	else if (dobj->namespace && dobj->namespace->catalog)
+ 		dobj->dump = dobj->objType == DO_FUNC ? true : false;
  	else
  		dobj->dump = true;
  }
*************** getFuncs(Archive *fout, DumpOptions *dop
*** 4364,4374 ****
  
  	/*
  	 * Find all user-defined functions.  Normally we can exclude functions in
! 	 * pg_catalog, which is worth doing since there are several thousand of
! 	 * 'em.  However, there are some extensions that create functions in
! 	 * pg_catalog.  In normal dumps we can still ignore those --- but in
! 	 * binary-upgrade mode, we must dump the member objects of the extension,
! 	 * so be sure to fetch any such functions.
  	 *
  	 * Also, in 9.2 and up, exclude functions that are internally dependent on
  	 * something else, since presumably those will be created as a result of
--- 4387,4397 ----
  
  	/*
  	 * Find all user-defined functions.  Normally we can exclude functions in
! 	 * pg_catalog, provided their ACLs are still the default, which is worth
! 	 * doing since there are several thousand of 'em.  However, there are
! 	 * some extensions that create functions in pg_catalog.  In normal dumps we
! 	 * can still ignore those --- but in binary-upgrade mode, we must dump the
! 	 * member objects of the extension, so be sure to fetch any such functions.
  	 *
  	 * Also, in 9.2 and up, exclude functions that are internally dependent on
  	 * something else, since presumably those will be created as a result of
*************** getFuncs(Archive *fout, DumpOptions *dop
*** 4387,4395 ****
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
! 						  "pronamespace != "
  						  "(SELECT oid FROM pg_namespace "
! 						  "WHERE nspname = 'pg_catalog')",
  						  username_subquery);
  		if (fout->remoteVersion >= 90200)
  			appendPQExpBufferStr(query,
--- 4410,4422 ----
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
! 						  "(pronamespace != "
  						  "(SELECT oid FROM pg_namespace "
! 						  "WHERE nspname = 'pg_catalog') OR "
! 						  "(pronamespace = "
! 						  "(SELECT oid FROM pg_namespace "
! 						  "WHERE nspname = 'pg_catalog') AND "
! 						  "proacl IS NOT NULL))",
  						  username_subquery);
  		if (fout->remoteVersion >= 90200)
  			appendPQExpBufferStr(query,
*************** dumpNamespace(Archive *fout, DumpOptions
*** 8246,8252 ****
  	char	   *qnspname;
  
  	/* Skip if not to be dumped */
! 	if (!nspinfo->dobj.dump || dopt->dataOnly)
  		return;
  
  	/* don't dump dummy namespace from pre-7.3 source */
--- 8273,8279 ----
  	char	   *qnspname;
  
  	/* Skip if not to be dumped */
! 	if (!nspinfo->dobj.dump || dopt->dataOnly || nspinfo->catalog)
  		return;
  
  	/* don't dump dummy namespace from pre-7.3 source */
*************** dumpFunc(Archive *fout, DumpOptions *dop
*** 10393,10412 ****
  	if (dopt->binary_upgrade)
  		binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
  
! 	ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
! 				 funcsig_tag,
! 				 finfo->dobj.namespace->dobj.name,
! 				 NULL,
! 				 finfo->rolname, false,
! 				 "FUNCTION", SECTION_PRE_DATA,
! 				 q->data, delqry->data, NULL,
! 				 NULL, 0,
! 				 NULL, NULL);
  
- 	/* Dump Function Comments and Security Labels */
- 	dumpComment(fout, dopt, labelq->data,
- 				finfo->dobj.namespace->dobj.name, finfo->rolname,
- 				finfo->dobj.catId, 0, finfo->dobj.dumpId);
  	dumpSecLabel(fout, dopt, labelq->data,
  				 finfo->dobj.namespace->dobj.name, finfo->rolname,
  				 finfo->dobj.catId, 0, finfo->dobj.dumpId);
--- 10420,10449 ----
  	if (dopt->binary_upgrade)
  		binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
  
! 	/*
! 	 * Do not include the definition or comment if its a catalog function,
! 	 * except if it is the member of an extension and this is for a binary
! 	 * upgrade.
! 	 */
! 	if (!finfo->dobj.namespace->catalog ||
! 		(dopt->binary_upgrade && finfo->dobj.ext_member))
! 	{
! 		ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
! 					 funcsig_tag,
! 					 finfo->dobj.namespace->dobj.name,
! 					 NULL,
! 					 finfo->rolname, false,
! 					 "FUNCTION", SECTION_PRE_DATA,
! 					 q->data, delqry->data, NULL,
! 					 NULL, 0,
! 					 NULL, NULL);
! 
! 		/* Dump Function Comments and Security Labels */
! 		dumpComment(fout, dopt, labelq->data,
! 					finfo->dobj.namespace->dobj.name, finfo->rolname,
! 					finfo->dobj.catId, 0, finfo->dobj.dumpId);
! 	}
  
  	dumpSecLabel(fout, dopt, labelq->data,
  				 finfo->dobj.namespace->dobj.name, finfo->rolname,
  				 finfo->dobj.catId, 0, finfo->dobj.dumpId);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
new file mode 100644
index a9d3c10..36100a8
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
*************** typedef struct _namespaceInfo
*** 98,103 ****
--- 98,104 ----
  	DumpableObject dobj;
  	char	   *rolname;		/* name of owner, or empty string */
  	char	   *nspacl;
+ 	bool		catalog;
  } NamespaceInfo;
  
  typedef struct _extensionInfo
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 8890ade..abe4e2c
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 1936 (  pg_stat_get_ba
*** 2756,2763 ****
--- 2756,2767 ----
  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 f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23,28,28}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
  DESCR("statistics: information about currently active backends");
+ DATA(insert OID = 3283 (  pg_stat_get_activity_all			PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23,28,28}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin}" _null_ pg_stat_get_activity_all _null_ _null_ _null_ ));
+ DESCR("statistics: information about currently active backends, unfiltered");
  DATA(insert OID = 3099 (  pg_stat_get_wal_senders	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{23,25,3220,3220,3220,3220,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,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");
+ DATA(insert OID = 3285 (  pg_stat_get_wal_senders_all	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{23,25,3220,3220,3220,3220,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders_all _null_ _null_ _null_ ));
+ DESCR("statistics: information about currently active replication, unfiltered");
  DATA(insert OID = 2026 (  pg_backend_pid				PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ ));
  DESCR("statistics: current backend PID");
  DATA(insert OID = 1937 (  pg_stat_get_backend_pid		PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 23 "23" _null_ _null_ _null_ _null_ pg_stat_get_backend_pid _null_ _null_ _null_ ));
*************** DATA(insert OID = 2171 ( pg_cancel_backe
*** 3107,3112 ****
--- 3111,3119 ----
  DESCR("cancel a server process' current query");
  DATA(insert OID = 2096 ( pg_terminate_backend		PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 16 "23" _null_ _null_ _null_ _null_ pg_terminate_backend _null_ _null_ _null_ ));
  DESCR("terminate a server process");
+ DATA(insert OID = 3284 ( pg_signal_backend		PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 16 "23 23" _null_ _null_ _null_ _null_ pg_signal_backend _null_ _null_ _null_ ));
+ DESCR("signal a server process");
+ 
  DATA(insert OID = 2172 ( pg_start_backup		PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 3220 "25 16" _null_ _null_ _null_ _null_ pg_start_backup _null_ _null_ _null_ ));
  DESCR("prepare for taking an online backup");
  DATA(insert OID = 2173 ( pg_stop_backup			PGNSP PGUID 12 1 0 0 0 f f f f t f v 0 0 3220 "" _null_ _null_ _null_ _null_ pg_stop_backup _null_ _null_ _null_ ));
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
new file mode 100644
index b10e784..e458621
*** a/src/include/replication/walsender.h
--- b/src/include/replication/walsender.h
*************** extern void WalSndWakeup(void);
*** 37,42 ****
--- 37,43 ----
  extern void WalSndRqstFileReload(void);
  
  extern Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS);
+ extern Datum pg_stat_get_wal_senders_all(PG_FUNCTION_ARGS);
  
  /*
   * Remember that we want to wakeup walsenders later
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index 6310641..444113a
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern Datum pg_ls_dir(PG_FUNCTION_ARGS)
*** 482,487 ****
--- 482,488 ----
  extern Datum current_database(PG_FUNCTION_ARGS);
  extern Datum current_query(PG_FUNCTION_ARGS);
  extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
+ extern Datum pg_signal_backend(PG_FUNCTION_ARGS);
  extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
  extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
  extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
new file mode 100644
index 1788270..b9ac3b8
*** a/src/test/regress/expected/rules.out
--- b/src/test/regress/expected/rules.out
*************** pg_stat_activity| SELECT s.datid,
*** 1636,1641 ****
--- 1636,1663 ----
      pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin),
      pg_authid u
    WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
+ pg_stat_activity_all| SELECT s.datid,
+     d.datname,
+     s.pid,
+     s.usesysid,
+     u.rolname AS usename,
+     s.application_name,
+     s.client_addr,
+     s.client_hostname,
+     s.client_port,
+     s.backend_start,
+     s.xact_start,
+     s.query_start,
+     s.state_change,
+     s.waiting,
+     s.state,
+     s.backend_xid,
+     s.backend_xmin,
+     s.query
+    FROM pg_database d,
+     pg_stat_get_activity_all(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin),
+     pg_authid u
+   WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
  pg_stat_all_indexes| SELECT c.oid AS relid,
      i.oid AS indexrelid,
      n.nspname AS schemaname,
*************** pg_stat_replication| SELECT s.pid,
*** 1743,1748 ****
--- 1765,1790 ----
      pg_authid u,
      pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state)
    WHERE ((s.usesysid = u.oid) AND (s.pid = w.pid));
+ pg_stat_replication_all| SELECT s.pid,
+     s.usesysid,
+     u.rolname AS usename,
+     s.application_name,
+     s.client_addr,
+     s.client_hostname,
+     s.client_port,
+     s.backend_start,
+     s.backend_xmin,
+     w.state,
+     w.sent_location,
+     w.write_location,
+     w.flush_location,
+     w.replay_location,
+     w.sync_priority,
+     w.sync_state
+    FROM pg_stat_get_activity_all(NULL::integer) s(datid, pid, usesysid, application_name, state, query, waiting, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin),
+     pg_authid u,
+     pg_stat_get_wal_senders_all() w(pid, state, sent_location, write_location, flush_location, replay_location, sync_priority, sync_state)
+   WHERE ((s.usesysid = u.oid) AND (s.pid = w.pid));
  pg_stat_sys_indexes| SELECT pg_stat_all_indexes.relid,
      pg_stat_all_indexes.indexrelid,
      pg_stat_all_indexes.schemaname,
