From d61a6cad6418f643a5773352038d0dfe5d3535b8 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Fri, 8 Mar 2024 09:31:52 +0900 Subject: [PATCH] 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 --- doc/src/sgml/ref/alter_table.sgml | 6 ++++-- src/backend/commands/tablecmds.c | 4 +++- src/backend/parser/gram.y | 10 ++++++++-- src/bin/psql/tab-complete.c | 3 ++- src/test/regress/expected/create_am.out | 23 +++++++++++++++++++++++ src/test/regress/sql/create_am.sql | 12 ++++++++++++ 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 9670671107..96e3d77605 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -76,7 +76,7 @@ ALTER TABLE [ IF EXISTS ] name CLUSTER ON index_name SET WITHOUT CLUSTER SET WITHOUT OIDS - SET ACCESS METHOD new_access_method + SET ACCESS METHOD { new_access_method | DEFAULT } SET TABLESPACE new_tablespace SET { LOGGED | UNLOGGED } SET ( storage_parameter [= value] [, ... ] ) @@ -733,7 +733,9 @@ WITH ( MODULUS numeric_literal, REM This form changes the access method of the table by rewriting it. See - for more information. + for more information. Writing + DEFAULT changes the access method of the table + to . diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c61f9305c2..7014be8039 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 130f7fc7c3..c6e2f679fd 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -338,6 +338,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type alter_identity_column_option_list %type alter_identity_column_option %type set_statistics_value +%type set_access_method_name %type 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 SET ACCESS METHOD */ - | SET ACCESS METHOD name + /* ALTER TABLE SET ACCESS METHOD { | 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 ')' diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index aa1acf8523..73133ce735 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -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 SET TABLESPACE provide a list of diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out index b50293d514..8d73e21356 100644 --- a/src/test/regress/expected/create_am.out +++ b/src/test/regress/expected/create_am.out @@ -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; diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/create_am.sql index 2785ffd8bb..606ee4cb24 100644 --- a/src/test/regress/sql/create_am.sql +++ b/src/test/regress/sql/create_am.sql @@ -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;