Hi

pá 3. 2. 2023 v 21:43 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

>
>
> pá 3. 2. 2023 v 21:21 odesílatel Tom Lane <t...@sss.pgh.pa.us> napsal:
>
>> Pavel Stehule <pavel.steh...@gmail.com> writes:
>> > Both patches are very simple - and they use almost already prepared
>> > infrastructure.
>>
>> It's not simple at all to make the psql feature depend on marking
>> "role" as GUC_REPORT when it never has been before.  That will
>> cause the feature to misbehave when using older servers.  I'm
>> even less impressed by having it fall back on PQuser(), which
>> would be misleading at exactly the times when it matters.
>>
>
> It is a good note. This can be disabled for older servers, and maybe it
> can  introduce its own GUC (and again - it can be disallowed for older
> servers).
>

Here is another version. For older servers it shows the string ERR0A000.
That is  ERR code of "feature is not supported"


> My goal at this moment is to get some prototype. We can talk if this
> feature request is valid or not, and we can talk about implementation.
>
> There is another possibility to directly execute "select current_user()"
> instead of looking at status parameters inside prompt processing. It can
> work too.
>

I tested using the query SELECT CURRENT_USER, but I don't think it is
usable now, because it doesn't work in the broken transaction.

Regards

Pavel



>
> Regards
>
> Pavel
>
>
>
>
>
>>                         regards, tom lane
>>
>
From 3b42bd47db4488f320b166d4c580193bd2c02de8 Mon Sep 17 00:00:00 2001
From: "ok...@github.com" <pavel.steh...@gmail.com>
Date: Sat, 4 Feb 2023 21:16:30 +0100
Subject: [PATCH] implementation of psql prompt substitution %N

this substitution shows used role specified by command SET ROLE.
it can show string ERRA0000 (SQL code - feature not supported)
when the variable "role" is not reported (PostgreSQL 15 and older).
---
 doc/src/sgml/libpq.sgml             |  4 +++-
 doc/src/sgml/ref/psql-ref.sgml      | 21 +++++++++++++++-
 src/backend/utils/misc/guc_tables.c |  2 +-
 src/bin/psql/prompt.c               | 37 +++++++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 0e7ae70c70..6a2f92b368 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2270,6 +2270,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>,
@@ -2284,7 +2285,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 dc6528dc11..5e313f06ab 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -4509,7 +4509,26 @@ 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 <literal>none</literal>. The value is same like
+          the value of the parameter <varname>role</varname> (can be
+          displayed by <command>SHOW</command>.
+         </para>
+
+         <para>
+          This substitution requires <productname>PostgreSQL</productname>
+          version 15 and up. When you use older version, the error value
+          <literal>ERR0A000</literal> 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 b46e3b8c55..3188fd015d 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -4144,7 +4144,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..ef720c8496 100644
--- a/src/bin/psql/prompt.c
+++ b/src/bin/psql/prompt.c
@@ -165,6 +165,43 @@ 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;
+
+						/*
+						 * 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)
+						{
+							const char *val;
+
+							val = PQparameterStatus(pset.db, "role");
+							if (val)
+								strlcpy(buf, val, sizeof(buf));
+							else
+								/* missing data */
+								strlcpy(buf, "ERR02000", sizeof(buf));
+						}
+						else
+						{
+							/* feature not supported */
+							strlcpy(buf, "ERR0A000", sizeof(buf));
+						}
+					}
+					break;
 					/* backend pid */
 				case 'p':
 					if (pset.db)
-- 
2.39.1

Reply via email to