* Robert Haas (robertmh...@gmail.com) wrote:
> Ugg, wait a minute.  This not only adds %U; it also changes the
> behavior of %u, which I don't think we've agreed on.  Also, emitting
> 'none' when not SET ROLE has been done is pretty ugly.  I'm back to
> thinking we need to push this out to 9.2 and take more time to think
> about this.

%u, user_name, etc changes reverted.

%U now always returns the role currently being used for permissions
checks, by using show_session_authorization() when show_role() returns
'none'.  Ditto for CSV updates.

git log below, re-based patch attached.  All regression tests passed,
tested with log_line_prefix and csvlog also, all looks good to me.

Robert, if you say this has to be punted to 9.2 again, I'm giving up. ;)

        Thanks,

                Stephen
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 3562,3568 **** local0.*    /var/log/postgresql
              </row>
              <row>
               <entry><literal>%u</literal></entry>
!              <entry>User name</entry>
               <entry>yes</entry>
              </row>
              <row>
--- 3562,3579 ----
              </row>
              <row>
               <entry><literal>%u</literal></entry>
!              <entry>Authenticated user name, the user name that the user used
!              to authenticate to <productname>PostgreSQL</productname> with.
!              <entry>yes</entry>
!             </row>
!             <row>
!              <entry><literal>%U</literal></entry>
!              <entry>Current role being used for permissions checking, can be
!              set with <command>SET ROLE</> or <command>SET SESSION
!              AUTHORIZATION</> (only allowed for superusers);
!              Note: Log messages from inside <literal>SECURITY DEFINER</>
!              functions will show the calling role, not the effective role
!              inside the <literal>SECURITY DEFINER</> function</entry>
               <entry>yes</entry>
              </row>
              <row>
***************
*** 3790,3795 **** FROM pg_stat_activity;
--- 3801,3807 ----
          with these columns:
          timestamp with milliseconds,
          user name,
+         current role name,
          database name,
          process ID,
          client host:port number,
***************
*** 3820,3825 **** CREATE TABLE postgres_log
--- 3832,3838 ----
  (
    log_time timestamp(3) with time zone,
    user_name text,
+   curr_role text,
    database_name text,
    process_id integer,
    connection_from text,
*** a/src/backend/commands/variable.c
--- b/src/backend/commands/variable.c
***************
*** 847,852 **** assign_session_authorization(const char *value, bool doit, GucSource source)
--- 847,857 ----
  	return result;
  }
  
+ /*
+  * function to return the stored session username, needed because we
+  * can't do catalog lookups when possibly being called after an error,
+  * eg: from elog.c or part of GUC handling.
+  */
  const char *
  show_session_authorization(void)
  {
***************
*** 972,977 **** assign_role(const char *value, bool doit, GucSource source)
--- 977,987 ----
  	return result;
  }
  
+ /*
+  * function to return the stored role username, needed because we
+  * can't do catalog lookups when possibly being called after an error,
+  * eg: from elog.c or part of GUC handling.
+  */
  const char *
  show_role(void)
  {
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
***************
*** 65,70 ****
--- 65,71 ----
  
  #include "access/transam.h"
  #include "access/xact.h"
+ #include "commands/variable.h"
  #include "libpq/libpq.h"
  #include "libpq/pqformat.h"
  #include "mb/pg_wchar.h"
***************
*** 1777,1782 **** log_line_prefix(StringInfo buf, ErrorData *edata)
--- 1778,1795 ----
  	int			format_len;
  	int			i;
  
+ 	/* gather current session and role names */
+ 	const char *session_auth = show_session_authorization();
+ 	const char *role_auth = show_role();
+ 
+ 	/* what we'll actually log as current role, based on if
+ 	 * a set role has been done or not */
+ 	char	   *curr_role = role_auth;
+ 
+ 	/* if show_role() returns 'none', then we log the session user instead */
+ 	if (strcmp(role_auth,"none") == 0)
+ 		curr_role = session_auth;
+ 
  	/*
  	 * This is one of the few places where we'd rather not inherit a static
  	 * variable's value from the postmaster.  But since we will, reset it when
***************
*** 1832,1837 **** log_line_prefix(StringInfo buf, ErrorData *edata)
--- 1845,1853 ----
  					appendStringInfoString(buf, username);
  				}
  				break;
+ 			case 'U':
+ 				appendStringInfoString(buf, curr_role);
+ 				break;
  			case 'd':
  				if (MyProcPort)
  				{
***************
*** 1967,1972 **** write_csvlog(ErrorData *edata)
--- 1983,2000 ----
  	/* has counter been reset in current process? */
  	static int	log_my_pid = 0;
  
+ 	/* pull the session authorization */
+ 	const char *session_auth = show_session_authorization();
+ 	const char *role_auth = show_role();
+ 
+ 	/* what we'll actually log as current role, based on if
+ 	 * a set role has been done or not */
+ 	char	   *curr_role = role_auth;
+ 
+ 	/* if show_role() returns 'none', then we log the session user instead */
+ 	if (strcmp(role_auth,"none") == 0)
+ 		curr_role = session_auth;
+ 
  	/*
  	 * This is one of the few places where we'd rather not inherit a static
  	 * variable's value from the postmaster.  But since we will, reset it when
***************
*** 1995,2005 **** write_csvlog(ErrorData *edata)
  	appendStringInfoString(&buf, formatted_log_time);
  	appendStringInfoChar(&buf, ',');
  
! 	/* username */
  	if (MyProcPort)
  		appendCSVLiteral(&buf, MyProcPort->user_name);
  	appendStringInfoChar(&buf, ',');
  
  	/* database name */
  	if (MyProcPort)
  		appendCSVLiteral(&buf, MyProcPort->database_name);
--- 2023,2037 ----
  	appendStringInfoString(&buf, formatted_log_time);
  	appendStringInfoChar(&buf, ',');
  
! 	/* authenticated-with username */
  	if (MyProcPort)
  		appendCSVLiteral(&buf, MyProcPort->user_name);
  	appendStringInfoChar(&buf, ',');
  
+ 	/* current role name, matches %U in log_line_prefix */
+ 	appendStringInfoString(&buf, curr_role);
+ 	appendStringInfoChar(&buf, ',');
+ 
  	/* database name */
  	if (MyProcPort)
  		appendCSVLiteral(&buf, MyProcPort->database_name);
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 361,367 ****
  #log_hostname = off
  #log_line_prefix = ''			# special values:
  					#   %a = application name
! 					#   %u = user name
  					#   %d = database name
  					#   %r = remote host and port
  					#   %h = remote host
--- 361,368 ----
  #log_hostname = off
  #log_line_prefix = ''			# special values:
  					#   %a = application name
! 					#   %u = authenticated user name
! 					#   %U = current role name
  					#   %d = database name
  					#   %r = remote host and port
  					#   %h = remote host

Attachment: signature.asc
Description: Digital signature

Reply via email to