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.
This commit is contained in:
Robert Haas 2015-12-16 07:43:56 -05:00
parent 0625dbb0b9
commit f27a6b15e6
5 changed files with 60 additions and 5 deletions

View 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++;

View 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

View 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

View 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;

View 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;