public inbox for [email protected]  
help / color / mirror / Atom feed
From: Pavel Luzanov <[email protected]>
To: [email protected] <[email protected]>
Subject: psql: Add role's membership options to the \du+ command
Date: Mon, 9 Jan 2023 19:09:19 +0300
Message-ID: <[email protected]> (raw)

When you include one role in another, you can specify three options:
ADMIN, INHERIT (added in e3ce2de0) and SET (3d14e171).

For example.

CREATE ROLE alice LOGIN;

GRANT pg_read_all_settings TO alice WITH ADMIN TRUE, INHERIT TRUE, SET TRUE;
GRANT pg_stat_scan_tables TO alice WITH ADMIN FALSE, INHERIT FALSE, SET 
FALSE;
GRANT pg_read_all_stats TO alice WITH ADMIN FALSE, INHERIT TRUE, SET FALSE;

For information about the options, you need to look in the pg_auth_members:

SELECT roleid::regrole, admin_option, inherit_option, set_option
FROM pg_auth_members
WHERE member = 'alice'::regrole;
         roleid        | admin_option | inherit_option | set_option
----------------------+--------------+----------------+------------
  pg_read_all_settings | t            | t              | t
  pg_stat_scan_tables  | f            | f              | f
  pg_read_all_stats    | f            | t              | f
(3 rows)

I think it would be useful to be able to get this information with a 
psql command
like \du (and \dg). With proposed patch the \du command still only lists
the roles of which alice is a member:

\du alice
                                      List of roles
  Role name | Attributes |                          Member of
-----------+------------+--------------------------------------------------------------
  alice     |            | 
{pg_read_all_settings,pg_read_all_stats,pg_stat_scan_tables}

But the \du+ command adds information about the selected ADMIN, INHERIT
and SET options:

\du+ alice
                                     List of roles
  Role name | Attributes |                   Member of                   
| Description
-----------+------------+-----------------------------------------------+-------------
  alice     |            | pg_read_all_settings WITH ADMIN, INHERIT, SET+|
            |            | pg_read_all_stats WITH INHERIT               +|
            |            | pg_stat_scan_tables                           |

One more change. The roles in the "Member of" column are sorted for both
\du+ and \du for consistent output.

Any comments are welcome.

-- 
Pavel Luzanov
Postgres Professional: https://postgrespro.com


Attachments:

  [text/x-patch] add_role_membership_options_to_du.patch (5.8K, ../[email protected]/2-add_role_membership_options_to_du.patch)
  download | inline diff:
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 8a5285da9a..ef3e87fa32 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1724,9 +1724,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
         <literal>S</literal> modifier to include system roles.
         If <replaceable class="parameter">pattern</replaceable> is specified,
         only those roles whose names match the pattern are listed.
-        If the form <literal>\dg+</literal> is used, additional information
-        is shown about each role; currently this adds the comment for each
-        role.
+        If the form <literal>\dg+</literal> is used, each role is listed
+        with its associated description and options for each role's membership.
         </para>
         </listitem>
       </varlistentry>
@@ -1964,9 +1963,8 @@ INSERT INTO tbl1 VALUES ($1, $2) \bind 'first value' 'second value' \g
         <literal>S</literal> modifier to include system roles.
         If <replaceable class="parameter">pattern</replaceable> is specified,
         only those roles whose names match the pattern are listed.
-        If the form <literal>\du+</literal> is used, additional information
-        is shown about each role; currently this adds the comment for each
-        role.
+        If the form <literal>\du+</literal> is used, each role is listed
+        with its associated description and options for each role's membership.
         </para>
         </listitem>
       </varlistentry>
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index df166365e8..c7b10f96f3 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3624,11 +3624,29 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
 	printfPQExpBuffer(&buf,
 					  "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
 					  "  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
-					  "  r.rolconnlimit, r.rolvaliduntil,\n"
-					  "  ARRAY(SELECT b.rolname\n"
-					  "        FROM pg_catalog.pg_auth_members m\n"
-					  "        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
-					  "        WHERE m.member = r.oid) as memberof");
+					  "  r.rolconnlimit, r.rolvaliduntil,\n");
+
+	if (verbose)
+	{
+		appendPQExpBufferStr(&buf,
+							 "  (SELECT string_agg (quote_ident(b.rolname) || regexp_replace(\n"
+							 "     CASE WHEN m.admin_option THEN ', ADMIN' ELSE '' END ||\n"
+							 "     CASE WHEN m.inherit_option THEN ', INHERIT' ELSE '' END ||\n"
+							 "     CASE WHEN m.set_option THEN ', SET' ELSE '' END, \n"
+							 "     '^,', ' WITH', 1), E'\\n' ORDER BY b.rolname)\n"
+							 "  FROM pg_catalog.pg_auth_members m\n"
+							 "  JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
+							 "  WHERE m.member = r.oid) as memberof");
+	}
+	else
+	{
+		appendPQExpBufferStr(&buf,
+							 "  ARRAY(SELECT b.rolname\n"
+							 "        FROM pg_catalog.pg_auth_members m\n"
+							 "        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
+							 "        WHERE m.member = r.oid\n"
+							 "        ORDER BY b.rolname) as memberof");
+	}
 
 	if (verbose)
 	{
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 8fc62cebd2..3a2eb65850 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -6578,3 +6578,24 @@ cross-database references are not implemented: "no.such.database"."no.such.schem
 cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.data.type"
 \dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
 cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.extended.statistics"
+-- check \du
+CREATE ROLE regress_du LOGIN;
+COMMENT ON ROLE regress_du IS 'Description for regress_du role';
+GRANT pg_read_all_settings TO regress_du WITH ADMIN TRUE, INHERIT TRUE, SET TRUE;
+GRANT pg_stat_scan_tables TO regress_du WITH ADMIN FALSE, INHERIT FALSE, SET FALSE;
+GRANT pg_read_all_stats TO regress_du WITH ADMIN FALSE, INHERIT TRUE, SET FALSE;
+\du regress_du
+                                     List of roles
+ Role name  | Attributes |                          Member of                           
+------------+------------+--------------------------------------------------------------
+ regress_du |            | {pg_read_all_settings,pg_read_all_stats,pg_stat_scan_tables}
+
+\du+ regress_du
+                                               List of roles
+ Role name  | Attributes |                   Member of                   |           Description           
+------------+------------+-----------------------------------------------+---------------------------------
+ regress_du |            | pg_read_all_settings WITH ADMIN, INHERIT, SET+| Description for regress_du role
+            |            | pg_read_all_stats WITH INHERIT               +| 
+            |            | pg_stat_scan_tables                           | 
+
+DROP ROLE regress_du;
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index 2da9665a19..6a5a57ab72 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1791,3 +1791,14 @@ DROP FUNCTION psql_error;
 \dP "no.such.database"."no.such.schema"."no.such.partitioned.relation"
 \dT "no.such.database"."no.such.schema"."no.such.data.type"
 \dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
+
+-- check \du
+CREATE ROLE regress_du LOGIN;
+COMMENT ON ROLE regress_du IS 'Description for regress_du role';
+GRANT pg_read_all_settings TO regress_du WITH ADMIN TRUE, INHERIT TRUE, SET TRUE;
+GRANT pg_stat_scan_tables TO regress_du WITH ADMIN FALSE, INHERIT FALSE, SET FALSE;
+GRANT pg_read_all_stats TO regress_du WITH ADMIN FALSE, INHERIT TRUE, SET FALSE;
+
+\du regress_du
+\du+ regress_du
+DROP ROLE regress_du;


view thread (9+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: psql: Add role's membership options to the \du+ command
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox