hi.

Currently in pg18, we can add not enforced check constraints.
but we can not do  ALTER TABLE ALTER CONSTRAINT [NOT] ENFORCED
for check constraint.

The attached patch is implementation of changing enforceability of
check constraint.
From 486cf69121b0ea37a5c050bf1ceaa67196acd682 Mon Sep 17 00:00:00 2001
From: jian he <jian.universal...@gmail.com>
Date: Mon, 2 Jun 2025 21:54:53 +0800
Subject: [PATCH v1 1/1] alter check constraint enforceability

context: https://git.postgresql.org/cgit/postgresql.git/commit/?id=ca87c415e2fccf81cec6fd45698dde9fae0ab570

discussion: https://postgr.es/m/
---
 doc/src/sgml/ref/alter_table.sgml         |   4 +-
 src/backend/commands/tablecmds.c          | 190 ++++++++++++++++++++--
 src/test/regress/expected/constraints.out |  54 ++++++
 src/test/regress/expected/inherit.out     |  63 +++++++
 src/test/regress/sql/constraints.sql      |  37 +++++
 src/test/regress/sql/inherit.sql          |  45 +++++
 6 files changed, 375 insertions(+), 18 deletions(-)

diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index d63f3a621ac..afb7b04aa69 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -559,8 +559,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
     <listitem>
      <para>
       This form alters the attributes of a constraint that was previously
-      created. Currently only foreign key constraints may be altered in
-      this fashion, but see below.
+      created. Currently <literal>FOREIGN KEY</literal> and
+      <literal>CHECK</literal> constraints may be altered in this fashion, but see below.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index acf11e83c04..9c1466041f9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -403,6 +403,10 @@ static bool ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cm
 											Oid ReferencedParentUpdTrigger,
 											Oid ReferencingParentInsTrigger,
 											Oid ReferencingParentUpdTrigger);
+static bool ATExecAlterCheckConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon,
+												 Relation conrel, Oid conrelid,
+												 HeapTuple contuple, bool recurse, bool recursing,
+												 LOCKMODE lockmode);
 static bool ATExecAlterConstrDeferrability(List **wqueue, ATAlterConstraint *cmdcon,
 										   Relation conrel, Relation tgrel, Relation rel,
 										   HeapTuple contuple, bool recurse,
@@ -421,6 +425,9 @@ static void AlterConstrEnforceabilityRecurse(List **wqueue, ATAlterConstraint *c
 											 Oid ReferencedParentUpdTrigger,
 											 Oid ReferencingParentInsTrigger,
 											 Oid ReferencingParentUpdTrigger);
+static void AlterCheckConstrEnforceabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon,
+												  Relation conrel, Oid conrelid,
+												  bool recurse, bool recursing, LOCKMODE lockmode);
 static void AlterConstrDeferrabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon,
 											Relation conrel, Relation tgrel, Relation rel,
 											HeapTuple contuple, bool recurse,
@@ -431,7 +438,7 @@ static ObjectAddress ATExecValidateConstraint(List **wqueue,
 											  Relation rel, char *constrName,
 											  bool recurse, bool recursing, LOCKMODE lockmode);
 static void QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation rel,
-										HeapTuple contuple, LOCKMODE lockmode);
+										HeapTuple contuple, LOCKMODE lockmode, bool recursing);
 static void QueueCheckConstraintValidation(List **wqueue, Relation conrel, Relation rel,
 										   char *constrName, HeapTuple contuple,
 										   bool recurse, bool recursing, LOCKMODE lockmode);
@@ -11867,7 +11874,7 @@ AttachPartitionForeignKey(List **wqueue,
 
 		/* Use the same lock as for AT_ValidateConstraint */
 		QueueFKConstraintValidation(wqueue, conrel, partition, partcontup,
-									ShareUpdateExclusiveLock);
+									ShareUpdateExclusiveLock, false);
 		ReleaseSysCache(partcontup);
 		table_close(conrel, RowExclusiveLock);
 	}
