Add support for DEFAULT in ALTER TABLE .. SET ACCESS METHOD
authorMichael Paquier
Fri, 8 Mar 2024 00:31:52 +0000 (09:31 +0900)
committerMichael Paquier
Fri, 8 Mar 2024 00:31:52 +0000 (09:31 +0900)
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
src/backend/commands/tablecmds.c
src/backend/parser/gram.y
src/bin/psql/tab-complete.c
src/test/regress/expected/create_am.out
src/test/regress/sql/create_am.sql

index 9670671107e16da0c9aec9b5d2bad8e70d64680d..96e3d776051f26ee647384742c12f368ae82d60b 100644 (file)
@@ -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 .
      
     
    
index c61f9305c2ed0208f6a200a4270baa76dd6f33a9..7014be80396ad49ef8e523540adab0dcbee56eb3 100644 (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;
index 130f7fc7c3f0a04116e5a5af5c24216f5b968872..c6e2f679fd5930072b1de5c1cdb974649c17229d 100644 (file)
@@ -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 ')'
index aa1acf85235e62397ce10870864b7eb7b8b3b493..73133ce7358f388fab5b2e5d6ab09661c699c5ac 100644 (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  SET TABLESPACE provide a list of
index b50293d514f8df9593144e5f6b74ea2232d10f8e..8d73e213563929d2fd9b12c5f773ffcdfef5e760 100644 (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;
index 2785ffd8bbb36afcad6b29f987b931dbd5040056..606ee4cb241fc3040b36fef86ba2d9db0fb9ca0f 100644 (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;