1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-10 09:21:54 +03:00

Fix loose ends for SQL ACCESS METHOD objects

COMMENT ON ACCESS METHOD was missing; add it, along psql tab-completion
support for it.

psql was also missing a way to list existing access methods; the new \dA
command does that.

Also add tab-completion support for DROP ACCESS METHOD.

Author: Michael Paquier
Discussion: https://www.postgresql.org/message-id/CAB7nPqTzdZdu8J7EF8SXr_R2U5bSUUYNOT3oAWBZdEoggnwhGA@mail.gmail.com
This commit is contained in:
Alvaro Herrera
2016-06-07 17:59:34 -04:00
parent 77ba610805
commit 4f04b66f97
9 changed files with 107 additions and 5 deletions

View File

@ -5,6 +5,7 @@ LANGUAGE C;
-- Access method -- Access method
CREATE ACCESS METHOD bloom TYPE INDEX HANDLER blhandler; CREATE ACCESS METHOD bloom TYPE INDEX HANDLER blhandler;
COMMENT ON ACCESS METHOD bloom IS 'bloom index access method';
-- Opclasses -- Opclasses

View File

@ -23,6 +23,7 @@ PostgreSQL documentation
<synopsis> <synopsis>
COMMENT ON COMMENT ON
{ {
ACCESS METHOD <replaceable class="PARAMETER">object_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">aggregate_name</replaceable> ( <replaceable>aggregate_signature</replaceable> ) | AGGREGATE <replaceable class="PARAMETER">aggregate_name</replaceable> ( <replaceable>aggregate_signature</replaceable> ) |
CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) | CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) |
COLLATION <replaceable class="PARAMETER">object_name</replaceable> | COLLATION <replaceable class="PARAMETER">object_name</replaceable> |
@ -89,6 +90,8 @@ COMMENT ON
Roles don't have owners, so the rule for <literal>COMMENT ON ROLE</> is Roles don't have owners, so the rule for <literal>COMMENT ON ROLE</> is
that you must be superuser to comment on a superuser role, or have the that you must be superuser to comment on a superuser role, or have the
<literal>CREATEROLE</> privilege to comment on non-superuser roles. <literal>CREATEROLE</> privilege to comment on non-superuser roles.
Likewise, access methods don't have owners either; you must be superuser
to comment on an access method.
Of course, a superuser can comment on anything. Of course, a superuser can comment on anything.
</para> </para>
@ -296,6 +299,7 @@ COMMENT ON TABLE mytable IS NULL;
Some more examples: Some more examples:
<programlisting> <programlisting>
COMMENT ON ACCESS METHOD rtree IS 'R-Tree access method';
COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance'; COMMENT ON AGGREGATE my_aggregate (double precision) IS 'Computes sample variance';
COMMENT ON CAST (text AS int4) IS 'Allow casts from text to int4'; COMMENT ON CAST (text AS int4) IS 'Allow casts from text to int4';
COMMENT ON COLLATION "fr_CA" IS 'Canadian French'; COMMENT ON COLLATION "fr_CA" IS 'Canadian French';

View File

