]> granicus.if.org Git - postgresql/commitdiff
Mark CHECK constraints declared NOT VALID valid if created with table.
authorRobert Haas <rhaas@postgresql.org>
Wed, 16 Dec 2015 12:43:56 +0000 (07:43 -0500)
committerRobert Haas <rhaas@postgresql.org>
Wed, 16 Dec 2015 12:43:56 +0000 (07:43 -0500)
FOREIGN KEY constraints have behaved this way for a long time, but for
some reason the behavior of CHECK constraints has been inconsistent up
until now.

Amit Langote and Amul Sul, with assorted tweaks by me.

src/backend/catalog/heap.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index 7d7d062c068f5e425f5f4147f583ea3982c47758..04c4f8f1ef20755f69c2063ff8a4d30c07dc9c20 100644 (file)
@@ -2349,7 +2349,7 @@ AddRelationNewConstraints(Relation rel,
                 * OK, store it.
                 */
                constrOid =
-                       StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
+                       StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
                                                  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
 
                numchecks++;
index 7916df8b099aa513532d2f0c607caf2897159c93..c4bed8a5ef7a9c84db656fe80adb9d94af01e33a 100644 (file)
@@ -3080,6 +3080,8 @@ ColConstraintElem:
                                        n->is_no_inherit = $5;
                                        n->raw_expr = $3;
                                        n->cooked_expr = NULL;
+                                       n->skip_validation = false;
+                                       n->initially_valid = true;
                                        $$ = (Node *)n;
                                }
                        | DEFAULT b_expr
index 344a40cf58e879ce3adc599cb2e39fbea7dac140..4c24c13cf8db057b0cc94e811e783a1d6d0784f4 100644 (file)
@@ -120,6 +120,8 @@ static IndexStmt *transformIndexConstraint(Constraint *constraint,
 static void transformFKConstraints(CreateStmtContext *cxt,
                                           bool skipValidation,
                                           bool isAddConstraint);
+static void transformCheckConstraints(CreateStmtContext *cxt,
+                                               bool skipValidation);
 static void transformConstraintAttrs(CreateStmtContext *cxt,
                                                 List *constraintList);
 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
@@ -319,6 +321,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
         */
        transformFKConstraints(&cxt, true, false);
 
+       /*
+        * Postprocess check constraints.
+        */
+       transformCheckConstraints(&cxt, true);
+
        /*
         * Output results.
         */
@@ -1914,6 +1921,40 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
        return index;
 }
 
+/*
+ * transformCheckConstraints
+ *             handle CHECK constraints
+ *
+ * Right now, there's nothing to do here when called from ALTER TABLE,
+ * but the other constraint-transformation functions are called in both
+ * the CREATE TABLE and ALTER TABLE paths, so do the same here, and just
+ * don't do anything if we're not authorized to skip validation.
+ */
+static void
+transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
+{
+       ListCell   *ckclist;
+
+       if (cxt->ckconstraints == NIL)
+               return;
+
+       /*
+        * If creating a new table, we can safely skip validation of check
+        * constraints, and nonetheless mark them valid.  (This will override
+        * any user-supplied NOT VALID flag.)
+        */
+       if (skipValidation)
+       {
+               foreach(ckclist, cxt->ckconstraints)
+               {
+                       Constraint *constraint = (Constraint *) lfirst(ckclist);
+
+                       constraint->skip_validation = true;
+                       constraint->initially_valid = true;
+               }
+       }
+}
+
 /*
  * transformFKConstraints
  *             handle FOREIGN KEY constraints
@@ -2567,10 +2608,10 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
        save_alist = cxt.alist;
        cxt.alist = NIL;
 
-       /* Postprocess index and FK constraints */
+       /* Postprocess constraints */
        transformIndexConstraints(&cxt);
-
        transformFKConstraints(&cxt, skipValidation, true);
+       transformCheckConstraints(&cxt, false);
 
        /*
         * Push any index-creation commands into the ALTER, so that they can be
index 61669b6c7f14e998b8925b2f0e1f4e2c9c982514..228ae6ec22134b05a8a93b85733c190765bfacd4 100644 (file)
@@ -380,7 +380,16 @@ DROP TABLE tmp2;
 -- NOT VALID with plan invalidation -- ensure we don't use a constraint for
 -- exclusion until validated
 set constraint_exclusion TO 'partition';
-create table nv_parent (d date);
+create table nv_parent (d date, check (false) no inherit not valid);
+-- not valid constraint added at creation time should automatically become valid
+\d nv_parent
+ Table "public.nv_parent"
+ Column | Type | Modifiers 
+--------+------+-----------
+ d      | date | 
+Check constraints:
+    "nv_parent_check" CHECK (false) NO INHERIT
+
 create table nv_child_2010 () inherits (nv_parent);
 create table nv_child_2011 () inherits (nv_parent);
 alter table nv_child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid;
index c0bb77ee22188e32973a4ec1a98918ebe7470c52..3db34609733779f7d8ded6b8b99d47ce64236932 100644 (file)
@@ -327,7 +327,10 @@ DROP TABLE tmp2;
 -- NOT VALID with plan invalidation -- ensure we don't use a constraint for
 -- exclusion until validated
 set constraint_exclusion TO 'partition';
-create table nv_parent (d date);
+create table nv_parent (d date, check (false) no inherit not valid);
+-- not valid constraint added at creation time should automatically become valid
+\d nv_parent
+
 create table nv_child_2010 () inherits (nv_parent);
 create table nv_child_2011 () inherits (nv_parent);
 alter table nv_child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid;