diff options
author | Tom Lane | 2009-06-18 01:27:02 +0000 |
---|---|---|
committer | Tom Lane | 2009-06-18 01:27:02 +0000 |
commit | 46f95306013011c4195fc222224dc3aa724c64d9 (patch) | |
tree | 4772de88da06169deb3bc3d06e55cee7137b5922 | |
parent | 70df25de8799e9c5d4a32d387c7501a33d89b726 (diff) |
Fix the just-reported problem that you can't specify all four trigger event
types in CREATE TRIGGER. While at it, clean up the amazingly tedious and
inextensible way that the trigger event type list was handled. Per report
from Greg Sabino Mullane.
-rw-r--r-- | src/backend/commands/tablecmds.c | 12 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 50 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 37 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 3 |
6 files changed, 27 insertions, 80 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 9401c18d92..7afe6e7f02 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -5206,14 +5206,13 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint, if (on_insert) { fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); - fk_trigger->actions[0] = 'i'; + fk_trigger->events = TRIGGER_TYPE_INSERT; } else { fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd"); - fk_trigger->actions[0] = 'u'; + fk_trigger->events = TRIGGER_TYPE_UPDATE; } - fk_trigger->actions[1] = '\0'; fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; @@ -5263,9 +5262,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; - fk_trigger->actions[0] = 'd'; - fk_trigger->actions[1] = '\0'; - + fk_trigger->events = TRIGGER_TYPE_DELETE; fk_trigger->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_del_action) @@ -5316,8 +5313,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint, fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; - fk_trigger->actions[0] = 'u'; - fk_trigger->actions[1] = '\0'; + fk_trigger->events = TRIGGER_TYPE_UPDATE; fk_trigger->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_upd_action) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index afa27d2e97..bd46102bb2 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -100,7 +100,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions) Oid funcoid; Oid funcrettype; Oid trigoid; - int i; char constrtrigname[NAMEDATALEN]; char *trigname; char *constrname; @@ -150,50 +149,13 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions) TRIGGER_SETT_BEFORE(tgtype); if (stmt->row) TRIGGER_SETT_ROW(tgtype); + tgtype |= stmt->events; - for (i = 0; stmt->actions[i]; i++) - { - switch (stmt->actions[i]) - { - case 'i': - if (TRIGGER_FOR_INSERT(tgtype)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple INSERT events specified"))); - TRIGGER_SETT_INSERT(tgtype); - break; - case 'd': - if (TRIGGER_FOR_DELETE(tgtype)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple DELETE events specified"))); - TRIGGER_SETT_DELETE(tgtype); - break; - case 'u': - if (TRIGGER_FOR_UPDATE(tgtype)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple UPDATE events specified"))); - TRIGGER_SETT_UPDATE(tgtype); - break; - case 't': - if (TRIGGER_FOR_TRUNCATE(tgtype)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple TRUNCATE events specified"))); - TRIGGER_SETT_TRUNCATE(tgtype); - /* Disallow ROW-level TRUNCATE triggers */ - if (stmt->row) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("TRUNCATE FOR EACH ROW triggers are not supported"))); - break; - default: - elog(ERROR, "unrecognized trigger event: %d", - (int) stmt->actions[i]); - break; - } - } + /* Disallow ROW-level TRUNCATE triggers */ + if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("TRUNCATE FOR EACH ROW triggers are not supported"))); /* * Find and validate the trigger function. diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index a1239d5fbf..2c7d48122b 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3081,7 +3081,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from) COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(before); COPY_SCALAR_FIELD(row); - strcpy(newnode->actions, from->actions); /* in-line string field */ + COPY_SCALAR_FIELD(events); COPY_SCALAR_FIELD(isconstraint); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 435d45b55f..c61de970e6 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -1639,8 +1639,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b) COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(before); COMPARE_SCALAR_FIELD(row); - if (strcmp(a->actions, b->actions) != 0) /* in-line string field */ - return false; + COMPARE_SCALAR_FIELD(events); COMPARE_SCALAR_FIELD(isconstraint); COMPARE_SCALAR_FIELD(deferrable); COMPARE_SCALAR_FIELD(initdeferred); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 9a4535501a..ac17b93bf6 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -53,6 +53,7 @@ #include "catalog/index.h" #include "catalog/namespace.h" +#include "catalog/pg_trigger.h" #include "commands/defrem.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -244,7 +245,7 @@ static TypeName *TableFuncTypeName(List *columns); %type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs %type <str> opt_lancompiler -%type <str> TriggerEvents +%type <ival> TriggerEvents TriggerOneEvent %type <value> TriggerFuncArg %type <str> relation_name copy_file_name @@ -266,7 +267,6 @@ static TypeName *TableFuncTypeName(List *columns); %type <privtarget> privilege_target %type <funwithargs> function_with_argtypes %type <list> function_with_argtypes_list -%type <chr> TriggerOneEvent %type <list> stmtblock stmtmulti OptTableElementList TableElementList OptInherit definition @@ -3133,7 +3133,7 @@ CreateTrigStmt: n->args = $13; n->before = $4; n->row = $8; - memcpy(n->actions, $5, 4); + n->events = $5; n->isconstraint = FALSE; n->deferrable = FALSE; n->initdeferred = FALSE; @@ -3153,11 +3153,10 @@ CreateTrigStmt: n->args = $18; n->before = FALSE; n->row = TRUE; - memcpy(n->actions, $6, 4); + n->events = $6; n->isconstraint = TRUE; n->deferrable = ($10 & 1) != 0; n->initdeferred = ($10 & 2) != 0; - n->constrrel = $9; $$ = (Node *)n; } @@ -3170,30 +3169,20 @@ TriggerActionTime: TriggerEvents: TriggerOneEvent + { $$ = $1; } + | TriggerEvents OR TriggerOneEvent { - char *e = palloc(4); - e[0] = $1; e[1] = '\0'; - $$ = e; - } - | TriggerOneEvent OR TriggerOneEvent - { - char *e = palloc(4); - e[0] = $1; e[1] = $3; e[2] = '\0'; - $$ = e; - } - | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent - { - char *e = palloc(4); - e[0] = $1; e[1] = $3; e[2] = $5; e[3] = '\0'; - $$ = e; + if ($1 & $3) + yyerror("duplicate trigger events specified"); + $$ = $1 | $3; } ; TriggerOneEvent: - INSERT { $$ = 'i'; } - | DELETE_P { $$ = 'd'; } - | UPDATE { $$ = 'u'; } - | TRUNCATE { $$ = 't'; } + INSERT { $$ = TRIGGER_TYPE_INSERT; } + | DELETE_P { $$ = TRIGGER_TYPE_DELETE; } + | UPDATE { $$ = TRIGGER_TYPE_UPDATE; } + | TRUNCATE { $$ = TRIGGER_TYPE_TRUNCATE; } ; TriggerForSpec: diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 71c864adf1..a108b80ddf 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1551,7 +1551,8 @@ typedef struct CreateTrigStmt List *args; /* list of (T_String) Values or NIL */ bool before; /* BEFORE/AFTER */ bool row; /* ROW/STATEMENT */ - char actions[4]; /* 1 to 3 of 'i', 'u', 'd', + trailing \0 */ + /* events uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */ + int16 events; /* INSERT/UPDATE/DELETE/TRUNCATE */ /* The following are used for referential */ /* integrity constraint triggers */ |