Tom Lane <t...@sss.pgh.pa.us> 于2025年4月2日周三 09:05写道:
> Alexander Lakhin <exclus...@gmail.com> writes: > > I've discovered that 95f650674 introduced a defect similar to bug #18297, > > but this time with DEFAULT. Namely, the following script: > > CREATE TABLE a (aa text); > > CREATE TABLE c (cc text) INHERITS (a); > > CREATE TABLE d (dd text) INHERITS (c, a); > > ALTER TABLE a ADD COLUMN i int DEFAULT 1; > > > fails with: > > ERROR: XX000: tuple already updated by self > > LOCATION: simple_heap_update, heapam.c:4421 > > Hmm, yeah. The failing call is here: > > /* Bump the existing child att's inhcount */ > ... > CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple); > > so I think you're right that that code path is now short a > CommandCounterIncrement() somewhere. I'll look tomorrow if > nobody beats me to it. > Yes, when table a process its children, which are table c and table d. Table c is first to be done. At the same time, table d is also child of table c, so after updating own pg_attribute tuple, table c will process its child table d. And table d update its pg_attribute catalog tuple. After finishing table c, the logic returning to continue to process table a's children, which this time is table d. Between table d pg_attribute tuple updated as child of table c and updating table d pg_attribute tuple again as child of table a, there is no call CommandCounterIncrement(). So let's add CommandCounterIncrement() after calling StoreAttrMissingVal(). -- Thanks, Tender Wang
From ee2bc290cab83daf0ebecf9f29cc23539ba19741 Mon Sep 17 00:00:00 2001 From: Tender Wang <tndrw...@gmail.com> Date: Wed, 2 Apr 2025 09:52:22 +0800 Subject: [PATCH] Fix "tuple already updated by self" issue. --- src/backend/commands/tablecmds.c | 2 ++ src/test/regress/expected/inherit.out | 17 +++++++++++++++++ src/test/regress/sql/inherit.sql | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 10624353b0a..67e0aabf4a7 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -7518,6 +7518,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, { StoreAttrMissingVal(rel, attribute->attnum, missingval); has_missing = true; + /* Make above changes visible */ + CommandCounterIncrement(); } FreeExecutorState(estate); } diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 4d07d0bd79b..ba4327e7acb 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1108,6 +1108,23 @@ Child tables: inhtb, inhtd DROP TABLE inhta, inhtb, inhtc, inhtd; +-- Test for adding a column wiht DEFAULT value +CREATE TABLE inhtda (aa text); +CREATE TABLE inhtdc (cc text) INHERITS (inhtda); +CREATE TABLE inhtdd (dd text) INHERITS (inhtdc, inhtda); +NOTICE: merging multiple inherited definitions of column "aa" +ALTER TABLE inhtda ADD COLUMN i int DEFAULT 1; +NOTICE: merging definition of column "i" for child "inhtdd" +\d+ inhtda + Table "public.inhtda" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+----------+--------------+------------- + aa | text | | | | extended | | + i | integer | | | 1 | plain | | +Child tables: inhtdc, + inhtdd + +DROP TABLE inhtda, inhtdc, inhtdd; -- Test for renaming in diamond inheritance CREATE TABLE inht2 (x int) INHERITS (inht1); CREATE TABLE inht3 (y int) INHERITS (inht1); diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index 941189761fd..d9fd6340798 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -384,6 +384,14 @@ ALTER TABLE inhta ADD COLUMN i int; \d+ inhta DROP TABLE inhta, inhtb, inhtc, inhtd; +-- Test for adding a column wiht DEFAULT value +CREATE TABLE inhtda (aa text); +CREATE TABLE inhtdc (cc text) INHERITS (inhtda); +CREATE TABLE inhtdd (dd text) INHERITS (inhtdc, inhtda); +ALTER TABLE inhtda ADD COLUMN i int DEFAULT 1; +\d+ inhtda +DROP TABLE inhtda, inhtdc, inhtdd; + -- Test for renaming in diamond inheritance CREATE TABLE inht2 (x int) INHERITS (inht1); CREATE TABLE inht3 (y int) INHERITS (inht1); -- 2.34.1