From 8d2ed66e4107ef27d05aef682c68af5952af7690 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Sat, 11 Jul 2020 14:14:49 +0300 Subject: [PATCH] Improvements to psql \dAo and \dAp commands * 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 | 2 +- src/bin/psql/describe.c | 93 ++++++++++++++-------------- src/bin/psql/describe.h | 2 +- src/test/regress/expected/psql.out | 98 +++++++++++++++--------------- src/test/regress/sql/psql.sql | 2 +- 5 files changed, 98 insertions(+), 99 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 560eacc7f0..9902a4a2ba 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -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; diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index cd39b913cd..3b870c3b17 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -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" diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index 4297f7fdfd..f0e3ec957c 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -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 */ diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 7d2d6328fc..555d464f91 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -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) diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index bd10aec6d6..5a16080980 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -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