| From: | Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> |
|---|---|
| To: | jian he <jian(dot)universality(at)gmail(dot)com> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Andrew Dunstan <andrew(at)dunslane(dot)net> |
| Subject: | Re: Fix bug of CHECK constraint enforceability recursion |
| Date: | 2026-05-26 06:27:34 |
| Message-ID: | DCE683F9-CEBF-4EDE-81D1-5E59CCD5CF82@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
> On May 26, 2026, at 14:05, jian he <jian(dot)universality(at)gmail(dot)com> wrote:
>
> On Tue, May 26, 2026 at 11:51 AM Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> wrote:
>>
>> Hi,
>>
>> I just tested “Add support for altering CHECK constraint enforceability” and found an issue where recursion is not handled properly.
>>
>> Here is a repro with inheritance tables:
>> ```
>> evantest=# create table p(a int constraint ck check (a > 0) enforced);
>> CREATE TABLE
>> evantest=# create table c() inherits (p);
>> CREATE TABLE
>> evantest=# alter table c alter constraint ck not enforced;
>> ALTER TABLE
>> evantest=# insert into c values (-1);
>> INSERT 0 1
>> evantest=# alter table p alter constraint ck enforced;
>> ALTER TABLE
>> evantest=# insert into c values (-2);
>> INSERT 0 1
>> evantest=# select * from p;
>> a
>> ----
>> -1
>> -2
>> (2 rows)
>> ```
>>
>> In this repro, the constraint on parent table p is already ENFORCED, but the constraint on child table c was altered to NOT ENFORCED. So when altering p to ENFORCED again, it didn't recurse to c.
>>
>> The same problem can happen with partitioned tables as well:
>> ```
>
> Hi.
>
> In MergeConstraintsIntoExisting, we have:
> /*
> * A NOT ENFORCED child constraint cannot be merged with an
> * ENFORCED parent constraint. However, the reverse is allowed,
> * where the child constraint is ENFORCED.
> */
> if (parent_con->conenforced && !child_con->conenforced)
> ereport(ERROR,
> (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
> errmsg("constraint \"%s\" conflicts with NOT ENFORCED
> constraint on child table \"%s\"",
> NameStr(child_con->conname),
> RelationGetRelationName(child_rel))));
>
> MergeWithExistingConstraint, we have comments like:
> /*
> * If the child constraint is required to be enforced while the parent
> * constraint is not, this should be allowed by marking the child
> * constraint as enforced. In the reverse case, an error would have
> * already been thrown before reaching this point.
> */
>
> So other commands (CREATE TABLE, ALTER TABLE ATTACH PARTITION) do not expect a
> state where the parent constraint is enforced but the child constraint is not.
> We can now reach this state via ALTER TABLE ALTER CONSTRAINT.
>
> We don't need to worry about Foreign Key Constraints because the
> foreign key constraint's conparentid is valid, therefore we cannot
> directly alter a partition's FK constraint.
> StoreRelCheck->CreateConstraintEntry comments ``/* no parent
> constraint */`` means that each CHECK constraint is on its own.
>
> Overall, i tend to think that we should reject ALTER TABLE ALTER
> CONSTRAINT if it
> would result in the parent constraint being enforced while the child constraint
> is not enforced.
>
I am not against the idea of "rejecting ALTER TABLE ALTER CONSTRAINT if it would result in the parent constraint being enforced while the child constrain is not enforced", but I’m afraid it’s too late for PG19. So, I guess we still need to fix the issue for 19, right?
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Peter Smith | 2026-05-26 06:28:43 | Re: Proposal: Conflict log history table for Logical Replication |
| Previous Message | Pavel Stehule | 2026-05-26 06:22:17 | Re: bugfix - fix broken output in expanded aligned format, when data are too short |