| From: | Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> |
|---|---|
| To: | Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com> |
| Cc: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Re: Fix bug of CHECK constraint enforceability recursion |
| Date: | 2026-06-03 01:54:01 |
| Message-ID: | 185FC597-BF26-4075-9D59-E5905ED74E0F@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
> On Jun 3, 2026, at 04:56, Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com> wrote:
>
> Hello
>
> + * During recursion, another parent outside this ALTER may still enforce
> + * the same constraint. In that case, keep the child constraint ENFORCED
> + * so that its merged enforceability still reflects the remaining enforced
> + * parent.
> + */
> + if (!cmdcon->is_enforced)
> + {
>
> This means once is_enforced is set to true, it will never be
> rechecked. See the following example which showcases an issue with
> this:
>
> create table g(a int constraint k check(a > 0) enforced);
> create table o(a int constraint k check(a > 0) enforced);
> create table s1() inherits(g);
> create table s2() inherits(g, o);
> create table s3() inherits(g);
> alter table g alter constraint k not enforced;
> select conrelid::regclass as tbl, conenforced
> from pg_constraint
> where conname = 'k' and contype = 'c'
> order by conrelid::regclass::text collate "C";
> insert into s1 values (-1);
> insert into s3 values (-1); -- bug: ERRORs out, but shouldn't
>
Hi Zsolt,
Thanks for your view.
I just tried your test with v6, but didn't see the bug you mentioned:
```
evantest=# create table g(a int constraint k check(a > 0) enforced);
CREATE TABLE
evantest=# create table o(a int constraint k check(a > 0) enforced);
CREATE TABLE
evantest=# create table s1() inherits(g);
CREATE TABLE
evantest=# create table s2() inherits(g, o);
NOTICE: merging multiple inherited definitions of column "a"
CREATE TABLE
evantest=# create table s3() inherits(g);
CREATE TABLE
evantest=# alter table g alter constraint k not enforced;
ALTER TABLE
evantest=# select conrelid::regclass as tbl, conenforced
evantest-# from pg_constraint
evantest-# where conname = 'k';
tbl | conenforced
-----+-------------
o | t
s2 | t
g | f
s1 | f
s3 | f
(5 rows)
evantest=# insert into s1 values (-1);
INSERT 0 1
evantest=# insert into s3 values (-1);
INSERT 0 1
```
Here, both s1 and s3 are the direct child of g, thus when g is set to “not enforced”, s1 and s3 is set to “not enforced" as well. While s2 is a child of both g and o, as o is still enforced, s2 remains enforced. The test result is right as expected.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
| From | Date | Subject | |
|---|---|---|---|
| Next Message | lin teletele | 2026-06-03 01:58:40 | Re: Use pg_current_xact_id() instead of deprecated txid_current() |
| Previous Message | Richard Guo | 2026-06-03 01:25:01 | Re: Eager aggregation, take 3 |