diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 271ae26cbaf..06b434a9445 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -146,6 +146,17 @@ typedef struct KeyActions #define CAS_NOT_ENFORCED 0x40 #define CAS_ENFORCED 0x80 +#define ALTER_DEFERRABILITY(bits) \ + (((bits) & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE | CAS_INITIALLY_IMMEDIATE | \ + CAS_INITIALLY_DEFERRED)) != 0) + +#define ALTER_VALID(bits) (((bits) & CAS_NOT_VALID) != 0) + +#define ALTER_INHERIT(bits) (((bits) & CAS_NO_INHERIT) != 0) + +#define ALTER_ENFORCEABILITY(bits) \ + (((bits) & (CAS_NOT_ENFORCED | CAS_ENFORCED)) != 0) + #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) #define parser_errposition(pos) scanner_errposition(pos, yyscanner) @@ -2662,11 +2673,27 @@ alter_table_cmd: n->subtype = AT_AlterConstraint; n->def = (Node *) c; c->conname = $3; - c->alterDeferrability = true; - processCASbits($4, @4, "FOREIGN KEY", + processCASbits($4, @4, NULL, &c->deferrable, &c->initdeferred, NULL, NULL, NULL, yyscanner); + c->alterDeferrability = ALTER_DEFERRABILITY($4); + /* cannot (currently) be changed by this syntax: */ + if (ALTER_ENFORCEABILITY($4)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter constraint enforceability"), + parser_errposition(@4)); + if (ALTER_VALID($4)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter constraint validity"), + parser_errposition(@4)); + if (ALTER_INHERIT($4)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot alter constraint inheritability"), + parser_errposition(@4)); $$ = (Node *) n; } /* ALTER TABLE ALTER CONSTRAINT SET INHERIT */ @@ -6061,9 +6088,27 @@ CreateTrigStmt: n->columns = (List *) lsecond($7); n->whenClause = $15; n->transitionRels = NIL; - processCASbits($11, @11, "TRIGGER", + processCASbits($11, @11, NULL, &n->deferrable, &n->initdeferred, NULL, NULL, NULL, yyscanner); + if (ALTER_ENFORCEABILITY($11)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraint triggers cannot be marked %s", + "ENFORCED/NOT ENFORCED"), + parser_errposition(@11)); + if (ALTER_VALID($11)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraint triggers cannot be marked %s", + "NOT VALID"), + parser_errposition(@11)); + if (ALTER_INHERIT($11)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraint triggers cannot be marked %s", + "INHERIT/NO INHERIT"), + parser_errposition(@11)); n->constrrel = $10; $$ = (Node *) n; } @@ -19528,7 +19573,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (deferrable) *deferrable = true; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ @@ -19541,7 +19586,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (initdeferred) *initdeferred = true; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ @@ -19554,7 +19599,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (not_valid) *not_valid = true; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ @@ -19567,7 +19612,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (no_inherit) *no_inherit = true; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ @@ -19580,7 +19625,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (is_enforced) *is_enforced = false; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ @@ -19602,7 +19647,7 @@ processCASbits(int cas_bits, int location, const char *constrType, { if (is_enforced) *is_enforced = true; - else + else if (constrType) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s is CHECK, UNIQUE, or similar */ diff --git a/src/test/regress/expected/constraints.out b/src/test/regress/expected/constraints.out index 4f39100fcdf..df2c27dd7e7 100644 --- a/src/test/regress/expected/constraints.out +++ b/src/test/regress/expected/constraints.out @@ -745,11 +745,11 @@ ERROR: misplaced NOT ENFORCED clause LINE 1: CREATE TABLE UNIQUE_NOTEN_TBL(i int UNIQUE NOT ENFORCED); ^ ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED; -ERROR: FOREIGN KEY constraints cannot be marked ENFORCED +ERROR: cannot alter constraint enforceability LINE 1: ...TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key ENFORCED; ^ ALTER TABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORCED; -ERROR: FOREIGN KEY constraints cannot be marked NOT ENFORCED +ERROR: cannot alter constraint enforceability LINE 1: ...ABLE unique_tbl ALTER CONSTRAINT unique_tbl_i_key NOT ENFORC... ^ DROP TABLE unique_tbl; diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 6a3374d5152..9d0f91a9039 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -1284,11 +1284,11 @@ ERROR: constraint declared INITIALLY DEFERRED must be DEFERRABLE LINE 1: ...e ALTER CONSTRAINT fktable_fk_fkey NOT DEFERRABLE INITIALLY ... ^ ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT; -ERROR: FOREIGN KEY constraints cannot be marked NO INHERIT +ERROR: cannot alter constraint inheritability LINE 1: ...ER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NO INHERIT... ^ ALTER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; -ERROR: FOREIGN KEY constraints cannot be marked NOT VALID +ERROR: cannot alter constraint validity LINE 1: ...ER TABLE fktable ALTER CONSTRAINT fktable_fk_fkey NOT VALID; ^ -- test order of firing of FK triggers when several RI-induced changes need to diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index 247c67c32ae..15423749506 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -2547,6 +2547,23 @@ select * from parted; drop table parted; drop function parted_trigfunc(); +-- constraint triggers +create constraint trigger foo after insert on pg_class not valid for each row execute procedure test(); +ERROR: constraint triggers cannot be marked NOT VALID +LINE 1: ...e constraint trigger foo after insert on pg_class not valid ... + ^ +create constraint trigger foo after insert on pg_class no inherit for each row execute procedure test(); +ERROR: constraint triggers cannot be marked INHERIT/NO INHERIT +LINE 1: ...e constraint trigger foo after insert on pg_class no inherit... + ^ +create constraint trigger foo after insert on pg_class enforced for each row execute procedure test(); +ERROR: constraint triggers cannot be marked ENFORCED/NOT ENFORCED +LINE 1: ...e constraint trigger foo after insert on pg_class enforced f... + ^ +create constraint trigger foo after insert on pg_class not enforced for each row execute procedure test(); +ERROR: constraint triggers cannot be marked ENFORCED/NOT ENFORCED +LINE 1: ...e constraint trigger foo after insert on pg_class not enforc... + ^ -- -- Constraint triggers and partitioned tables create table parted_constr_ancestor (a int, b text) diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 659972f1135..c10f5eac74e 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -1764,6 +1764,12 @@ select * from parted; drop table parted; drop function parted_trigfunc(); +-- constraint triggers +create constraint trigger foo after insert on pg_class not valid for each row execute procedure test(); +create constraint trigger foo after insert on pg_class no inherit for each row execute procedure test(); +create constraint trigger foo after insert on pg_class enforced for each row execute procedure test(); +create constraint trigger foo after insert on pg_class not enforced for each row execute procedure test(); + -- -- Constraint triggers and partitioned tables create table parted_constr_ancestor (a int, b text)