aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c119
1 files changed, 118 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index c00b4bebac8..b826297a718 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
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.114 2002/04/19 16:36:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.115 2002/04/26 19:29:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -504,6 +504,123 @@ RelationRemoveTriggers(Relation rel)
}
/*
+ * renametrig - changes the name of a trigger on a relation
+ *
+ * trigger name is changed in trigger catalog.
+ * No record of the previous name is kept.
+ *
+ * get proper relrelation from relation catalog (if not arg)
+ * scan trigger catalog
+ * for name conflict (within rel)
+ * for original trigger (if not arg)
+ * modify tgname in trigger tuple
+ * insert modified trigger in trigger catalog
+ * delete original trigger from trigger catalog
+ */
+void
+renametrig(Oid relid,
+ const char *oldname,
+ const char *newname)
+{
+ Relation targetrel;
+ Relation tgrel;
+ HeapTuple tuple;
+ SysScanDesc tgscan;
+ ScanKeyData key;
+ bool found = FALSE;
+ Relation idescs[Num_pg_trigger_indices];
+
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT
+ * release until end of transaction.
+ */
+ targetrel = heap_open(relid, AccessExclusiveLock);
+
+ /*
+ * Scan pg_trigger twice for existing triggers on relation. We do this in
+ * order to ensure a trigger does not exist with newname (The unique index
+ * on tgrelid/tgname would complain anyway) and to ensure a trigger does
+ * exist with oldname.
+ *
+ * NOTE that this is cool only because we have AccessExclusiveLock on the
+ * relation, so the trigger set won't be changing underneath us.
+ */
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
+
+ /*
+ * First pass -- look for name conflict
+ */
+ ScanKeyEntryInitialize(&key, 0,
+ Anum_pg_trigger_tgrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
+ SnapshotNow, 1, &key);
+ while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
+ {
+ Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
+
+ if (namestrcmp(&(pg_trigger->tgname), newname) == 0)
+ elog(ERROR, "renametrig: trigger %s already defined on relation %s",
+ newname, RelationGetRelationName(targetrel));
+ }
+ systable_endscan(tgscan);
+
+ /*
+ * Second pass -- look for trigger existing with oldname and update
+ */
+ ScanKeyEntryInitialize(&key, 0,
+ Anum_pg_trigger_tgrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true,
+ SnapshotNow, 1, &key);
+ while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
+ {
+ Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
+
+ if (namestrcmp(&(pg_trigger->tgname), oldname) == 0)
+ {
+ /*
+ * Update pg_trigger tuple with new tgname.
+ * (Scribbling on tuple is OK because it's a copy...)
+ */
+ namestrcpy(&(pg_trigger->tgname), newname);
+ simple_heap_update(tgrel, &tuple->t_self, tuple);
+
+ /*
+ * keep system catalog indices current
+ */
+ CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
+ CatalogCloseIndices(Num_pg_trigger_indices, idescs);
+
+ /*
+ * Invalidate relation's relcache entry so that other
+ * backends (and this one too!) are sent SI message to make them
+ * rebuild relcache entries.
+ */
+ CacheInvalidateRelcache(relid);
+
+ found = TRUE;
+ break;
+ }
+ }
+ systable_endscan(tgscan);
+
+ heap_close(tgrel, RowExclusiveLock);
+
+ if (!found)
+ elog(ERROR, "renametrig: trigger %s not defined on relation %s",
+ oldname, RelationGetRelationName(targetrel));
+
+ /*
+ * Close rel, but keep exclusive lock!
+ */
+ heap_close(targetrel, NoLock);
+}
+
+/*
* Build trigger data to attach to the given relcache entry.
*
* Note that trigger data must be allocated in CacheMemoryContext