@@ -102,12 +102,13 @@ static ObjectAddress AddNewRelationType(const char *typeName,
102102 Oid new_array_type );
103103static void RelationRemoveInheritance (Oid relid );
104104static Oid StoreRelCheck (Relation rel , const char * ccname , Node * expr ,
105- bool is_validated , bool is_local , int16 inhcount ,
106- bool is_no_inherit , bool is_internal );
105+ bool is_enforced , bool is_validated , bool is_local ,
106+ int16 inhcount , bool is_no_inherit , bool is_internal );
107107static void StoreConstraints (Relation rel , List * cooked_constraints ,
108108 bool is_internal );
109109static bool MergeWithExistingConstraint (Relation rel , const char * ccname , Node * expr ,
110110 bool allow_merge , bool is_local ,
111+ bool is_enforced ,
111112 bool is_initially_valid ,
112113 bool is_no_inherit );
113114static void SetRelationNumChecks (Relation rel , int numchecks );
@@ -2066,8 +2067,8 @@ SetAttrMissing(Oid relid, char *attname, char *value)
20662067 */
20672068static Oid
20682069StoreRelCheck (Relation rel , const char * ccname , Node * expr ,
2069- bool is_validated , bool is_local , int16 inhcount ,
2070- bool is_no_inherit , bool is_internal )
2070+ bool is_enforced , bool is_validated , bool is_local ,
2071+ int16 inhcount , bool is_no_inherit , bool is_internal )
20712072{
20722073 char * ccbin ;
20732074 List * varList ;
@@ -2132,6 +2133,7 @@ StoreRelCheck(Relation rel, const char *ccname, Node *expr,
21322133 CONSTRAINT_CHECK , /* Constraint Type */
21332134 false, /* Is Deferrable */
21342135 false, /* Is Deferred */
2136+ is_enforced , /* Is Enforced */
21352137 is_validated ,
21362138 InvalidOid , /* no parent constraint */
21372139 RelationGetRelid (rel ), /* relation */
@@ -2185,6 +2187,7 @@ StoreRelNotNull(Relation rel, const char *nnname, AttrNumber attnum,
21852187 CONSTRAINT_NOTNULL ,
21862188 false,
21872189 false,
2190+ true, /* Is Enforced */
21882191 is_validated ,
21892192 InvalidOid ,
21902193 RelationGetRelid (rel ),
@@ -2254,9 +2257,9 @@ StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
22542257 case CONSTR_CHECK :
22552258 con -> conoid =
22562259 StoreRelCheck (rel , con -> name , con -> expr ,
2257- ! con -> skip_validation , con -> is_local ,
2258- con -> inhcount , con -> is_no_inherit ,
2259- is_internal );
2260+ con -> is_enforced , ! con -> skip_validation ,
2261+ con -> is_local , con -> inhcount ,
2262+ con -> is_no_inherit , is_internal );
22602263 numchecks ++ ;
22612264 break ;
22622265
@@ -2390,6 +2393,7 @@ AddRelationNewConstraints(Relation rel,
23902393 cooked -> name = NULL ;
23912394 cooked -> attnum = colDef -> attnum ;
23922395 cooked -> expr = expr ;
2396+ cooked -> is_enforced = true;
23932397 cooked -> skip_validation = false;
23942398 cooked -> is_local = is_local ;
23952399 cooked -> inhcount = is_local ? 0 : 1 ;
@@ -2461,6 +2465,7 @@ AddRelationNewConstraints(Relation rel,
24612465 */
24622466 if (MergeWithExistingConstraint (rel , ccname , expr ,
24632467 allow_merge , is_local ,
2468+ cdef -> is_enforced ,
24642469 cdef -> initially_valid ,
24652470 cdef -> is_no_inherit ))
24662471 continue ;
@@ -2509,8 +2514,10 @@ AddRelationNewConstraints(Relation rel,
25092514 * OK, store it.
25102515 */
25112516 constrOid =
2512- StoreRelCheck (rel , ccname , expr , cdef -> initially_valid , is_local ,
2513- is_local ? 0 : 1 , cdef -> is_no_inherit , is_internal );
2517+ StoreRelCheck (rel , ccname , expr , cdef -> is_enforced ,
2518+ cdef -> initially_valid , is_local ,
2519+ is_local ? 0 : 1 , cdef -> is_no_inherit ,
2520+ is_internal );
25142521
25152522 numchecks ++ ;
25162523
@@ -2520,6 +2527,7 @@ AddRelationNewConstraints(Relation rel,
25202527 cooked -> name = ccname ;
25212528 cooked -> attnum = 0 ;
25222529 cooked -> expr = expr ;
2530+ cooked -> is_enforced = cdef -> is_enforced ;
25232531 cooked -> skip_validation = cdef -> skip_validation ;
25242532 cooked -> is_local = is_local ;
25252533 cooked -> inhcount = is_local ? 0 : 1 ;
@@ -2590,6 +2598,7 @@ AddRelationNewConstraints(Relation rel,
25902598 nncooked -> name = nnname ;
25912599 nncooked -> attnum = colnum ;
25922600 nncooked -> expr = NULL ;
2601+ nncooked -> is_enforced = true;
25932602 nncooked -> skip_validation = cdef -> skip_validation ;
25942603 nncooked -> is_local = is_local ;
25952604 nncooked -> inhcount = inhcount ;
@@ -2624,6 +2633,7 @@ AddRelationNewConstraints(Relation rel,
26242633static bool
26252634MergeWithExistingConstraint (Relation rel , const char * ccname , Node * expr ,
26262635 bool allow_merge , bool is_local ,
2636+ bool is_enforced ,
26272637 bool is_initially_valid ,
26282638 bool is_no_inherit )
26292639{
@@ -2714,12 +2724,24 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
27142724 * If the child constraint is "not valid" then cannot merge with a
27152725 * valid parent constraint.
27162726 */
2717- if (is_initially_valid && !con -> convalidated )
2727+ if (is_initially_valid && con -> conenforced && !con -> convalidated )
27182728 ereport (ERROR ,
27192729 (errcode (ERRCODE_INVALID_OBJECT_DEFINITION ),
27202730 errmsg ("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"" ,
27212731 ccname , RelationGetRelationName (rel ))));
27222732
2733+ /*
2734+ * A non-enforced child constraint cannot be merged with an enforced
2735+ * parent constraint. However, the reverse is allowed, where the child
2736+ * constraint is enforced.
2737+ */
2738+ if ((!is_local && is_enforced && !con -> conenforced ) ||
2739+ (is_local && !is_enforced && con -> conenforced ))
2740+ ereport (ERROR ,
2741+ (errcode (ERRCODE_INVALID_OBJECT_DEFINITION ),
2742+ errmsg ("constraint \"%s\" conflicts with NOT ENFORCED constraint on relation \"%s\"" ,
2743+ ccname , RelationGetRelationName (rel ))));
2744+
27232745 /* OK to update the tuple */
27242746 ereport (NOTICE ,
27252747 (errmsg ("merging constraint \"%s\" with inherited definition" ,
@@ -2755,6 +2777,19 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
27552777 con -> connoinherit = true;
27562778 }
27572779
2780+ /*
2781+ * If the child constraint is required to be enforced while the parent
2782+ * constraint is not, this should be allowed by marking the child
2783+ * constraint as enforced. In the reverse case, an error would have
2784+ * already been thrown before reaching this point.
2785+ */
2786+ if (is_enforced && !con -> conenforced )
2787+ {
2788+ Assert (is_local );
2789+ con -> conenforced = true;
2790+ con -> convalidated = true;
2791+ }
2792+
27582793 CatalogTupleUpdate (conDesc , & tup -> t_self , tup );
27592794 }
27602795
0 commit comments