diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/tablecmds.c | 44 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 75 |
2 files changed, 36 insertions, 83 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c54104200d7..4335792ee71 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.158 2005/05/30 06:52:38 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.159 2005/05/30 07:20:58 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -156,12 +156,6 @@ typedef struct NewColumnValue } NewColumnValue; -/* Used by attribute and relation renaming routines: */ -#define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */ -#define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */ -#define RI_TRIGGER_NONE 0 /* is not an RI trigger function */ - - static List *MergeAttributes(List *schema, List *supers, bool istemp, List **supOids, List **supconstr, int *supOidCount); static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno); @@ -246,7 +240,6 @@ static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename); static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace); static void copy_relation_data(Relation rel, SMgrRelation dst); -static int ri_trigger_type(Oid tgfoid); static void update_ri_trigger_args(Oid relid, const char *oldname, const char *newname, @@ -1571,39 +1564,6 @@ renamerel(Oid myrelid, const char *newrelname) relation_close(targetrelation, NoLock); } - -/* - * Given a trigger function OID, determine whether it is an RI trigger, - * and if so whether it is attached to PK or FK relation. - * - * XXX this probably doesn't belong here; should be exported by - * ri_triggers.c - */ -static int -ri_trigger_type(Oid tgfoid) -{ - switch (tgfoid) - { - case F_RI_FKEY_CASCADE_DEL: - case F_RI_FKEY_CASCADE_UPD: - case F_RI_FKEY_RESTRICT_DEL: - case F_RI_FKEY_RESTRICT_UPD: - case F_RI_FKEY_SETNULL_DEL: - case F_RI_FKEY_SETNULL_UPD: - case F_RI_FKEY_SETDEFAULT_DEL: - case F_RI_FKEY_SETDEFAULT_UPD: - case F_RI_FKEY_NOACTION_DEL: - case F_RI_FKEY_NOACTION_UPD: - return RI_TRIGGER_PK; - - case F_RI_FKEY_CHECK_INS: - case F_RI_FKEY_CHECK_UPD: - return RI_TRIGGER_FK; - } - - return RI_TRIGGER_NONE; -} - /* * Scan pg_trigger for RI triggers that are on the specified relation * (if fk_scan is false) or have it as the tgconstrrel (if fk_scan @@ -1663,7 +1623,7 @@ update_ri_trigger_args(Oid relid, const char *arga[RI_MAX_ARGUMENTS]; const char *argp; - tg_type = ri_trigger_type(pg_trigger->tgfoid); + tg_type = RI_FKey_trigger_type(pg_trigger->tgfoid); if (tg_type == RI_TRIGGER_NONE) { /* Not an RI trigger, forget it */ diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index a78ad890b3c..e0cfd334855 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.188 2005/05/06 17:24:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.189 2005/05/30 07:20:58 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -2994,54 +2994,47 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger, continue; /* - * If it is an RI UPDATE trigger, and the referenced keys have - * not changed, short-circuit queuing of the event; there's no - * need to fire the trigger. + * If this is an UPDATE of a PK table or FK table that does + * not change the PK or FK respectively, we can skip queuing + * the event: there is no need to fire the trigger. */ if ((event & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE) { - bool is_ri_trigger; - - switch (trigger->tgfoid) + switch (RI_FKey_trigger_type(trigger->tgfoid)) { - case F_RI_FKEY_NOACTION_UPD: - case F_RI_FKEY_CASCADE_UPD: - case F_RI_FKEY_RESTRICT_UPD: - case F_RI_FKEY_SETNULL_UPD: - case F_RI_FKEY_SETDEFAULT_UPD: - is_ri_trigger = true; + case RI_TRIGGER_PK: + /* Update on PK table */ + if (RI_FKey_keyequal_upd_pk(trigger, rel, oldtup, newtup)) + { + /* key unchanged, so skip queuing this event */ + continue; + } break; - default: - is_ri_trigger = false; + case RI_TRIGGER_FK: + /* + * Update on FK table + * + * There is one exception when updating FK tables: + * if the updated row was inserted by our own + * transaction and the FK is deferred, we still + * need to fire the trigger. This is because our + * UPDATE will invalidate the INSERT so the + * end-of-transaction INSERT RI trigger will not + * do anything, so we have to do the check for the + * UPDATE anyway. + */ + if (HeapTupleHeaderGetXmin(oldtup->t_data) != + GetCurrentTransactionId() && + RI_FKey_keyequal_upd_fk(trigger, rel, oldtup, newtup)) + { + continue; + } break; - } - if (is_ri_trigger) - { - TriggerData LocTriggerData; - - LocTriggerData.type = T_TriggerData; - LocTriggerData.tg_event = - TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW; - LocTriggerData.tg_relation = rel; - LocTriggerData.tg_trigtuple = oldtup; - LocTriggerData.tg_newtuple = newtup; - LocTriggerData.tg_trigger = trigger; - /* - * We do not currently know which buffers the passed tuples - * are in, but it does not matter because RI_FKey_keyequal_upd - * does not care. We could expand the API of this function - * if it becomes necessary to set these fields accurately. - */ - LocTriggerData.tg_trigtuplebuf = InvalidBuffer; - LocTriggerData.tg_newtuplebuf = InvalidBuffer; - - if (RI_FKey_keyequal_upd(&LocTriggerData)) - { - /* key unchanged, so skip queuing this event */ - continue; - } + case RI_TRIGGER_NONE: + /* Not an FK trigger */ + break; } } |