I've done up a patch per Tom's idea of combining the binary role
attributes into a single column.

Each attribute which differs from the default is listed on a separate
line, like so:

                  List of roles
  Role name  |   Attributes   |     Member of
-------------+----------------+-------------------
 bob         |                | {readers,writers}
 brendanjurd | Superuser      | {}
             : Create role
             : Create DB
 harry       | No inherit     | {}
 jim         | 10 connections | {readers}
 readers     | No login       | {}
 writers     | No login       | {}
(6 rows)

Notes:

 * The patch relies on array_to_string's current treatment of NULL
values in the array; they are ignored.  If that behaviour changes in
the future, the \du output will become very ugly indeed.
 * I'm not sure whether "No login" and "No inherit" are the best
phrases to use.  I took my cue from the SQL setting names NOLOGIN and
NOINHERIT, but maybe something more grammatically sensible with
"Cannot login" and "No inheritance" would be preferable.
 * If accepted, this patch would supercede the earlier patch mentioned
by Bernd Helmle upthread, which adds LOGIN to the output as a new
column: http://archives.postgresql.org/pgsql-patches/2007-11/msg00014.php

Cheers,
BJ
*** src/bin/psql/describe.c
--- src/bin/psql/describe.c
***************
*** 1611,1638 **** describeRoles(const char *pattern, bool verbose)
        PQExpBufferData buf;
        PGresult   *res;
        printQueryOpt myopt = pset.popt;
!       static const bool trans_columns[] = {false, true, true, true, true, 
false, false};
  
        initPQExpBuffer(&buf);
  
        printfPQExpBuffer(&buf,
                                          "SELECT r.rolname AS \"%s\",\n"
!                               "  CASE WHEN r.rolsuper THEN '%s' ELSE '%s' END 
AS \"%s\",\n"
!                  "  CASE WHEN r.rolcreaterole THEN '%s' ELSE '%s' END AS 
\"%s\",\n"
!                        "  CASE WHEN r.rolcreatedb THEN '%s' ELSE '%s' END AS 
\"%s\",\n"
!               "  CASE WHEN r.rolconnlimit < 0 THEN CAST('%s' AS 
pg_catalog.text)\n"
!                                         "       ELSE CAST(r.rolconnlimit AS 
pg_catalog.text)\n"
!                                         "  END AS \"%s\", \n"
                                          "  ARRAY(SELECT b.rolname FROM 
pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) 
WHERE m.member = r.oid) as \"%s\"",
                                          gettext_noop("Role name"),
-                                         gettext_noop("yes"), 
gettext_noop("no"),
                                          gettext_noop("Superuser"),
!                                         gettext_noop("yes"), 
gettext_noop("no"),
                                          gettext_noop("Create role"),
-                                         gettext_noop("yes"), 
gettext_noop("no"),
                                          gettext_noop("Create DB"),
!                                         gettext_noop("no limit"),
!                                         gettext_noop("Connections"),
                                          gettext_noop("Member of"));
  
        if (verbose)
--- 1611,1639 ----
        PQExpBufferData buf;
        PGresult   *res;
        printQueryOpt myopt = pset.popt;
!       static const bool trans_columns[] = {false, true, false, false};
  
        initPQExpBuffer(&buf);
  
        printfPQExpBuffer(&buf,
                                          "SELECT r.rolname AS \"%s\",\n"
!                                         "  array_to_string(ARRAY[\n"
!                               "    CASE WHEN r.rolsuper THEN '%s' ELSE NULL 
END,\n"
!                 "    CASE WHEN NOT r.rolinherit THEN '%s' ELSE NULL END,\n"
!                  "    CASE WHEN r.rolcreaterole THEN '%s' ELSE NULL END,\n"
!                        "    CASE WHEN r.rolcreatedb THEN '%s' ELSE NULL 
END,\n"
!                "    CASE WHEN NOT r.rolcanlogin THEN '%s' ELSE NULL END,\n"
!          "    CASE WHEN r.rolconnlimit >= 0 THEN 
r.rolconnlimit::pg_catalog.text || ' %s' ELSE NULL END\n"
!                                         "  ], chr(10)) AS \"%s\",\n"
                                          "  ARRAY(SELECT b.rolname FROM 
pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) 
WHERE m.member = r.oid) as \"%s\"",
                                          gettext_noop("Role name"),
                                          gettext_noop("Superuser"),
!                                         gettext_noop("No inherit"),
                                          gettext_noop("Create role"),
                                          gettext_noop("Create DB"),
!                                         gettext_noop("No login"),
!                                         gettext_noop("connections"),
!                                         gettext_noop("Attributes"),
                                          gettext_noop("Member of"));
  
        if (verbose)
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to