Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wV46T-001euM-2t for pgsql-bugs@arkaria.postgresql.org; Thu, 04 Jun 2026 09:11:06 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wV46R-005etV-1g for pgsql-bugs@arkaria.postgresql.org; Thu, 04 Jun 2026 09:11:03 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wV2eW-005RiC-1I for pgsql-bugs@lists.postgresql.org; Thu, 04 Jun 2026 07:38:08 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wV2eU-00000001CQI-1slr for pgsql-bugs@lists.postgresql.org; Thu, 04 Jun 2026 07:38:08 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=Yk8/dgo0cyV+MTywaJL3SigTw/9b0eYATeltq9wdAYg=; b=AyyUHqg57qrbWAycFPrLFT1xSa oyUr8DFeFWV9T9Ix/tu6UZ8WSMHGGUZoEBpLgoBLMWx5V1OCysqyxkG87THTWyt1X4FtFLxxRqqIz 8+x7+X7wg281eNpNyOz22450DkaCaesJmqyuNxGxE6oGtncLclOIU9P/q6hAb2DhXhXNRAaQ6BbLn tvXyZakq/5Yb76qYjH3jYETUcANxY+hTJKbXFjX5e7FPZP7gpMsfingAhBXuZVEqOKkVrxrZcgcYZ LbhOXXeN9TT9MSDwC3RdrT8CulbHeDAcqlk31mN2I6cnWgpX9QFy0tIDkHzL8dLK95PMwT4PBUxrd 9WtK51/A==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wV2eT-003Avg-0Z for pgsql-bugs@lists.postgresql.org; Thu, 04 Jun 2026 07:38:05 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wV2eR-007Etm-19 for pgsql-bugs@lists.postgresql.org; Thu, 04 Jun 2026 07:38:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19507: Auto-named partition table constraint conflicts To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: markoog@gmail.com Reply-To: markoog@gmail.com, pgsql-bugs@lists.postgresql.org Date: Thu, 04 Jun 2026 07:37:13 +0000 Message-ID: <19507-78eec77213b5284f@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19507 Logged by: Marko Grujic Email address: markoog@gmail.com PostgreSQL version: 18.4 Operating system: MacOS, Debian Description: =20 Hi all, I've stumbled on a peculiar class of edge cases involving partitioned tables, where at least one of the partitions is in a different schema from the parent, and auto-named constraints. I believe this can be classified as a bug, and probably warrants a fix. I'm seeing this on PG18 (18.4, official Docker image): postgres=3D# select version(); version ---------------------------------------------------------------------------= ----------------------------------------------- PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit (1 row) I'm also hitting it on latest master too (19beta1). The repro is quite simple, and can be reduced to 5 SQL statements: postgres=3D# create schema partitions; create table t(a int) partition by range (a); create table partitions.t_1_10 partition of t for values from (1) to (10); alter table partitions.t_1_10 add constraint t_a_not_null check (a is not null); alter table t alter column a set not null; CREATE SCHEMA CREATE TABLE CREATE TABLE ALTER TABLE ERROR: 42710: constraint "t_a_not_null" for relation "t_1_10" already exists LOCATION: AddRelationNewConstraints, heap.c:2666 Note that the last ALTER, which creates auto-named constraints, leads to an error, because a preceding ALTER, which created a user-named constraint, already picked the default name that the auto-generated name would use. Consequently, no new constraints are constructed for any of the tables in the hierarchy. A workaround could be to use an explicitly-named variant of the ALTER statement, but that is not necessarily obvious. In addition the auto-named variant should really resolve any pre-existing conflicts automatically. So the exact set of circumstances to hit this bug is slightly convoluted, but not unrealistic: 1. there's a partitioned table 2. which has at least one partition in another schema 3. that partition has a pre-existing constraint 4. (optional) the constraint was named by the user, and matches what PG would use by default Here's a couple more variants of the same issue: postgres=3D# create schema partitions; create table t(a int) partition by range (a); create table partitions.t_1_10 partition of t for values from (1) to (10); alter table partitions.t_1_10 add constraint t_a_check check (a > 100); alter table t add check (a > 0); CREATE SCHEMA CREATE TABLE CREATE TABLE ALTER TABLE ERROR: 42710: constraint "t_a_check" for relation "t_1_10" already exists LOCATION: MergeWithExistingConstraint, heap.c:2792 and postgres=3D# create schema partitions; create table t(a int) partition by range (a); create table partitions.t_1_10 partition of t for values from (1) to (10); alter table partitions.t_1_10 add constraint t_a_not_null check (a is not null); alter table t add not null a; CREATE SCHEMA CREATE TABLE CREATE TABLE ALTER TABLE ERROR: 42710: constraint "t_a_not_null" for relation "t_1_10" already exists LOCATION: AddRelationNewConstraints, heap.c:2666 To make matters worse, the same failure mode can be hit without the user naming the pre-existing constraint explicitly in the first place, for instance: postgres=3D# create schema partitions; create table t(a int) partition by range (a); create table partitions.t partition of t for values from (1) to (10); alter table partitions.t add check (a > 1); alter table t add check (a > 0); CREATE SCHEMA CREATE TABLE CREATE TABLE ALTER TABLE ERROR: 42710: constraint "t_a_check" for relation "t" already exists LOCATION: MergeWithExistingConstraint, heap.c:2792