aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2015-12-16 07:43:56 -0500
committerRobert Haas <rhaas@postgresql.org>2015-12-16 07:43:56 -0500
commitf27a6b15e6566fba7748d0d9a3fc5bcfd52c4a1b (patch)
tree8fbfe141a6684f3517078414fb007b496d007be3 /src
parent0625dbb0b96e2ecd557eb5bcdc458679123951db (diff)
downloadpostgresql-f27a6b15e6566fba7748d0d9a3fc5bcfd52c4a1b.tar.gz
postgresql-f27a6b15e6566fba7748d0d9a3fc5bcfd52c4a1b.zip
Mark CHECK constraints declared NOT VALID valid if created with table.
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/heap.c2
-rw-r--r--src/backend/parser/gram.y2
-rw-r--r--src/backend/parser/parse_utilcmd.c45
-rw-r--r--src/test/regress/expected/alter_table.out11
-rw-r--r--src/test/regress/sql/alter_table.sql5
5 files changed, 60 insertions, 5 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 7d7d062c068..04c4f8f1ef2 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 7916df8b099..c4bed8a5ef7 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 344a40cf58e..4c24c13cf8d 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,40 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
}
/*
+ * 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
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 61669b6c7f1..228ae6ec221 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -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;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index c0bb77ee221..3db34609733 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -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;