@ -1130,6 +1130,19 @@ testdb=&gt;
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>\dA[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
<listitem>
<para>
Lists access methods. If <replaceable
class="parameter">pattern</replaceable> is specified, only access
methods whose names match the pattern are shown. If
<literal>+</literal> is appended to the command name, each access
method is listed with its associated handler function and description.
</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>

View File

@ -5693,7 +5693,8 @@ opt_restart_seqs:
* The COMMENT ON statement can take different forms based upon the type of * The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is: * the object associated with the comment. The form of the statement is:
* *
* COMMENT ON [ [ CONVERSION | COLLATION | DATABASE | DOMAIN | * COMMENT ON [ [ ACCESS METHOD | CONVERSION | COLLATION |
* DATABASE | DOMAIN |
* EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER | * EXTENSION | EVENT TRIGGER | FOREIGN DATA WRAPPER |
* FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE | * FOREIGN TABLE | INDEX | [PROCEDURAL] LANGUAGE |
* MATERIALIZED VIEW | POLICY | ROLE | SCHEMA | SEQUENCE | * MATERIALIZED VIEW | POLICY | ROLE | SCHEMA | SEQUENCE |
@ -5713,7 +5714,7 @@ opt_restart_seqs:
* OPERATOR FAMILY <name> USING <access-method> | * OPERATOR FAMILY <name> USING <access-method> |
* RULE <rulename> ON <relname> | * RULE <rulename> ON <relname> |
* TRIGGER <triggername> ON <relname> ] * TRIGGER <triggername> ON <relname> ]
* IS 'text' * IS { 'text' | NULL }
* *
*****************************************************************************/ *****************************************************************************/
@ -5888,7 +5889,8 @@ CommentStmt:
; ;
comment_type: comment_type:
COLUMN { $$ = OBJECT_COLUMN; } ACCESS METHOD { $$ = OBJECT_ACCESS_METHOD; }
| COLUMN { $$ = OBJECT_COLUMN; }
| DATABASE { $$ = OBJECT_DATABASE; } | DATABASE { $$ = OBJECT_DATABASE; }
| SCHEMA { $$ = OBJECT_SCHEMA; } | SCHEMA { $$ = OBJECT_SCHEMA; }
| INDEX { $$ = OBJECT_INDEX; } | INDEX { $$ = OBJECT_INDEX; }

View File

@ -402,6 +402,9 @@ exec_command(const char *cmd,
/* standard listing of interesting things */ /* standard listing of interesting things */
success = listTables("tvmsE", NULL, show_verbose, show_system); success = listTables("tvmsE", NULL, show_verbose, show_system);
break; break;
case 'A':
success = describeAccessMethods(pattern, show_verbose);
break;
case 'a': case 'a':
success = describeAggregates(pattern, show_verbose, show_system); success = describeAggregates(pattern, show_verbose, show_system);
break; break;

View File

@ -129,6 +129,70 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
return true; return true;
} }
/* \dA
* Takes an optional regexp to select particular access methods
*/
bool
describeAccessMethods(const char *pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
static const bool translate_columns[] = {false, true, false};
if (pset.sversion < 90600)
{
psql_error("The server (version %d.%d) does not support access methods.\n",
pset.sversion / 10000, (pset.sversion / 100) % 100);
return true;
}
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT amname AS \"%s\",\n"
" CASE amtype"
" WHEN 'i' THEN '%s'"
" END AS \"%s\"",
gettext_noop("Name"),
gettext_noop("Index"),
gettext_noop("Type"));
if (verbose)
{
appendPQExpBuffer(&buf,
",\n amhandler AS \"%s\",\n"
" pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
gettext_noop("Handler"),
gettext_noop("Description"));
}
appendPQExpBufferStr(&buf,
"\nFROM pg_catalog.pg_am\n");
processSQLNamePattern(pset.db, &buf, pattern, false, false,
NULL, "amname", NULL,
NULL);
appendPQExpBufferStr(&buf, "ORDER BY 1;");
res = PSQLexec(buf.data);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of access methods");
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;
}
/* \db /* \db
* Takes an optional regexp to select particular tablespaces * Takes an optional regexp to select particular tablespaces
*/ */

View File

@ -12,6 +12,9 @@
/* \da */ /* \da */
extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem);
/* \dA */
extern bool describeAccessMethods(const char *pattern, bool verbose);
/* \db */ /* \db */
extern bool describeTablespaces(const char *pattern, bool verbose); extern bool describeTablespaces(const char *pattern, bool verbose);

View File

@ -215,6 +215,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\d[S+] list tables, views, and sequences\n")); fprintf(output, _(" \\d[S+] list tables, views, and sequences\n"));
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, _(" \\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"));

View File

@ -1276,7 +1276,7 @@ psql_completion(const char *text, int start, int end)
static const char *const backslash_commands[] = { static const char *const backslash_commands[] = {
"\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy", "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
"\\copyright", "\\crosstabview", "\\copyright", "\\crosstabview",
"\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD", "\\d", "\\da", "\\dA", "\\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", "\\drds", "\\ds", "\\dS", "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
@ -1910,7 +1910,8 @@ psql_completion(const char *text, int start, int end)
else if (Matches2("COMMENT", "ON")) else if (Matches2("COMMENT", "ON"))
{ {
static const char *const list_COMMENT[] = static const char *const list_COMMENT[] =
{"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION", {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
"EVENT TRIGGER", "EXTENSION",
"FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
"SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE", "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
"TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION", "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
@ -1919,6 +1920,8 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_COMMENT); COMPLETE_WITH_LIST(list_COMMENT);
} }
else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
else if (Matches3("COMMENT", "ON", "FOREIGN")) else if (Matches3("COMMENT", "ON", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE"); COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH")) else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
@ -2331,6 +2334,12 @@ psql_completion(const char *text, int start, int end)
else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny)) else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT"); COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* DROP ACCESS METHOD */
else if (Matches2("DROP", "ACCESS"))
COMPLETE_WITH_CONST("METHOD");
else if (Matches3("DROP", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
/* DROP EVENT TRIGGER */ /* DROP EVENT TRIGGER */
else if (Matches2("DROP", "EVENT")) else if (Matches2("DROP", "EVENT"))
COMPLETE_WITH_CONST("TRIGGER"); COMPLETE_WITH_CONST("TRIGGER");
@ -2931,6 +2940,8 @@ psql_completion(const char *text, int start, int end)
} }
else if (TailMatchesCS1("\\da*")) else if (TailMatchesCS1("\\da*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL); COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
else if (TailMatchesCS1("\\dA*"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
else if (TailMatchesCS1("\\db*")) else if (TailMatchesCS1("\\db*"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
else if (TailMatchesCS1("\\dD*")) else if (TailMatchesCS1("\\dD*"))