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 1wRmSy-002gwM-1B for pgsql-hackers@arkaria.postgresql.org; Tue, 26 May 2026 07:44:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wRmSw-003j9p-03 for pgsql-hackers@arkaria.postgresql.org; Tue, 26 May 2026 07:44:42 +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 1wRmSv-003j9f-2G for pgsql-hackers@lists.postgresql.org; Tue, 26 May 2026 07:44:42 +0000 Received: from mail-dl1-x1233.google.com ([2607:f8b0:4864:20::1233]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wRmSu-00000001U2n-1M9t for pgsql-hackers@lists.postgresql.org; Tue, 26 May 2026 07:44:42 +0000 Received: by mail-dl1-x1233.google.com with SMTP id a92af1059eb24-1331e851faaso5272991c88.1 for ; Tue, 26 May 2026 00:44:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779781477; x=1780386277; darn=lists.postgresql.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=YqFaeS0Qs1cTNc08iuqfsiPpglfXrjuzahapDvgp/vI=; b=HjAk/2hLi1USLU55mqftKW8vgbrgamHR/3Tauq/mnuZ5wKuXm7Hh6MGDGR+M1bWJYl DY0L7iMd1HluC6LeA6lklWhF+GdyyeBjlBv04f62mjLgSm6NS81I7ztAtMKAljfi7Z0s /DKo02NZQDUxGJl+SPRxYk57Ede6UvHOepcdsgNXvkPsdmC10cq1SwIQUccqUWOSlAp8 WKmnIZ6tG2S6lulSqitcoX43YWGCmAw57fi44Bek/ellG1FF/VtUKW4me/lupUANhJ78 jnAhbCfTv0v7eD/6tBIuTuLe8AfVn1v+bsH1JN4x0bmkPryhT04m21MxFOeyFWyaU9k/ y57w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779781477; x=1780386277; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-gg:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=YqFaeS0Qs1cTNc08iuqfsiPpglfXrjuzahapDvgp/vI=; b=BjutFG10AIKnnQFttNHKYLD19tFbG798XGIjiEd3gOmQLV7BGY6V3j2grzMo9bfTMy ius0ESHfyizCvaYQDPAO4kAc8/SeGF2f50vi6yDDfvlzhxLXCNu5gBw7iWyY99e6Yct0 L1UU9XWSITEtOhvkYE2aRn4cRV9M8j+NZ5Dix16BMtU4IhJxOqQSn2AcsJkvG2VmDrKZ e+PW5yGXJ7Dwwjq3fVXIwa2to4zGmgWhALYEEcmhAaR0UcOa9G995zJJaGvUlhFqAVyk ULfszCq/nDIs0iUajleqZHCs8oIqJt3AuCF3gOURIx5vUTSa/U77uBafV3yQTKh2Wc+b bnFA== X-Gm-Message-State: AOJu0YwoZmrWTe+DWwLeej772zaQwEyukSGnjSrUGV3VS0UJ5sgvfxz9 hb/G0LnkYO94s8fN6GmUCIcjrXsDNPBLPzzFtY5p1yGmiom4yexAxOMU X-Gm-Gg: Acq92OE3djpUx2lL4u4nedhWDx1cklSs3hVF2+EjpCWxc81SmWqrVKBJSyLVua3Hsie Ky++VUeQBaat5VahwNGJAAWtEQ/FA/th8tgxZ0hBgyesqCMOjwjTRxoWkthlD9atkVy3/q/CxcJ wW9ihcgiMGvZ8MKqNbibp5pbtwc+DZCib+WmTxSUbHNWJOs+pPDXWNv49w6rzWlEHi0ebZtynKz modOMd8XIY9Uq1nFK1xdzP5PpF2BY+ul38s/xlaJaeGViKUuYZJStg4J8FELHixDi3a/M/qv0vS XCJaQg+S80xMeaGAjNM97Vra+mCIgBT67WMu3Rd6zxDXrJ66+USHxED+ug8xSt4Tz1ZmN26XuXo MsjCCCFuB2wkI1TQCGWLgwnTfU99iNeHQRgXtrgVQs9TL1iBPLdjev6PmrpRFD+Bx0zAhzWy27V VvBVbJU19zZS93jTjxq0gGwlMlbKCDMYbPlAGDXMht X-Received: by 2002:a05:7022:7a4:b0:136:bb14:b0f8 with SMTP id a92af1059eb24-136bb14b75dmr2999194c88.5.1779781477174; Tue, 26 May 2026 00:44:37 -0700 (PDT) Received: from smtpclient.apple ([64.32.14.230]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-1366a2e686fsm7798205c88.1.2026.05.26.00.44.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 May 2026 00:44:36 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.600.51.1.1\)) Subject: Re: Fix bug of CHECK constraint enforceability recursion From: Chao Li In-Reply-To: Date: Tue, 26 May 2026 15:44:01 +0800 Cc: PostgreSQL Hackers , Andrew Dunstan Content-Transfer-Encoding: quoted-printable Message-Id: References: To: jian he X-Mailer: Apple Mail (2.3864.600.51.1.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > On May 26, 2026, at 14:27, Chao Li wrote: >=20 >=20 >=20 >> On May 26, 2026, at 14:05, jian he = wrote: >>=20 >> On Tue, May 26, 2026 at 11:51=E2=80=AFAM Chao Li = wrote: >>>=20 >>> Hi, >>>=20 >>> I just tested =E2=80=9CAdd support for altering CHECK constraint = enforceability=E2=80=9D and found an issue where recursion is not = handled properly. >>>=20 >>> Here is a repro with inheritance tables: >>> ``` >>> evantest=3D# create table p(a int constraint ck check (a > 0) = enforced); >>> CREATE TABLE >>> evantest=3D# create table c() inherits (p); >>> CREATE TABLE >>> evantest=3D# alter table c alter constraint ck not enforced; >>> ALTER TABLE >>> evantest=3D# insert into c values (-1); >>> INSERT 0 1 >>> evantest=3D# alter table p alter constraint ck enforced; >>> ALTER TABLE >>> evantest=3D# insert into c values (-2); >>> INSERT 0 1 >>> evantest=3D# select * from p; >>> a >>> ---- >>> -1 >>> -2 >>> (2 rows) >>> ``` >>>=20 >>> 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. >>>=20 >>> The same problem can happen with partitioned tables as well: >>> ``` >>=20 >> Hi. >>=20 >> 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)))); >>=20 >> 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. >> */ >>=20 >> 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. >>=20 >> 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. >>=20 >> 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. >>=20 >=20 > 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=E2=80=99m afraid it=E2=80=99s = too late for PG19. So, I guess we still need to fix the issue for 19, = right? >=20 I thought this over, and I changed my mind. The same rule should apply to both partitioned tables and regular = inheritance: * parent CHECK enforced + child CHECK not enforced =3D reject * parent CHECK not enforced + child CHECK enforced =3D allow That matches the existing merge/attach behavior. Also, this invariant = could not be broken through normal SQL in PG18, because PG18 does not = support ALTER TABLE ... ALTER CONSTRAINT ... [NOT] ENFORCED for CHECK = constraints. So we should not introduce a new way to break it in PG19. I will rework the patch forwards the =E2=80=9Creject=E2=80=9D direction. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/