Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rh3yk-009OL8-48 for pgsql-hackers@arkaria.postgresql.org; Mon, 04 Mar 2024 08:47:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rh3yi-006CHZ-93 for pgsql-hackers@arkaria.postgresql.org; Mon, 04 Mar 2024 08:47:20 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rh3yh-006CHR-2t for pgsql-hackers@lists.postgresql.org; Mon, 04 Mar 2024 08:47:20 +0000 Received: from wfhigh8-smtp.messagingengine.com ([64.147.123.159]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rh3yb-002lqR-KA for pgsql-hackers@postgresql.org; Mon, 04 Mar 2024 08:47:18 +0000 Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.west.internal (Postfix) with ESMTP id 1D20B18000AF; Mon, 4 Mar 2024 03:47:12 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Mon, 04 Mar 2024 03:47:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=paquier.xyz; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1709542031; x=1709628431; bh=hJVz4QkaFU iC8Y/KMsM9IjQOH5wNvD0F45/yk9jznpQ=; b=QRs3lxSi0zJ+m2birdNOmmQYAv Ja3yIsiPL+/yhSbzPMPUlixlIg6MDyvUIGGgU5fPKvypGUKtV7MvQf4EYjDZIqB6 YUeHPqmfJD7JTAO56+tXXZZ2g2cWrAD96zSfnQR8lHHord2Vv0q7ihcdpRHuyPrA rfH+1Doa5CuaqyMd3tmXkjgd/Cnp6mG6U0QKk9arzcuCslD0yjGLf9BDInWVDz09 Vlk7S1zebS2zW+YtlxXApQRRvbPaZAeqvI1kDgYdttgt6yW1nnuVKMDP6UqXYw+E fRhRH29hCpoYRRSBNE8/CsHs0N9mhZdeHhjtLkv+IidLWCsUo011eZhqCW8A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; t=1709542031; x=1709628431; bh=hJVz4QkaFUiC8Y/KMsM9IjQOH5wN vD0F45/yk9jznpQ=; b=mMKMW0+USHmIr1G2ptYRxYdEXXEh5p3PERcuaSKxclW1 rTR0dhJ10D7kACeuQEdAseURfR520AuMehAm/1779SJvYVbvVSOi1psI4cs5loe1 Fblgv3B3/FdlxvzxkOlNHOgQyxqVYvZMwx5XgYnCN3HA6ogtf7C7zMKA/hM8hV4D bZqVaLF6r/HU9xLxEkpbOqW1D4tSmEnyH0nwTo/rJtqtcbVnisEOe6G97WpLM2ES GsGXRr9AYkMbmP/AYl7KIkhv7bvKSR/oKrSGUZUjU2sACsGzHVwgnpBgqPj29NIV 2NSCeuBXhYKaMneCZP7r3OQUK6JzpxvjoxIVaFDk4w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrheeigdduvdduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne gfrhhlucfvnfffucdljedtmdenucfjughrpeffhffvvefukfhfgggtuggjsehgtderredt tddvnecuhfhrohhmpefoihgthhgrvghlucfrrghquhhivghruceomhhitghhrggvlhesph grqhhuihgvrhdrgiihiieqnecuggftrfgrthhtvghrnhepteelieefudffhffhtdetleeg geegfffhkeeuveetiefgudduvedutefggeeivdejnecuvehluhhsthgvrhfuihiivgeptd enucfrrghrrghmpehmrghilhhfrhhomhepmhhitghhrggvlhesphgrqhhuihgvrhdrgiih ii X-ME-Proxy: Feedback-ID: i0fe9450f:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 4 Mar 2024 03:47:08 -0500 (EST) Date: Mon, 4 Mar 2024 17:46:56 +0900 From: Michael Paquier To: Justin Pryzby Cc: Peter Eisentraut , Soumyadeep Chakraborty , Zhihong Yu , pgsql-hackers@postgresql.org, Ashwin Agrawal , vanjared@vmware.com Subject: Re: ALTER TABLE SET ACCESS METHOD on partitioned tables Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="9wSQnFLv3emD+9JY" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --9wSQnFLv3emD+9JY Content-Type: multipart/mixed; boundary="wZYC/6ns4foT4Uak" Content-Disposition: inline --wZYC/6ns4foT4Uak Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Mar 01, 2024 at 03:03:14PM -0600, Justin Pryzby wrote: > I think if the user sets something "explicitly", the catalog should > reflect what they set. Tablespaces have dattablespace, but AMs don't -- > it's a simpler case. Okay. > For 001: we don't *need* to support "ALTER SET AM default" for leaf > tables. It doesn't do anything that's not already possible. But, if > AMs for partitioned tables are optional rather than required, then seems > to be needed to allow (re)settinng relam=3D0. Indeed, for non-partitioned tables DEFAULT is a sugar flavor. Not mandatory, still it's nice to have to not have to type an AM. > But for partitioned tables, I think it should set relam=3D0 directly. > Currently it 1) falls through to default_table_am; and 2) detects that > it's the default, so then sets relam to 0. > > Since InvalidOid is already taken, I guess you might need to introduce a > boolean flag, like set_relam, indicating that the statement has an > ACCESS METHOD clause. Yes, I don't see an alternative. The default needs a different field to be tracked down to the execution. >> + * method defined so as their children can inherit it; however, this is= handled >=20 > so that >=20 >> + * Do nothing: access methods is a setting that partitions can >=20 > method (singular), or s/is/are/ Indeed. Fixed both. > In any case, it'd be a bit confusing for the error message to still say: >=20 > postgres=3D# CREATE TABLE a(i int) PARTITION BY RANGE(a) USING heap2; > ERROR: specifying a table access method is not supported on a partitione= d table I was looking at this one as well and I don't see why we could not remove it, so you are right (missed the tablespace part last week). A partitioned table created as a partition of a partitioned table would inherit the relam of its parent (0 if default is set, or non-0 is something is set). I have added some regression tests for that. And I'm finishing with the attached. To summarize SET ACCESS METHOD on a partitioned table, the semantics are: - DEFAULT sets the relam to 0, any partitions with storage would use the GUC at creation time. Partitioned tables use a relam of 0. - If a value is set for the am, relam becomes non-0. Any partitions created on it inherit it (partitioned as well as non-partitioned tables). - No USING clause means to set its relam to 0. 0001 seems OK here, 0002 needs more eyes. The bulk of the changes is in the regression tests to cover all the cases I could think of. -- Michael --wZYC/6ns4foT4Uak Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v3-0001-Add-DEFAULT-option-to-ALTER-TABLE-SET-ACCESS-METH.patch" Content-Transfer-Encoding: quoted-printable =46rom 4d8a5de79b829e4f1be875c668f85bbfa6d3f37a Mon Sep 17 00:00:00 2001 =46rom: Michael Paquier Date: Fri, 1 Mar 2024 10:22:22 +0900 Subject: [PATCH v3 1/2] Add DEFAULT option to ALTER TABLE SET ACCESS METHOD --- src/backend/commands/tablecmds.c | 3 ++- src/backend/parser/gram.y | 10 ++++++++-- src/test/regress/expected/create_am.out | 21 +++++++++++++++++++++ src/test/regress/sql/create_am.sql | 11 +++++++++++ doc/src/sgml/ref/alter_table.sgml | 6 ++++-- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablec= mds.c index f798794556..3b1c2590fd 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -15212,7 +15212,8 @@ ATPrepSetAccessMethod(AlteredTableInfo *tab, Relati= on rel, const char *amname) Oid amoid; =20 /* Check that the table access method exists */ - amoid =3D get_table_am_oid(amname, false); + amoid =3D get_table_am_oid(amname ? amname : default_table_access_method, + false); =20 if (rel->rd_rel->relam =3D=3D 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, Lis= t *aliases, Node *query); %type alter_identity_column_option_list %type alter_identity_column_option %type set_statistics_value +%type set_access_method_name =20 %type createdb_opt_list createdb_opt_items copy_opt_list transaction_mode_list @@ -2859,8 +2860,8 @@ alter_table_cmd: n->newowner =3D $3; $$ =3D (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 =3D makeNode(AlterTableCmd); =20 @@ -3076,6 +3077,11 @@ set_statistics_value: | DEFAULT { $$ =3D NULL; } ; =20 +set_access_method_name: + ColId { $$ =3D $1; } + | DEFAULT { $$ =3D NULL; } + ; + PartitionBoundSpec: /* a HASH partition */ FOR VALUES WITH '(' hash_partbound ')' diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/exp= ected/create_am.out index b50293d514..e843d39ee7 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=3D1) FROM hea= ptable; 9 | 1 (1 row) =20 +-- 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 =3D am.oid AND c.oid =3D 'heaptable'::regclass; + amname=20 +-------- + 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 =3D am.oid AND c.oid =3D 'heaptable'::regclass; + amname=20 +-------- + 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 diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/crea= te_am.sql index 2785ffd8bb..f752bf1678 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 =3D am.oid AND c.oid =3D 'heaptable'::regclass; SELECT COUNT(a), COUNT(1) FILTER(WHERE a=3D1) 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 =3D am.oid AND c.oid =3D '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 =3D am.oid AND c.oid =3D '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 diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_tab= le.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= [=3D 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 . --=20 2.43.0 --wZYC/6ns4foT4Uak Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v3-0002-Allow-specifying-access-method-of-partitioned-tab.patch" Content-Transfer-Encoding: quoted-printable =46rom 04ff808771fceee70ecd01aeb8474b1b5c8dd9fa Mon Sep 17 00:00:00 2001 =46rom: Michael Paquier Date: Mon, 4 Mar 2024 17:42:04 +0900 Subject: [PATCH v3 2/2] Allow specifying access method of partitioned tables =2E.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 | 185 +++++++++++++++++++++--- 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 | 158 +++++++++++++++++++- src/test/regress/sql/create_am.sql | 91 +++++++++++- 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, 489 insertions(+), 34 deletions(-) diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 3b7533e7bb..b505ed1bec 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, 1= 28); /* * Relation kinds with a table access method (rd_tableam). Although seque= nces * use the heap table AM, they are enough of a special case in most uses t= hat - * they are not included here. + * they are not included here. Likewise, partitioned tables can have an a= ccess + * method defined so that their children can inherit it; however, this is + * handled specially outside of this macro. */ #define RELKIND_HAS_TABLE_AM(relkind) \ ((relkind) =3D=3D 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/tablec= mds.c index 3b1c2590fd..bd225b2eb9 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -187,6 +187,7 @@ typedef struct AlteredTableInfo bool verify_new_notnull; /* T if we should recheck NOT NULL */ int rewrite; /* Reason for forced rewrite, if any */ Oid newAccessMethod; /* new access method; 0 means no change */ + bool defaultAccessMethod; /* true if SET ACCESS METHOD DEFAULT */ Oid newTableSpace; /* new tablespace; 0 means no change */ bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */ char newrelpersistence; /* if above is true */ @@ -592,6 +593,8 @@ static ObjectAddress ATExecClusterOn(Relation rel, cons= t char *indexName, LOCKMODE lockmode); static void ATExecDropCluster(Relation rel, LOCKMODE lockmode); static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, con= st char *amname); +static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMeth= od, + bool defaultAccessMethod); static bool ATPrepChangePersistence(Relation rel, bool toLogged); static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, const char *tablespacename, LOCKMODE lockmode); @@ -706,7 +709,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid owne= rId, Oid ofTypeId; ObjectAddress address; LOCKMODE parentLockmode; - const char *accessMethod =3D NULL; Oid accessMethodId =3D InvalidOid; =20 /* @@ -959,20 +961,25 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ow= nerId, * a type of relation that needs one, use the default. */ if (stmt->accessMethod !=3D NULL) + accessMethodId =3D get_table_am_oid(stmt->accessMethod, false); + else if (stmt->partbound) { - accessMethod =3D stmt->accessMethod; - - if (partitioned) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("specifying a table access method is not supported on a parti= tioned table"))); + /* + * For partitions, if no access method is specified, use the AM of the + * parent table. + */ + Assert(list_length(inheritOids) =3D=3D 1); + accessMethodId =3D get_rel_relam(linitial_oid(inheritOids)); } - else if (RELKIND_HAS_TABLE_AM(relkind)) - accessMethod =3D default_table_access_method; + else + accessMethodId =3D InvalidOid; =20 - /* look up the access method, verify it is for a table */ - if (accessMethod !=3D NULL) - accessMethodId =3D get_table_am_oid(accessMethod, false); + /* + * Still nothing? Use the default. Partitioned tables default to + * InvalidOid without an access method specified. + */ + if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId)) + accessMethodId =3D get_table_am_oid(default_table_access_method, false); =20 /* * Create the relation. Inherited defaults and constraints are passed in @@ -5048,12 +5055,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd= *cmd, case AT_SetAccessMethod: /* SET ACCESS METHOD */ ATSimplePermissions(cmd->subtype, rel, ATT_TABLE | ATT_MATVIEW); =20 - /* partitioned tables don't have an access method */ - if (rel->rd_rel->relkind =3D=3D 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 +5411,14 @@ 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 =3D=3D RELKIND_PARTITIONED_TABLE) + ATExecSetAccessMethodNoStorage(rel, tab->newAccessMethod, + tab->defaultAccessMethod); break; case AT_SetTableSpace: /* SET TABLESPACE */ =20 @@ -6402,6 +6411,7 @@ ATGetQueueEntry(List **wqueue, Relation rel) tab->relkind =3D rel->rd_rel->relkind; tab->oldDesc =3D CreateTupleDescCopyConstr(RelationGetDescr(rel)); tab->newAccessMethod =3D InvalidOid; + tab->defaultAccessMethod =3D false; tab->newTableSpace =3D InvalidOid; tab->newrelpersistence =3D RELPERSISTENCE_PERMANENT; tab->chgPersistence =3D false; @@ -15204,7 +15214,15 @@ ATExecDropCluster(Relation rel, LOCKMODE lockmode) * Preparation phase for SET ACCESS METHOD * * Check that access method exists. If it is the same as the table's curr= ent - * access method, it is a no-op. Otherwise, a table rewrite is necessary. + * access method, it is a no-op. Otherwise, a table rewrite is necessary = for + * relations with storage. + * + * amname is NULL for SET ACCESS METHOD DEFAULT. + * + * Partitioned tables may use InvalidOid to assign the default AM to parti= tions + * when created. This operation is a no-op if a DEFAULT was given and the + * partitioned table uses InvalidOid as relam, or if the relam and the acc= ess + * method match. */ static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amn= ame) @@ -15215,12 +15233,35 @@ ATPrepSetAccessMethod(AlteredTableInfo *tab, Rela= tion rel, const char *amname) amoid =3D get_table_am_oid(amname ? amname : default_table_access_method, false); =20 - if (rel->rd_rel->relam =3D=3D amoid) + if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind) && + rel->rd_rel->relam =3D=3D amoid) return; =20 + /* Partitioned tables are handled here */ + if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind)) + { + if (amname =3D=3D NULL) + { + /* DEFAULT implied, leave if relam is already InvalidOid */ + if (!OidIsValid(rel->rd_rel->relam)) + return; + } + else + { + /* + * Access method set by query, leave if only this matches with its + * relam. + */ + if (OidIsValid(rel->rd_rel->relam) && + amoid =3D=3D rel->rd_rel->relam) + return; + } + } + /* Save info for Phase 3 to do the real work */ tab->rewrite |=3D AT_REWRITE_ACCESS_METHOD; tab->newAccessMethod =3D amoid; + tab->defaultAccessMethod =3D (amname =3D=3D NULL); } =20 /* @@ -15545,6 +15586,110 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpa= ce, LOCKMODE lockmode) list_free(reltoastidxids); } =20 +/* + * 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. defaultAccessMethod tracks if a default value is wanted for + * the access method. + */ +static void +ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethodId, + bool defaultAccessMethod) +{ + Relation pg_class; + Oid oldAccessMethodId; + HeapTuple tuple; + Form_pg_class rd_rel; + Oid reloid =3D RelationGetRelid(rel); + + 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)); + + /* Get a modifiable copy of the relation's pg_class row. */ + pg_class =3D table_open(RelationRelationId, RowExclusiveLock); + + tuple =3D SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation %u", reloid); + rd_rel =3D (Form_pg_class) GETSTRUCT(tuple); + + /* Update the pg_class row. */ + oldAccessMethodId =3D rd_rel->relam; + rd_rel->relam =3D defaultAccessMethod ? InvalidOid : newAccessMethodId; + + /* Leave if no update required */ + if (rd_rel->relam =3D=3D 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 new access method is InvalidOid (default case). Be very careful + * that this has to compare the previous value stored in pg_class with the + * new one. + */ + if (!OidIsValid(oldAccessMethodId) && OidIsValid(rd_rel->relam)) + { + 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, rd_rel->relam); + recordDependencyOn(&relobj, &referenced, DEPENDENCY_NORMAL); + } + else if (OidIsValid(oldAccessMethodId) && + !OidIsValid(rd_rel->relam)) + { + /* + * 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) && + OidIsValid(rd_rel->relam)); + + /* Both are valid, so update the dependency */ + changeDependencyFor(RelationRelationId, reloid, + AccessMethodRelationId, + oldAccessMethodId, rd_rel->relam); + } + + 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; } =20 +/* + * 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 =3D SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup =3D (Form_pg_class) GETSTRUCT(tp); + result =3D reltup->relam; + ReleaseSysCache(tp); + + return result; +} + =20 /* ---------- TRANSFORM CACHE ---------- */ =20 diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/r= elcache.c index 37c37df56c..5ad439c685 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 =3D=3D RELKIND_SEQUENCE) RelationInitTableAccessMethod(relation); + else if (relation->rd_rel->relkind =3D=3D RELKIND_PARTITIONED_TABLE) + { + /* + * Do nothing: access methods are a setting that partitions can + * inherit. + */ + } else Assert(relation->rd_rel->relam =3D=3D InvalidOid); =20 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 *tbi= nfo) if (RELKIND_HAS_TABLESPACE(tbinfo->relkind)) tablespace =3D tbinfo->reltablespace; =20 - if (RELKIND_HAS_TABLE_AM(tbinfo->relkind)) + if (RELKIND_HAS_TABLE_AM(tbinfo->relkind) || + tbinfo->relkind =3D=3D RELKIND_PARTITIONED_TABLE) tableam =3D tbinfo->amname; =20 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_du= mp.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 =3D ( no_table_access_method =3D> 1, only_dump_measurement =3D> 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' =3D> { + create_order =3D> 19, + create_sql =3D> ' + CREATE TABLE dump_test.regress_pg_dump_table_am_parent (id int) PARTITI= ON 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 =3D> qr/^ + \QSET default_table_access_method =3D 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 =3D heap;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_child_1 (\E + (.*\n)* + \QSET default_table_access_method =3D regress_table_am;\E + (\n(?!SET[^;]+;)[^\n]*)* + \n\QCREATE TABLE dump_test.regress_pg_dump_table_am_child_2 (\E + (.*\n)*/xm, + like =3D> { + %full_runs, %dump_test_schema_runs, section_pre_data =3D> 1, + }, + unlike =3D> { + exclude_dump_test_schema =3D> 1, + no_table_access_method =3D> 1, + only_dump_measurement =3D> 1, + }, }); =20 ######################################### diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/exp= ected/create_am.out index e843d39ee7..d023f29c59 100644 --- a/src/test/regress/expected/create_am.out +++ b/src/test/regress/expected/create_am.out @@ -176,9 +176,16 @@ SELECT f1 FROM tableam_tblmv_heap2 ORDER BY f1; 1 (1 row) =20 --- CREATE TABLE .. PARTITION BY doesn't not support USING +-- CREATE TABLE .. PARTITION BY supports USING. CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a) US= ING heap2; -ERROR: specifying a table access method is not supported on a partitioned= table +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'tableam_parted_heap2' AND a.oid =3D c.relam; + amname=20 +-------- + heap2 +(1 row) + +DROP TABLE tableam_parted_heap2; CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a); -- new partitions will inherit from the current default, rather the partit= ion root SET default_table_access_method =3D 'heap'; @@ -334,12 +341,151 @@ ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD hea= p, 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 =3D '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 =3D 'am_partitioned'; + relam=20 +------- + 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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D 'am_partitioned'::regclass; + obj | refobj=20 +-----+-------- +(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 =3D 'am_partitioned' AND a.oid =3D c.relam; + amname=20 +-------- + 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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D 'am_partitioned'::regclass; + obj | refobj =20 +----------------------+--------------------- + table am_partitioned | access method heap2 +(1 row) + +-- Default is set, with dependency updated. +SET LOCAL default_table_access_method =3D 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'am_partitioned' AND a.oid =3D c.relam; + amname=20 +-------- + 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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D 'am_partitioned'::regclass; + obj | refobj=20 +-----+-------- +(0 rows) + +-- Default and AM set in in clause are the same, relam should be set. +SET LOCAL default_table_access_method =3D 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'am_partitioned' AND a.oid =3D c.relam; + amname=20 +-------- + heap2 +(1 row) + +-- Reset to default +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; + relam=20 +------- + 0 +(1 row) + +-- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitio= ns +-- will inherit the AM set. Existing partitioned are unchanged. +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; + relam=20 +------- + 0 +(1 row) + +SET LOCAL default_table_access_method =3D 'heap'; +CREATE TABLE am_partitioned_0 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 0); +SET LOCAL default_table_access_method =3D 'heap2'; +CREATE TABLE am_partitioned_1 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +SET LOCAL default_table_access_method =3D 'heap'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_2 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 2); +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; + relam=20 +------- + 0 +(1 row) + +CREATE TABLE am_partitioned_3 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 3); +-- Partitioned table with relam at 0 +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +CREATE TABLE am_partitioned_5p PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 5) PARTITION BY hash(y); +-- Partitions of this partitioned table inherit default AM at creation +-- time. +CREATE TABLE am_partitioned_5p1 PARTITION OF am_partitioned_5p + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +-- Partitioned table with relam set. +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_6p PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 6) PARTITION BY hash(y); +-- Partitions of this partitioned table inherit its AM. +CREATE TABLE am_partitioned_6p1 PARTITION OF am_partitioned_6p + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +SELECT c.relname, a.amname FROM pg_class c, pg_am a + WHERE c.relam =3D a.oid AND + c.relname LIKE 'am_partitioned%' +UNION ALL +SELECT c.relname, 'default' FROM pg_class c + WHERE c.relam =3D 0 + AND c.relname LIKE 'am_partitioned%' ORDER BY 1; + relname | amname =20 +--------------------+--------- + am_partitioned | heap2 + am_partitioned_0 | heap + am_partitioned_1 | heap2 + am_partitioned_2 | heap2 + am_partitioned_3 | heap + am_partitioned_5p | default + am_partitioned_5p1 | heap + am_partitioned_6p | heap2 + am_partitioned_6p1 | heap2 +(9 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 =3D 'heap2'; diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/crea= te_am.sql index f752bf1678..010c07cdd2 100644 --- a/src/test/regress/sql/create_am.sql +++ b/src/test/regress/sql/create_am.sql @@ -124,8 +124,11 @@ CREATE SEQUENCE tableam_seq_heap2 USING heap2; CREATE MATERIALIZED VIEW tableam_tblmv_heap2 USING heap2 AS SELECT * FROM = tableam_tbl_heap2; SELECT f1 FROM tableam_tblmv_heap2 ORDER BY f1; =20 --- CREATE TABLE .. PARTITION BY doesn't not support USING +-- CREATE TABLE .. PARTITION BY supports USING. CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a) US= ING heap2; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'tableam_parted_heap2' AND a.oid =3D c.relam; +DROP TABLE tableam_parted_heap2; =20 CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a); -- new partitions will inherit from the current default, rather the partit= ion root @@ -212,11 +215,91 @@ ALTER TABLE heaptable SET ACCESS METHOD heap, SET ACC= ESS METHOD heap2; ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD h= eap2; 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 =3D '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 =3D '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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D '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 =3D 'am_partitioned' AND a.oid =3D 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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D 'am_partitioned'::regclass; +-- Default is set, with dependency updated. +SET LOCAL default_table_access_method =3D 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'am_partitioned' AND a.oid =3D 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 =3D 'pg_am'::regclass + AND pg_am.oid =3D pg_depend.refobjid + AND pg_depend.objid =3D 'am_partitioned'::regclass; +-- Default and AM set in in clause are the same, relam should be set. +SET LOCAL default_table_access_method =3D 'heap2'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +SELECT a.amname FROM pg_class c, pg_am a + WHERE c.relname =3D 'am_partitioned' AND a.oid =3D c.relam; +-- Reset to default +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; +-- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitio= ns +-- will inherit the AM set. Existing partitioned are unchanged. +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; +SET LOCAL default_table_access_method =3D 'heap'; +CREATE TABLE am_partitioned_0 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 0); +SET LOCAL default_table_access_method =3D 'heap2'; +CREATE TABLE am_partitioned_1 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +SET LOCAL default_table_access_method =3D 'heap'; +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_2 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 2); +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +SELECT relam FROM pg_class WHERE relname =3D 'am_partitioned'; +CREATE TABLE am_partitioned_3 PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 3); +-- Partitioned table with relam at 0 +ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT; +CREATE TABLE am_partitioned_5p PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 5) PARTITION BY hash(y); +-- Partitions of this partitioned table inherit default AM at creation +-- time. +CREATE TABLE am_partitioned_5p1 PARTITION OF am_partitioned_5p + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +-- Partitioned table with relam set. +ALTER TABLE am_partitioned SET ACCESS METHOD heap2; +CREATE TABLE am_partitioned_6p PARTITION OF am_partitioned + FOR VALUES WITH (MODULUS 10, REMAINDER 6) PARTITION BY hash(y); +-- Partitions of this partitioned table inherit its AM. +CREATE TABLE am_partitioned_6p1 PARTITION OF am_partitioned_6p + FOR VALUES WITH (MODULUS 10, REMAINDER 1); +SELECT c.relname, a.amname FROM pg_class c, pg_am a + WHERE c.relam =3D a.oid AND + c.relname LIKE 'am_partitioned%' +UNION ALL +SELECT c.relname, 'default' FROM pg_class c + WHERE c.relam =3D 0 + AND c.relname LIKE 'am_partitioned%' ORDER BY 1; DROP TABLE am_partitioned; +COMMIT; =20 -- 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$<iteration count>:&l 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. =20 diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_tab= le.sgml index 96e3d77605..779c8b3122 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -737,6 +737,14 @@ WITH ( MODULUS numeri= c_literal, REM DEFAULT changes the access method of the table to . + + When applied to a partitioned table, there is no data to rewrite, bu= t any + partitions created afterwards will use that access method unless + overridden by a USING clause. Using + DEFAULT switches the partitioned table to rely on + the value of default_table_access_method set + when new partitions are created, instead. + =20 diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_t= able.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 nume= ric_literal, REM method is chosen for the new table. See for more information. + + When creating a partition, the table access method is the access met= hod + of its partitioned table, if set. + =20 --=20 2.43.0 --wZYC/6ns4foT4Uak-- --9wSQnFLv3emD+9JY Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEG72nH6vTowiyblFKnvQgOdbyQH0FAmXlioAACgkQnvQgOdby QH1l8A//SDgxkZgLxRG/Lr7Devf35aRiWn30vgyzJ1tHbEVWimV/oP7SGA6xgre6 oSdp1mV2FQHUXRrXBZO3afm++e7FxJ44ZpoBxSkVArMssu6ZAXhn5hGtbgBqyI2b 6KQI6c3hCGa7RmabGka/S6Ai/0+7tGJ/n97OFKHnt+pWXxdcXgKcpideCKkvoiMy 7DjKsovwAaSkQ1jgVMJHDL3dZiGG3MGgr1hpohIwbP7jeZPJqUfYYYc3FjszZkQe Qi5rMDVLi9ytSYQeeffMzJR0yCMB68ch0qACsyAI92kxm2E656MEhcw/3+gVvRdS T4j2ykIchKrIuBrvyCqtHcX0v3BPR1OBhL8ZqUI7p5iGFdhvVU23aSSAj/0uqt4/ RSYCOhUS/wjWNrNarvcv26mew4ijv7F6bZRZjXzeuNG5bMH8mEWpiOToalue34T3 OeOOWciJ9I3CJTH9EwEwOwxoQpx6EwQwrEpsVdKjY16CuRN0NqzF+eZWQ013HcHY 5dAkoqqLGDYoyoW/4VYF94uevTz4D8EOYDDV8TPq1ggJ953odzwd5w9/1P03l0d2 cy6vv4HjLJaNQeuZ99yjyGe7imEE8AGPrJGLhsRyZzfl9XFFTJuS1dOJQpqw1yEx gL4THAgaKJPUmkLZxAoEQUOcV1cSxYnv99/dhUzYfxgIYlhSHtw= =E8wZ -----END PGP SIGNATURE----- --9wSQnFLv3emD+9JY--