Show opclass and opfamily related information in psql

This commit provides psql commands for listing operator classes, operator
families and its contents in psql.  New commands will be useful for exploring
capabilities of both builtin opclasses/opfamilies as well as
opclasses/opfamilies defined in extensions.

Discussion: https://postgr.es/m/1529675324.14193.5.camel%40postgrespro.ru
Author: Sergey Cherkashin, Nikita Glukhov, Alexander Korotkov
Reviewed-by: Michael Paquier, Alvaro Herrera, Arthur Zakirov
Reviewed-by: Kyotaro Horiguchi, Andres Freund
This commit is contained in:
Alexander Korotkov 2020-03-08 13:32:25 +03:00
parent 691e8b2e18
commit b0b5e20cd8
8 changed files with 676 additions and 2 deletions

View File

@ -1231,6 +1231,97 @@ testdb=>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>\dAc[+]
[<link linkend="app-psql-patterns"><replaceable class="parameter">access-method-pattern</replaceable></link>
[<link linkend="app-psql-patterns"><replaceable class="parameter">input-type-pattern</replaceable></link>]]
</literal>
</term>
<listitem>
<para>
Lists operator classes
(see <xref linkend="catalog-pg-opclass"/>).
If <replaceable class="parameter">access-method-patttern</replaceable>
is specified, only operator classes associated with access methods whose
names match pattern are listed.
If <replaceable class="parameter">input-type-pattern</replaceable>
is specified, only operator classes associated with input types whose
names match the pattern are listed.
If <literal>+</literal> is appended to the command name, each operator
class is listed with its associated operator family and owner.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>\dAf[+]
[<link linkend="app-psql-patterns"><replaceable class="parameter">access-method-pattern</replaceable></link>
[<link linkend="app-psql-patterns"><replaceable class="parameter">input-type-pattern</replaceable></link>]]
</literal>
</term>
<listitem>
<para>
Lists operator families
(see <xref linkend="catalog-pg-opfamily"/>).
If <replaceable class="parameter">access-method-patttern</replaceable>
is specified, only operator families associated with access methods whose
names match pattern are listed.
If <replaceable class="parameter">input-type-pattern</replaceable>
is specified, only operator families associated with input types whose
names match the pattern are listed.
If <literal>+</literal> is appended to the command name, each operator
family is listed with its owner.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>\dAo[+]
[<link linkend="app-psql-patterns"><replaceable class="parameter">access-method-pattern</replaceable></link>
[<link linkend="app-psql-patterns"><replaceable class="parameter">operator-family-pattern</replaceable></link>]]
</literal>
</term>
<listitem>
<para>
Lists operators associated with operator families
(<xref linkend="catalog-pg-amop"/>).
If <replaceable class="parameter">access-method-patttern</replaceable>
is specified, only members of operator families associated with access
methods whose names match pattern are listed.
If <replaceable class="parameter">input-type-pattern</replaceable>
is specified, only memeber of operator families whose names match the
pattern are listed.
If <literal>+</literal> is appended to the command name, each operator
is listed with its strategy number, purpose and sort operator family.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<literal>\dAp[+]
[<link linkend="app-psql-patterns"><replaceable class="parameter">access-method-pattern</replaceable></link>
[<link linkend="app-psql-patterns"><replaceable class="parameter">operator-family-pattern</replaceable></link>]]
</literal>
</term>
<listitem>
<para>
Lists procedures associated with operator families
(<xref linkend="catalog-pg-amproc"/>).
If <replaceable class="parameter">access-method-patttern</replaceable>
is specified, only members of operator families associated with access
methods whose names match pattern are listed.
If <replaceable class="parameter">input-type-pattern</replaceable>
is specified, only memeber of operator families whose names match the
pattern are listed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\db[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>

View File

@ -721,7 +721,38 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
success = listTables("tvmsE", NULL, show_verbose, show_system);
break;
case 'A':
success = describeAccessMethods(pattern, show_verbose);
{
char *pattern2 = NULL;
if (pattern && cmd[2] != '\0' && cmd[2] != '+')
pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
switch (cmd[2])
{
case '\0':
case '+':
success = describeAccessMethods(pattern, show_verbose);
break;
case 'c':
success = listOperatorClasses(pattern, pattern2, show_verbose);
break;
case 'f':
success = listOperatorFamilies(pattern, pattern2, show_verbose);
break;
case 'o':
success = listOpFamilyOperators(pattern, pattern2, show_verbose);
break;
case 'p':
success = listOpFamilyProcedures(pattern, pattern2);
break;
default:
status = PSQL_CMD_UNKNOWN;
break;
}
if (pattern2)
free(pattern2);
}
break;
case 'a':
success = describeAggregates(pattern, show_verbose, show_system);

View File

@ -14,6 +14,7 @@
#include <ctype.h>
#include "catalog/pg_am.h"
#include "catalog/pg_attribute_d.h"
#include "catalog/pg_cast_d.h"
#include "catalog/pg_class_d.h"
@ -6015,3 +6016,337 @@ printACLColumn(PQExpBuffer buf, const char *colname)
"pg_catalog.array_to_string(%s, '\\n') AS \"%s\"",
colname, gettext_noop("Access privileges"));
}
/*
* \dAc
* Lists operator classes
*
* Takes an optional regexps to filter by index access method and type.
*/
bool
listOperatorClasses(const char *access_method_pattern,
const char *type_pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
bool have_where = false;
static const bool translate_columns[] = {false, false, false, false, false,
false, false, false};
initPQExpBuffer(&buf);
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"
" 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"
" END AS \"%s\",\n"
" (CASE WHEN c.opcdefault\n"
" THEN '%s'\n"
" ELSE '%s'\n"
" END) AS \"%s\"",
gettext_noop("AM"),
gettext_noop("Input type"),
gettext_noop("Storage type"),
gettext_noop("Operator class"),
gettext_noop("yes"),
gettext_noop("no"),
gettext_noop("Default?"));
if (verbose)
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"
" END AS \"%s\",\n"
" pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
gettext_noop("Operator family"),
gettext_noop("Owner"));
appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_opclass c\n"
" LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
" LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = c.opcintype\n"
);
if (verbose)
appendPQExpBuffer(&buf,
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
" LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
if (access_method_pattern)
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
false, false, NULL, "am.amname", NULL, NULL);
if (type_pattern)
processSQLNamePattern(pset.db, &buf, type_pattern, have_where, false,
NULL, "t1.typname", NULL, NULL);
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of operator classes");
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQclear(res);
return true;
}
/*
* \dAf
* Lists operator families
*
* Takes an optional regexps to filter by index access method and type.
*/
bool
listOperatorFamilies(const char *access_method_pattern,
const char *type_pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
bool have_where = false;
static const bool translate_columns[] = {false, false, false, false, false,
false, false, false};
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT DISTINCT"
" 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"
" END AS \"%s\",\n"
" (SELECT\n"
" string_agg(format_type(oc.opcintype, -1), ', ')\n"
" FROM pg_opclass oc\n"
" WHERE oc.opcfamily = f.oid) \"%s\"",
gettext_noop("AM"),
gettext_noop("Operator family"),
gettext_noop("Applicable types"));
if (verbose)
appendPQExpBuffer(&buf,
",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
gettext_noop("Owner"));
appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_opfamily f\n"
" LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n"
);
if (access_method_pattern)
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
false, false, NULL, "am.amname", NULL, NULL);
if (type_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"
" WHERE oc.opcfamily = f.oid",
have_where ? "AND" : "WHERE");
processSQLNamePattern(pset.db, &buf, type_pattern, true, false,
NULL, "t.typname", NULL, NULL);
appendPQExpBuffer(&buf, ")");
}
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of operator families");
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQclear(res);
return true;
}
/*
* \dAo
* Lists operators of operator families
*
* Takes an optional regexps to filter by index access method and operator
* family.
*/
bool
listOpFamilyOperators(const char *access_method_pattern,
const char *family_pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
bool have_where = false;
static const bool translate_columns[] = {false, false, false, false, false,
false, false, true, false};
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT\n"
" 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"
" 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",
gettext_noop("AM"),
gettext_noop("Opfamily Name"),
gettext_noop("Operator"));
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"),
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");
if (verbose)
appendPQExpBuffer(&buf,
" LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
if (access_method_pattern)
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
false, false, NULL, "am.amname",
NULL, NULL);
if (family_pattern)
processSQLNamePattern(pset.db, &buf, family_pattern, have_where, false,
"nsf.nspname", "of.opfname", NULL, NULL);
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, o.amopstrategy, 3;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of operators of operator families");
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQclear(res);
return true;
}
/*
* \dAp
* Lists procedures of operator families
*
* Takes an optional regexps to filter by index access method and operator
* family.
*/
bool
listOpFamilyProcedures(const char *access_method_pattern,
const char *family_pattern)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
bool have_where = false;
static const bool translate_columns[] = {false, false, false, false, false, false, false};
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT DISTINCT\n"
" 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"
" 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",
gettext_noop("AM"),
gettext_noop("Operator family"),
gettext_noop("Left arg type"),
gettext_noop("Right arg type"),
gettext_noop("Number"),
gettext_noop("Proc name"));
appendPQExpBuffer(&buf,
"FROM pg_catalog.pg_amproc ap\n"
" LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
" LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
" LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
" LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
if (access_method_pattern)
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
false, false, NULL, "am.amname",
NULL, NULL);
if (family_pattern)
processSQLNamePattern(pset.db, &buf, family_pattern, have_where, false,
"ns.nspname", "of.opfname", NULL, NULL);
appendPQExpBufferStr(&buf,
"ORDER BY 1, 2, 3, 4, 5;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of procedures of operator families");
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
myopt.n_translate_columns = lengthof(translate_columns);
printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
PQclear(res);
return true;
}

