ALTER TABLE: rework determination of access method ID
authorAlvaro Herrera <[email protected]>
Thu, 28 Mar 2024 15:51:20 +0000 (16:51 +0100)
committerAlvaro Herrera <[email protected]>
Thu, 28 Mar 2024 15:51:20 +0000 (16:51 +0100)
Avoid setting an access method OID for relation kinds that don't take
one.  Code review for new feature added in 374c7a229042.

Author: Justin Pryzby <[email protected]>
Reported-by: Alexander Lakhin <[email protected]>
Discussion: https://postgr.es/m/e5516ac1-5264-c3c0-d822-9e6f614ea93b@gmail.com

src/backend/commands/tablecmds.c
src/test/regress/expected/create_am.out
src/test/regress/sql/create_am.sql

index 8a02c5b05b64432d44e91bc975f5ec269eef976c..6741e721ae352a6c6a6aae49fff2e8eb484daddd 100644 (file)
@@ -958,22 +958,26 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
    }
 
    /*
-    * Select access method to use: an explicitly indicated one, or (in the
-    * case of a partitioned table) the parent's, if it has one.
+    * For relations with table AM and partitioned tables, select access
+    * method to use: an explicitly indicated one, or (in the case of a
+    * partitioned table) the parent's, if it has one.
     */
    if (stmt->accessMethod != NULL)
-       accessMethodId = get_table_am_oid(stmt->accessMethod, false);
-   else if (stmt->partbound)
    {
-       Assert(list_length(inheritOids) == 1);
-       accessMethodId = get_rel_relam(linitial_oid(inheritOids));
+       Assert(RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE);
+       accessMethodId = get_table_am_oid(stmt->accessMethod, false);
    }
-   else
-       accessMethodId = InvalidOid;
+   else if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE)
+   {
+       if (stmt->partbound)
+       {
+           Assert(list_length(inheritOids) == 1);
+           accessMethodId = get_rel_relam(linitial_oid(inheritOids));
+       }
 
-   /* still nothing? use the default */
-   if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
-       accessMethodId = get_table_am_oid(default_table_access_method, false);
+       if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
+           accessMethodId = get_table_am_oid(default_table_access_method, false);
+   }
 
    /*
     * Create the relation.  Inherited defaults and constraints are passed in
index a27805a8f5eb41d061d38006c5ce5d6eb0cccf4d..aa4cb4fa77f9811d0769adba9c9473049d382a65 100644 (file)
@@ -547,6 +547,9 @@ CREATE TABLE i_am_a_failure() USING "I do not exist AM";
 ERROR:  access method "I do not exist AM" does not exist
 CREATE TABLE i_am_a_failure() USING "btree";
 ERROR:  access method "btree" is not of type TABLE
+-- Other weird invalid cases that cause problems
+CREATE FOREIGN TABLE fp PARTITION OF pg_am DEFAULT SERVER x;
+ERROR:  "pg_am" is not partitioned
 -- Drop table access method, which fails as objects depends on it
 DROP ACCESS METHOD heap2;
 ERROR:  cannot drop access method heap2 because other objects depend on it
index adff0079f989728027610dd3a3746efffd6b86d5..c57a87da4b9c38c71357633a4dbd2ddf6220916b 100644 (file)
@@ -348,6 +348,9 @@ CREATE TABLE i_am_a_failure() USING i_do_not_exist_am;
 CREATE TABLE i_am_a_failure() USING "I do not exist AM";
 CREATE TABLE i_am_a_failure() USING "btree";
 
+-- Other weird invalid cases that cause problems
+CREATE FOREIGN TABLE fp PARTITION OF pg_am DEFAULT SERVER x;
+
 -- Drop table access method, which fails as objects depends on it
 DROP ACCESS METHOD heap2;