1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Fix bogus grammar for a CREATE CONSTRAINT TRIGGER error

If certain constraint characteristic clauses (NO INHERIT, NOT VALID, NOT
ENFORCED) are given to CREATE CONSTRAINT TRIGGER, the resulting error
message is
  ERROR:  TRIGGER constraints cannot be marked NO INHERIT
which is a bit silly, because these aren't "constraints of type
TRIGGER".  Hardcode a better error message to prevent it.  This is a
cosmetic fix for quite a fringe problem with no known complaints from
users, so no backpatch.

While at it, silently accept ENFORCED if given.

Author: Amul Sul <sulamul@gmail.com>
Reviewed-by: jian he <jian.universality@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/CAAJ_b97hd-jMTS7AjgU6TDBCzDx_KyuKxG+K-DtYmOieg+giyQ@mail.gmail.com
Discussion: https://postgr.es/m/CACJufxHSp2puxP=q8ZtUGL1F+heapnzqFBZy5ZNGUjUgwjBqTQ@mail.gmail.com
This commit is contained in:
Álvaro Herrera
2025-07-03 11:25:39 +02:00
parent 8ec04c8577
commit 87251e1149
4 changed files with 65 additions and 4 deletions

View File

@ -29,7 +29,7 @@ PostgreSQL documentation
CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name</replaceable> { BEFORE | AFTER | INSTEAD OF } { <replaceable class="parameter">event</replaceable> [ OR ... ] } CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name</replaceable> { BEFORE | AFTER | INSTEAD OF } { <replaceable class="parameter">event</replaceable> [ OR ... ] }
ON <replaceable class="parameter">table_name</replaceable> ON <replaceable class="parameter">table_name</replaceable>
[ FROM <replaceable class="parameter">referenced_table_name</replaceable> ] [ FROM <replaceable class="parameter">referenced_table_name</replaceable> ]
[ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ] [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ] [ ENFORCED ]
[ REFERENCING { { OLD | NEW } TABLE [ AS ] <replaceable class="parameter">transition_relation_name</replaceable> } [ ... ] ] [ REFERENCING { { OLD | NEW } TABLE [ AS ] <replaceable class="parameter">transition_relation_name</replaceable> } [ ... ] ]
[ FOR [ EACH ] { ROW | STATEMENT } ] [ FOR [ EACH ] { ROW | STATEMENT } ]
[ WHEN ( <replaceable class="parameter">condition</replaceable> ) ] [ WHEN ( <replaceable class="parameter">condition</replaceable> ) ]
@ -321,6 +321,13 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>ENFORCED</literal></term>
<listitem>
This is a noise word. Constraint triggers are always enforced.
</listitem>
</varlistitem>
<varlistentry> <varlistentry>
<term><literal>REFERENCING</literal></term> <term><literal>REFERENCING</literal></term>
<listitem> <listitem>

View File

@ -6041,6 +6041,26 @@ CreateTrigStmt:
EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')' EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')'
{ {
CreateTrigStmt *n = makeNode(CreateTrigStmt); CreateTrigStmt *n = makeNode(CreateTrigStmt);
bool dummy;
if (($11 & CAS_NOT_VALID) != 0)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("constraint triggers cannot be marked %s",
"NOT VALID"),
parser_errposition(@11));
if (($11 & CAS_NO_INHERIT) != 0)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("constraint triggers cannot be marked %s",
"NO INHERIT"),
parser_errposition(@11));
if (($11 & CAS_NOT_ENFORCED) != 0)
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("constraint triggers cannot be marked %s",
"NOT ENFORCED"),
parser_errposition(@11));
n->replace = $2; n->replace = $2;
if (n->replace) /* not supported, see CreateTrigger */ if (n->replace) /* not supported, see CreateTrigger */
@ -6060,7 +6080,7 @@ CreateTrigStmt:
n->whenClause = $15; n->whenClause = $15;
n->transitionRels = NIL; n->transitionRels = NIL;
processCASbits($11, @11, "TRIGGER", processCASbits($11, @11, "TRIGGER",
&n->deferrable, &n->initdeferred, NULL, &n->deferrable, &n->initdeferred, &dummy,
NULL, NULL, yyscanner); NULL, NULL, yyscanner);
n->constrrel = $10; n->constrrel = $10;
$$ = (Node *) n; $$ = (Node *) n;

View File

@ -2280,6 +2280,27 @@ select * from parted;
drop table parted; drop table parted;
drop function parted_trigfunc(); drop function parted_trigfunc();
-- --
-- Constraint triggers
--
create constraint trigger crtr
after insert on foo not valid
for each row execute procedure foo ();
ERROR: constraint triggers cannot be marked NOT VALID
LINE 2: after insert on foo not valid
^
create constraint trigger crtr
after insert on foo no inherit
for each row execute procedure foo ();
ERROR: constraint triggers cannot be marked NO INHERIT
LINE 2: after insert on foo no inherit
^
create constraint trigger crtr
after insert on foo not enforced
for each row execute procedure foo ();
ERROR: constraint triggers cannot be marked NOT ENFORCED
LINE 2: after insert on foo not enforced
^
--
-- Constraint triggers and partitioned tables -- Constraint triggers and partitioned tables
create table parted_constr_ancestor (a int, b text) create table parted_constr_ancestor (a int, b text)
partition by range (b); partition by range (b);
@ -2294,7 +2315,7 @@ create constraint trigger parted_trig after insert on parted_constr_ancestor
deferrable deferrable
for each row execute procedure trigger_notice_ab(); for each row execute procedure trigger_notice_ab();
create constraint trigger parted_trig_two after insert on parted_constr create constraint trigger parted_trig_two after insert on parted_constr
deferrable initially deferred deferrable initially deferred enforced
for each row when (bark(new.b) AND new.a % 2 = 1) for each row when (bark(new.b) AND new.a % 2 = 1)
execute procedure trigger_notice_ab(); execute procedure trigger_notice_ab();
-- The immediate constraint is fired immediately; the WHEN clause of the -- The immediate constraint is fired immediately; the WHEN clause of the

View File

@ -1576,6 +1576,19 @@ select * from parted;
drop table parted; drop table parted;
drop function parted_trigfunc(); drop function parted_trigfunc();
--
-- Constraint triggers
--
create constraint trigger crtr
after insert on foo not valid
for each row execute procedure foo ();
create constraint trigger crtr
after insert on foo no inherit
for each row execute procedure foo ();
create constraint trigger crtr
after insert on foo not enforced
for each row execute procedure foo ();
-- --
-- Constraint triggers and partitioned tables -- Constraint triggers and partitioned tables
create table parted_constr_ancestor (a int, b text) create table parted_constr_ancestor (a int, b text)
@ -1591,7 +1604,7 @@ create constraint trigger parted_trig after insert on parted_constr_ancestor
deferrable deferrable
for each row execute procedure trigger_notice_ab(); for each row execute procedure trigger_notice_ab();
create constraint trigger parted_trig_two after insert on parted_constr create constraint trigger parted_trig_two after insert on parted_constr
deferrable initially deferred deferrable initially deferred enforced
for each row when (bark(new.b) AND new.a % 2 = 1) for each row when (bark(new.b) AND new.a % 2 = 1)
execute procedure trigger_notice_ab(); execute procedure trigger_notice_ab();