From afc58e9013db888baf333768225afaf993fcfd54 Mon Sep 17 00:00:00 2001 From: "David G. Johnston" Date: Wed, 7 Jan 2026 14:50:36 -0700 Subject: [PATCH v3] docs: clarify ALTER TABLE behavior on partitioned tables Document how individual ALTER TABLE sub-commands behave when applied to partitioned tables. The existing ALTER TABLE documentation provides limited or incomplete information about how commands interact with partitioned tables, leaving users to infer behavior from experimentation. This patch systematically clarifies, for each relevant sub-command, whether changes propagate to existing partitions, can be applied independently to partitions, and how the ONLY keyword behaves. In addition, clarify in CREATE TABLE documentation which parent table settings are inherited by newly created partitions and which are not. This makes explicit that while most definition-level properties are inherited from the partitioned table, certain per-relation settings (such as ownership, schema, replica identity, row-level security, and per-attribute statistics/options) are not, unless explicitly specified. No behavior is changed by this patch; it is purely a documentation update intended to make existing semantics explicit and easier to understand. Author: Chao Li Author: David G. Johnston Reviewed-by: David G. Johnston Discussion: https://postgr.es/m/CAEoWx2=mYhCfsnHaN96Qqwq5b0GVS2YgO3zpVqPPRd_iO52wRw@mail.gmail.com --- doc/src/sgml/ref/alter_table.sgml | 306 ++++++++++++++++++++--------- doc/src/sgml/ref/create_table.sgml | 9 + 2 files changed, 222 insertions(+), 93 deletions(-) diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 1bd479c917a..8577e2cdcdd 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -171,6 +171,12 @@ WITH ( MODULUS numeric_literal, REM is specified and a column already exists with this name, no error is thrown. + + When applied to a partitioned table, the column is added to the + partitioned table definition and is implicitly added to all + partitions. Specifying ONLY is not allowed, and + this command cannot be used on individual partitions. + @@ -190,6 +196,12 @@ WITH ( MODULUS numeric_literal, REM does not exist, no error is thrown. In this case a notice is issued instead. + + When applied to a partitioned table, the column is removed from the + partitioned table definition and is implicitly removed from all + partitions. Specifying ONLY is not allowed, and + this command cannot be used on individual partitions. + @@ -211,7 +223,6 @@ WITH ( MODULUS numeric_literal, REM clause must be provided if there is no implicit or assignment cast from old to new type. - When this form is used, the column's statistics are removed, so running ANALYZE @@ -219,6 +230,12 @@ WITH ( MODULUS numeric_literal, REM For a virtual generated column, ANALYZE is not necessary because such columns never have statistics. + + When applied to a partitioned table, the data type change is applied + to the partitioned table definition and is implicitly applied to all + partitions. Specifying ONLY is not allowed, + and this command cannot be used on individual partitions. + @@ -232,6 +249,10 @@ WITH ( MODULUS numeric_literal, REM or UPDATE commands; it does not cause rows already in the table to change. + + When applied to a partitioned table, the default value is propagated + to all partitions unless ONLY is specified. + @@ -242,7 +263,6 @@ WITH ( MODULUS numeric_literal, REM These forms change whether a column is marked to allow null values or to reject null values. - SET NOT NULL may only be applied to a column provided none of the records in the table contain a @@ -255,18 +275,18 @@ WITH ( MODULUS numeric_literal, REM If a column has an invalid not-null constraint, SET NOT NULL validates it. - - If this table is a partition, one cannot perform DROP NOT NULL - on a column if it is marked NOT NULL in the parent - table. To drop the NOT NULL constraint from all the - partitions, perform DROP NOT NULL on the parent - table. Even if there is no NOT NULL constraint on the - parent, such a constraint can still be added to individual partitions, - if desired; that is, the children can disallow nulls even if the parent - allows them, but not the other way around. It is also possible to drop - the NOT NULL constraint from ONLY - the parent table, which does not remove it from the children. + If this table is a partition, one cannot perform + DROP NOT NULL on a column if it is marked + NOT NULL in the parent table. To drop the + NOT NULL constraint from all partitions, perform + DROP NOT NULL on the parent table. Even if there is + no NOT NULL constraint on the parent, such a + constraint can still be added to individual partitions; that is, the + children can disallow nulls even if the parent allows them, but not + the other way around. It is also possible to apply + SET NOT NULL or DROP NOT NULL to + ONLY the parent table. @@ -279,7 +299,6 @@ WITH ( MODULUS numeric_literal, REM in a stored generated column is rewritten and all the future changes will apply the new generation expression. - When this form is used on a stored generated column, its statistics are removed, so running @@ -288,6 +307,11 @@ WITH ( MODULUS numeric_literal, REM For a virtual generated column, ANALYZE is not necessary because such columns never have statistics. + + When applied to a partitioned table, the generation expression is + propagated to all partitions unless ONLY + is specified. + @@ -299,17 +323,21 @@ WITH ( MODULUS numeric_literal, REM Existing data in the columns is retained, but future changes will no longer apply the generation expression. - This form is currently only supported for stored generated columns (not virtual ones). - If DROP EXPRESSION IF EXISTS is specified and the column is not a generated column, no error is thrown. In this case a notice is issued instead. + + When applied to a partitioned table, the generation expression is + dropped from the partitioned table definition and from all + partitions. Specifying ONLY is not allowed, and + this command cannot be used on individual partitions. + @@ -327,12 +355,17 @@ WITH ( MODULUS numeric_literal, REM and UPDATE commands; they do not cause rows already in the table to change. - If DROP IDENTITY IF EXISTS is specified and the column is not an identity column, no error is thrown. In this case a notice is issued instead. + + When applied to a partitioned table, the identity property is defined + on the partitioned table and is applied to all partitions. + Specifying ONLY is not allowed, and these forms + cannot be used on individual partitions. + @@ -346,6 +379,13 @@ WITH ( MODULUS numeric_literal, REM supported by ALTER SEQUENCE such as INCREMENT BY. + + When applied to a partitioned table, these forms alter the sequence + associated with the identity column on the partitioned table + and all individual partitions. Specifying ONLY + is not allowed, and these forms cannot be used on individual + partitions. + @@ -369,6 +409,10 @@ WITH ( MODULUS numeric_literal, REM SET STATISTICS acquires a SHARE UPDATE EXCLUSIVE lock. + + For partitioned tables, this action applies to the partitioned table + and all of its partitions unless ONLY is specified. + @@ -403,6 +447,11 @@ WITH ( MODULUS numeric_literal, REM Changing per-attribute options acquires a SHARE UPDATE EXCLUSIVE lock. + + When applied to a partitioned table ONLY is implicit, + these forms must be applied separately to the partitioned table and/or to + individual partitions. + @@ -437,6 +486,10 @@ WITH ( MODULUS numeric_literal, REM during future table updates. See for more information. + + When applied to a partitioned table, the storage setting is propagated + to all existing partitions unless ONLY is specified. + @@ -467,6 +520,11 @@ WITH ( MODULUS numeric_literal, REM consulting the setting at the time of data insertion to determine the method to use. + + When applied to a partitioned table ONLY is implicit, + the compression method must be applied separately to the partitioned table + and/or to individual partitions. + @@ -479,7 +537,6 @@ WITH ( MODULUS numeric_literal, REM VALID, which is currently only allowed for foreign-key, CHECK, and not-null constraints. - Normally, this form will cause a scan of the table to verify that all existing rows in the table satisfy the new constraint. But if @@ -495,7 +552,6 @@ WITH ( MODULUS numeric_literal, REM See below for more information about using the NOT VALID option. - Although most forms of ADD table_constraint @@ -506,12 +562,15 @@ WITH ( MODULUS numeric_literal, REM referenced table, in addition to the lock on the table on which the constraint is declared. - Additional restrictions apply when unique or primary key constraints are added to partitioned tables; see CREATE TABLE. - + + When applied to a partitioned table, the constraint is added to the + partitioned table and is implicitly added to all partitions. + Specifying ONLY is not allowed. + @@ -523,7 +582,6 @@ WITH ( MODULUS numeric_literal, REM constraint to a table based on an existing unique index. All the columns of the index will be included in the constraint. - The index cannot have expression columns nor be a partial index. Also, it must be a b-tree index with default sort ordering. These @@ -531,7 +589,6 @@ WITH ( MODULUS numeric_literal, REM built by a regular ADD PRIMARY KEY or ADD UNIQUE command. - If PRIMARY KEY is specified, and the index's columns are not already marked NOT NULL, then this command will attempt to @@ -539,13 +596,11 @@ WITH ( MODULUS numeric_literal, REM That requires a full table scan to verify the column(s) contain no nulls. In all other cases, this is a fast operation. - If a constraint name is provided then the index will be renamed to match the constraint name. Otherwise the constraint will be named the same as the index. - After this command is executed, the index is owned by the constraint, in the same way as if the index had been built by @@ -553,11 +608,10 @@ WITH ( MODULUS numeric_literal, REM command. In particular, dropping the constraint will make the index disappear too. - - This form is not currently supported on partitioned tables. + This form is not supported on partitioned tables, but can be used on + individual partitions. - Adding a constraint using an existing index can be helpful in @@ -578,6 +632,12 @@ WITH ( MODULUS numeric_literal, REM created. Currently only foreign key constraints may be altered in this fashion, but see below. + + When applied to a partitioned table, the constraint is altered on the + partitioned table definition is implicitly applied to all partitions. + Specifying ONLY is not allowed, and this command + cannot be used on individual partitions. + @@ -596,7 +656,11 @@ WITH ( MODULUS numeric_literal, REM non-inheritable on a table with children, then the corresponding constraint on children will be marked as no longer inherited, but not removed. - + + + These forms are not supported on partitioned tables, but can be used + on individual partitions. + @@ -615,6 +679,12 @@ WITH ( MODULUS numeric_literal, REM This command acquires a SHARE UPDATE EXCLUSIVE lock. + + When applied to a partitioned table, the constraint is validated on the + partitioned table and on all partitions. Unlike most constraint-related + sub-commands, individual partitions may validate the constraint + independently of the partitioned table. + @@ -627,6 +697,12 @@ WITH ( MODULUS numeric_literal, REM If IF EXISTS is specified and the constraint does not exist, no error is thrown. In this case a notice is issued instead. + + When applied to a partitioned table, the constraint is dropped from + all existing partitions unless ONLY is specified. + Individual partitions may drop constraints independently of the + partitioned table. + @@ -648,7 +724,6 @@ WITH ( MODULUS numeric_literal, REM of course the integrity of the constraint cannot be guaranteed if the triggers are not executed. - The trigger firing mechanism is also affected by the configuration variable . Simply enabled @@ -658,7 +733,6 @@ WITH ( MODULUS numeric_literal, REM mode, and triggers configured as ENABLE ALWAYS will fire regardless of the current replication role. - The effect of this mechanism is that in the default configuration, triggers do not fire on replicas. This is useful because if a trigger @@ -670,13 +744,14 @@ WITH ( MODULUS numeric_literal, REM to ENABLE ALWAYS so that it is also fired on replicas. - When this command is applied to a partitioned table, the states of - corresponding clone triggers in the partitions are updated too, - unless ONLY is specified. + corresponding clone triggers in existing partitions are updated too, + unless ONLY is specified. Triggers in partitions + created afterwards inherit the trigger state from the partitioned + table, while individual partitions may configure trigger states + independently. - This command acquires a SHARE ROW EXCLUSIVE lock. @@ -694,12 +769,16 @@ WITH ( MODULUS numeric_literal, REM are always applied in order to keep views working even if the current session is in a non-default replication role. - The rule firing mechanism is also affected by the configuration variable , analogous to triggers as described above. + + When applied to a partitioned table ONLY is implicit, + these forms must be applied separately to the partitioned table + and/or to individual partitions. + @@ -715,6 +794,11 @@ WITH ( MODULUS numeric_literal, REM See also CREATE POLICY. + + When applied to a partitioned table ONLY is implicit, + these forms must be applied separately to the partitioned table and/or to + individual partitions. + @@ -730,6 +814,11 @@ WITH ( MODULUS numeric_literal, REM See also CREATE POLICY. + + When applied to a partitioned table ONLY is implicit, + this form must be applied separately to the partitioned table and/or to + individual partitions. + @@ -744,6 +833,10 @@ WITH ( MODULUS numeric_literal, REM Changing cluster options acquires a SHARE UPDATE EXCLUSIVE lock. + + This form is not supported on partitioned tables, but can be used on + individual partitions. + @@ -759,6 +852,10 @@ WITH ( MODULUS numeric_literal, REM Changing cluster options acquires a SHARE UPDATE EXCLUSIVE lock. + + This form is not supported on partitioned tables, but can be used on + individual partitions. + @@ -785,11 +882,13 @@ WITH ( MODULUS numeric_literal, REM See for more information. - When applied to a partitioned table, there is no data to rewrite, - but partitions created afterwards will default to the given access - method unless overridden by a USING clause. - Specifying DEFAULT removes a previous value, - causing future partitions to default to + When applied to a partitioned table, there is no data to rewrite. + Partitions created afterwards will use the access method specified + on the partitioned table, if any, unless overridden by a + USING clause; otherwise they default to + default_table_access_method. Specifying + DEFAULT removes a previously set access method, + causing future partitions to use default_table_access_method. @@ -803,12 +902,11 @@ WITH ( MODULUS numeric_literal, REM moves the data file(s) associated with the table to the new tablespace. Indexes on the table, if any, are not moved; but they can be moved separately with additional SET TABLESPACE commands. - When applied to a partitioned table, nothing is moved, but any - partitions created afterwards with - CREATE TABLE PARTITION OF will use that tablespace, - unless overridden by a TABLESPACE clause. + When applied to a partitioned table, no data is moved. Existing + partitions are not affected, but partitions created afterwards with + CREATE TABLE PARTITION OF will use the specified + tablespace unless overridden by a TABLESPACE clause. - All tables in the current database in a tablespace can be moved by using the ALL IN TABLESPACE form, which will lock all tables @@ -835,15 +933,14 @@ WITH ( MODULUS numeric_literal, REM (see ). It cannot be applied to a temporary table. - This also changes the persistence of any sequences linked to the table (for identity or serial columns). However, it is also possible to change the persistence of such sequences separately. - - This form is not supported for partitioned tables. + This form is not supported on partitioned tables, but can be used on + individual partitions. @@ -865,12 +962,15 @@ WITH ( MODULUS numeric_literal, REM time the table is locked so currently executing queries will not be affected. - SHARE UPDATE EXCLUSIVE lock will be taken for fillfactor, TOAST and autovacuum storage parameters, as well as the planner parameter parallel_workers. + + This form is not supported on partitioned tables, but can be used on + individual partitions. + @@ -882,6 +982,11 @@ WITH ( MODULUS numeric_literal, REM defaults. As with SET, a table rewrite might be needed to update the table entirely. + + When applied to a partitioned table, this form is accepted but has no + effect. It can be used on individual partitions, where it + behaves as for a regular table. + @@ -895,7 +1000,6 @@ WITH ( MODULUS numeric_literal, REM already contain all the same columns as the parent (it could have additional columns, too). The columns must have matching data types. - In addition, all CHECK and NOT NULL constraints on the parent must also exist on the child, except those @@ -907,6 +1011,10 @@ WITH ( MODULUS numeric_literal, REM FOREIGN KEY constraints are not considered, but this might change in the future. + + This form does not support partitioned tables; it cannot be applied to + either a partitioned table or its partitions. + @@ -919,6 +1027,10 @@ WITH ( MODULUS numeric_literal, REM Queries against the parent table will no longer include records drawn from the target table. + + This form does not support partitioned tables; it cannot be applied to + either a partitioned table or its partitions. + @@ -933,6 +1045,10 @@ WITH ( MODULUS numeric_literal, REM that CREATE TABLE OF would permit an equivalent table definition. + + When applied to a partitioned table ONLY is implicit, + and this form cannot be used on individual partitions. + @@ -942,6 +1058,10 @@ WITH ( MODULUS numeric_literal, REM This form dissociates a typed table from its type. + + When applied to a partitioned table ONLY is implicit, + and this form cannot be used on individual partitions. + @@ -952,6 +1072,11 @@ WITH ( MODULUS numeric_literal, REM This form changes the owner of the table, sequence, view, materialized view, or foreign table to the specified user. + + When applied to a partitioned table ONLY is implicit, + this form must be applied separately to the partitioned table and/or to + individual partitions. + @@ -1008,6 +1133,12 @@ WITH ( MODULUS numeric_literal, REM + + + When applied to a partitioned table ONLY is implicit, + this form must be applied independently to the partitioned table and/or + to individual partitions. + @@ -1022,6 +1153,11 @@ WITH ( MODULUS numeric_literal, REM the index is renamed as well. There is no effect on the stored data. + + For partitioned tables, this form behaves the same as for regular + tables. Renaming a partitioned table, column, or constraint does not + propagate to partitions. + @@ -1032,6 +1168,11 @@ WITH ( MODULUS numeric_literal, REM This form moves the table into another schema. Associated indexes, constraints, and sequences owned by table columns are moved as well. + + When applied to a partitioned table ONLY is implicit, + this form must be applied independently to the partitioned table and/or + to individual partitions. + @@ -1410,6 +1551,27 @@ WITH ( MODULUS numeric_literal, REM * can be specified after the table name to explicitly indicate that descendant tables are included. + + + For a table that uses table inheritance, descendant tables are those + that inherit from the named table, directly or indirectly. + For a partitioned table, descendant tables are its partitions. + + + + Note that for partitioned tables, ONLY does not control + recursion for all ALTER TABLE actions. Some actions + apply only to the partitioned table itself, regardless of whether + ONLY is specified, while others are propagated to + partitions. The exact behavior depends on the specific action being + performed. + + + + Users should consult the documentation of each individual + ALTER TABLE action to determine whether and how it + affects partitions. + @@ -1767,48 +1929,6 @@ WITH ( MODULUS numeric_literal, REM the column. - - If a table has any descendant tables, it is not permitted to add, - rename, or change the type of a column in the parent table without doing - the same to the descendants. This ensures that the descendants always - have columns matching the parent. Similarly, a CHECK - constraint cannot be renamed in the parent without also renaming it in - all descendants, so that CHECK constraints also match - between the parent and its descendants. (That restriction does not apply - to index-based constraints, however.) - Also, because selecting from the parent also selects from its descendants, - a constraint on the parent cannot be marked valid unless it is also marked - valid for those descendants. In all of these cases, ALTER TABLE - ONLY will be rejected. - - - - A recursive DROP COLUMN operation will remove a - descendant table's column only if the descendant does not inherit - that column from any other parents and never had an independent - definition of the column. A nonrecursive DROP - COLUMN (i.e., ALTER TABLE ONLY ... DROP - COLUMN) never removes any descendant columns, but - instead marks them as independently defined rather than inherited. - A nonrecursive DROP COLUMN command will fail for a - partitioned table, because all partitions of a table must have the same - columns as the partitioning root. - - - - The actions for identity columns (ADD - GENERATED, SET etc., DROP - IDENTITY), as well as the actions - CLUSTER, OWNER, - and TABLESPACE never recurse to descendant tables; - that is, they always act as though ONLY were specified. - Actions affecting trigger states recurse to partitions of partitioned - tables (unless ONLY is specified), but never to - traditional-inheritance descendants. - Adding a constraint recurses only for CHECK constraints - that are not marked NO INHERIT. - - Changing any part of a system catalog table is not permitted. diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 77c5a763d45..780e4f0799f 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -633,6 +633,15 @@ WITH ( MODULUS numeric_literal, REM concurrent operations on the partitioned table. + + When a new partition is created, it generally inherits the current + definition-level settings of the parent partitioned table. However, + some table properties are not inherited automatically. In particular, + settings related to ownership, schema, replica identity, row-level + security configuration, per-attribute statistics targets, and + per-attribute options are not inherited unless explicitly specified + for the partition. + -- 2.39.5 (Apple Git-154)