On Wed, Feb 21, 2024 at 08:46:48AM +0100, Peter Eisentraut wrote: > Yes, I think most people agreed that that would be the preferred behavior.
Challenge accepted. As of the patch attached. Tablespaces rely MyDatabaseTableSpace to fallback to the database's default if not specified, but we cannot do that for table AMs as there is no equivalent to dattablespace. I have implemented that so as we keep the default, historical behavior: if pg_class.relam is 0 for a partitioned table, use the AM defined by default_table_access_method. The patch only adds a path to switch to a different AM than the GUC when creating a new partition if and only if a partitioned table has been manipulated with ALTER TABLE SET ACCESS METHOD to update its AM to something else than the GUC. Similarly to tablespaces, CREATE TABLE USING is *not* supported for partitioned tables, same behavior as previously. There is a bit more regarding the handling of the entries in pg_depend, but nothing really complicated, knowing that there can be three possible patterns: - Add a new dependency if changing the AM to be something different than the GUC. - Remove the dependency if changing the AM to the value of the GUC, when something existing previously. - Update the dependency if switching between AMs that don't refer to the GUC at all. If the AM of a partitioned table is not changed, there is no need to update the catalogs at all. The prep phase of the sub-command is already aware of that, setting the new AM OID to InvalidOid in this case. The attached includes regression tests that check all the dependency entries, the contents of pg_class for partitioned tables, as well as the creation of partitions when pg_class.relam is not 0. I'd welcome more eyes regarding these changes. pg_dump needs to be tweaked to save the AM information of a partitioned table, like the previous versions. There are tests for these dump patterns, that needed a slight tweak to work. Docs have been refreshed. Thoughts, comments? -- Michael
From 4309cd0806f92c573bb362f0da92eba95c34a827 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Wed, 28 Feb 2024 17:06:16 +0900 Subject: [PATCH v2] Allow specifying access method of partitioned tables ..to be inherited by partitions See also: ca4103025dfe26eaaf6a500dec9170fbb176eebc 8586bf7ed8889f39a59dd99b292014b73be85342 ebfe2dbd6b624e2a428e14b7ee9322cc096f63f7 - prevent DROP AM Authors: Justin Pryzby, Soumyadeep Chakraborty --- src/include/catalog/pg_class.h | 4 +- src/include/utils/lsyscache.h | 1 + src/backend/commands/tablecmds.c | 138 +++++++++++++++++++++--- src/backend/utils/cache/lsyscache.c | 22 ++++ src/backend/utils/cache/relcache.c | 7 ++ src/bin/pg_dump/pg_dump.c | 3 +- src/bin/pg_dump/t/002_pg_dump.pl | 35 ++++++ src/test/regress/expected/create_am.out | 100 ++++++++++++++++- src/test/regress/sql/create_am.sql | 54 +++++++++- doc/src/sgml/catalogs.sgml | 5 +- doc/src/sgml/ref/alter_table.sgml | 8 ++ doc/src/sgml/ref/create_table.sgml | 4 + 12 files changed, 357 insertions(+), 24 deletions(-) diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 3b7533e7bb..304241923b 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -219,7 +219,9 @@ MAKE_SYSCACHE(RELNAMENSP, pg_class_relname_nsp_index, 128); /* * Relation kinds with a table access method (rd_tableam). Although sequences * use the heap table AM, they are enough of a special case in most uses that - * they are not included here. + * they are not included here. Likewise, partitioned tables can have an access + * method defined so as their children can inherit it; however, this is handled + * specially outside of this macro. */ #define RELKIND_HAS_TABLE_AM(relkind) \ ((relkind) == RELKIND_RELATION || \ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index e4a200b00e..35a8dec2b9 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -139,6 +139,7 @@ extern char get_rel_relkind(Oid relid); extern bool get_rel_relispartition(Oid relid); extern Oid get_rel_tablespace(Oid relid); extern char get_rel_persistence(Oid relid); +extern Oid get_rel_relam(Oid relid); extern Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes); extern Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes); extern bool get_typisdefined(Oid typid); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f798794556..4b4b34278e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -592,6 +592,7 @@ static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode); static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname); +static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethod); static bool ATPrepChangePersistence(Relation rel, bool toLogged); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, const char *tablespacename, LOCKMODE lockmode); @@ -706,7 +707,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, Oid ofTypeId; ObjectAddress address; LOCKMODE parentLockmode; - const char *accessMethod = NULL; Oid accessMethodId = InvalidOid; /* @@ -960,19 +960,28 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, */ if (stmt->accessMethod != NULL) { - accessMethod = stmt->accessMethod; + accessMethodId = get_table_am_oid(stmt->accessMethod, false); if (partitioned) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("specifying a table access method is not supported on a partitioned table"))); } - else if (RELKIND_HAS_TABLE_AM(relkind)) - accessMethod = default_table_access_method; + else if (stmt->partbound) + { + /* + * For partitions, if no access method is specified, use the AM of the + * parent table. + */ + Assert(list_length(inheritOids) == 1); + accessMethodId = get_rel_relam(linitial_oid(inheritOids)); + } + else + accessMethodId = InvalidOid; - /* look up the access method, verify it is for a table */ - if (accessMethod != NULL) - accessMethodId = get_table_am_oid(accessMethod, false); + /* Still nothing? Use the default */ + 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 @@ -5048,12 +5057,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, case AT_SetAccessMethod: /* SET ACCESS METHOD */ ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); - /* partitioned tables don't have an access method */ - if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("cannot change access method of a partitioned table"))); - /* check if another access method change was already requested */ if (OidIsValid(tab->newAccessMethod)) ereport(ERROR, @@ -5410,6 +5413,13 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, break; case AT_SetAccessMethod: /* SET ACCESS METHOD */ /* handled specially in Phase 3 */ + + /* + * Only do this for partitioned tables, for which this is just a + * catalog change. Tables with storage are handled by Phase 3. + */ + if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + ATExecSetAccessMethodNoStorage(rel, tab->newAccessMethod); break; case AT_SetTableSpace: /* SET TABLESPACE */ @@ -15544,6 +15554,108 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) list_free(reltoastidxids); } +/* + * Special handling of ALTER TABLE SET ACCESS METHOD for relations with no + * storage that have an interest in preserving AM. + * + * Since these have no storage, setting the access method is a catalog only + * operation. + */ +static void +ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId) +{ + Relation pg_class; + Oid oldAccessMethodId; + HeapTuple tuple; + Form_pg_class rd_rel; + Oid reloid = RelationGetRelid(rel); + Oid defaultAccessMethodId; + + if (!OidIsValid(newAccessMethodId)) + { + /* if the access method is unchanged, leave */ + return; + } + + /* + * Shouldn't be called on relations having storage; these are processed in + * phase 3. + */ + Assert(!RELKIND_HAS_STORAGE(rel->rd_rel->relkind)); + defaultAccessMethodId = get_table_am_oid(default_table_access_method, false); + + /* Get a modifiable copy of the relation's pg_class row. */ + pg_class = table_open(RelationRelationId, RowExclusiveLock); + + tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation %u", reloid); + rd_rel = (Form_pg_class) GETSTRUCT(tuple); + + /* Update the pg_class row. */ + oldAccessMethodId = rd_rel->relam; + rd_rel->relam = (newAccessMethodId == defaultAccessMethodId) ? + InvalidOid : newAccessMethodId; + + /* Leave if no update required */ + if (rd_rel->relam == oldAccessMethodId) + { + heap_freetuple(tuple); + table_close(pg_class, RowExclusiveLock); + return; + } + + CatalogTupleUpdate(pg_class, &tuple->t_self, tuple); + + /* + * Update the dependency on the new access method. No dependency is added + * if the access method is InvalidOid. + */ + if (!OidIsValid(oldAccessMethodId) && OidIsValid(newAccessMethodId)) + { + ObjectAddress relobj, + referenced; + + /* + * New access method is defined and there was no dependency + * previously, so record a new one. + */ + ObjectAddressSet(relobj, RelationRelationId, reloid); + ObjectAddressSet(referenced, AccessMethodRelationId, newAccessMethodId); + recordDependencyOn(&relobj, &referenced, DEPENDENCY_NORMAL); + } + else if (OidIsValid(oldAccessMethodId) && + newAccessMethodId == defaultAccessMethodId) + { + /* + * There was an access method defined, and no new one, so just remove + * the existing dependency. + */ + deleteDependencyRecordsForClass(RelationRelationId, reloid, + AccessMethodRelationId, + DEPENDENCY_NORMAL); + } + else + { + Assert(OidIsValid(oldAccessMethodId) && + newAccessMethodId != defaultAccessMethodId); + + /* Both are valid, so update the dependency */ + changeDependencyFor(RelationRelationId, reloid, AccessMethodRelationId, + oldAccessMethodId, newAccessMethodId); + } + + CommandCounterIncrement(); + + InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0); + + heap_freetuple(tuple); + table_close(pg_class, RowExclusiveLock); + + /* Make sure the relam change is visible */ + CommandCounterIncrement(); +} + /* * Special handling of ALTER TABLE SET TABLESPACE for relations with no * storage that have an interest in preserving tablespace. diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index f730aa26c4..2ea249e90c 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -2068,6 +2068,28 @@ get_rel_persistence(Oid relid) return result; } +/* + * get_rel_relam + * + * Returns the relam associated with a given relation. + */ +Oid +get_rel_relam(Oid relid) +{ + HeapTuple tp; + Form_pg_class reltup; + Oid result; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup = (Form_pg_class) GETSTRUCT(tp); + result = reltup->relam; + ReleaseSysCache(tp); + + return result; +} + /* ---------- TRANSFORM CACHE ---------- */ diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 50acae4529..e80f156912 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1210,6 +1210,13 @@ retry: else if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) || relation->rd_rel->relkind == RELKIND_SEQUENCE) RelationInitTableAccessMethod(relation); + else if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) + { + /* + * Do nothing: access methods is a setting that partitions can + * inherit. + */ + } else Assert(relation->rd_rel->relam == InvalidOid); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 2225a12718..91a7031b05 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -16610,7 +16610,8 @@ dumpTableSchema(Archive *fout, const TableInfo *tbinfo) if (RELKIND_HAS_TABLESPACE(tbinfo->relkind)) tablespace = tbinfo->reltablespace; - if (RELKIND_HAS_TABLE_AM(tbinfo->relkind)) + if (RELKIND_HAS_TABLE_AM(tbinfo->relkind) || + tbinfo->relkind == RELKIND_PARTITIONED_TABLE) tableam = tbinfo->amname; ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 00b5092713..dfee1982f4 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -4587,6 +4587,41 @@ my %tests = ( no_table_access_method => 1, only_dump_measurement => 1, }, + }, + + # CREATE TABLE with partitioned table and various AMs. One + # partition uses the same default as the parent, and a second + # uses its own AM. + 'CREATE TABLE regress_pg_dump_table_part' => { + create_order => 19, + create_sql => ' + CREATE TABLE dump_test.regress_pg_dump_table_am_parent (id int) PARTITION BY LIST (id); + ALTER TABLE dump_test.regress_pg_dump_table_am_parent SET ACCESS METHOD regress_table_am; + CREATE TABLE dump_test.regress_pg_dump_table_am_child_1 + PARTITION OF dump_test.regress_pg_dump_table_am_parent FOR VALUES IN (1) USING heap; + CREATE TABLE dump_test.regress_pg_dump_table_am_child_2 + PARTITION OF dump_test.regress_pg_dump_table_am_parent FOR VALUES IN (2);', + regexp => qr/^ + \QSET default_table_access_method = regress_table_am;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_parent (\E + (.*\n)* + \QSET default_table_access_method = heap;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_child_1 (\E + (.*\n)* + \QSET default_table_access_method = regress_table_am;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_child_2 (\E + (.*\n)*/xm, + like => { + %full_runs, %dump_test_schema_runs, section_pre_data => 1, + }, + unlike => { + exclude_dump_test_schema => 1, + no_table_access_method => 1, + only_dump_measurement => 1, + }, }); ######################################### diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out index b50293d514..77089e2905 100644 --- a/src/test/regress/expected/create_am.out +++ b/src/test/regress/expected/create_am.out @@ -313,12 +313,104 @@ 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; --- No support for partitioned tables. -CREATE TABLE am_partitioned(x INT, y INT) - PARTITION BY hash (x); +-- Partition hierarchies with access methods +BEGIN; +SET LOCAL default_table_access_method = 'heap'; +CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x); +-- pg_class.relam is 0, no dependency recorded between the AM and the +-- partitioned table. +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; + relam +------- + 0 +(1 row) + +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 +-----+-------- +(0 rows) + +-- New default is set, with dependency added. ALTER TABLE am_partitioned SET ACCESS METHOD heap2; -ERROR: cannot change access method of a partitioned table +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname = 'am_partitioned' AND a.oid = c.relam; + amname +-------- + heap2 +(1 row) + +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) + +-- Default is set, with dependency updated. +SET LOCAL default_table_access_method = 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname = 'am_partitioned' AND a.oid = c.relam; + amname +-------- + heap +(1 row) + +-- Dependency pinned, hence removed. +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 +-----+-------- +(0 rows) + +-- Reset to default +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; + relam +------- + 0 +(1 row) + +-- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitions +-- will inherit the AM set. Existing partitioned are unchanged +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; + relam +------- + 0 +(1 row) + +SET LOCAL default_table_access_method = 'heap'; +CREATE TABLE am_partitioned_1 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 0); +SET LOCAL default_table_access_method = 'heap2'; +CREATE TABLE am_partitioned_2 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 1); +SET LOCAL default_table_access_method = 'heap'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_3 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 2); +SELECT relname, amname FROM pg_class c, pg_am am + WHERE c.relam = am.oid AND c.relname LIKE 'am_partitioned%' ORDER BY 1; + relname | amname +------------------+-------- + am_partitioned | heap2 + am_partitioned_1 | heap + am_partitioned_2 | heap2 + am_partitioned_3 | heap2 +(4 rows) + DROP TABLE am_partitioned; +COMMIT; -- Second, create objects in the new AM by changing the default AM BEGIN; SET LOCAL default_table_access_method = 'heap2'; diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/create_am.sql index 2785ffd8bb..884f49e1a3 100644 --- a/src/test/regress/sql/create_am.sql +++ b/src/test/regress/sql/create_am.sql @@ -201,11 +201,59 @@ ALTER TABLE heaptable SET ACCESS METHOD heap, SET ACCESS METHOD heap2; ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2; DROP MATERIALIZED VIEW heapmv; DROP TABLE heaptable; --- No support for partitioned tables. -CREATE TABLE am_partitioned(x INT, y INT) - PARTITION BY hash (x); + +-- Partition hierarchies with access methods +BEGIN; +SET LOCAL default_table_access_method = 'heap'; +CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x); +-- pg_class.relam is 0, no dependency recorded between the AM and the +-- partitioned table. +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; +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; +-- New default is set, with dependency added. ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname = 'am_partitioned' AND a.oid = c.relam; +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; +-- Default is set, with dependency updated. +SET LOCAL default_table_access_method = 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname = 'am_partitioned' AND a.oid = c.relam; +-- Dependency pinned, hence removed. +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; +-- Reset to default +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; +-- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitions +-- will inherit the AM set. Existing partitioned are unchanged +SELECT relam FROM pg_class WHERE relname = 'am_partitioned'; +SET LOCAL default_table_access_method = 'heap'; +CREATE TABLE am_partitioned_1 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 0); +SET LOCAL default_table_access_method = 'heap2'; +CREATE TABLE am_partitioned_2 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 1); +SET LOCAL default_table_access_method = 'heap'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_3 PARTITION OF am_partitioned FOR VALUES WITH (MODULUS 3,REMAINDER 2); +SELECT relname, amname FROM pg_class c, pg_am am + WHERE c.relam = am.oid AND c.relname LIKE 'am_partitioned%' ORDER BY 1; DROP TABLE am_partitioned; +COMMIT; -- Second, create objects in the new AM by changing the default AM BEGIN; diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 880f717b10..359d03b7f1 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1989,8 +1989,9 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </para> <para> If this is a table or an index, the access method used (heap, - B-tree, hash, etc.); otherwise zero (zero occurs for sequences, - as well as relations without storage, such as views) + B-tree, hash, etc.); otherwise zero. Zero occurs for sequences, + as well as relations without storage, such as views. Partitioned + tables may use a non-zero value. </para></entry> </row> diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 9670671107..e5dc11fafd 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -735,6 +735,14 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM This form changes the access method of the table by rewriting it. See <xref linkend="tableam"/> for more information. </para> + <para> + When applied to a partitioned table, there is no data to rewrite, but any + partitions created afterwards will use that access method unless + overridden by a <literal>USING</literal> clause. If the value + specified is the same as <varname>default_table_access_method</varname> + the partitioned table is switched to rely on the default that is set at + the time when new partitions are created, instead. + </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 4cbaaccaf7..b79081a5ec 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -1330,6 +1330,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM method is chosen for the new table. See <xref linkend="guc-default-table-access-method"/> for more information. </para> + <para> + When creating a partition, the table access method is the access method + of its partitioned table, if set. + </para> </listitem> </varlistentry> -- 2.43.0
signature.asc
Description: PGP signature