aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index d2d82c9c596..ca028d2a66d 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -954,6 +954,8 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
case CONSTR_ATTR_NOT_DEFERRABLE:
case CONSTR_ATTR_DEFERRED:
case CONSTR_ATTR_IMMEDIATE:
+ case CONSTR_ATTR_ENFORCED:
+ case CONSTR_ATTR_NOT_ENFORCED:
/* transformConstraintAttrs took care of these */
break;
@@ -1093,6 +1095,8 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
case CONSTR_ATTR_NOT_DEFERRABLE:
case CONSTR_ATTR_DEFERRED:
case CONSTR_ATTR_IMMEDIATE:
+ case CONSTR_ATTR_ENFORCED:
+ case CONSTR_ATTR_NOT_ENFORCED:
elog(ERROR, "invalid context for constraint type %d",
constraint->contype);
break;
@@ -1433,6 +1437,8 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
{
char *ccname = constr->check[ccnum].ccname;
char *ccbin = constr->check[ccnum].ccbin;
+ bool ccenforced = constr->check[ccnum].ccenforced;
+ bool ccvalid = constr->check[ccnum].ccvalid;
bool ccnoinherit = constr->check[ccnum].ccnoinherit;
Node *ccbin_node;
bool found_whole_row;
@@ -1462,13 +1468,14 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
n->contype = CONSTR_CHECK;
n->conname = pstrdup(ccname);
n->location = -1;
+ n->is_enforced = ccenforced;
+ n->initially_valid = ccvalid;
n->is_no_inherit = ccnoinherit;
n->raw_expr = NULL;
n->cooked_expr = nodeToString(ccbin_node);
/* We can skip validation, since the new table should be empty. */
n->skip_validation = true;
- n->initially_valid = true;
atsubcmd = makeNode(AlterTableCmd);
atsubcmd->subtype = AT_AddConstraint;
@@ -2921,9 +2928,11 @@ transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
return;
/*
- * If creating a new table (but not a foreign table), we can safely skip
- * validation of check constraints, and nonetheless mark them valid. (This
- * will override any user-supplied NOT VALID flag.)
+ * When creating a new table (but not a foreign table), we can safely skip
+ * the validation of check constraints and mark them as valid based on the
+ * constraint enforcement flag, since NOT ENFORCED constraints must always
+ * be marked as NOT VALID. (This will override any user-supplied NOT VALID
+ * flag.)
*/
if (skipValidation)
{
@@ -2932,7 +2941,7 @@ transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
Constraint *constraint = (Constraint *) lfirst(ckclist);
constraint->skip_validation = true;
- constraint->initially_valid = true;
+ constraint->initially_valid = constraint->is_enforced;
}
}
}
@@ -3859,6 +3868,7 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
Constraint *lastprimarycon = NULL;
bool saw_deferrability = false;
bool saw_initially = false;
+ bool saw_enforced = false;
ListCell *clist;
#define SUPPORTS_ATTRS(node) \
@@ -3954,12 +3964,49 @@ transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
lastprimarycon->initdeferred = false;
break;
+ case CONSTR_ATTR_ENFORCED:
+ if (lastprimarycon == NULL ||
+ lastprimarycon->contype != CONSTR_CHECK)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("misplaced ENFORCED clause"),
+ parser_errposition(cxt->pstate, con->location)));
+ if (saw_enforced)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"),
+ parser_errposition(cxt->pstate, con->location)));
+ saw_enforced = true;
+ lastprimarycon->is_enforced = true;
+ break;
+
+ case CONSTR_ATTR_NOT_ENFORCED:
+ if (lastprimarycon == NULL ||
+ lastprimarycon->contype != CONSTR_CHECK)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("misplaced NOT ENFORCED clause"),
+ parser_errposition(cxt->pstate, con->location)));
+ if (saw_enforced)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple ENFORCED/NOT ENFORCED clauses not allowed"),
+ parser_errposition(cxt->pstate, con->location)));
+ saw_enforced = true;
+ lastprimarycon->is_enforced = false;
+
+ /* A NOT ENFORCED constraint must be marked as invalid. */
+ lastprimarycon->skip_validation = true;
+ lastprimarycon->initially_valid = false;
+ break;
+
default:
/* Otherwise it's not an attribute */
lastprimarycon = con;
/* reset flags for new primary node */
saw_deferrability = false;
saw_initially = false;
+ saw_enforced = false;
break;
}
}