Segfault in RI UPDATE CASCADE on partitioned tables with LIKE+ATTACH child (attnum drift) - Mailing list pgsql-bugs

From Dmitry Fomin
Subject Segfault in RI UPDATE CASCADE on partitioned tables with LIKE+ATTACH child (attnum drift)
Date
Msg-id 7DCE78D7-0520-4207-822B-92F60AEA14B4@gmail.com
Whole thread Raw
Responses Re: Segfault in RI UPDATE CASCADE on partitioned tables with LIKE+ATTACH child (attnum drift)
List pgsql-bugs
Hello,We’re seeing a backend segfault when an ON UPDATE CASCADE fires across partitions, if the destination partition was created via CREATE TABLE … LIKE + ATTACH (so its physical tuple descriptor differs from the parent due to dropped-column tombstones/attnum drift). Names/types match by inspection, but the crash occurs during tuple materialization in the RI trigger execution.
Minimal Reproducer (self-contained)

DROP SCHEMA IF EXISTS t CASCADE;
CREATE SCHEMA t;

-- Pipelines (partitioned)
CREATE TABLE t.pipelines (
  partition_id int NOT NULL,
  id           bigint NOT NULL,
  PRIMARY KEY (partition_id, id)
) PARTITION BY LIST (partition_id);
CREATE TABLE t.pipelines_102 PARTITION OF t.pipelines FOR VALUES IN (102);
CREATE TABLE t.pipelines_50  PARTITION OF t.pipelines FOR VALUES IN (50);

-- Stages (partitioned) with ON UPDATE CASCADE to pipelines.
-- Create a mid column and drop it to leave a tombstone gap in attnums.
CREATE TABLE t.stages (
  partition_id int NOT NULL,
  id           bigint NOT NULL,
  tmp_mid      int,               -- dropped below, leaves parent attnum gap
  pipeline_id  bigint NOT NULL,
  name         text,
  status       int,
  PRIMARY KEY (partition_id, id),
  FOREIGN KEY (partition_id, pipeline_id)
    REFERENCES t.pipelines(partition_id, id)
    ON UPDATE CASCADE ON DELETE CASCADE
) PARTITION BY LIST (partition_id);
CREATE TABLE t.stages_102 PARTITION OF t.stages FOR VALUES IN (102);
ALTER TABLE t.stages DROP COLUMN tmp_mid;

-- Miscreate destination stage partition via LIKE + ATTACH (no tombstone, different attnums).
CREATE TABLE t.stages_50_like (LIKE t.stages INCLUDING DEFAULTS);
ALTER TABLE t.stages ATTACH PARTITION t.stages_50_like FOR VALUES IN (50);

-- Builds (partitioned), cascades to both stages and pipelines.
CREATE TABLE t.builds (
  partition_id int NOT NULL,
  id           bigint NOT NULL,
  stage_id     bigint NOT NULL,
  commit_id    bigint NOT NULL,
  PRIMARY KEY (partition_id, id),
  FOREIGN KEY (partition_id, stage_id)
    REFERENCES t.stages(partition_id, id)
    ON UPDATE CASCADE ON DELETE CASCADE,
  FOREIGN KEY (partition_id, commit_id)
    REFERENCES t.pipelines(partition_id, id)
    ON UPDATE CASCADE ON DELETE CASCADE
) PARTITION BY LIST (partition_id);
CREATE TABLE t.builds_102 PARTITION OF t.builds FOR VALUES IN (102);
CREATE TABLE t.builds_50  PARTITION OF t.builds FOR VALUES IN (50);

-- Seed rows in source partition 102.
INSERT INTO t.pipelines_102(partition_id, id) VALUES (102, 1);
INSERT INTO t.stages_102   (partition_id, id, pipeline_id, name, status)
VALUES (102, 10, 1, 's', 0);
INSERT INTO t.builds_102   (partition_id, id, stage_id, commit_id)
VALUES (102, 100, 10, 1);

-- Crash repro: cascaded UPDATE across partitions
UPDATE t.pipelines
SET partition_id = 50
WHERE partition_id = 102 AND id = 1;


server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

Postgres logs:
 
2025-10-16 09:23:08.535 UTC [18630] LOG:  client backend (PID 18673) was terminated by signal 11: Segmentation fault
2025-10-16 09:23:08.535 UTC [18630] DETAIL:  Failed process was running: UPDATE t.pipelines
        SET partition_id = 50
        WHERE partition_id = 102 AND id = 1;

Environment
  • PostgreSQL:
postgres=# SHOW server_version;
 server_version
----------------
 18.0
(1 row)

postgres=# SHOW server_version_num;
 server_version_num
--------------------
 180000
(1 row)

postgres=# SELECT version();
                                                 version
----------------------------------------------------------------------------------------------------------
 PostgreSQL 18.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5), 64-bit
(1 row)

postgres=# SHOW shared_preload_libraries;
 shared_preload_libraries
--------------------------

(1 row)

postgres=# SELECT extname, extversion FROM pg_extension ORDER BY 1;
 extname | extversion
---------+------------
 plpgsql | 1.0
(1 row)


  • OS/Kernel/Libc:
[root@postgres-source ~]# uname -a
Linux postgres-source 5.14.0-427.22.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 19 04:14:38 PDT 2024 x86_64 x86_64 x86_64 GNU/Linux
[root@postgres-source ~]# cat /etc/os-release
NAME="Oracle Linux Server"
VERSION="9.3"
ID="ol"
ID_LIKE="fedora"
VARIANT="Server"
VARIANT_ID="server"
VERSION_ID="9.3"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Oracle Linux Server 9.3"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:oracle:linux:9:3:server"
HOME_URL="https://linux.oracle.com/"
BUG_REPORT_URL="https://github.com/oracle/oracle-linux"

ORACLE_BUGZILLA_PRODUCT="Oracle Linux 9"
ORACLE_BUGZILLA_PRODUCT_VERSION=9.3
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
ORACLE_SUPPORT_PRODUCT_VERSION=9.3
[root@postgres-source ~]# ldd --version
ldd (GNU libc) 2.34
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Backrace in attachment 

Issue is reproducible at least in Postgres 16, 17, 18

Please let me know if I need to provide some other information 

BR Dmitry


Attachment

pgsql-bugs by date:

Previous
From: 崔紫玉
Date:
Subject: Re: BUG #19081: Inconsistent target rows seen by the UPDATE and INSERT statements within the same transaction
Next
From: Jacob Champion
Date:
Subject: Re: BUG #19089: Mounting Issue