/* table_rewrite */
Oid table_rewrite_oid; /* InvalidOid, or set for table_rewrite
* event */ int table_rewrite_reason; /* AT_REWRITE reason */
/* Support for command collection */ bool commandCollectionInhibited;
CollectedCommand *currentCommand;
List *commandList; /* list of CollectedCommand; see
* deparse_utility.h */ struct EventTriggerQueryState *previous;
} EventTriggerQueryState;
/* Support for dropped objects */ typedefstruct SQLDropObject
{
ObjectAddress address; constchar *schemaname; constchar *objname; constchar *objidentity; constchar *objecttype;
List *addrnames;
List *addrargs; bool original; bool normal; bool istemp;
slist_node next;
} SQLDropObject;
staticvoid AlterEventTriggerOwner_internal(Relation rel,
HeapTuple tup,
Oid newOwnerId); staticvoid error_duplicate_filter_variable(constchar *defname); static Datum filter_list_to_array(List *filterlist); static Oid insert_event_trigger_tuple(constchar *trigname, constchar *eventname,
Oid evtOwner, Oid funcoid, List *taglist); staticvoid validate_ddl_tags(constchar *filtervar, List *taglist); staticvoid validate_table_rewrite_tags(constchar *filtervar, List *taglist); staticvoid EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata); staticbool obtain_object_name_namespace(const ObjectAddress *object,
SQLDropObject *obj); staticconstchar *stringify_grant_objtype(ObjectType objtype); staticconstchar *stringify_adefprivs_objtype(ObjectType objtype); staticvoid SetDatabaseHasLoginEventTriggers(void);
/* *Createaneventtrigger.
*/
Oid
CreateEventTrigger(CreateEventTrigStmt *stmt)
{
HeapTuple tuple;
Oid funcoid;
Oid funcrettype;
Oid evtowner = GetUserId();
ListCell *lc;
List *tags = NULL;
/* *Itwouldbenicetoallowdatabaseownersorevenregularuserstodo *this,butthereareobviousprivilegeescalationriskswhichwouldhave *tosomehowbepluggedfirst.
*/ if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to create event trigger \"%s\"",
stmt->trigname),
errhint("Must be superuser to create an event trigger.")));
if (commandTag == CMDTAG_UNKNOWN)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",
tagstr, filtervar))); if (!command_tag_event_trigger_ok(commandTag))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s represents an SQL statement name */
errmsg("event triggers are not supported for %s",
tagstr)));
}
}
if (!command_tag_table_rewrite_ok(commandTag))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), /* translator: %s represents an SQL statement name */
errmsg("event triggers are not supported for %s",
tagstr)));
}
}
/* *Complainaboutaduplicatefiltervariable.
*/ staticvoid
error_duplicate_filter_variable(constchar *defname)
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("filter variable \"%s\" specified more than once",
defname)));
}
/* *Insertthenewpg_event_triggerrowandrecorddependencies.
*/ static Oid
insert_event_trigger_tuple(constchar *trigname, constchar *eventname, Oid evtOwner,
Oid funcoid, List *taglist)
{
Relation tgrel;
Oid trigoid;
HeapTuple tuple;
Datum values[Natts_pg_event_trigger]; bool nulls[Natts_pg_event_trigger];
NameData evtnamedata,
evteventdata;
ObjectAddress myself,
referenced;
/* Open pg_event_trigger. */
tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
CStringGetDatum(stmt->trigname)); if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("event trigger \"%s\" does not exist",
stmt->trigname)));
if (!object_ownercheck(EventTriggerRelationId, form->oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
NameStr(form->evtname));
/* 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.")));
/* Fetch a copy of the tuple to scribble on */
ScanKeyInit(&key[0],
Anum_pg_database_oid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(MyDatabaseId));
/* Restore old memory context and delete the temporary one. */
MemoryContextSwitchTo(oldcontext);
MemoryContextDelete(context);
}
/* *Doeventtriggerssupportthisobjecttype? * *Seealsoeventtriggerdocumentationinevent-trigger.sgml.
*/ bool
EventTriggerSupportsObjectType(ObjectType obtype)
{ switch (obtype)
{ case OBJECT_DATABASE: case OBJECT_TABLESPACE: case OBJECT_ROLE: case OBJECT_PARAMETER_ACL: /* no support for global objects (except subscriptions) */ returnfalse; case OBJECT_EVENT_TRIGGER: /* no support for event triggers on event triggers */ returnfalse; default: returntrue;
}
}
/* *Doeventtriggerssupportthisobjectclass? * *Seealsoeventtriggerdocumentationinevent-trigger.sgml.
*/ bool
EventTriggerSupportsObject(const ObjectAddress *object)
{ switch (object->classId)
{ case DatabaseRelationId: case TableSpaceRelationId: case AuthIdRelationId: case AuthMemRelationId: case ParameterAclRelationId: /* no support for global objects (except subscriptions) */ returnfalse; case EventTriggerRelationId: /* no support for event triggers on event triggers */ returnfalse; default: returntrue;
}
}
if (object->classId == NamespaceRelationId)
{ /* Special handling is needed for temp namespaces */ if (isTempNamespace(object->objectId))
obj->istemp = true; elseif (isAnyTempNamespace(object->objectId))
{ /* don't report temp schemas except my own */
pfree(obj);
MemoryContextSwitchTo(oldcxt); return;
}
obj->objname = get_namespace_name(object->objectId);
} elseif (object->classId == AttrDefaultRelationId)
{ /* We treat a column default as temp if its table is temp */
ObjectAddress colobject;
colobject = GetAttrDefaultColumnAddress(object->objectId); if (OidIsValid(colobject.objectId))
{ if (!obtain_object_name_namespace(&colobject, obj))
{
pfree(obj);
MemoryContextSwitchTo(oldcxt); return;
}
}
} elseif (object->classId == TriggerRelationId)
{ /* Similarly, a trigger is temp if its table is temp */ /* Sadly, there's no lsyscache.c support for trigger objects */
Relation pg_trigger_rel;
ScanKeyData skey[1];
SysScanDesc sscan;
HeapTuple tuple;
Oid relid;
/* Fetch the trigger's table OID the hard way */
pg_trigger_rel = table_open(TriggerRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_trigger_oid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
sscan = systable_beginscan(pg_trigger_rel, TriggerOidIndexId, true,
NULL, 1, skey);
tuple = systable_getnext(sscan); if (HeapTupleIsValid(tuple))
relid = ((Form_pg_trigger) GETSTRUCT(tuple))->tgrelid; else
relid = InvalidOid; /* shouldn't happen */
systable_endscan(sscan);
table_close(pg_trigger_rel, AccessShareLock); /* Do nothing if we didn't find the trigger */ if (OidIsValid(relid))
{
ObjectAddress relobject;
relobject.classId = RelationRelationId;
relobject.objectId = relid; /* Arbitrarily set objectSubId nonzero so as not to fill objname */
relobject.objectSubId = 1; if (!obtain_object_name_namespace(&relobject, obj))
{
pfree(obj);
MemoryContextSwitchTo(oldcxt); return;
}
}
} elseif (object->classId == PolicyRelationId)
{ /* Similarly, a policy is temp if its table is temp */ /* Sadly, there's no lsyscache.c support for policy objects */
Relation pg_policy_rel;
ScanKeyData skey[1];
SysScanDesc sscan;
HeapTuple tuple;
Oid relid;
/* Fetch the policy's table OID the hard way */
pg_policy_rel = table_open(PolicyRelationId, AccessShareLock);
ScanKeyInit(&skey[0],
Anum_pg_policy_oid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
sscan = systable_beginscan(pg_policy_rel, PolicyOidIndexId, true,
NULL, 1, skey);
tuple = systable_getnext(sscan); if (HeapTupleIsValid(tuple))
relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid; else
relid = InvalidOid; /* shouldn't happen */
systable_endscan(sscan);
table_close(pg_policy_rel, AccessShareLock); /* Do nothing if we didn't find the policy */ if (OidIsValid(relid))
{
ObjectAddress relobject;
relobject.classId = RelationRelationId;
relobject.objectId = relid; /* Arbitrarily set objectSubId nonzero so as not to fill objname */
relobject.objectSubId = 1; if (!obtain_object_name_namespace(&relobject, obj))
{
pfree(obj);
MemoryContextSwitchTo(oldcxt); return;
}
}
} else
{ /* Generic handling for all other object classes */ if (!obtain_object_name_namespace(object, obj))
{ /* don't report temp objects except my own */
pfree(obj);
MemoryContextSwitchTo(oldcxt); return;
}
}
if (tuple)
{
AttrNumber attnum;
Datum datum; bool isnull;
attnum = get_object_attnum_namespace(object->classId); if (attnum != InvalidAttrNumber)
{
datum = heap_getattr(tuple, attnum,
RelationGetDescr(catalog), &isnull); if (!isnull)
{
Oid namespaceId;
namespaceId = DatumGetObjectId(datum); /* temp objects are only reported if they are my own */ if (isTempNamespace(namespaceId))
{
obj->schemaname = "pg_temp";
obj->istemp = true;
} elseif (isAnyTempNamespace(namespaceId))
{ /* no need to fill any fields of *obj */
table_close(catalog, AccessShareLock); returnfalse;
} else
{
obj->schemaname = get_namespace_name(namespaceId);
obj->istemp = false;
}
}
}
if (get_object_namensp_unique(object->classId) &&
object->objectSubId == 0)
{
attnum = get_object_attnum_name(object->classId); if (attnum != InvalidAttrNumber)
{
datum = heap_getattr(tuple, attnum,
RelationGetDescr(catalog), &isnull); if (!isnull)
obj->objname = pstrdup(NameStr(*DatumGetName(datum)));
}
}
}
/* *Protectthisfunctionfrombeingcalledoutofcontext
*/ if (!currentEventTriggerState ||
!currentEventTriggerState->in_sql_drop)
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
errmsg("%s can only be called in a sql_drop event trigger function", "pg_event_trigger_dropped_objects()")));
/* Build tuplestore to hold the result rows */
InitMaterializedSRF(fcinfo, 0);
slist_foreach(iter, &(currentEventTriggerState->SQLDropList))
{
SQLDropObject *obj; int i = 0;
Datum values[12] = {0}; bool nulls[12] = {0};
/* *pg_event_trigger_table_rewrite_oid * *MaketheOidofthetablegoingtoberewrittenavailabletotheuser *functionrunbytheEventTrigger.
*/
Datum
pg_event_trigger_table_rewrite_oid(PG_FUNCTION_ARGS)
{ /* *Protectthisfunctionfrombeingcalledoutofcontext
*/ if (!currentEventTriggerState ||
currentEventTriggerState->table_rewrite_oid == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
errmsg("%s can only be called in a table_rewrite event trigger function", "pg_event_trigger_table_rewrite_oid()")));
/* *pg_event_trigger_table_rewrite_reason * *Maketherewritereasonavailabletotheuser.
*/
Datum
pg_event_trigger_table_rewrite_reason(PG_FUNCTION_ARGS)
{ /* *Protectthisfunctionfrombeingcalledoutofcontext
*/ if (!currentEventTriggerState ||
currentEventTriggerState->table_rewrite_reason == 0)
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
errmsg("%s can only be called in a table_rewrite event trigger function", "pg_event_trigger_table_rewrite_reason()")));
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* *EventTriggerCollectAlterOpFam *SavedataaboutanALTEROPERATORFAMILYADD/DROPcommandbeing *executed
*/ void
EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
List *operators, List *procedures)
{
MemoryContext oldcxt;
CollectedCommand *command;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* *EventTriggerCollectCreateOpClass *SavedataaboutaCREATEOPERATORCLASScommandbeingexecuted
*/ void
EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
List *operators, List *procedures)
{
MemoryContext oldcxt;
CollectedCommand *command;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* *EventTriggerCollectAlterTSConfig *SavedataaboutanALTERTEXTSEARCHCONFIGURATIONcommandbeing *executed
*/ void
EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
Oid *dictIds, int ndicts)
{
MemoryContext oldcxt;
CollectedCommand *command;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* ignore if event trigger context not set, or collection disabled */ if (!currentEventTriggerState ||
currentEventTriggerState->commandCollectionInhibited) return;
/* *Protectthisfunctionfrombeingcalledoutofcontext
*/ if (!currentEventTriggerState)
ereport(ERROR,
(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
errmsg("%s can only be called in an event trigger function", "pg_event_trigger_ddl_commands()")));
/* Build tuplestore to hold the result rows */
InitMaterializedSRF(fcinfo, 0);
foreach(lc, currentEventTriggerState->commandList)
{
CollectedCommand *cmd = lfirst(lc);
Datum values[9]; bool nulls[9] = {0};
ObjectAddress addr; int i = 0;
switch (cmd->type)
{ case SCT_Simple: case SCT_AlterTable: case SCT_AlterOpFamily: case SCT_CreateOpClass: case SCT_AlterTSConfig:
{ char *identity; char *type; char *schema = NULL;
/* *ReturntheObjectTypeasastring,asitwouldappearinGRANTand *REVOKEcommands.
*/ staticconstchar *
stringify_grant_objtype(ObjectType objtype)
{ switch (objtype)
{ case OBJECT_COLUMN: return"COLUMN"; case OBJECT_TABLE: return"TABLE"; case OBJECT_SEQUENCE: return"SEQUENCE"; case OBJECT_DATABASE: return"DATABASE"; case OBJECT_DOMAIN: return"DOMAIN"; case OBJECT_FDW: return"FOREIGN DATA WRAPPER"; case OBJECT_FOREIGN_SERVER: return"FOREIGN SERVER"; case OBJECT_FUNCTION: return"FUNCTION"; case OBJECT_LANGUAGE: return"LANGUAGE"; case OBJECT_LARGEOBJECT: return"LARGE OBJECT"; case OBJECT_SCHEMA: return"SCHEMA"; case OBJECT_PARAMETER_ACL: return"PARAMETER"; case OBJECT_PROCEDURE: return"PROCEDURE"; case OBJECT_ROUTINE: return"ROUTINE"; case OBJECT_TABLESPACE: return"TABLESPACE"; case OBJECT_TYPE: return"TYPE"; /* these currently aren't used */ case OBJECT_ACCESS_METHOD: case OBJECT_AGGREGATE: case OBJECT_AMOP: case OBJECT_AMPROC: case OBJECT_ATTRIBUTE: case OBJECT_CAST: case OBJECT_COLLATION: case OBJECT_CONVERSION: case OBJECT_DEFAULT: case OBJECT_DEFACL: case OBJECT_DOMCONSTRAINT: case OBJECT_EVENT_TRIGGER: case OBJECT_EXTENSION: case OBJECT_FOREIGN_TABLE: case OBJECT_INDEX: case OBJECT_MATVIEW: case OBJECT_OPCLASS: case OBJECT_OPERATOR: case OBJECT_OPFAMILY: case OBJECT_POLICY: case OBJECT_PUBLICATION: case OBJECT_PUBLICATION_NAMESPACE: case OBJECT_PUBLICATION_REL: case OBJECT_ROLE: case OBJECT_RULE: case OBJECT_STATISTIC_EXT: case OBJECT_SUBSCRIPTION: case OBJECT_TABCONSTRAINT: case OBJECT_TRANSFORM: case OBJECT_TRIGGER: case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: case OBJECT_VIEW:
elog(ERROR, "unsupported object type: %d", (int) objtype);
}
return"???"; /* keep compiler quiet */
}
/* *ReturntheObjectTypeasastring;asabove,butusethespelling *inALTERDEFAULTPRIVILEGEScommandsinstead.Generallythisisjust *theplural.
*/ staticconstchar *
stringify_adefprivs_objtype(ObjectType objtype)
{ switch (objtype)
{ case OBJECT_COLUMN: return"COLUMNS"; case OBJECT_TABLE: return"TABLES"; case OBJECT_SEQUENCE: return"SEQUENCES"; case OBJECT_DATABASE: return"DATABASES"; case OBJECT_DOMAIN: return"DOMAINS"; case OBJECT_FDW: return"FOREIGN DATA WRAPPERS"; case OBJECT_FOREIGN_SERVER: return"FOREIGN SERVERS"; case OBJECT_FUNCTION: return"FUNCTIONS"; case OBJECT_LANGUAGE: return"LANGUAGES"; case OBJECT_LARGEOBJECT: return"LARGE OBJECTS"; case OBJECT_SCHEMA: return"SCHEMAS"; case OBJECT_PROCEDURE: return"PROCEDURES"; case OBJECT_ROUTINE: return"ROUTINES"; case OBJECT_TABLESPACE: return"TABLESPACES"; case OBJECT_TYPE: return"TYPES"; /* these currently aren't used */ case OBJECT_ACCESS_METHOD: case OBJECT_AGGREGATE: case OBJECT_AMOP: case OBJECT_AMPROC: case OBJECT_ATTRIBUTE: case OBJECT_CAST: case OBJECT_COLLATION: case OBJECT_CONVERSION: case OBJECT_DEFAULT: case OBJECT_DEFACL: case OBJECT_DOMCONSTRAINT: case OBJECT_EVENT_TRIGGER: case OBJECT_EXTENSION: case OBJECT_FOREIGN_TABLE: case OBJECT_INDEX: case OBJECT_MATVIEW: case OBJECT_OPCLASS: case OBJECT_OPERATOR: case OBJECT_OPFAMILY: case OBJECT_PARAMETER_ACL: case OBJECT_POLICY: case OBJECT_PUBLICATION: case OBJECT_PUBLICATION_NAMESPACE: case OBJECT_PUBLICATION_REL: case OBJECT_ROLE: case OBJECT_RULE: case OBJECT_STATISTIC_EXT: case OBJECT_SUBSCRIPTION: case OBJECT_TABCONSTRAINT: case OBJECT_TRANSFORM: case OBJECT_TRIGGER: case OBJECT_TSCONFIGURATION: case OBJECT_TSDICTIONARY: case OBJECT_TSPARSER: case OBJECT_TSTEMPLATE: case OBJECT_USER_MAPPING: case OBJECT_VIEW:
elog(ERROR, "unsupported object type: %d", (int) objtype);
}
return"???"; /* keep compiler quiet */
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.53 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.