diff options
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 57 |
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; } } |