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.
This commit is contained in:
parent
c30446b9c9
commit
f08e5e92e8
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.287 2009/06/11 20:46:11 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.288 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -5206,14 +5206,13 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
|
|||||||
if (on_insert)
|
if (on_insert)
|
||||||
{
|
{
|
||||||
fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
|
fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
|
||||||
fk_trigger->actions[0] = 'i';
|
fk_trigger->events = TRIGGER_TYPE_INSERT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd");
|
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->isconstraint = true;
|
||||||
fk_trigger->deferrable = fkconstraint->deferrable;
|
fk_trigger->deferrable = fkconstraint->deferrable;
|
||||||
@ -5263,9 +5262,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
|||||||
fk_trigger->relation = fkconstraint->pktable;
|
fk_trigger->relation = fkconstraint->pktable;
|
||||||
fk_trigger->before = false;
|
fk_trigger->before = false;
|
||||||
fk_trigger->row = true;
|
fk_trigger->row = true;
|
||||||
fk_trigger->actions[0] = 'd';
|
fk_trigger->events = TRIGGER_TYPE_DELETE;
|
||||||
fk_trigger->actions[1] = '\0';
|
|
||||||
|
|
||||||
fk_trigger->isconstraint = true;
|
fk_trigger->isconstraint = true;
|
||||||
fk_trigger->constrrel = myRel;
|
fk_trigger->constrrel = myRel;
|
||||||
switch (fkconstraint->fk_del_action)
|
switch (fkconstraint->fk_del_action)
|
||||||
@ -5316,8 +5313,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
|
|||||||
fk_trigger->relation = fkconstraint->pktable;
|
fk_trigger->relation = fkconstraint->pktable;
|
||||||
fk_trigger->before = false;
|
fk_trigger->before = false;
|
||||||
fk_trigger->row = true;
|
fk_trigger->row = true;
|
||||||
fk_trigger->actions[0] = 'u';
|
fk_trigger->events = TRIGGER_TYPE_UPDATE;
|
||||||
fk_trigger->actions[1] = '\0';
|
|
||||||
fk_trigger->isconstraint = true;
|
fk_trigger->isconstraint = true;
|
||||||
fk_trigger->constrrel = myRel;
|
fk_trigger->constrrel = myRel;
|
||||||
switch (fkconstraint->fk_upd_action)
|
switch (fkconstraint->fk_upd_action)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.247 2009/06/11 14:48:56 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.248 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -100,7 +100,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions)
|
|||||||
Oid funcoid;
|
Oid funcoid;
|
||||||
Oid funcrettype;
|
Oid funcrettype;
|
||||||
Oid trigoid;
|
Oid trigoid;
|
||||||
int i;
|
|
||||||
char constrtrigname[NAMEDATALEN];
|
char constrtrigname[NAMEDATALEN];
|
||||||
char *trigname;
|
char *trigname;
|
||||||
char *constrname;
|
char *constrname;
|
||||||
@ -150,50 +149,13 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid, bool checkPermissions)
|
|||||||
TRIGGER_SETT_BEFORE(tgtype);
|
TRIGGER_SETT_BEFORE(tgtype);
|
||||||
if (stmt->row)
|
if (stmt->row)
|
||||||
TRIGGER_SETT_ROW(tgtype);
|
TRIGGER_SETT_ROW(tgtype);
|
||||||
|
tgtype |= stmt->events;
|
||||||
|
|
||||||
for (i = 0; stmt->actions[i]; i++)
|
/* Disallow ROW-level TRUNCATE triggers */
|
||||||
{
|
if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
|
||||||
switch (stmt->actions[i])
|
ereport(ERROR,
|
||||||
{
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
case 'i':
|
errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find and validate the trigger function.
|
* Find and validate the trigger function.
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.431 2009/06/11 14:48:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.432 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -3081,7 +3081,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
|
|||||||
COPY_NODE_FIELD(args);
|
COPY_NODE_FIELD(args);
|
||||||
COPY_SCALAR_FIELD(before);
|
COPY_SCALAR_FIELD(before);
|
||||||
COPY_SCALAR_FIELD(row);
|
COPY_SCALAR_FIELD(row);
|
||||||
strcpy(newnode->actions, from->actions); /* in-line string field */
|
COPY_SCALAR_FIELD(events);
|
||||||
COPY_SCALAR_FIELD(isconstraint);
|
COPY_SCALAR_FIELD(isconstraint);
|
||||||
COPY_SCALAR_FIELD(deferrable);
|
COPY_SCALAR_FIELD(deferrable);
|
||||||
COPY_SCALAR_FIELD(initdeferred);
|
COPY_SCALAR_FIELD(initdeferred);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.354 2009/06/11 14:48:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.355 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1639,8 +1639,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
|
|||||||
COMPARE_NODE_FIELD(args);
|
COMPARE_NODE_FIELD(args);
|
||||||
COMPARE_SCALAR_FIELD(before);
|
COMPARE_SCALAR_FIELD(before);
|
||||||
COMPARE_SCALAR_FIELD(row);
|
COMPARE_SCALAR_FIELD(row);
|
||||||
if (strcmp(a->actions, b->actions) != 0) /* in-line string field */
|
COMPARE_SCALAR_FIELD(events);
|
||||||
return false;
|
|
||||||
COMPARE_SCALAR_FIELD(isconstraint);
|
COMPARE_SCALAR_FIELD(isconstraint);
|
||||||
COMPARE_SCALAR_FIELD(deferrable);
|
COMPARE_SCALAR_FIELD(deferrable);
|
||||||
COMPARE_SCALAR_FIELD(initdeferred);
|
COMPARE_SCALAR_FIELD(initdeferred);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.664 2009/05/27 20:42:29 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.665 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
|
#include "catalog/pg_trigger.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
@ -244,7 +245,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
%type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs
|
%type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs
|
||||||
%type <str> opt_lancompiler
|
%type <str> opt_lancompiler
|
||||||
|
|
||||||
%type <str> TriggerEvents
|
%type <ival> TriggerEvents TriggerOneEvent
|
||||||
%type <value> TriggerFuncArg
|
%type <value> TriggerFuncArg
|
||||||
|
|
||||||
%type <str> relation_name copy_file_name
|
%type <str> relation_name copy_file_name
|
||||||
@ -266,7 +267,6 @@ static TypeName *TableFuncTypeName(List *columns);
|
|||||||
%type <privtarget> privilege_target
|
%type <privtarget> privilege_target
|
||||||
%type <funwithargs> function_with_argtypes
|
%type <funwithargs> function_with_argtypes
|
||||||
%type <list> function_with_argtypes_list
|
%type <list> function_with_argtypes_list
|
||||||
%type <chr> TriggerOneEvent
|
|
||||||
|
|
||||||
%type <list> stmtblock stmtmulti
|
%type <list> stmtblock stmtmulti
|
||||||
OptTableElementList TableElementList OptInherit definition
|
OptTableElementList TableElementList OptInherit definition
|
||||||
@ -3133,7 +3133,7 @@ CreateTrigStmt:
|
|||||||
n->args = $13;
|
n->args = $13;
|
||||||
n->before = $4;
|
n->before = $4;
|
||||||
n->row = $8;
|
n->row = $8;
|
||||||
memcpy(n->actions, $5, 4);
|
n->events = $5;
|
||||||
n->isconstraint = FALSE;
|
n->isconstraint = FALSE;
|
||||||
n->deferrable = FALSE;
|
n->deferrable = FALSE;
|
||||||
n->initdeferred = FALSE;
|
n->initdeferred = FALSE;
|
||||||
@ -3153,11 +3153,10 @@ CreateTrigStmt:
|
|||||||
n->args = $18;
|
n->args = $18;
|
||||||
n->before = FALSE;
|
n->before = FALSE;
|
||||||
n->row = TRUE;
|
n->row = TRUE;
|
||||||
memcpy(n->actions, $6, 4);
|
n->events = $6;
|
||||||
n->isconstraint = TRUE;
|
n->isconstraint = TRUE;
|
||||||
n->deferrable = ($10 & 1) != 0;
|
n->deferrable = ($10 & 1) != 0;
|
||||||
n->initdeferred = ($10 & 2) != 0;
|
n->initdeferred = ($10 & 2) != 0;
|
||||||
|
|
||||||
n->constrrel = $9;
|
n->constrrel = $9;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
@ -3170,30 +3169,20 @@ TriggerActionTime:
|
|||||||
|
|
||||||
TriggerEvents:
|
TriggerEvents:
|
||||||
TriggerOneEvent
|
TriggerOneEvent
|
||||||
|
{ $$ = $1; }
|
||||||
|
| TriggerEvents OR TriggerOneEvent
|
||||||
{
|
{
|
||||||
char *e = palloc(4);
|
if ($1 & $3)
|
||||||
e[0] = $1; e[1] = '\0';
|
yyerror("duplicate trigger events specified");
|
||||||
$$ = e;
|
$$ = $1 | $3;
|
||||||
}
|
|
||||||
| 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;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
TriggerOneEvent:
|
TriggerOneEvent:
|
||||||
INSERT { $$ = 'i'; }
|
INSERT { $$ = TRIGGER_TYPE_INSERT; }
|
||||||
| DELETE_P { $$ = 'd'; }
|
| DELETE_P { $$ = TRIGGER_TYPE_DELETE; }
|
||||||
| UPDATE { $$ = 'u'; }
|
| UPDATE { $$ = TRIGGER_TYPE_UPDATE; }
|
||||||
| TRUNCATE { $$ = 't'; }
|
| TRUNCATE { $$ = TRIGGER_TYPE_TRUNCATE; }
|
||||||
;
|
;
|
||||||
|
|
||||||
TriggerForSpec:
|
TriggerForSpec:
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.394 2009/06/11 14:49:11 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.395 2009/06/18 01:27:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1551,7 +1551,8 @@ typedef struct CreateTrigStmt
|
|||||||
List *args; /* list of (T_String) Values or NIL */
|
List *args; /* list of (T_String) Values or NIL */
|
||||||
bool before; /* BEFORE/AFTER */
|
bool before; /* BEFORE/AFTER */
|
||||||
bool row; /* ROW/STATEMENT */
|
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 */
|
/* The following are used for referential */
|
||||||
/* integrity constraint triggers */
|
/* integrity constraint triggers */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user