@@ -12151,7 +12158,7 @@ GetForeignKeyCheckTriggers(Relation trigrel,
  *
  * Update the attributes of a constraint.
  *
- * Currently only works for Foreign Key and not null constraints.
+ * Currently works for Foreign Key, CHECK, and not null constraints.
  *
  * If the constraint is modified, returns its address; otherwise, return
  * InvalidObjectAddress.
@@ -12213,11 +12220,13 @@ ATExecAlterConstraint(List **wqueue, Relation rel, ATAlterConstraint *cmdcon,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key constraint",
 						cmdcon->conname, RelationGetRelationName(rel))));
-	if (cmdcon->alterEnforceability && currcon->contype != CONSTRAINT_FOREIGN)
+	if (cmdcon->alterEnforceability &&
+		(currcon->contype != CONSTRAINT_FOREIGN && currcon->contype != CONSTRAINT_CHECK))
 		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot alter enforceability of constraint \"%s\" of relation \"%s\"",
-						cmdcon->conname, RelationGetRelationName(rel))));
+				errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				errmsg("cannot alter enforceability of constraint \"%s\" of relation \"%s\"",
+						cmdcon->conname, RelationGetRelationName(rel)),
+				errhint("Only foreign key, check constraint can change enforceability"));
 	if (cmdcon->alterInheritability &&
 		currcon->contype != CONSTRAINT_NOTNULL)
 		ereport(ERROR,
@@ -12319,16 +12328,21 @@ ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon,
 	 * enforceability, we don't need to explicitly update multiple entries in
 	 * pg_trigger related to deferrability.
 	 *
-	 * Modifying enforceability involves either creating or dropping the
-	 * trigger, during which the deferrability setting will be adjusted
+	 * Modifying foreign key enforceability involves either creating or dropping
+	 * the trigger, during which the deferrability setting will be adjusted
 	 * automatically.
 	 */
-	if (cmdcon->alterEnforceability &&
+	if (cmdcon->alterEnforceability && currcon->contype == CONSTRAINT_FOREIGN &&
 		ATExecAlterConstrEnforceability(wqueue, cmdcon, conrel, tgrel,
 										currcon->conrelid, currcon->confrelid,
 										contuple, lockmode, InvalidOid,
 										InvalidOid, InvalidOid, InvalidOid))
 		changed = true;
+	else if (cmdcon->alterEnforceability && currcon->contype == CONSTRAINT_CHECK &&
+		ATExecAlterCheckConstrEnforceability(wqueue, cmdcon, conrel,
+											 currcon->conrelid,
+											 contuple, recurse, false, lockmode))
+		changed = true;
 
 	else if (cmdcon->alterDeferrability &&
 			 ATExecAlterConstrDeferrability(wqueue, cmdcon, conrel, tgrel, rel,
@@ -12359,7 +12373,148 @@ ATExecAlterConstraintInternal(List **wqueue, ATAlterConstraint *cmdcon,
 }
 
 /*
- * Returns true if the constraint's enforceability is altered.
+ * Returns true if the CHECK constraint's enforceability is altered.
+ *
+ * Note that we must recurse even when trying to change a constraint to not
+ * enforced if it is already not enforced, in case descendant constraints might
+ * be enforced and need to be changed to not enforced. Conversely, we should do
+ * nothing if a constraint is being set to enforced and is already enforced, as
+ * descendant constraints cannot be different in that case.
+ */
+static bool
+ATExecAlterCheckConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon,
+									 Relation conrel, Oid conrelid,
+									 HeapTuple contuple, bool recurse, bool recursing,
+									 LOCKMODE lockmode)
+{
+	Form_pg_constraint currcon;
+	Relation	rel;
+	bool		changed = false;
+	List	   *children = NIL;
+
+	/* Since this function recurses, it could be driven to stack overflow */
+	check_stack_depth();
+
+	Assert(cmdcon->alterEnforceability);
+	currcon = (Form_pg_constraint) GETSTRUCT(contuple);
+
+	rel = table_open(currcon->conrelid, lockmode);
+
+	/*
+	 * If we're recursing, the parent has already done this, so skip it. Also,
+	 * if the constraint is a NO INHERIT constraint, we shouldn't try to look
+	 * for it in the children.
+	 */
+	if (!recursing && !currcon->connoinherit)
+		children = find_all_inheritors(RelationGetRelid(rel),
+									   lockmode, NULL);
+
+	/*
+	 * For CHECK constraints, we must ensure that we only mark the constraint as
+	 * enforced on the parent if it's already enforced on the children.
+	 *
+	 * We recurse before changing enforceability  on the parent, to reduce risk
+	 * of deadlocks.
+	 */
+	foreach_oid(childoid, children)
+	{
+		if (childoid == RelationGetRelid(rel))
+			continue;
+
+		/*
+		 * If we are told not to recurse, there had better not be any child
+		 * tables, because we can't changing constraint enforceability on the
+		 * parent unless we have chaned enforceability for all child tables.
+		 */
+		if (!recurse)
+			ereport(ERROR,
+					errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+					errmsg("constraint must be altered on child tables too"));
+
+		AlterCheckConstrEnforceabilityRecurse(wqueue, cmdcon, conrel, childoid, false, true, lockmode);
+	}
+
+	/*
+	 * Tell Phase 3 to check that the constraint is satisfied by existing rows.
+	 * We do this only when alter the constraint from not enforced to enforced.
+	 */
+	if (rel->rd_rel->relkind == RELKIND_RELATION &&
+		cmdcon->is_enforced &&
+		!currcon->conenforced)
+	{
+		AlteredTableInfo *tab;
+		NewConstraint *newcon;
+		Datum		val;
+		char	   *conbin;
+
+		newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
+		newcon->name = pstrdup(NameStr(currcon->conname));
+		newcon->contype = CONSTR_CHECK;
+		newcon->refrelid = InvalidOid;
+		newcon->refindid = InvalidOid;
+		newcon->conid = currcon->oid;
+
+		val = SysCacheGetAttrNotNull(CONSTROID, contuple,
+									 Anum_pg_constraint_conbin);
+		conbin = TextDatumGetCString(val);
+		newcon->qual = expand_generated_columns_in_expr(stringToNode(conbin), rel, 1);
+
+		/* Find or create work queue entry for this table */
+		tab = ATGetQueueEntry(wqueue, rel);
+		tab->constraints = lappend(tab->constraints, newcon);
+	}
+
+	if (currcon->conenforced != cmdcon->is_enforced)
+	{
+		AlterConstrUpdateConstraintEntry(cmdcon, conrel, contuple);
+		changed = true;
+	}
+
+	table_close(rel, NoLock);
+	return changed;
+}
+
+
+static void
+AlterCheckConstrEnforceabilityRecurse(List **wqueue, ATAlterConstraint *cmdcon,
+									  Relation conrel, Oid conrelid,
+									  bool recurse, bool recursing,
+									  LOCKMODE lockmode)
+{
+	SysScanDesc pscan;
+	HeapTuple	childtup;
+	ScanKeyData skey[3];
+
+	ScanKeyInit(&skey[0],
+				Anum_pg_constraint_conrelid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(conrelid));
+	ScanKeyInit(&skey[1],
+				Anum_pg_constraint_contypid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(InvalidOid));
+	ScanKeyInit(&skey[2],
+				Anum_pg_constraint_conname,
+				BTEqualStrategyNumber, F_NAMEEQ,
+				CStringGetDatum(cmdcon->conname));
+
+	pscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
+							   NULL, 3, skey);
+
+	if (!HeapTupleIsValid(childtup = systable_getnext(pscan)))
+		ereport(ERROR,
+				errcode(ERRCODE_UNDEFINED_OBJECT),
+				errmsg("constraint \"%s\" of relation \"%s\" does not exist",
+						 cmdcon->conname, get_rel_name(conrelid)));
+
+	ATExecAlterCheckConstrEnforceability(wqueue, cmdcon, conrel,
+										 conrelid, childtup, recurse, recursing, lockmode);
+
+	systable_endscan(pscan);
+}
+
+/*
+ * Returns true if the FOREIGN KEY constraint's enforceability is altered.
  *
  * Depending on whether the constraint is being set to ENFORCED or NOT
  * ENFORCED, it creates or drops the trigger accordingly.
@@ -12919,7 +13074,7 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
 	{
 		if (con->contype == CONSTRAINT_FOREIGN)
 		{
-			QueueFKConstraintValidation(wqueue, conrel, rel, tuple, lockmode);
+			QueueFKConstraintValidation(wqueue, conrel, rel, tuple, lockmode, false);
 		}
 		else if (con->contype == CONSTRAINT_CHECK)
 		{
@@ -12953,7 +13108,7 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
  */
 static void
 QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation rel,
-							HeapTuple contuple, LOCKMODE lockmode)
+							HeapTuple contuple, LOCKMODE lockmode, bool recursing)
 {
 	Form_pg_constraint con;
 	AlteredTableInfo *tab;
@@ -12983,8 +13138,11 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation rel,
 		newcon->qual = (Node *) fkconstraint;
 
 		/* Find or create work queue entry for this table */
-		tab = ATGetQueueEntry(wqueue, rel);
-		tab->constraints = lappend(tab->constraints, newcon);
+		if (!recursing)
+		{
+			tab = ATGetQueueEntry(wqueue, rel);
+			tab->constraints = lappend(tab->constraints, newcon);
+		}
 	}
 
 	/*
@@ -13024,7 +13182,7 @@ QueueFKConstraintValidation(List **wqueue, Relation conrel, Relation rel,
 			childrel = table_open(childcon->conrelid, lockmode);
 
 			QueueFKConstraintValidation(wqueue, conrel, childrel, childtup,
-										lockmode);
+										lockmode, true);
 			table_close(childrel, NoLock);
 		}
 
diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out
index ad6aaab7385..8e25ca4858c 100644
--- a/src/test/regress/expected/constraints.out
+++ b/src/test/regress/expected/constraints.out
@@ -390,6 +390,58 @@ SELECT * FROM COPY_TBL;
  6 | OK            | 4
 (2 rows)
 
+--
+-- CHECK constraints
+-- ALTER TABLE ALTER CONSTRAINT [NO] ENFORCED
+create table parted_ch_tbl(a int, constraint cc check (a > 10) not enforced, b int ) partition by range(a);
+create table parted_ch_tbl_1 partition of parted_ch_tbl for values from (0) to (10) partition by list(b);
+create table parted_ch_tbl_11 partition of parted_ch_tbl_1 for values in (0, 1);
+create table parted_ch_tbl_12 partition of parted_ch_tbl_1 for values in (2);
+create table parted_ch_tbl_2 partition of parted_ch_tbl for values from (10) to (20);
+alter table parted_ch_tbl_2 add constraint cc_2 check( a < 15) not enforced;
+insert into parted_ch_tbl values (1, 2), (9, 1), (16, 16);
+alter table parted_ch_tbl alter constraint cc enforced; --error
+ERROR:  check constraint "cc" of relation "parted_ch_tbl_11" is violated by some row
+delete from parted_ch_tbl where a = 1;
+alter table parted_ch_tbl alter constraint cc enforced; --error
+ERROR:  check constraint "cc" of relation "parted_ch_tbl_11" is violated by some row
+delete from parted_ch_tbl where a = 9;
+alter table parted_ch_tbl alter constraint cc enforced; --ok
+--check these CHECK constraint status
+select  conname, conrelid::regclass, conenforced, convalidated
+from    pg_constraint
+where   conrelid::regclass::text ~* '^parted_ch' and conname = 'cc'
+order by conrelid::regclass, conname;
+ conname |     conrelid     | conenforced | convalidated 
+---------+------------------+-------------+--------------
+ cc      | parted_ch_tbl    | t           | t
+ cc      | parted_ch_tbl_1  | t           | t
+ cc      | parted_ch_tbl_11 | t           | t
+ cc      | parted_ch_tbl_12 | t           | t
+ cc      | parted_ch_tbl_2  | t           | t
+(5 rows)
+
+alter table parted_ch_tbl_2 alter constraint cc_2 enforced; --error
+ERROR:  check constraint "cc_2" of relation "parted_ch_tbl_2" is violated by some row
+delete from parted_ch_tbl where a = 16;
+alter table parted_ch_tbl_2 alter constraint cc_2 enforced; --ok
+alter table parted_ch_tbl alter constraint cc not enforced; --ok
+--check these CHECK constraint status
+select  conname, conrelid::regclass, conenforced, convalidated
+from    pg_constraint
+where   conrelid::regclass::text ~* '^parted_ch' and contype = 'c'
+order by conrelid::regclass, conname;
+ conname |     conrelid     | conenforced | convalidated 
+---------+------------------+-------------+--------------
+ cc      | parted_ch_tbl    | f           | f
+ cc      | parted_ch_tbl_1  | f           | f
+ cc      | parted_ch_tbl_11 | f           | f
+ cc      | parted_ch_tbl_12 | f           | f
+ cc      | parted_ch_tbl_2  | f           | f
+ cc_2    | parted_ch_tbl_2  | t           | t
+(6 rows)
+
+drop table parted_ch_tbl;
 --
 -- Primary keys
 --
@@ -746,8 +798,10 @@ LINE 1: CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED);
                                                    ^
 ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED;
 ERROR:  cannot alter enforceability of constraint "unique_tbl_i_key" of relation "unique_tbl"
+HINT:  Only foreign key, check constraint can change enforceability
 ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORCED;
 ERROR:  cannot alter enforceability of constraint "unique_tbl_i_key" of relation "unique_tbl"
+HINT:  Only foreign key, check constraint can change enforceability
 DROP TABLE unique_tbl;
 --
 -- EXCLUDE constraints
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index f9b0c415cfd..a24fe7962d5 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1418,11 +1418,55 @@ order by 1, 2;
  p1_c3   | inh_check_constraint9  | f          |           2 | t           | t
 (38 rows)
 
+alter table p1 drop constraint inh_check_constraint1;
+alter table p1_c1 drop constraint inh_check_constraint1;
+insert into p1_c1 values(-2);
+insert into p1_c3 values(-3);
+alter table only p1 alter constraint inh_check_constraint3 enforced; --error
+ERROR:  constraint must be altered on child tables too
+alter table only p1 alter constraint inh_check_constraint3 not enforced; --error
+ERROR:  constraint must be altered on child tables too
+alter table p1 alter constraint inh_check_constraint3 enforced; --error
+ERROR:  check constraint "inh_check_constraint3" of relation "p1_c1" is violated by some row
+delete from only p1_c1 where f1 = -2;
+alter table p1_c1 alter constraint inh_check_constraint3 enforced; --error
+ERROR:  check constraint "inh_check_constraint3" of relation "p1_c3" is violated by some row
+delete from only p1_c3 where f1 = -3;
+alter table p1 alter constraint inh_check_constraint3 enforced; --ok
+alter table p1 alter constraint inh_check_constraint3 not enforced; --ok
+select  conname, conenforced, convalidated, conrelid::regclass
+from    pg_constraint
+where   conname = 'inh_check_constraint3' and contype = 'c'
+order by conrelid::regclass;
+        conname        | conenforced | convalidated | conrelid 
+-----------------------+-------------+--------------+----------
+ inh_check_constraint3 | f           | f            | p1
+ inh_check_constraint3 | f           | f            | p1_c1
+ inh_check_constraint3 | f           | f            | p1_c2
+ inh_check_constraint3 | f           | f            | p1_c3
+(4 rows)
+
 drop table p1 cascade;
 NOTICE:  drop cascades to 3 other objects
 DETAIL:  drop cascades to table p1_c1
 drop cascades to table p1_c2
 drop cascades to table p1_c3
+--ALTER TABLE ALTER CONSTRAINT
+--for "no inherit" check constraint, it will not recurse to child table
+create table p1(f1 int constraint p1_a_check check (f1 > 0) no inherit not enforced);
+create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
+alter table p1_c1 inherit p1;
+insert into p1_c1 values(-11);
+insert into p1 values(-1);
+alter table p1 alter constraint p1_a_check not enforced; --ok
+alter table p1 alter constraint p1_a_check enforced; --error
+ERROR:  check constraint "p1_a_check" of relation "p1" is violated by some row
+delete from only p1 where f1 = -1;
+alter table p1 alter constraint p1_a_check enforced; --ok
+alter table p1_c1 alter constraint p1_a_check enforced; --error
+ERROR:  check constraint "p1_a_check" of relation "p1_c1" is violated by some row
+drop table p1 cascade;
+NOTICE:  drop cascades to table p1_c1
 --
 -- Similarly, check the merging of existing constraints; a parent constraint
 -- marked as NOT ENFORCED can merge with an ENFORCED child constraint, but the
@@ -1431,6 +1475,25 @@ drop cascades to table p1_c3
 create table p1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
 create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) enforced);
 alter table p1_c1 inherit p1;
+insert into p1 values(-1); --ok
+insert into p1_c1 values(-1); --error
+ERROR:  new row for relation "p1_c1" violates check constraint "p1_a_check"
+DETAIL:  Failing row contains (-1).
+alter table p1 alter constraint p1_a_check enforced; --error
+ERROR:  check constraint "p1_a_check" of relation "p1" is violated by some row
+truncate p1;
+alter table p1 alter constraint p1_a_check enforced; --ok
+alter table p1 alter constraint p1_a_check not enforced; --ok
+select  conname, conenforced, convalidated, conrelid::regclass
+from    pg_constraint
+where   conname = 'p1_a_check' and contype = 'c'
+order by conrelid::regclass;
+  conname   | conenforced | convalidated | conrelid 
+------------+-------------+--------------+----------
+ p1_a_check | f           | f            | p1
+ p1_a_check | f           | f            | p1_c1
+(2 rows)
+
 drop table p1 cascade;
 NOTICE:  drop cascades to table p1_c1
 create table p1(f1 int constraint p1_a_check check (f1 > 0) enforced);
diff --git a/src/test/regress/sql/constraints.sql b/src/test/regress/sql/constraints.sql
index 337baab7ced..4a540120005 100644
--- a/src/test/regress/sql/constraints.sql
+++ b/src/test/regress/sql/constraints.sql
@@ -266,6 +266,43 @@ COPY COPY_TBL FROM :'filename';
 
 SELECT * FROM COPY_TBL;
 
+--
+-- CHECK constraints
+-- ALTER TABLE ALTER CONSTRAINT [NO] ENFORCED
+create table parted_ch_tbl(a int, constraint cc check (a > 10) not enforced, b int ) partition by range(a);
+create table parted_ch_tbl_1 partition of parted_ch_tbl for values from (0) to (10) partition by list(b);
+create table parted_ch_tbl_11 partition of parted_ch_tbl_1 for values in (0, 1);
+create table parted_ch_tbl_12 partition of parted_ch_tbl_1 for values in (2);
+create table parted_ch_tbl_2 partition of parted_ch_tbl for values from (10) to (20);
+
+alter table parted_ch_tbl_2 add constraint cc_2 check( a < 15) not enforced;
+insert into parted_ch_tbl values (1, 2), (9, 1), (16, 16);
+
+alter table parted_ch_tbl alter constraint cc enforced; --error
+delete from parted_ch_tbl where a = 1;
+alter table parted_ch_tbl alter constraint cc enforced; --error
+delete from parted_ch_tbl where a = 9;
+alter table parted_ch_tbl alter constraint cc enforced; --ok
+
+--check these CHECK constraint status
+select  conname, conrelid::regclass, conenforced, convalidated
+from    pg_constraint
+where   conrelid::regclass::text ~* '^parted_ch' and conname = 'cc'
+order by conrelid::regclass, conname;
+
+alter table parted_ch_tbl_2 alter constraint cc_2 enforced; --error
+delete from parted_ch_tbl where a = 16;
+alter table parted_ch_tbl_2 alter constraint cc_2 enforced; --ok
+
+alter table parted_ch_tbl alter constraint cc not enforced; --ok
+--check these CHECK constraint status
+select  conname, conrelid::regclass, conenforced, convalidated
+from    pg_constraint
+where   conrelid::regclass::text ~* '^parted_ch' and contype = 'c'
+order by conrelid::regclass, conname;
+
+drop table parted_ch_tbl;
+
 --
 -- Primary keys
 --
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index 699e8ac09c8..0f505eadc85 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -510,6 +510,40 @@ select conrelid::regclass::text as relname, conname, conislocal, coninhcount, co
 from pg_constraint where conname like 'inh\_check\_constraint%'
 order by 1, 2;
 
+
+alter table p1 drop constraint inh_check_constraint1;
+alter table p1_c1 drop constraint inh_check_constraint1;
+
+insert into p1_c1 values(-2);
+insert into p1_c3 values(-3);
+alter table only p1 alter constraint inh_check_constraint3 enforced; --error
+alter table only p1 alter constraint inh_check_constraint3 not enforced; --error
+
+alter table p1 alter constraint inh_check_constraint3 enforced; --error
+delete from only p1_c1 where f1 = -2;
+alter table p1_c1 alter constraint inh_check_constraint3 enforced; --error
+
+delete from only p1_c3 where f1 = -3;
+alter table p1 alter constraint inh_check_constraint3 enforced; --ok
+alter table p1 alter constraint inh_check_constraint3 not enforced; --ok
+select  conname, conenforced, convalidated, conrelid::regclass
+from    pg_constraint
+where   conname = 'inh_check_constraint3' and contype = 'c'
+order by conrelid::regclass;
+drop table p1 cascade;
+
+--ALTER TABLE ALTER CONSTRAINT
+--for "no inherit" check constraint, it will not recurse to child table
+create table p1(f1 int constraint p1_a_check check (f1 > 0) no inherit not enforced);
+create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
+alter table p1_c1 inherit p1;
+insert into p1_c1 values(-11);
+insert into p1 values(-1);
+alter table p1 alter constraint p1_a_check not enforced; --ok
+alter table p1 alter constraint p1_a_check enforced; --error
+delete from only p1 where f1 = -1;
+alter table p1 alter constraint p1_a_check enforced; --ok
+alter table p1_c1 alter constraint p1_a_check enforced; --error
 drop table p1 cascade;
 
 --
@@ -520,6 +554,17 @@ drop table p1 cascade;
 create table p1(f1 int constraint p1_a_check check (f1 > 0) not enforced);
 create table p1_c1(f1 int constraint p1_a_check check (f1 > 0) enforced);
 alter table p1_c1 inherit p1;
+insert into p1 values(-1); --ok
+insert into p1_c1 values(-1); --error
+alter table p1 alter constraint p1_a_check enforced; --error
+truncate p1;
+alter table p1 alter constraint p1_a_check enforced; --ok
+alter table p1 alter constraint p1_a_check not enforced; --ok
+
+select  conname, conenforced, convalidated, conrelid::regclass
+from    pg_constraint
+where   conname = 'p1_a_check' and contype = 'c'
+order by conrelid::regclass;
 drop table p1 cascade;
 
 create table p1(f1 int constraint p1_a_check check (f1 > 0) enforced);
-- 
2.34.1

Reply via email to