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.c63
1 files changed, 51 insertions, 12 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index b205deca29f..f4c93e5b254 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -1152,6 +1152,39 @@ get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
}
/*
+ * Perform permissions and integrity checks before acquiring a relation lock.
+ */
+static void
+RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
+ void *arg)
+{
+ HeapTuple tuple;
+ Form_pg_class form;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ return; /* concurrently dropped */
+ form = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* only tables and views can have triggers */
+ if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a table or view", rv->relname)));
+
+ /* you must own the table to rename one of its triggers */
+ if (!pg_class_ownercheck(relid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
+ if (!allowSystemTableMods && IsSystemClass(form))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied: \"%s\" is a system catalog",
+ rv->relname)));
+
+ ReleaseSysCache(tuple);
+}
+
+/*
* renametrig - changes the name of a trigger on a relation
*
* trigger name is changed in trigger catalog.
@@ -1165,21 +1198,26 @@ get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
* update row in catalog
*/
void
-renametrig(Oid relid,
- const char *oldname,
- const char *newname)
+renametrig(RenameStmt *stmt)
{
Relation targetrel;
Relation tgrel;
HeapTuple tuple;
SysScanDesc tgscan;
ScanKeyData key[2];
+ Oid relid;
/*
- * Grab an exclusive lock on the target table, which we will NOT release
- * until end of transaction.
+ * Look up name, check permissions, and acquire lock (which we will NOT
+ * release until end of transaction).
*/
- targetrel = heap_open(relid, AccessExclusiveLock);
+ relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
+ false, false,
+ RangeVarCallbackForRenameTrigger,
+ NULL);
+
+ /* Have lock already, so just need to build relcache entry. */
+ targetrel = relation_open(relid, NoLock);
/*
* Scan pg_trigger twice for existing triggers on relation. We do this in
@@ -1202,14 +1240,14 @@ renametrig(Oid relid,
ScanKeyInit(&key[1],
Anum_pg_trigger_tgname,
BTEqualStrategyNumber, F_NAMEEQ,
- PointerGetDatum(newname));
+ PointerGetDatum(stmt->newname));
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
SnapshotNow, 2, key);
if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("trigger \"%s\" for relation \"%s\" already exists",
- newname, RelationGetRelationName(targetrel))));
+ stmt->newname, RelationGetRelationName(targetrel))));
systable_endscan(tgscan);
/*
@@ -1222,7 +1260,7 @@ renametrig(Oid relid,
ScanKeyInit(&key[1],
Anum_pg_trigger_tgname,
BTEqualStrategyNumber, F_NAMEEQ,
- PointerGetDatum(oldname));
+ PointerGetDatum(stmt->subname));
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
SnapshotNow, 2, key);
if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
@@ -1232,7 +1270,8 @@ renametrig(Oid relid,
*/
tuple = heap_copytuple(tuple); /* need a modifiable copy */
- namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname, newname);
+ namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
+ stmt->newname);
simple_heap_update(tgrel, &tuple->t_self, tuple);
@@ -1251,7 +1290,7 @@ renametrig(Oid relid,
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("trigger \"%s\" for table \"%s\" does not exist",
- oldname, RelationGetRelationName(targetrel))));
+ stmt->subname, RelationGetRelationName(targetrel))));
}
systable_endscan(tgscan);
@@ -1261,7 +1300,7 @@ renametrig(Oid relid,
/*
* Close rel, but keep exclusive lock!
*/
- heap_close(targetrel, NoLock);
+ relation_close(targetrel, NoLock);
}