View File

@ -114,4 +114,23 @@ bool describePublications(const char *pattern);
/* \dRs */
bool describeSubscriptions(const char *pattern, bool verbose);
/* \dAc */
extern bool listOperatorClasses(const char *access_method_pattern,
const char *opclass_pattern,
bool verbose);
/* \dAf */
extern bool listOperatorFamilies(const char *access_method_pattern,
const char *opclass_pattern,
bool verbose);
/* \dAo */
extern bool listOpFamilyOperators(const char *accessMethod_pattern,
const char *family_pattern, bool verbose);
/* \dAp */
extern bool listOpFamilyProcedures(const char *access_method_pattern,
const char *family_pattern);
#endif /* DESCRIBE_H */

View File

@ -227,6 +227,10 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\d[S+] NAME describe table, view, sequence, or index\n"));
fprintf(output, _(" \\da[S] [PATTERN] list aggregates\n"));
fprintf(output, _(" \\dA[+] [PATTERN] list access methods\n"));
fprintf(output, _(" \\dAc[+] [AMPTRN [TYPEPTRN]] list operator classes\n"));
fprintf(output, _(" \\dAf[+] [AMPTRN [TYPEPTRN]] list operator families\n"));
fprintf(output, _(" \\dAo[+] [AMPTRN [OPFPTRN]] list operators of operator families\n"));
fprintf(output, _(" \\dAp [AMPTRN [OPFPTRN]] list procedures of operator families\n"));
fprintf(output, _(" \\db[+] [PATTERN] list tablespaces\n"));
fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n"));
fprintf(output, _(" \\dC[+] [PATTERN] list casts\n"));

View File

@ -510,6 +510,13 @@ static const SchemaQuery Query_for_list_of_partitioned_relations = {
.result = "pg_catalog.quote_ident(c.relname)",
};
static const SchemaQuery Query_for_list_of_operator_families = {
.catname = "pg_catalog.pg_opfamily c",
.viscondition = "pg_catalog.pg_opfamily_is_visible(c.oid)",
.namespace = "c.opfnamespace",
.result = "pg_catalog.quote_ident(c.opfname)",
};
/* Relations supporting INSERT, UPDATE or DELETE */
static const SchemaQuery Query_for_list_of_updatables = {
.catname = "pg_catalog.pg_class c",
@ -1462,7 +1469,8 @@ psql_completion(const char *text, int start, int end)
"\\a",
"\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
"\\copyright", "\\crosstabview",
"\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
"\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
"\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
"\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
@ -3698,6 +3706,12 @@ psql_completion(const char *text, int start, int end)
}
else if (TailMatchesCS("\\da*"))
COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
else if (TailMatchesCS("\\dAc*", MatchAny) ||
TailMatchesCS("\\dAf*", MatchAny))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
else if (TailMatchesCS("\\dAo*", MatchAny) ||
TailMatchesCS("\\dAp*", MatchAny))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_operator_families, NULL);
else if (TailMatchesCS("\\dA*"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
else if (TailMatchesCS("\\db*"))

View File

@ -4809,3 +4809,165 @@ Owning table: "pg_catalog.pg_statistic"
Indexes:
"pg_toast_2619_index" PRIMARY KEY, btree (chunk_id, chunk_seq)
-- check printing info about access methods
\dA
List of access methods
Name | Type
--------+-------
brin | Index
btree | Index
gin | Index
gist | Index
hash | Index
heap | Table
heap2 | Table
spgist | Index
(8 rows)
\dA *
List of access methods
Name | Type
--------+-------
brin | Index
btree | Index
gin | Index
gist | Index
hash | Index
heap | Table
heap2 | Table
spgist | Index
(8 rows)
\dA h*
List of access methods
Name | Type
-------+-------
hash | Index
heap | Table
heap2 | Table
(3 rows)
\dA foo
List of access methods
Name | Type
------+------
(0 rows)
\dA foo bar
List of access methods
Name | Type
------+------
(0 rows)
\dA: extra argument "bar" ignored
\dA+
List of access methods
Name | Type | Handler | Description
--------+-------+----------------------+----------------------------------------
brin | Index | brinhandler | block range index (BRIN) access method
btree | Index | bthandler | b-tree index access method
gin | Index | ginhandler | GIN index access method
gist | Index | gisthandler | GiST index access method
hash | Index | hashhandler | hash index access method
heap | Table | heap_tableam_handler | heap table access method
heap2 | Table | heap_tableam_handler |
spgist | Index | spghandler | SP-GiST index access method
(8 rows)
\dA+ *
List of access methods
Name | Type | Handler | Description
--------+-------+----------------------+----------------------------------------
brin | Index | brinhandler | block range index (BRIN) access method
btree | Index | bthandler | b-tree index access method
gin | Index | ginhandler | GIN index access method
gist | Index | gisthandler | GiST index access method
hash | Index | hashhandler | hash index access method
heap | Table | heap_tableam_handler | heap table access method
heap2 | Table | heap_tableam_handler |
spgist | Index | spghandler | SP-GiST index access method
(8 rows)
\dA+ h*
List of access methods
Name | Type | Handler | Description
-------+-------+----------------------+--------------------------
hash | Index | hashhandler | hash index access method
heap | Table | heap_tableam_handler | heap table access method
heap2 | Table | heap_tableam_handler |
(3 rows)
\dA+ foo
List of access methods
Name | Type | Handler | Description
------+------+---------+-------------
(0 rows)
\dAc brin pg*.oid*
List of operator classes
AM | Input type | Storage type | Operator class | Default?
------+------------+--------------+----------------+----------
brin | oid | | oid_minmax_ops | yes
(1 row)
\dAf spgist
List of operator families
AM | Operator family | Applicable types
--------+-----------------+------------------
spgist | box_ops | box
spgist | kd_point_ops | point
spgist | network_ops | inet
spgist | poly_ops | polygon
spgist | quad_point_ops | point
spgist | range_ops | anyrange
spgist | text_ops | text
(7 rows)
\dAf btree int4
List of operator families
AM | Operator family | Applicable types
-------+-----------------+---------------------------
btree | integer_ops | smallint, integer, bigint
(1 row)
\dAo brin uuid_minmax_ops
List of operators of operator families
AM | Opfamily Name | Operator
------+-----------------+-----------------
brin | uuid_minmax_ops | < (uuid, uuid)
brin | uuid_minmax_ops | <= (uuid, uuid)
brin | uuid_minmax_ops | = (uuid, uuid)
brin | uuid_minmax_ops | >= (uuid, uuid)
brin | uuid_minmax_ops | > (uuid, uuid)
(5 rows)
\dAo * pg_catalog.jsonb_path_ops
List of operators of operator families
AM | Opfamily Name | Operator
-----+----------------+----------------------
gin | jsonb_path_ops | @> (jsonb, jsonb)
gin | jsonb_path_ops | @? (jsonb, jsonpath)
gin | jsonb_path_ops | @@ (jsonb, jsonpath)
(3 rows)
\dAp brin uuid_minmax_ops
List of procedures of operator families
AM | Operator family | Left arg type | Right arg type | Number | Proc name
------+-----------------+---------------+----------------+--------+------------------------
brin | uuid_minmax_ops | uuid | uuid | 1 | brin_minmax_opcinfo
brin | uuid_minmax_ops | uuid | uuid | 2 | brin_minmax_add_value
brin | uuid_minmax_ops | uuid | uuid | 3 | brin_minmax_consistent
brin | uuid_minmax_ops | uuid | uuid | 4 | brin_minmax_union
(4 rows)
\dAp * pg_catalog.uuid_ops
List of procedures of operator families
AM | Operator family | Left arg type | Right arg type | Number | Proc name
-------+-----------------+---------------+----------------+--------+--------------------
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)

View File

@ -1182,3 +1182,21 @@ drop role regress_partitioning_role;
-- \d on toast table (use pg_statistic's toast table, which has a known name)
\d pg_toast.pg_toast_2619
-- check printing info about access methods
\dA
\dA *
\dA h*
\dA foo
\dA foo bar
\dA+
\dA+ *
\dA+ h*
\dA+ foo
\dAc brin pg*.oid*
\dAf spgist
\dAf btree int4
\dAo brin uuid_minmax_ops
\dAo * pg_catalog.jsonb_path_ops
\dAp brin uuid_minmax_ops
\dAp * pg_catalog.uuid_ops