| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 303677365(at)qq(dot)com |
| Subject: | BUG #19818: ATTACH PARTITION / CREATE INDEX accept a child index whose deferrable property differs from the pare |
| Date: | 2026-10-30 06:49:16 |
| Message-ID: | 19818-3f0f800aae5c2c9d@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19818
Logged by: chunling qin
Email address: 303677365(at)qq(dot)com
PostgreSQL version: 18.6
Operating system: Linux (TencentOS 4.4, x86_64)
Description:
Hello,
CompareIndexInfo() (src/backend/catalog/index.c:2570) decides whether an
existing partition index can be attached under a partitioned parent index.
It compares uniqueness, NULLS NOT DISTINCT, expressions, predicates and
collations -- but it does not compare indimmediate (the deferrable
property). As a result, ATTACH PARTITION and CREATE INDEX silently attach
a child index whose deferrable property differs from the parent index, and
every INSERT ... ON CONFLICT on that partition is then permanently broken.
The most natural way to hit this is to attach a partition that already has
a deferrable primary key:
CREATE TABLE z9_root (a int, b text, PRIMARY KEY (a)) PARTITION BY RANGE
(a);
CREATE TABLE z9_p1 (a int, b text, PRIMARY KEY (a) DEFERRABLE);
ALTER TABLE z9_root ATTACH PARTITION z9_p1 FOR VALUES FROM (0) TO
(1000);
-- succeeds silently: z9_p1_pkey (indimmediate=f) attached under
-- z9_root_pkey (indimmediate=t)
-- the consequence: ON CONFLICT is now unusable on this partition
INSERT INTO z9_p1 VALUES (1,'x') ON CONFLICT (a) DO UPDATE SET b = 'y';
-- ERROR: ON CONFLICT does not support deferrable unique constraints/
-- exclusion constraints as arbiters
Verification of the resulting state:
SELECT c.relname, i.indisunique, i.indimmediate, i.indisvalid
FROM pg_index i JOIN pg_class c ON c.oid = i.indexrelid
WHERE c.relname IN ('z9_p1_pkey','z9_root_pkey');
-- z9_p1_pkey | t | f | t
-- z9_root_pkey | t | t | t
Expected: ATTACH PARTITION / CREATE INDEX should reject (or at least warn
about) a child index whose indimmediate differs from the parent, the same
way it already handles the other index properties it compares. The
consumer side already treats this as an error: ExecCheckIndexConstraints()
(src/backend/executor/execIndexing.c:607) refuses !indimmediate arbiters,
which is what makes every later ON CONFLICT fail.
Actual: the attach succeeds with no warning of any kind, and every
subsequent INSERT ... ON CONFLICT on that partition fails with
"ON CONFLICT does not support deferrable unique constraints/exclusion
constraints as arbiters", with no hint that the ATTACH was the cause.
Related: this is the sibling path of the issue recently discussed by
Zsolt Parragi ("Routed ON CONFLICT inserts broken by partition-local
deferrable unique constraints in 19 and master", 2026-08-28), where
commit 90eae926abbb had taught IsIndexCompatibleAsArbiter() to match
leaf indexes, and commit dc5f8cb9346 then made IsIndexCompatibleAsArbiter()
compare indimmediate for the routed-insert path. The path reported here
(attaching a child index to a parent through CompareIndexInfo()) was not
covered by that fix.
Reproduced on:
- PostgreSQL 20devel (snapshot of 2026-10-27, x86_64-pc-linux-gnu)
- PostgreSQL 18.6 (REL_18_STABLE, self-built)
A draft fix location would be CompareIndexInfo()
(src/backend/catalog/index.c): include indimmediate in the comparison,
mirroring how the other index properties are already compared there.
Regards,
Chunling Qin
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Gaurav Singh | 2026-10-30 06:50:13 | Re: postgres_fdw returns wrong rows for age(timestamptz, timestamptz) filters |
| Previous Message | PG Bug reporting form | 2026-10-30 06:40:13 | BUG #19817: CREATE UNIQUE INDEX on a partitioned table can silently attach an invalid, not-ready child index, le |