Fix dependency of partitioned table and table AM with CREATE TABLE .. USING

A pg_depend entry between a partitioned table and its table access
method was missing when using CREATE TABLE .. USING with an unpinned
access method.  DROP ACCESS METHOD could be used, while it should be
blocked if CASCADE is not specified, even if there was a partitioned
table that depends on the table access method.  pg_class.relam would
then hold an orphaned OID value still pointing to the AM dropped.

The problem is fixed by adding a dependency between the partitioned
table and its table access method if set when the relation is created.
A test checking the contents of pg_depend in this case is added.

Issue introduced in 374c7a2290, that has added support for CREATE
TABLE .. USING for partitioned tables.

Reviewed-by: Alexander Lakhin
Discussion: https://postgr.es/m/18674-1ef01eceec278fab@postgresql.org
Backpatch-through: 17
This commit is contained in:
Michael Paquier 2024-10-29 08:41:33 +09:00
parent 70b9adb98e
commit 49a23441ca
3 changed files with 28 additions and 2 deletions

View File

@ -1471,9 +1471,11 @@ heap_create_with_catalog(const char *relname,
* access method is.
*
* No need to add an explicit dependency for the toast table, as the
* main table depends on it.
* main table depends on it. Partitioned tables may not have an
* access method set.
*/
if (RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE)
if ((RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE) ||
(relkind == RELKIND_PARTITIONED_TABLE && OidIsValid(accessmtd)))
{
ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
add_exact_object_address(&referenced, addrs);

View File

@ -343,6 +343,20 @@ ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
DROP MATERIALIZED VIEW heapmv;
DROP TABLE heaptable;
-- Partitioned table with USING
CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2;
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
obj | refobj
----------------------+---------------------
table am_partitioned | access method heap2
(1 row)
DROP TABLE am_partitioned;
-- Partition hierarchies with access methods
BEGIN;
SET LOCAL default_table_access_method = 'heap';

View File

@ -217,6 +217,16 @@ ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
DROP MATERIALIZED VIEW heapmv;
DROP TABLE heaptable;
-- Partitioned table with USING
CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2;
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
DROP TABLE am_partitioned;
-- Partition hierarchies with access methods
BEGIN;
SET LOCAL default_table_access_method = 'heap';