Re: [PG19] Three bugs with a CHECK constraint that only the child enforces

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: shihao zhong <zhong950419(at)gmail(dot)com>
Cc: pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, jian he <jian(dot)universality(at)gmail(dot)com>, Andrew Dunstan <andrew(at)dunslane(dot)net>, Nikolay Samokhvalov <nik(at)postgres(dot)ai>, Ashutosh Bapat <ashutosh(dot)bapat(dot)oss(at)gmail(dot)com>, Álvaro Herrera <alvherre(at)kurilemu(dot)de>, Peter Eisentraut <peter(at)eisentraut(dot)org>
Subject: Re: [PG19] Three bugs with a CHECK constraint that only the child enforces
Date: 2026-10-12 05:33:45
Message-ID: 3F02FC65-3913-479A-B0AD-8F757B616074@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Oct 9, 2026, at 12:42, shihao zhong <zhong950419(at)gmail(dot)com> wrote:
>
> Hi hackers,
>
> I used Opus to analyze the new features in PG19, and it found three
> bugs with a CHECK constraint that a child enforces and its parent
> does not. Each item has a script and a patch with its number.
> "Before" is 19 and master today. "After" is with the patch, and is
> the output I expect.
>
> 1. ALTER CONSTRAINT ... ENFORCED on the parent does not check a child
> whose constraint is ENFORCED but NOT VALID. The parent is marked
> validated anyway, so a query on it can miss the child's bad row.
>
> create table p (a int, constraint c check (a > 0) not enforced);
> create table k (a int);
> insert into k values (-1);
> alter table k add constraint c check (a > 0) not valid;
> alter table k inherit p;
> alter table p alter constraint c enforced;
> select count(*) from (select a from p union all select 1) s
> where a < 0;
> Before:
> ALTER TABLE
> count
> -------
> 0
> After 0001:
> ERROR: check constraint "c" of relation "k" is violated by some row
> count
> -------
> 1
>

I can reproduce the bug, and the fix in 0001 looks good.

However, this bug report raised a concern that I didn’t notice while working on my previous enforceability fix [1].

This bug report relies on ALTER TABLE p ALTER CONSTRAINT c ENFORCED also changing the child table k’s constraint from NOT VALID to VALID.

I verified the following on PG18:
```
evantest=# create table t(a int);
CREATE TABLE
evantest=# insert into t values (-1);
INSERT 0 1
evantest=# alter table t add constraint c check (a>0) enforced not valid;
ALTER TABLE
evantest=#
evantest=# select conenforced, convalidated from pg_constraint where conname='c';
conenforced | convalidated
-------------+--------------
t | f
(1 row)
```

The test shows that a CHECK constraint can be both ENFORCED and NOT VALID. This tests adding a constraint, however, rather than changing its enforceability.

Returning to your reproducer, after altering k to inherit from p, k’s constraint c remains NOT VALID:
```
evantest=# create table p (a int, constraint c check (a > 0) not enforced);
CREATE TABLE
evantest=# create table k (a int);
CREATE TABLE
evantest=# insert into k values (-1);
INSERT 0 1
evantest=# alter table k add constraint c check (a > 0) not valid;
ALTER TABLE
evantest=# alter table k inherit p;
ALTER TABLE
evantest=# select conrelid::regclass, conenforced, convalidated from pg_constraint where conname='c';
conrelid | conenforced | convalidated
----------+-------------+--------------
p | f | f
k | t | f
(2 rows)
```

So the design question here is whether changing a constraint from NOT ENFORCED to ENFORCED should automatically validate it.

I read through the original discussion at [2]. It explicitly mentions validating existing rows, but I didn’t find a discussion of whether NOT VALID should be retained. That might be reasonable, because the original patch followed the existing behavior for changing foreign key constraints to ENFORCED.

IMO, changing enforceability should retain NOT VALID. However, I understand that the current implementation validates existing rows, so this patch fixes a bug under those semantics. My concern is with the original design, and it may be too late to reopen that discussion at this point. I will create a separate thread for v20.

[1] https://www.postgresql.org/message-id/E74C57FA-1DD0-4C8E-8FB1-538034752592%40gmail.com
[2] https://postgr.es/m/CACJufxHCh_FU-FsEwsCvg9mN6-5tzR6H9ntn+0KUgTCaerDOmg@mail.gmail.com

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Heikki Linnakangas 2026-10-12 05:35:08 Re: [PATCH] Two remaining shmem attachment issues in single-user mode
Previous Message Tatsuya Kawata 2026-10-12 05:16:25 Re: Material node doesn't show "Maximum Storage" for parallel workers