]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix bogus grammar for a CREATE CONSTRAINT TRIGGER error
authorÁlvaro Herrera <alvherre@kurilemu.de>
Thu, 3 Jul 2025 09:25:39 +0000 (11:25 +0200)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Thu, 3 Jul 2025 09:25:39 +0000 (11:25 +0200)
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

doc/src/sgml/ref/create_trigger.sgml
src/backend/parser/gram.y
src/test/regress/expected/triggers.out
src/test/regress/sql/triggers.sql

index 982ab6f3ee4509cc813021c734c32f20fb6b0810..dc437b82edbaaa6841171035656b49c58384d810 100644 (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 ... ] }
     ON <replaceable class="parameter">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> } [ ... ] ]
     [ FOR [ EACH ] { ROW | STATEMENT } ]
     [ WHEN ( <replaceable class="parameter">condition</replaceable> ) ]
@@ -321,6 +321,13 @@ UPDATE OF <replaceable>column_name1</replaceable> [, <replaceable>column_name2</
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>ENFORCED</literal></term>
+    <listitem>
+     This is a noise word.  Constraint triggers are always enforced.
+    </listitem>
+   </varlistitem>
+
    <varlistentry>
     <term><literal>REFERENCING</literal></term>
     <listitem>
index a751bf0d531ba971e1c3477b0c392fb7125dfccf..70a0d832a119c69962c83e99727d0bce24dee110 100644 (file)
@@ -6041,6 +6041,26 @@ CreateTrigStmt:
                        EXECUTE FUNCTION_or_PROCEDURE func_name '(' TriggerFuncArgs ')'
                                {
                                        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;
                                        if (n->replace) /* not supported, see CreateTrigger */
@@ -6060,7 +6080,7 @@ CreateTrigStmt:
                                        n->whenClause = $15;
                                        n->transitionRels = NIL;
                                        processCASbits($11, @11, "TRIGGER",
-                                                                  &n->deferrable, &n->initdeferred, NULL,
+                                                                  &n->deferrable, &n->initdeferred, &dummy,
                                                                   NULL, NULL, yyscanner);
                                        n->constrrel = $10;
                                        $$ = (Node *) n;
index 2bf0e77d61ecb66484e094d6364083aa2dbfdbb0..872b9100e1a01b175767affac5a22a75b715eb79 100644 (file)
@@ -2280,6 +2280,27 @@ select * from parted;
 drop table parted;
 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
 create table parted_constr_ancestor (a int, b text)
   partition by range (b);
@@ -2294,7 +2315,7 @@ create constraint trigger parted_trig after insert on parted_constr_ancestor
   deferrable
   for each row execute procedure trigger_notice_ab();
 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)
   execute procedure trigger_notice_ab();
 -- The immediate constraint is fired immediately; the WHEN clause of the
index 9ffd318385ff69f5405b38854fb8ddcb1a97644d..d674b25c83be4a05d719754e6ce497afb9be97fb 100644 (file)
@@ -1576,6 +1576,19 @@ select * from parted;
 drop table parted;
 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
 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
   for each row execute procedure trigger_notice_ab();
 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)
   execute procedure trigger_notice_ab();