Commit f27a6b15 authored by Robert Haas's avatar Robert Haas

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.
parent 0625dbb0
...@@ -2349,7 +2349,7 @@ AddRelationNewConstraints(Relation rel, ...@@ -2349,7 +2349,7 @@ AddRelationNewConstraints(Relation rel,
* OK, store it. * OK, store it.
*/ */
constrOid = 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); is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
numchecks++; numchecks++;
......
...@@ -3080,6 +3080,8 @@ ColConstraintElem: ...@@ -3080,6 +3080,8 @@ ColConstraintElem:
n->is_no_inherit = $5; n->is_no_inherit = $5;
n->raw_expr = $3; n->raw_expr = $3;
n->cooked_expr = NULL; n->cooked_expr = NULL;
n->skip_validation = false;
n->initially_valid = true;
$$ = (Node *)n; $$ = (Node *)n;
} }
| DEFAULT b_expr | DEFAULT b_expr
......
...@@ -120,6 +120,8 @@ static IndexStmt *transformIndexConstraint(Constraint *constraint, ...@@ -120,6 +120,8 @@ static IndexStmt *transformIndexConstraint(Constraint *constraint,
static void transformFKConstraints(CreateStmtContext *cxt, static void transformFKConstraints(CreateStmtContext *cxt,
bool skipValidation, bool skipValidation,
bool isAddConstraint); bool isAddConstraint);
static void transformCheckConstraints(CreateStmtContext *cxt,
bool skipValidation);
static void transformConstraintAttrs(CreateStmtContext *cxt, static void transformConstraintAttrs(CreateStmtContext *cxt,
List *constraintList); List *constraintList);
static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column); static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
...@@ -319,6 +321,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) ...@@ -319,6 +321,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
*/ */
transformFKConstraints(&cxt, true, false); transformFKConstraints(&cxt, true, false);
/*
* Postprocess check constraints.
*/
transformCheckConstraints(&cxt, true);
/* /*
* Output results. * Output results.
*/ */
...@@ -1914,6 +1921,40 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) ...@@ -1914,6 +1921,40 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
return index; 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 * transformFKConstraints
* handle FOREIGN KEY constraints * handle FOREIGN KEY constraints
...@@ -2567,10 +2608,10 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, ...@@ -2567,10 +2608,10 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
save_alist = cxt.alist; save_alist = cxt.alist;
cxt.alist = NIL; cxt.alist = NIL;
/* Postprocess index and FK constraints */ /* Postprocess constraints */
transformIndexConstraints(&cxt); transformIndexConstraints(&cxt);
transformFKConstraints(&cxt, skipValidation, true); transformFKConstraints(&cxt, skipValidation, true);
transformCheckConstraints(&cxt, false);
/* /*
* Push any index-creation commands into the ALTER, so that they can be * Push any index-creation commands into the ALTER, so that they can be
......
...@@ -380,7 +380,16 @@ DROP TABLE tmp2; ...@@ -380,7 +380,16 @@ DROP TABLE tmp2;
-- NOT VALID with plan invalidation -- ensure we don't use a constraint for -- NOT VALID with plan invalidation -- ensure we don't use a constraint for
-- exclusion until validated -- exclusion until validated
set constraint_exclusion TO 'partition'; 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_2010 () inherits (nv_parent);
create table nv_child_2011 () 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; alter table nv_child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid;
......
...@@ -327,7 +327,10 @@ DROP TABLE tmp2; ...@@ -327,7 +327,10 @@ DROP TABLE tmp2;
-- NOT VALID with plan invalidation -- ensure we don't use a constraint for -- NOT VALID with plan invalidation -- ensure we don't use a constraint for
-- exclusion until validated -- exclusion until validated
set constraint_exclusion TO 'partition'; 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_2010 () inherits (nv_parent);
create table nv_child_2011 () 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; alter table nv_child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment