Commit 4f04b66f authored by Alvaro Herrera's avatar Alvaro Herrera

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
parent 77ba6108
...@@ -5,6 +5,7 @@ LANGUAGE C; ...@@ -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
......
...@@ -23,6 +23,7 @@ PostgreSQL documentation ...@@ -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 ...@@ -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; ...@@ -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';
......
...@@ -1130,6 +1130,19 @@ testdb=&gt; ...@@ -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>
......
...@@ -5693,7 +5693,8 @@ opt_restart_seqs: ...@@ -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: ...@@ -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: ...@@ -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; }
......
...@@ -402,6 +402,9 @@ exec_command(const char *cmd, ...@@ -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;
......
...@@ -129,6 +129,70 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) ...@@ -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
*/ */
......
...@@ -12,6 +12,9 @@ ...@@ -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);
......
...@@ -215,6 +215,7 @@ slashUsage(unsigned short int pager) ...@@ -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"));
......
...@@ -1276,7 +1276,7 @@ psql_completion(const char *text, int start, int end) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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*"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment