Add support for DEFAULT in ALTER TABLE .. SET ACCESS METHOD

This option can be used to switch a relation to use the access method
set by default_table_access_method when running the command.

This has come up when discussing the possibility to support setting
pg_class.relam for partitioned tables (left out here as future work),
while being useful on its own for relations with physical storage as
these must have an access method set.

Per suggestion from Justin Pryzby.

Author: Michael Paquier
Reviewed-by: Justin Pryzby
Discussion: https://postgr.es/m/ZeCZ89xAVFeOmrQC@pryzbyj2023
This commit is contained in:
Michael Paquier 2024-03-08 09:31:52 +09:00
parent 4f8c1e7aaf
commit d61a6cad64
6 changed files with 52 additions and 6 deletions

View File

@ -76,7 +76,7 @@ ALTER TABLE [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
CLUSTER ON <replaceable class="parameter">index_name</replaceable>
SET WITHOUT CLUSTER
SET WITHOUT OIDS
SET ACCESS METHOD <replaceable class="parameter">new_access_method</replaceable>
SET ACCESS METHOD { <replaceable class="parameter">new_access_method</replaceable> | DEFAULT }
SET TABLESPACE <replaceable class="parameter">new_tablespace</replaceable>
SET { LOGGED | UNLOGGED }
SET ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
@ -733,7 +733,9 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
<listitem>
<para>
This form changes the access method of the table by rewriting it. See
<xref linkend="tableam"/> for more information.
<xref linkend="tableam"/> for more information. Writing
<literal>DEFAULT</literal> changes the access method of the table
to <xref linkend="guc-default-table-access-method"/>.
</para>
</listitem>
</varlistentry>

View File

@ -15202,6 +15202,7 @@ ATExecDropCluster(Relation rel, LOCKMODE lockmode)
*
* Check that access method exists. If it is the same as the table's current
* access method, it is a no-op. Otherwise, a table rewrite is necessary.
* If amname is NULL, select default_table_access_method as access method.
*/
static void
ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname)
@ -15209,7 +15210,8 @@ ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname)
Oid amoid;
/* Check that the table access method exists */
amoid = get_table_am_oid(amname, false);
amoid = get_table_am_oid(amname ? amname : default_table_access_method,
false);
if (rel->rd_rel->relam == amoid)
return;

View File

@ -338,6 +338,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> alter_identity_column_option_list
%type <defelt> alter_identity_column_option
%type <node> set_statistics_value
%type <str> set_access_method_name
%type <list> createdb_opt_list createdb_opt_items copy_opt_list
transaction_mode_list
@ -2859,8 +2860,8 @@ alter_table_cmd:
n->newowner = $3;
$$ = (Node *) n;
}
/* ALTER TABLE <name> SET ACCESS METHOD <amname> */
| SET ACCESS METHOD name
/* ALTER TABLE <name> SET ACCESS METHOD { <amname> | DEFAULT } */
| SET ACCESS METHOD set_access_method_name
{
AlterTableCmd *n = makeNode(AlterTableCmd);
@ -3076,6 +3077,11 @@ set_statistics_value:
| DEFAULT { $$ = NULL; }
;
set_access_method_name:
ColId { $$ = $1; }
| DEFAULT { $$ = NULL; }
;
PartitionBoundSpec:
/* a HASH partition */
FOR VALUES WITH '(' hash_partbound ')'

View File

@ -2563,7 +2563,8 @@ psql_completion(const char *text, int start, int end)
* AMs.
*/
else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_table_access_methods,
"DEFAULT");
/*
* If we have ALTER TABLE <sth> SET TABLESPACE provide a list of

View File

@ -283,6 +283,27 @@ SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heaptable;
9 | 1
(1 row)
-- DEFAULT access method
BEGIN;
SET LOCAL default_table_access_method TO heap2;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap2
(1 row)
SET LOCAL default_table_access_method TO heap;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap
(1 row)
ROLLBACK;
-- ALTER MATERIALIZED VIEW SET ACCESS METHOD
CREATE MATERIALIZED VIEW heapmv USING heap AS SELECT * FROM heaptable;
SELECT amname FROM pg_class c, pg_am am
@ -309,6 +330,8 @@ SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heapmv;
-- No support for multiple subcommands
ALTER TABLE heaptable SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
DROP MATERIALIZED VIEW heapmv;

View File

@ -188,6 +188,17 @@ ALTER TABLE heaptable SET ACCESS METHOD heap2;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heaptable;
-- DEFAULT access method
BEGIN;
SET LOCAL default_table_access_method TO heap2;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
SET LOCAL default_table_access_method TO heap;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
ROLLBACK;
-- ALTER MATERIALIZED VIEW SET ACCESS METHOD
CREATE MATERIALIZED VIEW heapmv USING heap AS SELECT * FROM heaptable;
SELECT amname FROM pg_class c, pg_am am
@ -198,6 +209,7 @@ SELECT amname FROM pg_class c, pg_am am
SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heapmv;
-- No support for multiple subcommands
ALTER TABLE heaptable SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT, SET ACCESS METHOD heap2;
ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
DROP MATERIALIZED VIEW heapmv;
DROP TABLE heaptable;