mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-30 10:11:13 +02:00
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:
parent
691e8b2e18
commit
b0b5e20cd8
@ -1231,6 +1231,97 @@ testdb=>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</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>
|
<varlistentry>
|
||||||
<term><literal>\db[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
<term><literal>\db[+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
||||||
|
|
||||||
|
@ -721,8 +721,39 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
|
|||||||
success = listTables("tvmsE", NULL, show_verbose, show_system);
|
success = listTables("tvmsE", NULL, show_verbose, show_system);
|
||||||
break;
|
break;
|
||||||
case 'A':
|
case 'A':
|
||||||
|
{
|
||||||
|
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);
|
success = describeAccessMethods(pattern, show_verbose);
|
||||||
break;
|
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':
|
case 'a':
|
||||||
success = describeAggregates(pattern, show_verbose, show_system);
|
success = describeAggregates(pattern, show_verbose, show_system);
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "catalog/pg_am.h"
|
||||||
#include "catalog/pg_attribute_d.h"
|
#include "catalog/pg_attribute_d.h"
|
||||||
#include "catalog/pg_cast_d.h"
|
#include "catalog/pg_cast_d.h"
|
||||||
#include "catalog/pg_class_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\"",
|
"pg_catalog.array_to_string(%s, '\\n') AS \"%s\"",
|
||||||
colname, gettext_noop("Access privileges"));
|
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;
|
||||||
|
}
|
||||||
|
@ -114,4 +114,23 @@ bool describePublications(const char *pattern);
|
|||||||
/* \dRs */
|
/* \dRs */
|
||||||
bool describeSubscriptions(const char *pattern, bool verbose);
|
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 */
|
#endif /* DESCRIBE_H */
|
||||||
|
@ -227,6 +227,10 @@ slashUsage(unsigned short int pager)
|
|||||||
fprintf(output, _(" \\d[S+] NAME describe table, view, sequence, or index\n"));
|
fprintf(output, _(" \\d[S+] NAME describe table, view, sequence, or index\n"));
|
||||||
fprintf(output, _(" \\da[S] [PATTERN] list aggregates\n"));
|
fprintf(output, _(" \\da[S] [PATTERN] list aggregates\n"));
|
||||||
fprintf(output, _(" \\dA[+] [PATTERN] list access methods\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, _(" \\db[+] [PATTERN] list tablespaces\n"));
|
||||||
fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n"));
|
fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n"));
|
||||||
fprintf(output, _(" \\dC[+] [PATTERN] list casts\n"));
|
fprintf(output, _(" \\dC[+] [PATTERN] list casts\n"));
|
||||||
|
@ -510,6 +510,13 @@ static const SchemaQuery Query_for_list_of_partitioned_relations = {
|
|||||||
.result = "pg_catalog.quote_ident(c.relname)",
|
.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 */
|
/* Relations supporting INSERT, UPDATE or DELETE */
|
||||||
static const SchemaQuery Query_for_list_of_updatables = {
|
static const SchemaQuery Query_for_list_of_updatables = {
|
||||||
.catname = "pg_catalog.pg_class c",
|
.catname = "pg_catalog.pg_class c",
|
||||||
@ -1462,7 +1469,8 @@ psql_completion(const char *text, int start, int end)
|
|||||||
"\\a",
|
"\\a",
|
||||||
"\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
|
"\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
|
||||||
"\\copyright", "\\crosstabview",
|
"\\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",
|
"\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
|
||||||
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
|
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
|
||||||
"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
|
"\\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*"))
|
else if (TailMatchesCS("\\da*"))
|
||||||
COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
|
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*"))
|
else if (TailMatchesCS("\\dA*"))
|
||||||
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
|
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
|
||||||
else if (TailMatchesCS("\\db*"))
|
else if (TailMatchesCS("\\db*"))
|
||||||
|
@ -4809,3 +4809,165 @@ Owning table: "pg_catalog.pg_statistic"
|
|||||||
Indexes:
|
Indexes:
|
||||||
"pg_toast_2619_index" PRIMARY KEY, btree (chunk_id, chunk_seq)
|
"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)
|
||||||
|
|
||||||
|
@ -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 on toast table (use pg_statistic's toast table, which has a known name)
|
||||||
\d pg_toast.pg_toast_2619
|
\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
|
||||||
|
Loading…
Reference in New Issue
Block a user