event-trigger-morecleanup.patch
application/octet-stream
Filename: event-trigger-morecleanup.patch
Type: application/octet-stream
Part: 0
Message:
Re: Event Triggers reduced, v1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/aclchk.c | 40 | 0 |
| src/backend/catalog/objectaddress.c | 5 | 1 |
| src/backend/commands/alter.c | 4 | 4 |
| src/backend/commands/dropcmds.c | 4 | 0 |
| src/backend/commands/event_trigger.c | 48 | 49 |
| src/backend/parser/gram.y | 2 | 23 |
| src/backend/tcop/utility.c | 1 | 1 |
| src/backend/utils/adt/pseudotypes.c | 27 | 0 |
| src/bin/pg_dump/pg_dump.c | 4 | 4 |
| src/bin/pg_dump/pg_dump_sort.c | 4 | 3 |
| src/include/catalog/pg_proc.h | 4 | 0 |
| src/include/catalog/pg_type.h | 1 | 1 |
| src/include/utils/acl.h | 2 | 0 |
| src/include/utils/builtins.h | 2 | 0 |
| src/pl/plperl/plperl.c | 1 | 1 |
| src/pl/plpgsql/src/pl_comp.c | 2 | 2 |
| src/pl/plpgsql/src/pl_exec.c | 2 | 2 |
| src/test/regress/expected/event_triggers.out | 17 | 14 |
| src/test/regress/expected/type_sanity.out | 8 | 10 |
| src/test/regress/sql/event_triggers.sql | 13 | 14 |
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 56c40b1..b097813 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -29,6 +29,7 @@
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
+#include "catalog/pg_event_trigger.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
@@ -277,6 +278,10 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
case ACL_KIND_FOREIGN_SERVER:
whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
break;
+ case ACL_KIND_EVENT_TRIGGER:
+ elog(ERROR, "grantable rights not supported for event triggers");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
case ACL_KIND_TYPE:
whole_mask = ACL_ALL_RIGHTS_TYPE;
break;
@@ -3286,6 +3291,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
gettext_noop("permission denied for foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
gettext_noop("permission denied for foreign server %s"),
+ /* ACL_KIND_EVENT_TRIGGER */
+ gettext_noop("permission denied for event trigger %s"),
/* ACL_KIND_EXTENSION */
gettext_noop("permission denied for extension %s"),
};
@@ -3330,6 +3337,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
gettext_noop("must be owner of foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
gettext_noop("must be owner of foreign server %s"),
+ /* ACL_KIND_EVENT_TRIGGER */
+ gettext_noop("must be owner of event trigger %s"),
/* ACL_KIND_EXTENSION */
gettext_noop("must be owner of extension %s"),
};
@@ -3455,6 +3464,10 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FOREIGN_SERVER:
return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
+ case ACL_KIND_EVENT_TRIGGER:
+ elog(ERROR, "grantable rights not supported for event triggers");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
case ACL_KIND_TYPE:
return pg_type_aclmask(table_oid, roleid, mask, how);
default:
@@ -4876,6 +4889,33 @@ pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
}
/*
+ * Ownership check for an event trigger (specified by OID).
+ */
+bool
+pg_event_trigger_ownercheck(Oid et_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("event trigger with OID %u does not exist",
+ et_oid)));
+
+ ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
* Ownership check for a database (specified by OID).
*/
bool
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 40ae60d..5b8140b 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -997,6 +997,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
NameListToString(objname));
break;
+ case OBJECT_EVENT_TRIGGER:
+ if (!pg_event_trigger_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+ NameListToString(objname));
+ break;
case OBJECT_LANGUAGE:
if (!pg_language_ownercheck(address.objectId, roleid))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
@@ -1075,7 +1080,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
break;
case OBJECT_TSPARSER:
case OBJECT_TSTEMPLATE:
- case OBJECT_EVENT_TRIGGER:
/* We treat these object types as being owned by superusers */
if (!superuser_arg(roleid))
ereport(ERROR,
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 78ef831..19f9895 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -70,10 +70,6 @@ ExecRenameStmt(RenameStmt *stmt)
RenameDatabase(stmt->subname, stmt->newname);
break;
- case OBJECT_EVENT_TRIGGER:
- RenameEventTrigger(stmt->subname, stmt->newname);
- break;
-
case OBJECT_FDW:
RenameForeignDataWrapper(stmt->subname, stmt->newname);
break;
@@ -82,6 +78,10 @@ ExecRenameStmt(RenameStmt *stmt)
RenameForeignServer(stmt->subname, stmt->newname);
break;
+ case OBJECT_EVENT_TRIGGER:
+ RenameEventTrigger(stmt->subname, stmt->newname);
+ break;
+
case OBJECT_FUNCTION:
RenameFunction(stmt->object, stmt->objarg, stmt->newname);
break;
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index 1b8529e..8f5d7e0 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -206,6 +206,10 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
args = NameListToString(list_truncate(objname,
list_length(objname) - 1));
break;
+ case OBJECT_EVENT_TRIGGER:
+ msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
+ name = NameListToString(objname);
+ break;
case OBJECT_RULE:
msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
name = strVal(llast(objname));
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 561ce42..f9a3ea2 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -49,23 +49,6 @@ static void AlterEventTriggerOwner_internal(Relation rel,
Oid newOwnerId);
/*
- * Check permission: event triggers are only available for superusers. Raise
- * an exception when requirements are not fullfilled.
- *
- * It's not clear how to accept that database owners be able to create command
- * triggers, a superuser could run a command that fires a trigger's procedure
- * written by the database owner and now running with superuser privileges.
- */
-static void
-CheckEventTriggerPrivileges()
-{
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to use event triggers"))));
-}
-
-/*
* Insert Command Trigger Tuple
*
* Insert the new pg_event_trigger row, and return the OID assigned to the new
@@ -158,7 +141,16 @@ CreateEventTrigger(CreateEventTrigStmt *stmt, const char *queryString)
Oid funcrettype;
Oid evtowner = GetUserId();
- CheckEventTriggerPrivileges();
+ /*
+ * It would be nice to allow database owners or even regular users to do
+ * this, but there are obvious privilege escalation risks which would have
+ * to somehow be plugged first.
+ */
+ if (!superuser())
+ ereport(ERROR,
+ (errmsg("permission denied to create event trigger \"%s\"",
+ stmt->trigname),
+ errhint("Must be superuser to create an event trigger.")));
/*
* Find and validate the trigger function.
@@ -171,7 +163,7 @@ CreateEventTrigger(CreateEventTrigStmt *stmt, const char *queryString)
if (funcrettype != EVTTRIGGEROID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("function \"%s\" must return type \"command_trigger\"",
+ errmsg("function \"%s\" must return type \"event_trigger\"",
NameListToString(stmt->funcname))));
/*
@@ -224,15 +216,18 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
Form_pg_event_trigger evtForm;
char tgenabled = stmt->tgenabled;
- CheckEventTriggerPrivileges();
-
tgrel = heap_open(EventTriggerRelationId, RowExclusiveLock);
- tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(stmt->trigname));
+ tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
+ CStringGetDatum(stmt->trigname));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("event trigger \"%s\" does not exist", stmt->trigname)));
+ errmsg("event trigger \"%s\" does not exist",
+ stmt->trigname)));
+ if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+ stmt->trigname);
/* tuple is a copy, so we can modify it below */
evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
@@ -257,8 +252,6 @@ RenameEventTrigger(const char *trigname, const char *newname)
Relation rel;
Form_pg_event_trigger evtForm;
- CheckEventTriggerPrivileges();
-
rel = heap_open(EventTriggerRelationId, RowExclusiveLock);
/* newname must be available */
@@ -273,6 +266,9 @@ RenameEventTrigger(const char *trigname, const char *newname)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("event trigger \"%s\" does not exist", trigname)));
+ if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+ trigname);
evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
@@ -344,22 +340,31 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
{
Form_pg_event_trigger form;
- CheckEventTriggerPrivileges();
-
form = (Form_pg_event_trigger) GETSTRUCT(tup);
- if (form->evtowner != newOwnerId)
- {
- form->evtowner = newOwnerId;
+ if (form->evtowner == newOwnerId)
+ return;
- simple_heap_update(rel, &tup->t_self, tup);
- CatalogUpdateIndexes(rel, tup);
+ if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+ NameStr(form->evtname));
- /* Update owner dependency reference */
- changeDependencyOnOwner(EventTriggerRelationId,
- HeapTupleGetOid(tup),
- newOwnerId);
- }
+ /* New owner must be a superuser */
+ if (!superuser_arg(newOwnerId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to change owner of event trigger \"%s\"",
+ NameStr(form->evtname)),
+ errhint("The owner of an event trigger must be a superuser.")));
+
+ form->evtowner = newOwnerId;
+ simple_heap_update(rel, &tup->t_self, tup);
+ CatalogUpdateIndexes(rel, tup);
+
+ /* Update owner dependency reference */
+ changeDependencyOnOwner(EventTriggerRelationId,
+ HeapTupleGetOid(tup),
+ newOwnerId);
}
/*
@@ -412,14 +417,14 @@ call_event_trigger_procedure(EventContext ev_ctx, TrigEvent tev,
* Prepare the event trigger function context from the Command Context.
* We prepare a dedicated Node here so as not to publish internal data.
*/
- trigdata.type = T_EventTriggerData;
- trigdata.toplevel = ev_ctx->toplevel;
- trigdata.tag = ev_ctx->tag;
- trigdata.objectId = ev_ctx->objectId;
+ trigdata.type = T_EventTriggerData;
+ trigdata.toplevel = ev_ctx->toplevel;
+ trigdata.tag = ev_ctx->tag;
+ trigdata.objectId = ev_ctx->objectId;
trigdata.schemaname = ev_ctx->schemaname;
trigdata.objectname = ev_ctx->objectname;
- trigdata.parsetree = ev_ctx->parsetree;
- trigdata.when = pstrdup(event_to_string(tev));
+ trigdata.parsetree = ev_ctx->parsetree;
+ trigdata.when = pstrdup(event_to_string(tev));
/*
* Call the function, passing no arguments but setting a context.
@@ -448,12 +453,6 @@ InitEventContext(EventContext evt, const Node *parsetree)
evt->objectname = NULL;
evt->schemaname = NULL;
- /*
- * Fill in the event command, which is an enum constant to match against
- * what's stored into catalogs. As we are storing that on disk, we need the
- * enum values to be stable, see src/include/catalog/pg_event_trigger.h for
- * details.
- */
switch (nodeTag(parsetree))
{
case T_CreateSchemaStmt:
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ec5c8f8..068834b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -214,7 +214,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
CreateUserStmt CreateUserMappingStmt CreateRoleStmt
CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
- DropAssertStmt DropTrigStmt DropEventTrigStmt DropRuleStmt DropCastStmt
+ DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt
DropRoleStmt DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
DropForeignServerStmt DropUserMappingStmt ExplainStmt FetchStmt
GrantStmt GrantRoleStmt IndexStmt InsertStmt ListenStmt LoadStmt
@@ -755,7 +755,6 @@ stmt :
| DropStmt
| DropTableSpaceStmt
| DropTrigStmt
- | DropEventTrigStmt
| DropRoleStmt
| DropUserStmt
| DropUserMappingStmt
@@ -4378,27 +4377,6 @@ trigger_command:
;
-DropEventTrigStmt:
- DROP EVENT TRIGGER name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_EVENT_TRIGGER;
- n->objects = list_make1(list_make1(makeString($4)));
- n->behavior = $5;
- n->missing_ok = false;
- $$ = (Node *) n;
- }
- | DROP EVENT TRIGGER IF_P EXISTS name opt_drop_behavior
- {
- DropStmt *n = makeNode(DropStmt);
- n->removeType = OBJECT_EVENT_TRIGGER;
- n->objects = list_make1(list_make1(makeString($6)));
- n->behavior = $7;
- n->missing_ok = true;
- $$ = (Node *) n;
- }
- ;
-
AlterEventTrigStmt:
ALTER EVENT TRIGGER name enable_trigger
{
@@ -5002,6 +4980,7 @@ drop_type: TABLE { $$ = OBJECT_TABLE; }
| VIEW { $$ = OBJECT_VIEW; }
| INDEX { $$ = OBJECT_INDEX; }
| FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; }
+ | EVENT TRIGGER { $$ = OBJECT_EVENT_TRIGGER; }
| TYPE_P { $$ = OBJECT_TYPE; }
| DOMAIN_P { $$ = OBJECT_DOMAIN; }
| COLLATION { $$ = OBJECT_COLLATION; }
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index c8c1a81..b772f2b 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -356,7 +356,7 @@ standard_ProcessUtility(Node *parsetree,
completionTag[0] = '\0';
/* Event Trigger support for command_start */
- InitEventContext(&evt, (Node *)parsetree);
+ InitEventContext(&evt, parsetree);
if (CommandFiresTriggersForEvent(&evt, E_CommandStart))
ExecEventTriggers(&evt, E_CommandStart);
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index d7770b8..8590f3c 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -293,6 +293,33 @@ trigger_out(PG_FUNCTION_ARGS)
/*
+ * event_trigger_in - input routine for pseudo-type event_trigger.
+ */
+Datum
+event_trigger_in(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot accept a value of type event_trigger")));
+
+ PG_RETURN_VOID(); /* keep compiler quiet */
+}
+
+/*
+ * event_trigger_out - output routine for pseudo-type event_trigger.
+ */
+Datum
+event_trigger_out(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot display a value of type event_trigger")));
+
+ PG_RETURN_VOID(); /* keep compiler quiet */
+}
+
+
+/*
* language_handler_in - input routine for pseudo-type LANGUAGE_HANDLER.
*/
Datum
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index bcd042e..09ca6dd 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -5313,7 +5313,7 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
i_oid,
i_evtname,
i_evtevent,
- i_evtowner,
+ i_evtowner,
i_evttags,
i_evtfname,
i_evtenabled;
@@ -5333,7 +5333,7 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
"SELECT e.tableoid, e.oid, evtname, evtenabled, "
"evtevent, (%s evtowner) AS evtowner, "
"array_to_string(array("
- "select '''' || x || '''' "
+ "select quote_literal(x) "
" from unnest(evttags) as t(x)), ', ') as evttags, "
"e.evtfoid::regproc as evtfname "
"FROM pg_event_trigger e "
@@ -13756,7 +13756,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
appendPQExpBuffer(query, "CREATE EVENT TRIGGER ");
appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name));
appendPQExpBuffer(query, " ON ");
- appendPQExpBufferStr(query, evtinfo->evtevent);
+ appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
appendPQExpBufferStr(query, " ");
if (strcmp("", evtinfo->evttags) != 0)
@@ -13768,7 +13768,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
appendPQExpBuffer(query, "\n EXECUTE PROCEDURE ");
appendPQExpBufferStr(query, evtinfo->evtfname);
- appendPQExpBuffer(query, " ();\n");
+ appendPQExpBuffer(query, "();\n");
if (evtinfo->evtenabled != 'O')
{
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 6d4c2ba..5318e7a 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -24,8 +24,9 @@ static const char *modulename = gettext_noop("sorter");
* Objects are sorted by priority levels, and within an equal priority level
* by OID. (This is a relatively crude hack to provide semi-reasonable
* behavior for old databases without full dependency info.) Note: collations,
- * extensions, text search, foreign-data, and default ACL objects can't really
- * happen here, so the rather bogus priorities for them don't matter.
+ * extensions, text search, foreign-data, event trigger, and default ACL
+ * objects can't really happen here, so the rather bogus priorities for them
+ * don't matter.
*
* NOTE: object-type priorities must match the section assignments made in
* pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY,
@@ -114,7 +115,7 @@ static const int newObjectTypePriority[] =
24, /* DO_BLOB_DATA */
22, /* DO_PRE_DATA_BOUNDARY */
25, /* DO_POST_DATA_BOUNDARY */
- 30 /* DO_EVENT_TRIGGER */
+ 32 /* DO_EVENT_TRIGGER */
};
static DumpId preDataBoundId;
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index bee7154..743f890 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3456,6 +3456,10 @@ DATA(insert OID = 2300 ( trigger_in PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 2
DESCR("I/O");
DATA(insert OID = 2301 ( trigger_out PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "2279" _null_ _null_ _null_ _null_ trigger_out _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3594 ( event_trigger_in PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 3838 "2275" _null_ _null_ _null_ _null_ event_trigger_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 3595 ( event_trigger_out PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "3838" _null_ _null_ _null_ _null_ event_trigger_out _null_ _null_ _null_ ));
+DESCR("I/O");
DATA(insert OID = 2302 ( language_handler_in PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 2280 "2275" _null_ _null_ _null_ _null_ language_handler_in _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 2303 ( language_handler_out PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "2280" _null_ _null_ _null_ _null_ language_handler_out _null_ _null_ _null_ ));
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 98c7dd5..86be998 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -650,7 +650,7 @@ DATA(insert OID = 2278 ( void PGNSP PGUID 4 t p P f t \054 0 0 0 void_in void
#define VOIDOID 2278
DATA(insert OID = 2279 ( trigger PGNSP PGUID 4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
#define TRIGGEROID 2279
-DATA(insert OID = 3838 ( event_trigger PGNSP PGUID 4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3838 ( event_trigger PGNSP PGUID 4 t p P f t \054 0 0 0 event_trigger_in event_trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
#define EVTTRIGGEROID 3838
DATA(insert OID = 2280 ( language_handler PGNSP PGUID 4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
#define LANGUAGE_HANDLEROID 2280
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 2d1cccb..5700e54 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -195,6 +195,7 @@ typedef enum AclObjectKind
ACL_KIND_TSCONFIGURATION, /* pg_ts_config */
ACL_KIND_FDW, /* pg_foreign_data_wrapper */
ACL_KIND_FOREIGN_SERVER, /* pg_foreign_server */
+ ACL_KIND_EVENT_TRIGGER, /* pg_event_trigger */
ACL_KIND_EXTENSION, /* pg_extension */
MAX_ACL_KIND /* MUST BE LAST */
} AclObjectKind;
@@ -322,6 +323,7 @@ extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid);
extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
+extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid);
extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
extern bool has_createrole_privilege(Oid roleid);
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 1063403..8b9291c 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -532,6 +532,8 @@ extern Datum void_recv(PG_FUNCTION_ARGS);
extern Datum void_send(PG_FUNCTION_ARGS);
extern Datum trigger_in(PG_FUNCTION_ARGS);
extern Datum trigger_out(PG_FUNCTION_ARGS);
+extern Datum event_trigger_in(PG_FUNCTION_ARGS);
+extern Datum event_trigger_out(PG_FUNCTION_ARGS);
extern Datum language_handler_in(PG_FUNCTION_ARGS);
extern Datum language_handler_out(PG_FUNCTION_ARGS);
extern Datum fdw_handler_in(PG_FUNCTION_ARGS);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 5b456aa..f772fd4 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1571,7 +1571,7 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
}
-/* Set up the arguments for a command trigger call. */
+/* Set up the arguments for an event trigger call. */
static SV *
plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
{
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 77c5ed9..9d17686 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -536,7 +536,7 @@ do_compile(FunctionCallInfo fcinfo,
if (rettypeid == VOIDOID ||
rettypeid == RECORDOID)
/* okay */ ;
- else if (rettypeid == TRIGGEROID)
+ else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("trigger functions can only be called as triggers")));
@@ -689,7 +689,7 @@ do_compile(FunctionCallInfo fcinfo,
if (procStruct->pronargs != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("command trigger functions cannot have declared arguments")));
+ errmsg("event trigger functions cannot have declared arguments")));
/* Add the variable tg_when */
var = plpgsql_build_variable("tg_when", 0,
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index fd59d75..373facf 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -773,8 +773,8 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
return rettup;
}
-void plpgsql_exec_event_trigger(PLpgSQL_function *func,
- EventTriggerData *trigdata)
+void
+plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
{
PLpgSQL_execstate estate;
ErrorContextCallback plerrcontext;
diff --git a/src/test/regress/expected/event_triggers.out b/src/test/regress/expected/event_triggers.out
index 415605b..6eac7e9 100644
--- a/src/test/regress/expected/event_triggers.out
+++ b/src/test/regress/expected/event_triggers.out
@@ -10,9 +10,6 @@ begin
raise notice 'snitch: % % %.%', tg_when, tg_tag, tg_schemaname, tg_objectname;
end;
$$;
---
--- TODO: REASSIGN OWNED and DROP OWNED
---
create event trigger any_t on command_start
execute procedure snitch();
create event trigger foo_t on command_start
@@ -67,8 +64,12 @@ NOTICE: snitch: command_start CREATE SCHEMA <NULL>.<NULL>
create schema cmd2;
NOTICE: snitch: command_start CREATE SCHEMA <NULL>.<NULL>
NOTICE: snitch: command_start CREATE SCHEMA <NULL>.<NULL>
-create role regbob;
-alter event trigger snitch owner to regbob;
+create role regression_bob;
+alter event trigger snitch owner to regression_bob;
+ERROR: permission denied to change owner of event trigger "snitch"
+HINT: The owner of an event trigger must be a superuser.
+alter role regression_bob superuser;
+alter event trigger snitch owner to regression_bob;
create table cmd.foo(id bigserial primary key);
NOTICE: snitch: command_start CREATE TABLE <NULL>.<NULL>
NOTICE: snitch: command_start CREATE TABLE <NULL>.<NULL>
@@ -158,7 +159,7 @@ NOTICE: snitch: command_start ALTER TABLE <NULL>.<NULL>
create sequence test_seq_;
NOTICE: snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
NOTICE: snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
-alter sequence test_seq_ owner to regbob;
+alter sequence test_seq_ owner to regression_bob;
NOTICE: snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
NOTICE: snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
alter sequence test_seq_ rename to test_seq;
@@ -197,7 +198,7 @@ NOTICE: snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
create view view_test as select id, things from cmd.test;
NOTICE: snitch: command_start CREATE VIEW <NULL>.<NULL>
NOTICE: snitch: command_start CREATE VIEW <NULL>.<NULL>
-alter view view_test owner to regbob;
+alter view view_test owner to regression_bob;
NOTICE: snitch: command_start ALTER VIEW <NULL>.<NULL>
NOTICE: snitch: command_start ALTER VIEW <NULL>.<NULL>
alter view view_test rename to view_test2;
@@ -248,7 +249,7 @@ NOTICE: snitch: command_start ALTER FUNCTION <NULL>.<NULL>
alter function notfun(int) set schema cmd;
NOTICE: snitch: command_start ALTER FUNCTION <NULL>.<NULL>
NOTICE: snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-alter function cmd.notfun(int) owner to regbob;
+alter function cmd.notfun(int) owner to regression_bob;
NOTICE: snitch: command_start ALTER FUNCTION <NULL>.<NULL>
NOTICE: snitch: command_start ALTER FUNCTION <NULL>.<NULL>
alter function cmd.notfun(int) cost 77;
@@ -297,7 +298,7 @@ NOTICE: snitch: command_start ALTER TYPE <NULL>.<NULL>
create type cmd.type_test AS (a integer, b integer, c text);
NOTICE: snitch: command_start CREATE TYPE <NULL>.<NULL>
NOTICE: snitch: command_start CREATE TYPE <NULL>.<NULL>
-alter type cmd.type_test owner to regbob;
+alter type cmd.type_test owner to regression_bob;
NOTICE: snitch: command_start ALTER TYPE <NULL>.<NULL>
NOTICE: snitch: command_start ALTER TYPE <NULL>.<NULL>
alter type cmd.type_test rename to type_test2;
@@ -349,7 +350,7 @@ NOTICE: snitch: command_start ALTER DOMAIN <NULL>.<NULL>
alter domain cmd.us_postal_code drop constraint dummy_constraint;
NOTICE: snitch: command_start ALTER DOMAIN <NULL>.<NULL>
NOTICE: snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-alter domain cmd.us_postal_code owner to regbob;
+alter domain cmd.us_postal_code owner to regression_bob;
NOTICE: snitch: command_start ALTER DOMAIN <NULL>.<NULL>
NOTICE: snitch: command_start ALTER DOMAIN <NULL>.<NULL>
alter domain cmd.us_postal_code set schema cmd2;
@@ -455,12 +456,14 @@ drop schema cmd2 cascade;
NOTICE: snitch: command_start DROP SCHEMA <NULL>.<NULL>
NOTICE: snitch: command_start DROP SCHEMA <NULL>.<NULL>
-- fail because owning event trigger snitch
-drop role regbob;
-ERROR: role "regbob" cannot be dropped because some objects depend on it
+drop role regression_bob;
+ERROR: role "regression_bob" cannot be dropped because some objects depend on it
DETAIL: owner of event trigger snitch
drop event trigger any_t;
-drop event trigger snitch;
-drop role regbob;
+drop event trigger if exists snitch;
+drop event trigger if exists snitch;
+NOTICE: event trigger "snitch" does not exist, skipping
+drop role regression_bob;
create table onerow(id integer);
create or replace function insert_one_row()
returns event_trigger
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 0dac40f..70eab92 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -134,11 +134,10 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p1.typelem != 0 AND p1.typlen < 0) AND NOT
(p2.prorettype = p1.oid AND NOT p2.proretset)
ORDER BY 1;
- oid | typname | oid | proname
-------+---------------+------+------------
- 1790 | refcursor | 46 | textin
- 3838 | event_trigger | 2300 | trigger_in
-(2 rows)
+ oid | typname | oid | proname
+------+-----------+-----+---------
+ 1790 | refcursor | 46 | textin
+(1 row)
-- Varlena array types will point to array_in
-- Exception as of 8.1: int2vector and oidvector have their own I/O routines
@@ -178,11 +177,10 @@ WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
(p2.oid = 'array_out'::regproc AND
p1.typelem != 0 AND p1.typlen = -1)))
ORDER BY 1;
- oid | typname | oid | proname
-------+---------------+------+-------------
- 1790 | refcursor | 47 | textout
- 3838 | event_trigger | 2301 | trigger_out
-(2 rows)
+ oid | typname | oid | proname
+------+-----------+-----+---------
+ 1790 | refcursor | 47 | textout
+(1 row)
SELECT p1.oid, p1.typname, p2.oid, p2.proname
FROM pg_type AS p1, pg_proc AS p2
diff --git a/src/test/regress/sql/event_triggers.sql b/src/test/regress/sql/event_triggers.sql
index cf25ee7..84a00e4 100644
--- a/src/test/regress/sql/event_triggers.sql
+++ b/src/test/regress/sql/event_triggers.sql
@@ -11,10 +11,6 @@ begin
end;
$$;
---
--- TODO: REASSIGN OWNED and DROP OWNED
---
-
create event trigger any_t on command_start
execute procedure snitch();
@@ -68,9 +64,11 @@ alter event trigger foo_t rename to snitch;
create schema cmd;
create schema cmd2;
-create role regbob;
-alter event trigger snitch owner to regbob;
+create role regression_bob;
+alter event trigger snitch owner to regression_bob;
+alter role regression_bob superuser;
+alter event trigger snitch owner to regression_bob;
create table cmd.foo(id bigserial primary key);
create view cmd.v as select * from cmd.foo;
@@ -103,7 +101,7 @@ alter table cmd.test set with oids;
alter table cmd.test set without oids;
create sequence test_seq_;
-alter sequence test_seq_ owner to regbob;
+alter sequence test_seq_ owner to regression_bob;
alter sequence test_seq_ rename to test_seq;
alter sequence test_seq set schema cmd;
alter sequence cmd.test_seq start with 3;
@@ -117,7 +115,7 @@ alter sequence cmd.test_seq cycle;
alter sequence cmd.test_seq no cycle;
create view view_test as select id, things from cmd.test;
-alter view view_test owner to regbob;
+alter view view_test owner to regression_bob;
alter view view_test rename to view_test2;
alter view view_test2 set schema cmd;
alter view cmd.view_test2 alter column id set default 9;
@@ -142,7 +140,7 @@ as $$ select t from cmd.foo where id = $1; $$;
alter function fun(int) strict;
alter function fun(int) rename to notfun;
alter function notfun(int) set schema cmd;
-alter function cmd.notfun(int) owner to regbob;
+alter function cmd.notfun(int) owner to regression_bob;
alter function cmd.notfun(int) cost 77;
drop function cmd.notfun(int);
@@ -170,7 +168,7 @@ create type cmd.compfoo AS (f1 int, f2 text);
alter type cmd.compfoo add attribute f3 text;
create type cmd.type_test AS (a integer, b integer, c text);
-alter type cmd.type_test owner to regbob;
+alter type cmd.type_test owner to regression_bob;
alter type cmd.type_test rename to type_test2;
alter type cmd.type_test2 set schema public;
alter type public.type_test2 rename attribute a to z;
@@ -191,7 +189,7 @@ alter domain cmd.us_postal_code drop default;
alter domain cmd.us_postal_code drop not null;
alter domain cmd.us_postal_code add constraint dummy_constraint check (value ~ '^\d{8}$');
alter domain cmd.us_postal_code drop constraint dummy_constraint;
-alter domain cmd.us_postal_code owner to regbob;
+alter domain cmd.us_postal_code owner to regression_bob;
alter domain cmd.us_postal_code set schema cmd2;
drop domain cmd2.us_postal_code;
@@ -248,11 +246,12 @@ drop schema cmd1 cascade;
drop schema cmd2 cascade;
-- fail because owning event trigger snitch
-drop role regbob;
+drop role regression_bob;
drop event trigger any_t;
-drop event trigger snitch;
-drop role regbob;
+drop event trigger if exists snitch;
+drop event trigger if exists snitch;
+drop role regression_bob;
create table onerow(id integer);