From e8b76c375d7fe5ec739e3eee0382dcec2051e504 Mon Sep 17 00:00:00 2001
From: Amul Sul <sul_amul@yahoo.co.in>
Date: Wed, 16 Dec 2015 13:58:40 +0530
Subject: [PATCH] Make check constraint(s) valid at table creation even if NOT
 VALID option provided

---
 src/backend/catalog/heap.c                 |  2 +-
 src/backend/parser/gram.y                  |  2 ++
 src/backend/parser/parse_utilcmd.c         | 35 ++++++++++++++++++++++++++++++
 src/test/regress/expected/create_table.out | 18 +++++++++++++++
 src/test/regress/sql/create_table.sql      | 11 ++++++++++
 5 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 7d7d062..04c4f8f 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -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++;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7916df8..c4bed8a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 344a40c..566597b 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -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);
@@ -320,6 +322,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 	transformFKConstraints(&cxt, true, false);
 
 	/*
+	 * Postprocess check constraints.
+	 */
+	transformCheckConstraints(&cxt, true);
+
+	/*
 	 * Output results.
 	 */
 	stmt->tableElts = cxt.columns;
@@ -1915,6 +1922,34 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 }
 
 /*
+ * transformCheckConstraints
+ *		handle CHECK constraints
+ */
+static void
+transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
+{
+	ListCell   *ckclist;
+
+	if (cxt->ckconstraints == NIL)
+		return;
+	/*
+	 * If CREATE 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
  */
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 41ceb87..8a73970 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -253,3 +253,21 @@ DROP TABLE as_select1;
 -- check that the oid column is added before the primary key is checked
 CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
 DROP TABLE oid_pk;
+-- at table creation, override NOT VALID flag
+CREATE TABLE foo (a SERIAL PRIMARY KEY);
+CREATE TABLE bar (a INT,
+					FOREIGN KEY(a) REFERENCES foo NOT VALID,
+					CHECK(a != 0) NOT VALID);
+\d bar
+      Table "public.bar"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ a      | integer | 
+Check constraints:
+    "bar_a_check" CHECK (a <> 0)
+Foreign-key constraints:
+    "bar_a_fkey" FOREIGN KEY (a) REFERENCES foo(a)
+
+--cleanup
+DROP TABLE bar;
+DROP TABLE foo;
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 78bdc8b..3fb1675 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -269,3 +269,14 @@ DROP TABLE as_select1;
 -- check that the oid column is added before the primary key is checked
 CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
 DROP TABLE oid_pk;
+
+-- at table creation, override NOT VALID flag
+CREATE TABLE foo (a SERIAL PRIMARY KEY);
+
+CREATE TABLE bar (a INT,
+					FOREIGN KEY(a) REFERENCES foo NOT VALID,
+					CHECK(a != 0) NOT VALID);
+\d bar
+--cleanup
+DROP TABLE bar;
+DROP TABLE foo;
-- 
2.6.2

