út 4. 4. 2023 v 21:11 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

>
>
> út 4. 4. 2023 v 20:50 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
> napsal:
>
>>
>>
>> út 4. 4. 2023 v 19:55 odesílatel Tom Lane <t...@sss.pgh.pa.us> napsal:
>>
>>> Pavel Stehule <pavel.steh...@gmail.com> writes:
>>> > út 4. 4. 2023 v 18:42 odesílatel Tom Lane <t...@sss.pgh.pa.us> napsal:
>>> >> Basically, I want to reject this on the grounds that it's not
>>> >> useful enough to justify the overhead of marking the "role" GUC
>>> >> as GUC_REPORT.  The problems with it not going to work properly
>>> >> with old servers are an additional reason not to like it.
>>>
>>> > If I understand to next comment correctly, the overhead should not be
>>> too
>>> > big
>>>
>>> Yeah, but how big is the use-case?  The reason I'm skeptical is that
>>> half the time what you're going to get is "none":
>>>
>>> $ psql
>>> psql (16devel)
>>> Type "help" for help.
>>>
>>> regression=# show role;
>>>  role
>>> ------
>>>  none
>>> (1 row)
>>>
>>> That's required by SQL spec I believe, but that doesn't make it useful
>>> data to keep in one's prompt.
>>>
>>
>> Who needs it, and who uses different roles, then very quickly uses SET
>> ROLE TO command.
>>
>> But I fully agree so current behavior can be a little bit messy. I like
>> this feature, and I think it can have some benefits. Proposed
>> implementation is minimalistic.
>>
>> One hard problem is translation of the oid of current_user to name. It
>> requires an opened transaction, and then it cannot be postponed to the end
>> of the statement. On the other hand, when the change of role is done inside
>> a nested command, then it should not be visible from the client side.
>>
>> Can you accept the introduction of a new invisible GUC, that can be
>> modified only by SET ROLE TO command when it is executed as top command?
>>
>
> It was stupid idea.
>
> There can be implemented fallbacks. When the role is "none", then the
> :USER can be displayed instead.
>
> It can work, because the custom role "none" is not allowed
>
> (2023-04-04 21:10:25) postgres=# create role none;
> ERROR:  role name "none" is reserved
> LINE 1: create role none;
>
> ?
>
>
attached updated patch

Regards

Pavel



>
>
>
>>
>> Regards
>>
>> Pavel
>>
>>
>>
>>
>>
>>
>>>
>>>                         regards, tom lane
>>>
>>
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9f72dd29d8..966cce9559 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2482,6 +2482,7 @@ const char *PQparameterStatus(const PGconn *conn, const char *paramName);
        <varname>in_hot_standby</varname>,
        <varname>is_superuser</varname>,
        <varname>session_authorization</varname>,
+       <varname>role</varname>,
        <varname>DateStyle</varname>,
        <varname>IntervalStyle</varname>,
        <varname>TimeZone</varname>,
@@ -2496,7 +2497,8 @@ const char *PQparameterStatus(const PGconn *conn, const char *paramName);
        9.0;
        <varname>default_transaction_read_only</varname> and
        <varname>in_hot_standby</varname> were not reported by releases before
-       14.)
+       14;
+       <varname>role</varname> was not reported by releases before 16;)
        Note that
        <varname>server_version</varname>,
        <varname>server_encoding</varname> and
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 29bbec2188..98669fc18a 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -4540,7 +4540,24 @@ testdb=&gt; <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
         <listitem><para>The port number at which the database server is listening.</para></listitem>
       </varlistentry>
 
-      <varlistentry id="app-psql-prompting-n">
+      <varlistentry id="app-psql-prompting-n-uc">
+        <term><literal>%N</literal></term>
+        <listitem>
+         <para>
+          The database role name. This value is specified by command
+          <command>SET ROLE</command>. Until execution of this command
+          the value is set to the database session user name.
+         </para>
+
+         <para>
+          This substitution requires <productname>PostgreSQL</productname>
+          version 16 and up. When you use older version, the empty string
+          is used instead.
+         </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry id="app-psql-prompting-n-lc">
         <term><literal>%n</literal></term>
         <listitem>
          <para>
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 8062589efd..3eec4768b3 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4174,7 +4174,7 @@ struct config_string ConfigureNamesString[] =
 		{"role", PGC_USERSET, UNGROUPED,
 			gettext_noop("Sets the current role."),
 			NULL,
-			GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
+			GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
 		},
 		&role_string,
 		"none",
diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c
index 969cd9908e..7399bacd5f 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -165,6 +165,41 @@ get_prompt(promptStatus_t status, ConditionalStack cstack)
 					if (pset.db)
 						strlcpy(buf, session_username(), sizeof(buf));
 					break;
+					/* DB server user role */
+				case 'N':
+					if (pset.db)
+					{
+						int			minServerMajor;
+						int			serverMajor;
+						const char *rolename;
+
+						/*
+						 * This feature requires GUC "role" to be marked
+						 * as GUC_REPORT. Without it is hard to specify fallback
+						 * result. Returning empty value can be messy, returning
+						 * PQuser like session_username can be messy too.
+						 * Exec query is not too practical too, because it doesn't
+						 * work when session is not in transactional state, and
+						 * CURRENT_ROLE returns different result when role is not
+						 * explicitly specified by SET ROLE.
+						 */
+						minServerMajor = 1600;
+						serverMajor = PQserverVersion(pset.db) / 100;
+						if (serverMajor >= minServerMajor)
+						{
+							rolename  = PQparameterStatus(pset.db, "role");
+
+							/* fallback when role is not set yet */
+							if (strcmp(rolename, "none") == 0)
+								rolename = session_username();
+						}
+
+						if (rolename)
+							strlcpy(buf, rolename, sizeof(buf));
+						else
+							buf[0] = '\0';
+					}
+					break;
 					/* backend pid */
 				case 'p':
 					if (pset.db)

Reply via email to