Improvements to psql \dAo and \dAp commands
authorAlexander Korotkov <akorotkov@postgresql.org>
Sat, 11 Jul 2020 11:14:49 +0000 (14:14 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Mon, 13 Jul 2020 15:53:20 +0000 (18:53 +0300)
 * Strategy number and purpose are essential information for opfamily operator.
   So, show those columns in non-verbose output.
 * "Left/right arg type" \dAp column names are confusing, because those type
   don't necessary match to function arguments.  Rename them to "Registered
   left/right type".
 * Replace manual assembling of operator/procedure names with casts to
   regoperator/regprocedure.
 * Add schema-qualification for pg_catalog functions and tables.

Reported-by: Peter Eisentraut, Tom Lane
Reviewed-by: Tom Lane
Discussion: https://postgr.es/m/2edc7b27-031f-b2b6-0db2-864241c91cb9%402ndquadrant.com
Backpatch-through: 13

src/bin/psql/command.c
src/bin/psql/describe.c
src/bin/psql/describe.h
src/test/regress/expected/psql.out
src/test/regress/sql/psql.sql

index 560eacc7f0c8bd73ed6356bb078b05a1efeb9003..9902a4a2ba8eb94f0c268880030d9200c56148cf 100644 (file)
@@ -747,7 +747,7 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
                            success = listOpFamilyOperators(pattern, pattern2, show_verbose);
                            break;
                        case 'p':
-                           success = listOpFamilyFunctions(pattern, pattern2);
+                           success = listOpFamilyFunctions(pattern, pattern2, show_verbose);
                            break;
                        default:
                            status = PSQL_CMD_UNKNOWN;
index cd39b913cda906b845de781f9ab2fe0a42e48e68..3b870c3b17e238c327d1b7ec3833f8c54c5e77bd 100644 (file)
@@ -6067,15 +6067,16 @@ listOperatorClasses(const char *access_method_pattern,
    printfPQExpBuffer(&buf,
                      "SELECT DISTINCT"
                      "  am.amname AS \"%s\",\n"
-                     "  c.opcintype::pg_catalog.regtype AS \"%s\",\n"
-                     "  (CASE WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
-                     "    THEN c.opckeytype\n"
-                     "    ELSE NULL -- c.opcintype\n"
-                     "  END)::pg_catalog.regtype AS \"%s\",\n"
+                     "  pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
+                     "  CASE\n"
+                     "    WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
+                     "    THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
+                     "    ELSE NULL\n"
+                     "  END AS \"%s\",\n"
                      "  CASE\n"
                      "    WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
-                     "    THEN format('%%I', c.opcname)\n"
-                     "    ELSE format('%%I.%%I', n.nspname, c.opcname)\n"
+                     "    THEN pg_catalog.format('%%I', c.opcname)\n"
+                     "    ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
                      "  END AS \"%s\",\n"
                      "  (CASE WHEN c.opcdefault\n"
                      "    THEN '%s'\n"
@@ -6092,8 +6093,8 @@ listOperatorClasses(const char *access_method_pattern,
        appendPQExpBuffer(&buf,
                          ",\n  CASE\n"
                          "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
-                         "    THEN format('%%I', of.opfname)\n"
-                         "    ELSE format('%%I.%%I', ofn.nspname, of.opfname)\n"
+                         "    THEN pg_catalog.format('%%I', of.opfname)\n"
+                         "    ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
                          "  END AS \"%s\",\n"
                          " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
                          gettext_noop("Operator family"),
@@ -6157,12 +6158,12 @@ listOperatorFamilies(const char *access_method_pattern,
                      "  am.amname AS \"%s\",\n"
                      "  CASE\n"
                      "    WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
-                     "    THEN format('%%I', f.opfname)\n"
-                     "    ELSE format('%%I.%%I', n.nspname, f.opfname)\n"
+                     "    THEN pg_catalog.format('%%I', f.opfname)\n"
+                     "    ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
                      "  END AS \"%s\",\n"
                      "  (SELECT\n"
-                     "     string_agg(format_type(oc.opcintype, -1), ', ')\n"
-                     "   FROM pg_opclass oc\n"
+                     "     pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
+                     "   FROM pg_catalog.pg_opclass oc\n"
                      "   WHERE oc.opcfamily = f.oid) \"%s\"",
                      gettext_noop("AM"),
                      gettext_noop("Operator family"),
@@ -6185,8 +6186,8 @@ listOperatorFamilies(const char *access_method_pattern,
        appendPQExpBuffer(&buf,
                          "\n  %s EXISTS (\n"
                          "    SELECT 1\n"
-                         "    FROM pg_type t\n"
-                         "    JOIN pg_opclass oc ON oc.opcintype = t.oid\n"
+                         "    FROM pg_catalog.pg_type t\n"
+                         "    JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
                          "    WHERE oc.opcfamily = f.oid",
                          have_where ? "AND" : "WHERE");
        processSQLNamePattern(pset.db, &buf, type_pattern, true, false,
@@ -6237,38 +6238,29 @@ listOpFamilyOperators(const char *access_method_pattern,
                      "  am.amname AS \"%s\",\n"
                      "  CASE\n"
                      "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
-                     "    THEN format('%%I', of.opfname)\n"
-                     "    ELSE format('%%I.%%I', nsf.nspname, of.opfname)\n"
+                     "    THEN pg_catalog.format('%%I', of.opfname)\n"
+                     "    ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
                      "  END AS \"%s\",\n"
-                     "  format ('%%s (%%s, %%s)',\n"
-                     "    CASE\n"
-                     "      WHEN pg_catalog.pg_operator_is_visible(op.oid) \n"
-                     "      THEN op.oprname::pg_catalog.text \n"
-                     "      ELSE o.amopopr::pg_catalog.regoper::pg_catalog.text \n"
-                     "    END,\n"
-                     "    pg_catalog.format_type(o.amoplefttype, NULL),\n"
-                     "    pg_catalog.format_type(o.amoprighttype, NULL)\n"
-                     "  ) AS \"%s\"\n",
+                     "  o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
+                     "  o.amopstrategy AS \"%s\",\n"
+                     "  CASE o.amoppurpose\n"
+                     "    WHEN 'o' THEN '%s'\n"
+                     "    WHEN 's' THEN '%s'\n"
+                     "  END AS \"%s\"\n",
                      gettext_noop("AM"),
                      gettext_noop("Operator family"),
-                     gettext_noop("Operator"));
+                     gettext_noop("Operator"),
+                     gettext_noop("Strategy"),
+                     gettext_noop("ordering"),
+                     gettext_noop("search"),
+                     gettext_noop("Purpose"));
 
    if (verbose)
        appendPQExpBuffer(&buf,
-                         ", o.amopstrategy AS \"%s\",\n"
-                         "  CASE o.amoppurpose\n"
-                         "    WHEN 'o' THEN '%s'\n"
-                         "    WHEN 's' THEN '%s'\n"
-                         "  END AS \"%s\",\n"
-                         "  ofs.opfname AS \"%s\"\n",
-                         gettext_noop("Strategy"),
-                         gettext_noop("ordering"),
-                         gettext_noop("search"),
-                         gettext_noop("Purpose"),
+                         ", ofs.opfname AS \"%s\"\n",
                          gettext_noop("Sort opfamily"));
    appendPQExpBuffer(&buf,
                      "FROM pg_catalog.pg_amop o\n"
-                     "  LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
                      "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
                      "  LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
                      "  LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
@@ -6317,7 +6309,7 @@ listOpFamilyOperators(const char *access_method_pattern,
  */
 bool
 listOpFamilyFunctions(const char *access_method_pattern,
-                     const char *family_pattern)
+                     const char *family_pattern, bool verbose)
 {
    PQExpBufferData buf;
    PGresult   *res;
@@ -6332,19 +6324,26 @@ listOpFamilyFunctions(const char *access_method_pattern,
                      "  am.amname AS \"%s\",\n"
                      "  CASE\n"
                      "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
-                     "    THEN format('%%I', of.opfname)\n"
-                     "    ELSE format('%%I.%%I', ns.nspname, of.opfname)\n"
+                     "    THEN pg_catalog.format('%%I', of.opfname)\n"
+                     "    ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
                      "  END AS \"%s\",\n"
                      "  pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
                      "  pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
-                     "  ap.amprocnum AS \"%s\"\n,"
-                     "  p.proname AS \"%s\"\n",
+                     "  ap.amprocnum AS \"%s\"\n",
                      gettext_noop("AM"),
                      gettext_noop("Operator family"),
-                     gettext_noop("Left arg type"),
-                     gettext_noop("Right arg type"),
-                     gettext_noop("Number"),
-                     gettext_noop("Function"));
+                     gettext_noop("Registered left type"),
+                     gettext_noop("Registered right type"),
+                     gettext_noop("Number"));
+
+   if (!verbose)
+       appendPQExpBuffer(&buf,
+                         ", p.proname AS \"%s\"\n",
+                         gettext_noop("Function"));
+   else
+       appendPQExpBuffer(&buf,
+                         ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
+                         gettext_noop("Function"));
 
    appendPQExpBuffer(&buf,
                      "FROM pg_catalog.pg_amproc ap\n"
index 4297f7fdfdf7ce9ccb07ca8e6aa5ec3d6d101a0b..f0e3ec957c0552fd42022f9ee89e6da84c2aec5c 100644 (file)
@@ -130,7 +130,7 @@ extern bool listOpFamilyOperators(const char *accessMethod_pattern,
 
 /* \dAp */
 extern bool listOpFamilyFunctions(const char *access_method_pattern,
-                                 const char *family_pattern);
+                                 const char *family_pattern, bool verbose);
 
 
 #endif                         /* DESCRIBE_H */
index 7d2d6328fc8004c5d87335d91337bab423d3f5e9..555d464f9182a716f4ea5c6b9437e2dbd0352700 100644 (file)
@@ -4953,62 +4953,62 @@ List of access methods
 (1 row)
 
 \dAo+ btree float_ops
-                                 List of operators of operator families
-  AM   | Operator family |                Operator                 | Strategy | Purpose | Sort opfamily 
--------+-----------------+-----------------------------------------+----------+---------+---------------
- btree | float_ops       | < (double precision, double precision)  |        1 | search  | 
- btree | float_ops       | <= (double precision, double precision) |        2 | search  | 
- btree | float_ops       | = (double precision, double precision)  |        3 | search  | 
- btree | float_ops       | >= (double precision, double precision) |        4 | search  | 
- btree | float_ops       | > (double precision, double precision)  |        5 | search  | 
- btree | float_ops       | < (real, real)                          |        1 | search  | 
- btree | float_ops       | <= (real, real)                         |        2 | search  | 
- btree | float_ops       | = (real, real)                          |        3 | search  | 
- btree | float_ops       | >= (real, real)                         |        4 | search  | 
- btree | float_ops       | > (real, real)                          |        5 | search  | 
- btree | float_ops       | < (double precision, real)              |        1 | search  | 
- btree | float_ops       | <= (double precision, real)             |        2 | search  | 
- btree | float_ops       | = (double precision, real)              |        3 | search  | 
- btree | float_ops       | >= (double precision, real)             |        4 | search  | 
- btree | float_ops       | > (double precision, real)              |        5 | search  | 
- btree | float_ops       | < (real, double precision)              |        1 | search  | 
- btree | float_ops       | <= (real, double precision)             |        2 | search  | 
- btree | float_ops       | = (real, double precision)              |        3 | search  | 
- btree | float_ops       | >= (real, double precision)             |        4 | search  | 
- btree | float_ops       | > (real, double precision)              |        5 | search  | 
+                                List of operators of operator families
+  AM   | Operator family |               Operator                | Strategy | Purpose | Sort opfamily 
+-------+-----------------+---------------------------------------+----------+---------+---------------
+ btree | float_ops       | <(double precision,double precision)  |        1 | search  | 
+ btree | float_ops       | <=(double precision,double precision) |        2 | search  | 
+ btree | float_ops       | =(double precision,double precision)  |        3 | search  | 
+ btree | float_ops       | >=(double precision,double precision) |        4 | search  | 
+ btree | float_ops       | >(double precision,double precision)  |        5 | search  | 
+ btree | float_ops       | <(real,real)                          |        1 | search  | 
+ btree | float_ops       | <=(real,real)                         |        2 | search  | 
+ btree | float_ops       | =(real,real)                          |        3 | search  | 
+ btree | float_ops       | >=(real,real)                         |        4 | search  | 
+ btree | float_ops       | >(real,real)                          |        5 | search  | 
+ btree | float_ops       | <(double precision,real)              |        1 | search  | 
+ btree | float_ops       | <=(double precision,real)             |        2 | search  | 
+ btree | float_ops       | =(double precision,real)              |        3 | search  | 
+ btree | float_ops       | >=(double precision,real)             |        4 | search  | 
+ btree | float_ops       | >(double precision,real)              |        5 | search  | 
+ btree | float_ops       | <(real,double precision)              |        1 | search  | 
+ btree | float_ops       | <=(real,double precision)             |        2 | search  | 
+ btree | float_ops       | =(real,double precision)              |        3 | search  | 
+ btree | float_ops       | >=(real,double precision)             |        4 | search  | 
+ btree | float_ops       | >(real,double precision)              |        5 | search  | 
 (20 rows)
 
 \dAo * pg_catalog.jsonb_path_ops
-    List of operators of operator families
- AM  | Operator family |       Operator       
------+-----------------+----------------------
- gin | jsonb_path_ops  | @> (jsonb, jsonb)
- gin | jsonb_path_ops  | @? (jsonb, jsonpath)
- gin | jsonb_path_ops  | @@ (jsonb, jsonpath)
+             List of operators of operator families
+ AM  | Operator family |      Operator      | Strategy | Purpose 
+-----+-----------------+--------------------+----------+---------
+ gin | jsonb_path_ops  | @>(jsonb,jsonb)    |        7 | search
+ gin | jsonb_path_ops  | @?(jsonb,jsonpath) |       15 | search
+ gin | jsonb_path_ops  | @@(jsonb,jsonpath) |       16 | search
 (3 rows)
 
-\dAp btree float_ops
-                        List of support functions of operator families
-  AM   | Operator family |  Left arg type   |  Right arg type  | Number |      Function       
--------+-----------------+------------------+------------------+--------+---------------------
- btree | float_ops       | double precision | double precision |      1 | btfloat8cmp
- btree | float_ops       | double precision | double precision |      2 | btfloat8sortsupport
- btree | float_ops       | double precision | double precision |      3 | in_range
- btree | float_ops       | real             | real             |      1 | btfloat4cmp
- btree | float_ops       | real             | real             |      2 | btfloat4sortsupport
- btree | float_ops       | double precision | real             |      1 | btfloat84cmp
- btree | float_ops       | real             | double precision |      1 | btfloat48cmp
- btree | float_ops       | real             | double precision |      3 | in_range
+\dAp+ btree float_ops
+                                                         List of support functions of operator families
+  AM   | Operator family | Registered left type | Registered right type | Number |                                   Function                                   
+-------+-----------------+----------------------+-----------------------+--------+------------------------------------------------------------------------------
+ btree | float_ops       | double precision     | double precision      |      1 | btfloat8cmp(double precision,double precision)
+ btree | float_ops       | double precision     | double precision      |      2 | btfloat8sortsupport(internal)
+ btree | float_ops       | double precision     | double precision      |      3 | in_range(double precision,double precision,double precision,boolean,boolean)
+ btree | float_ops       | real                 | real                  |      1 | btfloat4cmp(real,real)
+ btree | float_ops       | real                 | real                  |      2 | btfloat4sortsupport(internal)
+ btree | float_ops       | double precision     | real                  |      1 | btfloat84cmp(double precision,real)
+ btree | float_ops       | real                 | double precision      |      1 | btfloat48cmp(real,double precision)
+ btree | float_ops       | real                 | double precision      |      3 | in_range(real,real,double precision,boolean,boolean)
 (8 rows)
 
 \dAp * pg_catalog.uuid_ops
-                     List of support functions of operator families
-  AM   | Operator family | Left arg type | Right arg type | Number |      Function      
--------+-----------------+---------------+----------------+--------+--------------------
- btree | uuid_ops        | uuid          | uuid           |      1 | uuid_cmp
- btree | uuid_ops        | uuid          | uuid           |      2 | uuid_sortsupport
- btree | uuid_ops        | uuid          | uuid           |      4 | btequalimage
- hash  | uuid_ops        | uuid          | uuid           |      1 | uuid_hash
- hash  | uuid_ops        | uuid          | uuid           |      2 | uuid_hash_extended
+                            List of support functions of operator families
+  AM   | Operator family | Registered left type | Registered right type | Number |      Function      
+-------+-----------------+----------------------+-----------------------+--------+--------------------
+ btree | uuid_ops        | uuid                 | uuid                  |      1 | uuid_cmp
+ btree | uuid_ops        | uuid                 | uuid                  |      2 | uuid_sortsupport
+ btree | uuid_ops        | uuid                 | uuid                  |      4 | btequalimage
+ hash  | uuid_ops        | uuid                 | uuid                  |      1 | uuid_hash
+ hash  | uuid_ops        | uuid                 | uuid                  |      2 | uuid_hash_extended
 (5 rows)
 
index bd10aec6d6799d3abbc24e9ea6dcd8e2039f0abd..5a160809807be855ca70850a77a5c06b8180e986 100644 (file)
@@ -1205,5 +1205,5 @@ drop role regress_partitioning_role;
 \dAf btree int4
 \dAo+ btree float_ops
 \dAo * pg_catalog.jsonb_path_ops
-\dAp btree float_ops
+\dAp+ btree float_ops
 \dAp * pg_catalog.uuid_ops