"Greg Sabino Mullane" <g...@turnstep.com> writes: > Thanks. I'll leave the [5] restriction call to someone else, seems it > does no harm to me though (not as if we'd change it that often anyway). > Revised patch below. I looked through other places that might be affected, > but did not see anything else except ecpg/preproc/preproc.y, which > looks as though it's already been changed to handle four events.
preproc.y is a derived file nowadays, so if you looked at it after having fixed gram.y it would've looked fixed. However, I felt we should fix this code properly instead of propagating its existing klugy approach still further. It gets a whole lot simpler and shorter if you make the grammar produce the bitmap representation that trigger.c actually wants; as per attached applied patch. regards, tom lane Index: src/backend/commands/tablecmds.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v retrieving revision 1.287 diff -c -r1.287 tablecmds.c *** src/backend/commands/tablecmds.c 11 Jun 2009 20:46:11 -0000 1.287 --- src/backend/commands/tablecmds.c 18 Jun 2009 01:13:04 -0000 *************** *** 5206,5219 **** if (on_insert) { fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); ! fk_trigger->actions[0] = 'i'; } else { fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd"); ! fk_trigger->actions[0] = 'u'; } - fk_trigger->actions[1] = '\0'; fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; --- 5206,5218 ---- if (on_insert) { fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); ! fk_trigger->events = TRIGGER_TYPE_INSERT; } else { fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd"); ! fk_trigger->events = TRIGGER_TYPE_UPDATE; } fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; *************** *** 5263,5271 **** 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->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_del_action) --- 5262,5268 ---- fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; ! fk_trigger->events = TRIGGER_TYPE_DELETE; fk_trigger->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_del_action) *************** *** 5316,5323 **** 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->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_upd_action) --- 5313,5319 ---- fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; ! fk_trigger->events = TRIGGER_TYPE_UPDATE; fk_trigger->isconstraint = true; fk_trigger->constrrel = myRel; switch (fkconstraint->fk_upd_action) Index: src/backend/commands/trigger.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/commands/trigger.c,v retrieving revision 1.247 diff -c -r1.247 trigger.c *** src/backend/commands/trigger.c 11 Jun 2009 14:48:56 -0000 1.247 --- src/backend/commands/trigger.c 18 Jun 2009 01:13:04 -0000 *************** *** 100,106 **** Oid funcoid; Oid funcrettype; Oid trigoid; - int i; char constrtrigname[NAMEDATALEN]; char *trigname; char *constrname; --- 100,105 ---- *************** *** 150,199 **** TRIGGER_SETT_BEFORE(tgtype); if (stmt->row) TRIGGER_SETT_ROW(tgtype); ! 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; ! } ! } /* * Find and validate the trigger function. --- 149,161 ---- TRIGGER_SETT_BEFORE(tgtype); if (stmt->row) TRIGGER_SETT_ROW(tgtype); + tgtype |= stmt->events; ! /* 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. Index: src/backend/nodes/copyfuncs.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.431 diff -c -r1.431 copyfuncs.c *** src/backend/nodes/copyfuncs.c 11 Jun 2009 14:48:58 -0000 1.431 --- src/backend/nodes/copyfuncs.c 18 Jun 2009 01:13:04 -0000 *************** *** 3081,3087 **** COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(before); COPY_SCALAR_FIELD(row); ! strcpy(newnode->actions, from->actions); /* in-line string field */ COPY_SCALAR_FIELD(isconstraint); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); --- 3081,3087 ---- COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(before); COPY_SCALAR_FIELD(row); ! COPY_SCALAR_FIELD(events); COPY_SCALAR_FIELD(isconstraint); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.354 diff -c -r1.354 equalfuncs.c *** src/backend/nodes/equalfuncs.c 11 Jun 2009 14:48:58 -0000 1.354 --- src/backend/nodes/equalfuncs.c 18 Jun 2009 01:13:04 -0000 *************** *** 1639,1646 **** 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(isconstraint); COMPARE_SCALAR_FIELD(deferrable); COMPARE_SCALAR_FIELD(initdeferred); --- 1639,1645 ---- COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(before); COMPARE_SCALAR_FIELD(row); ! COMPARE_SCALAR_FIELD(events); COMPARE_SCALAR_FIELD(isconstraint); COMPARE_SCALAR_FIELD(deferrable); COMPARE_SCALAR_FIELD(initdeferred); Index: src/backend/parser/gram.y =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.664 diff -c -r2.664 gram.y *** src/backend/parser/gram.y 27 May 2009 20:42:29 -0000 2.664 --- src/backend/parser/gram.y 18 Jun 2009 01:13:04 -0000 *************** *** 53,58 **** --- 53,59 ---- #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,250 **** %type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs %type <str> opt_lancompiler ! %type <str> TriggerEvents %type <value> TriggerFuncArg %type <str> relation_name copy_file_name --- 245,251 ---- %type <boolean> TriggerActionTime TriggerForSpec opt_trusted opt_restart_seqs %type <str> opt_lancompiler ! %type <ival> TriggerEvents TriggerOneEvent %type <value> TriggerFuncArg %type <str> relation_name copy_file_name *************** *** 266,272 **** %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 --- 267,272 ---- *************** *** 3133,3139 **** n->args = $13; n->before = $4; n->row = $8; ! memcpy(n->actions, $5, 4); n->isconstraint = FALSE; n->deferrable = FALSE; n->initdeferred = FALSE; --- 3133,3139 ---- n->args = $13; n->before = $4; n->row = $8; ! n->events = $5; n->isconstraint = FALSE; n->deferrable = FALSE; n->initdeferred = FALSE; *************** *** 3153,3163 **** n->args = $18; n->before = FALSE; n->row = TRUE; ! memcpy(n->actions, $6, 4); n->isconstraint = TRUE; n->deferrable = ($10 & 1) != 0; n->initdeferred = ($10 & 2) != 0; - n->constrrel = $9; $$ = (Node *)n; } --- 3153,3162 ---- n->args = $18; n->before = FALSE; n->row = TRUE; ! n->events = $6; n->isconstraint = TRUE; n->deferrable = ($10 & 1) != 0; n->initdeferred = ($10 & 2) != 0; n->constrrel = $9; $$ = (Node *)n; } *************** *** 3170,3199 **** TriggerEvents: 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; } ; TriggerOneEvent: ! INSERT { $$ = 'i'; } ! | DELETE_P { $$ = 'd'; } ! | UPDATE { $$ = 'u'; } ! | TRUNCATE { $$ = 't'; } ; TriggerForSpec: --- 3169,3188 ---- TriggerEvents: TriggerOneEvent + { $$ = $1; } + | TriggerEvents OR TriggerOneEvent { ! if ($1 & $3) ! yyerror("duplicate trigger events specified"); ! $$ = $1 | $3; } ; TriggerOneEvent: ! INSERT { $$ = TRIGGER_TYPE_INSERT; } ! | DELETE_P { $$ = TRIGGER_TYPE_DELETE; } ! | UPDATE { $$ = TRIGGER_TYPE_UPDATE; } ! | TRUNCATE { $$ = TRIGGER_TYPE_TRUNCATE; } ; TriggerForSpec: Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.394 diff -c -r1.394 parsenodes.h *** src/include/nodes/parsenodes.h 11 Jun 2009 14:49:11 -0000 1.394 --- src/include/nodes/parsenodes.h 18 Jun 2009 01:13:05 -0000 *************** *** 1551,1557 **** 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 */ /* The following are used for referential */ /* integrity constraint triggers */ --- 1551,1558 ---- List *args; /* list of (T_String) Values or NIL */ bool before; /* BEFORE/AFTER */ bool row; /* ROW/STATEMENT */ ! /* 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 */ -- Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-bugs