Обсуждение: ALTER TABLE: warn when actions do not recurse to partitions
Hi Hacker,
This patch is part of a broader effort to make ALTER TABLE actions behave more consistently with respect to partitioned tables. There has been ongoing discussion around this area; see [1], which also links to earlier related threads.
In short, changing ALTER TABLE semantics requires more discussion and coordination than a single patch can realistically achieve. Before that larger work happens, I’m following up on [1] by trying to clarify the current behavior, both in documentation and in user-facing feedback.
This patch adds warning messages for sub-commands that appear to recurse but in fact do not. These currently include:
* SET STATISTICS
* SET/RESET (attribute_option = value)
* ENABLE/DISABLE [ REPLICA | ALWAYS] RULE
* ENABLE/DISABLE ROW LEVEL SECURITY
* NO FORCE / FORCE ROW LEVEL SECURITY
* OWNER TO
* REPLICA IDENTITY
* SET SCHEMA
* SET/RESET (attribute_option = value)
* ENABLE/DISABLE [ REPLICA | ALWAYS] RULE
* ENABLE/DISABLE ROW LEVEL SECURITY
* NO FORCE / FORCE ROW LEVEL SECURITY
* OWNER TO
* REPLICA IDENTITY
* SET SCHEMA
For example, if a user runs:
```
ALTER TABLE ONLY a_partitioned_table REPLICA IDENTITY FULL;
```
the semantics are clear: only the partitioned table itself is modified.
However, if the user runs the same command without ONLY:
```
ALTER TABLE a_partitioned_table REPLICA IDENTITY FULL;
```
```
there is potential confusion. From the command syntax alone, it is reasonable to assume that the change would propagate to child partitions, but in reality, it does not. Since the ALTER TABLE documentation does not explicitly spell this out, users often need to test the behavior themselves to be sure, which is a poor user experience.
With this patch, the command instead emits a warning such as:
```
evantest=# alter table sensor_data replica identity full;
WARNING: REPLICA IDENTITY is only applied to the partitioned table itself
ALTER TABLE
```
This makes the behavior explicit and removes the ambiguity.
For now, I’ve limited the change to REPLICA IDENTITY to see whether there are objections to this approach. If there are none, I plan to extend the same warning behavior to the other sub-commands listed above. After that, users can reasonably assume that an ALTER TABLE partitioned_table ... action will recurse to child partitions unless a warning explicitly tells them otherwise.
Вложения
On Monday, January 12, 2026, Chao Li <li.evan.chao@gmail.com> wrote:
For now, I’ve limited the change to REPLICA IDENTITY to see whether there are objections to this approach. If there are none, I plan to extend the same warning behavior to the other sub-commands listed above. After that, users can reasonably assume that an ALTER TABLE partitioned_table ... action will recurse to child partitions unless a warning explicitly tells them otherwise.
It should be a notice, not a warning.
How about indicating how many partitions were affected in the notice and allowing the absence of such a notice to be the indicator that cascading did not happen?
David J.
On Mon, Jan 12, 2026 at 9:40 AM David G. Johnston <david.g.johnston@gmail.com> wrote:
How about indicating how many partitions were affected in the notice and allowing the absence of such a notice to be the indicator that cascading did not happen?
I like the idea of number of partitions, but think we need to be more explicit than people surmising the lack of a notice is significant.
Cheers,
Greg
--
Crunchy Data - https://www.crunchydata.com
Enterprise Postgres Software Products & Tech Support
Hi David and Greg,
Thanks a lot for your reviews and feedbacks.
On Jan 12, 2026, at 22:40, David G. Johnston <david.g.johnston@gmail.com> wrote:
On Monday, January 12, 2026, Chao Li <li.evan.chao@gmail.com> wrote:
For now, I’ve limited the change to REPLICA IDENTITY to see whether there are objections to this approach. If there are none, I plan to extend the same warning behavior to the other sub-commands listed above. After that, users can reasonably assume that an ALTER TABLE partitioned_table ... action will recurse to child partitions unless a warning explicitly tells them otherwise.
It should be a notice, not a warning.
Make sense. I changed to NOTICE in v2.
How about indicating how many partitions were affected in the notice and
I added partition count in the notice message in v2.
allowing the absence of such a notice to be the indicator that cascading did not happen?
David J.
I don’t think relying on the absence of a notice works well in this case.
Currently, cascading never happens, which is exactly why I’m adding a NOTICE. If we rely on silence to indicate “no cascade”, users have no signal that their expectation was incorrect.
The ALTER TABLE documentation says:
```
If ONLY is specified before the table name, only that table is altered. If ONLY is not specified, the table and all its descendant tables (if any) are altered.
```
Given this, users reasonably expect that omitting ONLY will cause REPLICA IDENTITY to cascade to partitions. In reality, it never does, which breaks that expectation. The NOTICE is intended to make this behavior explicit in exactly that case.
On Jan 12, 2026, at 23:23, Greg Sabino Mullane <htamfids@gmail.com> wrote:
On Mon, Jan 12, 2026 at 9:40 AM David G. Johnston <david.g.johnston@gmail.com> wrote:
How about indicating how many partitions were affected in the notice and allowing the absence of such a notice to be the indicator that cascading did not happen?
I like the idea of number of partitions, but think we need to be more explicit than people surmising the lack of a notice is significant.
Cheers,
Greg
As explained above, the NOTICE is only emitted in the case where the documented ALTER TABLE semantics suggest cascading, but REPLICA IDENTITY
does not actually cascade to partitions. This makes the behavior explicit, rather than relying on users to infer meaning from the absence of a message.
PSA v2:
* Changed level log to NOTICE
* Rephrased the notice message and included partition count in the message.
Now, the message is like:
```
evantest=# alter table sensor_data replica identity full;
NOTICE: REPLICA IDENTITY does not apply to partitions (1 affected)
ALTER TABLE
```
Best regards,
Вложения
On Monday, January 12, 2026, Chao Li <li.evan.chao@gmail.com> wrote:
Now, the message is like:```evantest=# alter table sensor_data replica identity full;NOTICE: REPLICA IDENTITY does not apply to partitions (1 affected)ALTER TABLE
If it doesn't recurse there should be no count. It would either always be 1, so not helpful, or if did show a partition count, beside the point. In the later case suppress the message if there are no partitions present.
The statement “does not apply to partitions” is also factually wrong. One would just need to name the partition explicitly.
NOTICE: present partitions not affected
HINT: partitions may be modified individually using separate commands
ALTER TABLE
David J.
On Tue, Jan 13, 2026 at 11:42 AM David G. Johnston <david.g.johnston@gmail.com> wrote:
On Monday, January 12, 2026, Chao Li <li.evan.chao@gmail.com> wrote:Now, the message is like:```evantest=# alter table sensor_data replica identity full;NOTICE: REPLICA IDENTITY does not apply to partitions (1 affected)ALTER TABLEIf it doesn't recurse there should be no count. It would either always be 1, so not helpful, or if did show a partition count, beside the point. In the later case suppress the message if there are no partitions present.
The count was real. I agree that we can suppress the message when there are no partitions. Addressed that in v3.
The statement “does not apply to partitions” is also factually wrong. One would just need to name the partition explicitly.NOTICE: present partitions not affectedHINT: partitions may be modified individually using separate commandsALTER TABLE
Thanks for the suggestion, I took that in v3.
PSA v3:
* Rephrased the notice message as David's suggestion.
* Removed partition count from notice message.
* If a partitioned table doesn't have any partition, then suppress the message.
Now the command outputs look like:
```
evantest=# alter table sensor_data replica identity full;
NOTICE: present partitions not affected
HINT: partitions may be modified individually using separate commands
ALTER TABLE
```
```
evantest=# alter table sensor_data replica identity full;
NOTICE: present partitions not affected
HINT: partitions may be modified individually using separate commands
ALTER TABLE
```
Best regards,
--
Chao Li (Evan)HighGo Software Co., Ltd.
Вложения
Hi Chao On 13/01/2026 05:02, Chao Li wrote: > > PSA v3: > > * Rephrased the notice message as David's suggestion. > * Removed partition count from notice message. > * If a partitioned table doesn't have any partition, then suppress the > message. I've been playing with this patch, and it seems to work as expected - I'm surprised it didn't break any existing tests :). Do you plan to extend this patch to other subcommands mentioned in your initial post, such as SET STATISTICS? Thanks for the patch Best, Jim == tests == CREATE TABLE m (a int NOT NULL, b int) PARTITION BY RANGE (a); CREATE TABLE m_p1 PARTITION OF m FOR VALUES FROM (1) TO (10); CREATE TABLE m_p2 PARTITION OF m FOR VALUES FROM (10) TO (20); CREATE UNIQUE INDEX m_idx ON m(a); CREATE UNIQUE INDEX m_p1_idx ON m_p1(a); CREATE UNIQUE INDEX m_p2_idx ON m_p2(a); CREATE TABLE CREATE TABLE CREATE TABLE CREATE INDEX CREATE INDEX CREATE INDEX -- issue a NOTICE (m has partitions) ALTER TABLE m REPLICA IDENTITY NOTHING; ALTER TABLE m REPLICA IDENTITY FULL; ALTER TABLE m REPLICA IDENTITY DEFAULT; ALTER TABLE m REPLICA IDENTITY USING INDEX m_idx; NOTICE: present partitions not affected HINT: partitions may be modified individually using separate commands ALTER TABLE NOTICE: present partitions not affected HINT: partitions may be modified individually using separate commands ALTER TABLE NOTICE: present partitions not affected HINT: partitions may be modified individually using separate commands ALTER TABLE NOTICE: present partitions not affected HINT: partitions may be modified individually using separate commands ALTER TABLE -- does not issue a NOTICE (with ONLY: no recursion into partitions) ALTER TABLE ONLY m REPLICA IDENTITY NOTHING; ALTER TABLE ONLY m REPLICA IDENTITY FULL; ALTER TABLE ONLY m REPLICA IDENTITY DEFAULT; ALTER TABLE ONLY m REPLICA IDENTITY USING INDEX m_idx; ALTER TABLE ALTER TABLE ALTER TABLE ALTER TABLE -- does not issue a NOTICE (p1 has no partitions) ALTER TABLE m_p1 REPLICA IDENTITY NOTHING; ALTER TABLE m_p1 REPLICA IDENTITY FULL; ALTER TABLE m_p1 REPLICA IDENTITY DEFAULT; ALTER TABLE m_p1 REPLICA IDENTITY USING INDEX m_p1_idx; ALTER TABLE ALTER TABLE ALTER TABLE ALTER TABLE -- does not issue a NOTICE (m no longer has partitions) DROP TABLE m_p1, m_p2; DROP TABLE ALTER TABLE m REPLICA IDENTITY NOTHING; ALTER TABLE m REPLICA IDENTITY FULL; ALTER TABLE m REPLICA IDENTITY DEFAULT; ALTER TABLE m REPLICA IDENTITY USING INDEX m_idx; ALTER TABLE ALTER TABLE ALTER TABLE ALTER TABLE
> On Jan 13, 2026, at 19:16, Jim Jones <jim.jones@uni-muenster.de> wrote: > > Hi Chao > > On 13/01/2026 05:02, Chao Li wrote: >> >> PSA v3: >> >> * Rephrased the notice message as David's suggestion. >> * Removed partition count from notice message. >> * If a partitioned table doesn't have any partition, then suppress the >> message. > > I've been playing with this patch, and it seems to work as expected - > I'm surprised it didn't break any existing tests :). Do you plan to > extend this patch to other subcommands mentioned in your initial post, > such as SET STATISTICS? > > Thanks for the patch > > Best, Jim > Hi Jim, Thanks for your testing. Yes, I plan to add the notice to other sub-commands as needed. I only updated REPLICA IDENTITY firstto call for feedback. As you see, David has suggested the great wording for the notice message. Once the change on REPLICAIDENTITY is reviewed, it’s easy to extend to other sub-commands. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/
On Jan 14, 2026, at 08:52, Chao Li <li.evan.chao@gmail.com> wrote:On Jan 13, 2026, at 19:16, Jim Jones <jim.jones@uni-muenster.de> wrote:
Hi Chao
On 13/01/2026 05:02, Chao Li wrote:
PSA v3:
* Rephrased the notice message as David's suggestion.
* Removed partition count from notice message.
* If a partitioned table doesn't have any partition, then suppress the
message.
I've been playing with this patch, and it seems to work as expected -
I'm surprised it didn't break any existing tests :). Do you plan to
extend this patch to other subcommands mentioned in your initial post,
such as SET STATISTICS?
Thanks for the patch
Best, Jim
Hi Jim,
Thanks for your testing. Yes, I plan to add the notice to other sub-commands as needed. I only updated REPLICA IDENTITY first to call for feedback. As you see, David has suggested the great wording for the notice message. Once the change on REPLICA IDENTITY is reviewed, it’s easy to extend to other sub-commands.
PFA v4.
I’ve extended the NOTICE to cover all sub-commands for which ONLY has no effect and where actions on a partitioned table do not propagate to its partitions:
- ALTER COLUMN SET/RESET attribute_option
- ALTER COLUMN SET COMPRESSION
- ENABLE/DISABLE RULE
- ENABLE/DISABLE/FORCE/NO FORCE ROW LEVEL SECURITY
- REPLICA IDENTITY
- OWNER TO
- SET TABLESPACE
- SET SCHEMA
RENAME is intentionally excluded. Using ONLY (or not) has no effect for RENAME, since relation names are independent by nature and there is no expectation of recursion.
OF / NOT OF are also excluded. Using ONLY has no effect for these commands, as they apply only to the partitioned table itself and not to its partitions.
One thing worth noting: following David’s suggestion, I removed the action name from the NOTICE message in v2. However, I later realized that we do need to include the action name, because an ALTER TABLE command may contain multiple sub-commands, and the NOTICE would otherwise be ambiguous.
In v4, I reuse alter_table_type_to_string() to construct the action name, consistent with what ATSimplePermissions() does. The NOTICE message itself also follows the same style as messages emitted by ATSimplePermissions(). For example, when an ALTER TABLE contains multiple sub-commands, the output now looks like:
```
evantest=# alter table p_test replica identity full, alter column username set (n_distinct = 0.1);
NOTICE: ALTER action REPLICA IDENTITY on relation "p_test" does not affect present partitions
HINT: partitions may be modified individually, or specify ONLY to suppress this message
NOTICE: ALTER action ALTER COLUMN ... SET on relation "p_test" does not affect present partitions
HINT: partitions may be modified individually, or specify ONLY to suppress this message
ALTER TABLE
```
Regression tests have been updated, and a few new tests have been added. v4 should now be ready for review.
Вложения
Hi Chao
On 22/01/2026 06:45, Chao Li wrote:
> evantest=# alter table p_test replica identity full, alter column
> username set (n_distinct = 0.1);
> NOTICE: ALTER action REPLICA IDENTITY on relation "p_test" does not
> affect present partitions
> HINT: partitions may be modified individually, or specify ONLY to
> suppress this message
> NOTICE: ALTER action ALTER COLUMN ... SET on relation "p_test" does not
> affect present partitions
> HINT: partitions may be modified individually, or specify ONLY to
> suppress this message
> ALTER TABLE
One could argue that encapsulating all conditions in
EmitPartitionNoRecurseNotice(), meaning it is called all the time, is
slightly inefficient, but the impact is really negligible in this case -
and it is how it is done in similar functions in tablecmds.c :) The code
LGTM.
One small thing:
errhint is supposed to be capitalised - see Error Message Style Guide[1]
"Detail and hint messages: Use complete sentences, and end each with a
period. Capitalize the first word of sentences. Put two spaces after the
period if another sentence follows (for English text; might be
inappropriate in other languages)."
ereport(NOTICE,
errmsg("ALTER action %s on relation \"%s\" does not affect present
partitions",
action_str,
RelationGetRelationName(rel)),
errhint("partitions may be modified individually, or specify ONLY to
suppress this message"));
What about this?
HINT: To update partitions, apply the command to each one individually,
or specify ONLY to suppress this message.
I'll test the newly covered subcomands tomorrow.
Best, Jim
1 - https://www.postgresql.org/docs/current/error-style-guide.html
> On Jan 23, 2026, at 03:27, Jim Jones <jim.jones@uni-muenster.de> wrote:
>
> Hi Chao
>
> On 22/01/2026 06:45, Chao Li wrote:
>> evantest=# alter table p_test replica identity full, alter column
>> username set (n_distinct = 0.1);
>> NOTICE: ALTER action REPLICA IDENTITY on relation "p_test" does not
>> affect present partitions
>> HINT: partitions may be modified individually, or specify ONLY to
>> suppress this message
>> NOTICE: ALTER action ALTER COLUMN ... SET on relation "p_test" does not
>> affect present partitions
>> HINT: partitions may be modified individually, or specify ONLY to
>> suppress this message
>> ALTER TABLE
>
>
> One could argue that encapsulating all conditions in
> EmitPartitionNoRecurseNotice(), meaning it is called all the time, is
> slightly inefficient, but the impact is really negligible in this case -
> and it is how it is done in similar functions in tablecmds.c :) The code
> LGTM.
Hi Jim, thanks a lot for the review.
>
> One small thing:
>
> errhint is supposed to be capitalised - see Error Message Style Guide[1]
Thanks for the info, I wasn’t aware of that. When I wrote the code, I searched “errhint” over the source tree, and
didn’tfind a standard to follow.
>
> "Detail and hint messages: Use complete sentences, and end each with a
> period. Capitalize the first word of sentences. Put two spaces after the
> period if another sentence follows (for English text; might be
> inappropriate in other languages)."
>
> ereport(NOTICE,
> errmsg("ALTER action %s on relation \"%s\" does not affect present
> partitions",
> action_str,
> RelationGetRelationName(rel)),
> errhint("partitions may be modified individually, or specify ONLY to
> suppress this message"));
>
> What about this?
>
> HINT: To update partitions, apply the command to each one individually,
> or specify ONLY to suppress this message.
Looks good. I will integrate your edit to the next version.
>
> I'll test the newly covered subcomands tomorrow.
Thanks again for testing. I will wait to see the test results and address all issues together in next version.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
On 23/01/2026 01:11, Chao Li wrote:
> I will wait to see the test results and address all issues together in next version.
While testing some edge cases I found out that the NOTICE is being
emitted too early in the code path, e.g.
postgres=# ALTER TABLE m ALTER COLUMN b SET COMPRESSION pglz;
NOTICE: ALTER action ALTER COLUMN ... SET COMPRESSION on relation "m"
does not affect present partitions
HINT: partitions may be modified individually, or specify ONLY to
suppress this message
ERROR: column data type integer does not support compression
I'd argue that emitting only the ERROR message in this case would be the
right approach. What about moving the EmitPartitionNoRecurseNotice()
call to ATExecCmd, right **after** the changes were successfully
executed? For instance, in the case I mentioned above, you could explore:
@@ -5446,6 +5475,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
address = ATExecSetCompression(rel, cmd->name,
cmd->def,
lockmode);
+ /* Emit notice after validation passes */
+ EmitPartitionNoRecurseNotice(cmd->subtype, rel,
cmd->recurse, false);
break;
Not sure if cmd->recurse is propagated in this code path. If not, you
might need to do it manually, e.g.
@@ -4936,6 +4937,14 @@ ATPrepCmd(List **wqueue, Relation rel,
AlterTableCmd *cmd,
*/
cmd = copyObject(cmd);
+ if (recurse)
+ cmd->recurse = true;
+
I'm not saying it should be exactly this way, but it sounds more
reasonable to me to emit the NOTICE only if we know that the command is
going to be successfully executed (or was successfully executed).
This patch touches a lot of regression tests, but mostly to add the
keyword ONLY to the ALTER TABLE statements, to avoid the NOTICE message,
so that's ok.
Thanks!
Best, Jim