Thread: BUG #18550: Cross-partition update of a former inheritance parent leads to an assertion failure

The following bug has been logged on the website:

Bug reference:      18550
Logged by:          Alexander Lakhin
Email address:      exclusion@gmail.com
PostgreSQL version: 17beta2
Operating system:   Ubuntu 22.04
Description:

The following script:
CREATE TABLE t1 (a int);
CREATE TABLE t2 () INHERITS (t1);
DROP TABLE t2;
CREATE TABLE t (a int) PARTITION BY LIST (a);
ALTER TABLE t ATTACH PARTITION t1 FOR VALUES IN (1);
INSERT INTO t1 VALUES (1);
UPDATE t1 SET a = 2 WHERE a = 1

triggers an assertion failure (due to t1 is not recognized as a leaf
partition):
TRAP: failed Assert("rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE"),
File: "partdesc.c", Line: 73, PID: 37464
ExceptionalCondition at assert.c:52:13
RelationGetPartitionDesc at partdesc.c:83:6
PartitionDirectoryLookup at partdesc.c:458:11
ExecInitPartitionDispatchInfo at execPartition.c:1128:13
ExecSetupPartitionTupleRouting at execPartition.c:240:9
ExecCrossPartitionUpdate at nodeModifyTable.c:1791:39
ExecUpdateAct at nodeModifyTable.c:2046:7
ExecUpdate at nodeModifyTable.c:2336:12
ExecModifyTable at nodeModifyTable.c:4114:12
ExecProcNodeFirst at execProcnode.c:465:1
ExecProcNode at executor.h:275:1
ExecutePlan at execMain.c:1646:10
standard_ExecutorRun at execMain.c:363:3
ExecutorRun at execMain.c:305:1
ProcessQuery at pquery.c:165:5
PortalRunMulti at pquery.c:1277:5
PortalRun at pquery.c:795:5

Reproduced on REL_14_STABLE (starting from 8f4a6b9e4) .. master.


PG Bug reporting form <noreply@postgresql.org> writes:
> The following script:
> CREATE TABLE t1 (a int);
> CREATE TABLE t2 () INHERITS (t1);
> DROP TABLE t2;
> CREATE TABLE t (a int) PARTITION BY LIST (a);
> ALTER TABLE t ATTACH PARTITION t1 FOR VALUES IN (1);
> INSERT INTO t1 VALUES (1);
> UPDATE t1 SET a = 2 WHERE a = 1

> triggers an assertion failure (due to t1 is not recognized as a leaf
> partition):
> TRAP: failed Assert("rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE"),

Hmm.  Without the DROP TABLE, the ATTACH would fail:

regression=# ALTER TABLE t ATTACH PARTITION t1 FOR VALUES IN (1);
ERROR:  cannot attach inheritance parent as partition

I observe that in the case given, t1 still has pg_class.relhassubclass
true after the ATTACH PARTITION.  Maybe it'd be wise to force that
false after verifying there are no subclasses?  (I tried fixing it
manually, and that prevents the assertion crash.)

            regards, tom lane



On 2024-Jul-23, Tom Lane wrote:

> I observe that in the case given, t1 still has pg_class.relhassubclass
> true after the ATTACH PARTITION.  Maybe it'd be wise to force that
> false after verifying there are no subclasses?  (I tried fixing it
> manually, and that prevents the assertion crash.)

Yeah, that seems to work.  We can do that essentially for free in
StorePartitionBound(), like in the attached (which was taken in 14).

I'd add Alexander's script as a test too, somewhere near the bottom of
create_table.sql.


If the affected table is a foreign table, it doesn't seem to have the
same problem (I tried using contrib_regression's ft1 as t1 in
Alexander's script).  I suspect that's because we assume somewhere that
foreign tables are not in turn partitioned.

-- 
Álvaro Herrera        Breisgau, Deutschland  —  https://www.EnterpriseDB.com/

Attachment
Alvaro Herrera <alvherre@alvh.no-ip.org> writes:
> On 2024-Jul-23, Tom Lane wrote:
>> I observe that in the case given, t1 still has pg_class.relhassubclass
>> true after the ATTACH PARTITION.  Maybe it'd be wise to force that
>> false after verifying there are no subclasses?  (I tried fixing it
>> manually, and that prevents the assertion crash.)

> Yeah, that seems to work.  We can do that essentially for free in
> StorePartitionBound(), like in the attached (which was taken in 14).

Looks sane.

> I'd add Alexander's script as a test too, somewhere near the bottom of
> create_table.sql.

Personally I'd include this in the existing alter_table.sql test case,
to save a few steps:

 -- check that the table being attached is not part of regular inheritance
 CREATE TABLE parent (LIKE list_parted);
 CREATE TABLE child () INHERITS (parent);
 ALTER TABLE list_parted ATTACH PARTITION child FOR VALUES IN (1);
 ERROR:  cannot attach inheritance child as partition
 ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
 ERROR:  cannot attach inheritance parent as partition
+DROP TABLE child;
+-- now it should work
+ALTER TABLE list_parted ATTACH PARTITION parent FOR VALUES IN (1);
+-- test insert/update, per bug #18550
+INSERT INTO parent ...
+UPDATE parent ...
 DROP TABLE parent CASCADE;

            regards, tom lane



On 2024-Jul-23, Tom Lane wrote:

> Alvaro Herrera <alvherre@alvh.no-ip.org> writes:

> > Yeah, that seems to work.  We can do that essentially for free in
> > StorePartitionBound(), like in the attached (which was taken in 14).
> 
> Looks sane.

Thanks for looking.

> > I'd add Alexander's script as a test too, somewhere near the bottom of
> > create_table.sql.
> 
> Personally I'd include this in the existing alter_table.sql test case,
> to save a few steps:

Nice!  Done that way.

I didn't see the connection between the assertion failure and
8f4a6b9e4f5b, but I didn't spend much time on it.  But I didn't see any
reason not to backpatch this all the way down, either, so I did that.

Thanks, Alexander, for reporting this.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
<Schwern> It does it in a really, really complicated way
<crab> why does it need to be complicated?
<Schwern> Because it's MakeMaker.