PostgreSQL Source Code git master
Loading...
Searching...
No Matches
event_trigger.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_database.h"
#include "catalog/pg_event_trigger.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_parameter_acl.h"
#include "catalog/pg_policy.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_ts_config.h"
#include "catalog/pg_type.h"
#include "commands/event_trigger.h"
#include "commands/extension.h"
#include "commands/trigger.h"
#include "funcapi.h"
#include "lib/ilist.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "pgstat.h"
#include "storage/lmgr.h"
#include "tcop/deparse_utility.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/evtcache.h"
#include "utils/fmgroids.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tuplestore.h"
Include dependency graph for event_trigger.c:

Go to the source code of this file.

Data Structures

struct  EventTriggerQueryState
 
struct  SQLDropObject
 

Typedefs

typedef struct EventTriggerQueryState EventTriggerQueryState
 
typedef struct SQLDropObject SQLDropObject
 

Functions

static void AlterEventTriggerOwner_internal (Relation rel, HeapTuple tup, Oid newOwnerId)
 
static void error_duplicate_filter_variable (const char *defname)
 
static Datum filter_list_to_array (List *filterlist)
 
static Oid insert_event_trigger_tuple (const char *trigname, const char *eventname, Oid evtOwner, Oid funcoid, List *taglist)
 
static void validate_ddl_tags (const char *filtervar, List *taglist)
 
static void validate_table_rewrite_tags (const char *filtervar, List *taglist)
 
static void EventTriggerInvoke (List *fn_oid_list, EventTriggerData *trigdata)
 
static bool obtain_object_name_namespace (const ObjectAddress *object, SQLDropObject *obj)
 
static const charstringify_grant_objtype (ObjectType objtype)
 
static const charstringify_adefprivs_objtype (ObjectType objtype)
 
static void SetDatabaseHasLoginEventTriggers (void)
 
Oid CreateEventTrigger (CreateEventTrigStmt *stmt)
 
Oid AlterEventTrigger (AlterEventTrigStmt *stmt)
 
ObjectAddress AlterEventTriggerOwner (const char *name, Oid newOwnerId)
 
void AlterEventTriggerOwner_oid (Oid trigOid, Oid newOwnerId)
 
Oid get_event_trigger_oid (const char *trigname, bool missing_ok)
 
static bool filter_event_trigger (CommandTag tag, EventTriggerCacheItem *item)
 
static CommandTag EventTriggerGetTag (Node *parsetree, EventTriggerEvent event)
 
static ListEventTriggerCommonSetup (Node *parsetree, EventTriggerEvent event, const char *eventstr, EventTriggerData *trigdata, bool unfiltered)
 
void EventTriggerDDLCommandStart (Node *parsetree)
 
void EventTriggerDDLCommandEnd (Node *parsetree)
 
void EventTriggerSQLDrop (Node *parsetree)
 
void EventTriggerOnLogin (void)
 
void EventTriggerTableRewrite (Node *parsetree, Oid tableOid, int reason)
 
bool EventTriggerSupportsObjectType (ObjectType obtype)
 
bool EventTriggerSupportsObject (const ObjectAddress *object)
 
bool EventTriggerBeginCompleteQuery (void)
 
void EventTriggerEndCompleteQuery (void)
 
bool trackDroppedObjectsNeeded (void)
 
void EventTriggerSQLDropAddObject (const ObjectAddress *object, bool original, bool normal)
 
Datum pg_event_trigger_dropped_objects (PG_FUNCTION_ARGS)
 
Datum pg_event_trigger_table_rewrite_oid (PG_FUNCTION_ARGS)
 
Datum pg_event_trigger_table_rewrite_reason (PG_FUNCTION_ARGS)
 
void EventTriggerInhibitCommandCollection (void)
 
void EventTriggerUndoInhibitCommandCollection (void)
 
void EventTriggerCollectSimpleCommand (ObjectAddress address, ObjectAddress secondaryObject, const Node *parsetree)
 
void EventTriggerAlterTableStart (const Node *parsetree)
 
void EventTriggerAlterTableRelid (Oid objectId)
 
void EventTriggerCollectAlterTableSubcmd (const Node *subcmd, ObjectAddress address)
 
void EventTriggerAlterTableEnd (void)
 
void EventTriggerCollectGrant (InternalGrant *istmt)
 
void EventTriggerCollectAlterOpFam (const AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
 
void EventTriggerCollectCreateOpClass (const CreateOpClassStmt *stmt, Oid opcoid, List *operators, List *procedures)
 
void EventTriggerCollectAlterTSConfig (const AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
 
void EventTriggerCollectAlterDefPrivs (const AlterDefaultPrivilegesStmt *stmt)
 
Datum pg_event_trigger_ddl_commands (PG_FUNCTION_ARGS)
 

Variables

static EventTriggerQueryStatecurrentEventTriggerState = NULL
 
bool event_triggers = true
 

Typedef Documentation

◆ EventTriggerQueryState

◆ SQLDropObject

Function Documentation

◆ AlterEventTrigger()

Oid AlterEventTrigger ( AlterEventTrigStmt stmt)

Definition at line 429 of file event_trigger.c.

430{
433 Oid trigoid;
435 char tgenabled = stmt->tgenabled;
436
438
440 CStringGetDatum(stmt->trigname));
441 if (!HeapTupleIsValid(tup))
444 errmsg("event trigger \"%s\" does not exist",
445 stmt->trigname)));
446
448 trigoid = evtForm->oid;
449
452 stmt->trigname);
453
454 /* tuple is a copy, so we can modify it below */
455 evtForm->evtenabled = tgenabled;
456
457 CatalogTupleUpdate(tgrel, &tup->t_self, tup);
458
459 /*
460 * Login event triggers have an additional flag in pg_database to enable
461 * faster lookups in hot codepaths. Set the flag unless already True.
462 */
463 if (namestrcmp(&evtForm->evtevent, "login") == 0 &&
464 tgenabled != TRIGGER_DISABLED)
466
468 trigoid, 0);
469
470 /* clean up */
473
474 return trigoid;
475}
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4133
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
static void SetDatabaseHasLoginEventTriggers(void)
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
#define RowExclusiveLock
Definition lockdefs.h:38
Oid GetUserId(void)
Definition miscinit.c:470
int namestrcmp(Name name, const char *str)
Definition name.c:247
static char * errmsg
#define InvokeObjectPostAlterHook(classId, objectId, subId)
@ OBJECT_EVENT_TRIGGER
END_CATALOG_STRUCT typedef FormData_pg_event_trigger * Form_pg_event_trigger
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
unsigned int Oid
static int fb(int x)
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
#define TRIGGER_DISABLED
Definition trigger.h:154

References aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleUpdate(), CStringGetDatum(), ereport, errcode(), errmsg, ERROR, fb(), Form_pg_event_trigger, GETSTRUCT(), GetUserId(), heap_freetuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, namestrcmp(), OBJECT_EVENT_TRIGGER, object_ownercheck(), RowExclusiveLock, SearchSysCacheCopy1, SetDatabaseHasLoginEventTriggers(), stmt, table_close(), table_open(), and TRIGGER_DISABLED.

Referenced by standard_ProcessUtility().

◆ AlterEventTriggerOwner()

ObjectAddress AlterEventTriggerOwner ( const char name,
Oid  newOwnerId 
)

Definition at line 481 of file event_trigger.c.

482{
483 Oid evtOid;
486 Relation rel;
487 ObjectAddress address;
488
490
492
493 if (!HeapTupleIsValid(tup))
496 errmsg("event trigger \"%s\" does not exist", name)));
497
499 evtOid = evtForm->oid;
500
502
504
506
508
509 return address;
510}
static void AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
#define ObjectAddressSet(addr, class_id, object_id)
const char * name

References AlterEventTriggerOwner_internal(), CStringGetDatum(), ereport, errcode(), errmsg, ERROR, fb(), Form_pg_event_trigger, GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, name, ObjectAddressSet, RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by ExecAlterOwnerStmt().

◆ AlterEventTriggerOwner_internal()

static void AlterEventTriggerOwner_internal ( Relation  rel,
HeapTuple  tup,
Oid  newOwnerId 
)
static

Definition at line 541 of file event_trigger.c.

542{
544
546
547 if (form->evtowner == newOwnerId)
548 return;
549
552 NameStr(form->evtname));
553
554 /* New owner must be a superuser */
558 errmsg("permission denied to change owner of event trigger \"%s\"",
559 NameStr(form->evtname)),
560 errhint("The owner of an event trigger must be a superuser.")));
561
562 form->evtowner = newOwnerId;
563 CatalogTupleUpdate(rel, &tup->t_self, tup);
564
565 /* Update owner dependency reference */
567 form->oid,
568 newOwnerId);
569
571 form->oid, 0);
572}
#define NameStr(name)
Definition c.h:835
int errhint(const char *fmt,...) pg_attribute_printf(1
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
bool superuser_arg(Oid roleid)
Definition superuser.c:57

References aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleUpdate(), changeDependencyOnOwner(), ereport, errcode(), errhint(), errmsg, ERROR, fb(), Form_pg_event_trigger, GETSTRUCT(), GetUserId(), InvokeObjectPostAlterHook, NameStr, OBJECT_EVENT_TRIGGER, object_ownercheck(), and superuser_arg().

Referenced by AlterEventTriggerOwner(), and AlterEventTriggerOwner_oid().

◆ AlterEventTriggerOwner_oid()

void AlterEventTriggerOwner_oid ( Oid  trigOid,
Oid  newOwnerId 
)

Definition at line 516 of file event_trigger.c.

517{
519 Relation rel;
520
522
524
525 if (!HeapTupleIsValid(tup))
528 errmsg("event trigger with OID %u does not exist", trigOid)));
529
531
533
535}
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252

References AlterEventTriggerOwner_internal(), ereport, errcode(), errmsg, ERROR, fb(), heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum(), RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by shdepReassignOwned_Owner().

◆ CreateEventTrigger()

Oid CreateEventTrigger ( CreateEventTrigStmt stmt)

Definition at line 126 of file event_trigger.c.

127{
128 HeapTuple tuple;
129 Oid funcoid;
131 Oid evtowner = GetUserId();
132 ListCell *lc;
133 List *tags = NULL;
134
135 /*
136 * It would be nice to allow database owners or even regular users to do
137 * this, but there are obvious privilege escalation risks which would have
138 * to somehow be plugged first.
139 */
140 if (!superuser())
143 errmsg("permission denied to create event trigger \"%s\"",
144 stmt->trigname),
145 errhint("Must be superuser to create an event trigger.")));
146
147 /* Validate event name. */
148 if (strcmp(stmt->eventname, "ddl_command_start") != 0 &&
149 strcmp(stmt->eventname, "ddl_command_end") != 0 &&
150 strcmp(stmt->eventname, "sql_drop") != 0 &&
151 strcmp(stmt->eventname, "login") != 0 &&
152 strcmp(stmt->eventname, "table_rewrite") != 0)
155 errmsg("unrecognized event name \"%s\"",
156 stmt->eventname)));
157
158 /* Validate filter conditions. */
159 foreach(lc, stmt->whenclause)
160 {
161 DefElem *def = (DefElem *) lfirst(lc);
162
163 if (strcmp(def->defname, "tag") == 0)
164 {
165 if (tags != NULL)
167 tags = (List *) def->arg;
168 }
169 else
172 errmsg("unrecognized filter variable \"%s\"", def->defname)));
173 }
174
175 /* Validate tag list, if any. */
176 if ((strcmp(stmt->eventname, "ddl_command_start") == 0 ||
177 strcmp(stmt->eventname, "ddl_command_end") == 0 ||
178 strcmp(stmt->eventname, "sql_drop") == 0)
179 && tags != NULL)
180 validate_ddl_tags("tag", tags);
181 else if (strcmp(stmt->eventname, "table_rewrite") == 0
182 && tags != NULL)
184 else if (strcmp(stmt->eventname, "login") == 0 && tags != NULL)
187 errmsg("tag filtering is not supported for login event triggers")));
188
189 /*
190 * Give user a nice error message if an event trigger of the same name
191 * already exists.
192 */
194 if (HeapTupleIsValid(tuple))
197 errmsg("event trigger \"%s\" already exists",
198 stmt->trigname)));
199
200 /* Find and validate the trigger function. */
201 funcoid = LookupFuncName(stmt->funcname, 0, NULL, false);
206 errmsg("function %s must return type %s",
207 NameListToString(stmt->funcname), "event_trigger")));
208
209 /* Insert catalog entries. */
210 return insert_event_trigger_tuple(stmt->trigname, stmt->eventname,
211 evtowner, funcoid, tags);
212}
static void validate_table_rewrite_tags(const char *filtervar, List *taglist)
static void validate_ddl_tags(const char *filtervar, List *taglist)
static void error_duplicate_filter_variable(const char *defname)
static Oid insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtOwner, Oid funcoid, List *taglist)
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1875
char * NameListToString(const List *names)
Definition namespace.c:3666
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
#define lfirst(lc)
Definition pg_list.h:172
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
char * defname
Definition parsenodes.h:860
Node * arg
Definition parsenodes.h:861
Definition pg_list.h:54
bool superuser(void)
Definition superuser.c:47
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References DefElem::arg, CStringGetDatum(), DefElem::defname, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg, ERROR, error_duplicate_filter_variable(), fb(), get_func_rettype(), GetUserId(), HeapTupleIsValid, insert_event_trigger_tuple(), lfirst, LookupFuncName(), NameListToString(), SearchSysCache1(), stmt, superuser(), validate_ddl_tags(), and validate_table_rewrite_tags().

Referenced by standard_ProcessUtility().

◆ error_duplicate_filter_variable()

static void error_duplicate_filter_variable ( const char defname)
static

Definition at line 267 of file event_trigger.c.

268{
271 errmsg("filter variable \"%s\" specified more than once",
272 defname)));
273}

References ereport, errcode(), errmsg, ERROR, and fb().

Referenced by CreateEventTrigger().

◆ EventTriggerAlterTableEnd()

void EventTriggerAlterTableEnd ( void  )

Definition at line 1842 of file event_trigger.c.

1843{
1844 CollectedCommand *parent;
1845
1846 /* ignore if event trigger context not set, or collection disabled */
1849 return;
1850
1852
1853 /* If no subcommands, don't collect */
1855 {
1857
1859
1863
1865 }
1866 else
1868
1870}
static EventTriggerQueryState * currentEventTriggerState
List * lappend(List *list, void *datum)
Definition list.c:339
void pfree(void *pointer)
Definition mcxt.c:1616
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define NIL
Definition pg_list.h:68
union CollectedCommand::@137 d
struct CollectedCommand * parent
struct CollectedCommand::@137::@139 alterTable
CollectedCommand * currentCommand

References CollectedCommand::alterTable, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, EventTriggerQueryState::currentCommand, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), lappend(), MemoryContextSwitchTo(), NIL, CollectedCommand::parent, pfree(), and CollectedCommand::subcmds.

Referenced by AlterTableMoveAll(), ProcessUtilityForAlterTable(), and ProcessUtilitySlow().

◆ EventTriggerAlterTableRelid()

◆ EventTriggerAlterTableStart()

void EventTriggerAlterTableStart ( const Node parsetree)

Definition at line 1755 of file event_trigger.c.

1756{
1758 CollectedCommand *command;
1759
1760 /* ignore if event trigger context not set, or collection disabled */
1763 return;
1764
1766
1768
1769 command->type = SCT_AlterTable;
1771
1773 command->d.alterTable.objectId = InvalidOid;
1774 command->d.alterTable.subcmds = NIL;
1775 command->parsetree = copyObject(parsetree);
1776
1779
1781}
@ SCT_AlterTable
bool creating_extension
Definition extension.c:80
#define palloc_object(type)
Definition fe_memutils.h:74
#define copyObject(obj)
Definition nodes.h:232
#define InvalidOid
CollectedCommandType type

References CollectedCommand::alterTable, CollectedCommand::classId, EventTriggerQueryState::commandCollectionInhibited, copyObject, creating_extension, EventTriggerQueryState::currentCommand, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), CollectedCommand::in_extension, InvalidOid, MemoryContextSwitchTo(), NIL, CollectedCommand::objectId, palloc_object, CollectedCommand::parent, CollectedCommand::parsetree, SCT_AlterTable, CollectedCommand::subcmds, and CollectedCommand::type.

Referenced by AlterTableMoveAll(), ProcessUtilityForAlterTable(), and ProcessUtilitySlow().

◆ EventTriggerBeginCompleteQuery()

bool EventTriggerBeginCompleteQuery ( void  )

Definition at line 1185 of file event_trigger.c.

1186{
1188 MemoryContext cxt;
1189
1190 /*
1191 * Currently, sql_drop, table_rewrite, ddl_command_end events are the only
1192 * reason to have event trigger state at all; so if there are none, don't
1193 * install one.
1194 */
1196 return false;
1197
1199 "event trigger state",
1202 state->cxt = cxt;
1203 slist_init(&(state->SQLDropList));
1204 state->in_sql_drop = false;
1205 state->table_rewrite_oid = InvalidOid;
1206
1207 state->commandCollectionInhibited = currentEventTriggerState ?
1209 state->currentCommand = NULL;
1210 state->commandList = NIL;
1211 state->previous = currentEventTriggerState;
1213
1214 return true;
1215}
bool trackDroppedObjectsNeeded(void)
static void slist_init(slist_head *head)
Definition ilist.h:986
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, EventTriggerQueryState::commandCollectionInhibited, currentEventTriggerState, fb(), InvalidOid, MemoryContextAlloc(), NIL, slist_init(), TopMemoryContext, and trackDroppedObjectsNeeded().

Referenced by ProcessUtilitySlow().

◆ EventTriggerCollectAlterDefPrivs()

void EventTriggerCollectAlterDefPrivs ( const AlterDefaultPrivilegesStmt stmt)

Definition at line 2029 of file event_trigger.c.

2030{
2032 CollectedCommand *command;
2033
2034 /* ignore if event trigger context not set, or collection disabled */
2037 return;
2038
2040
2043 command->d.defprivs.objtype = stmt->action->objtype;
2045 command->parsetree = (Node *) copyObject(stmt);
2046
2050}
@ SCT_AlterDefaultPrivileges
#define palloc0_object(type)
Definition fe_memutils.h:75
struct CollectedCommand::@137::@144 defprivs
Definition nodes.h:135

References EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, CollectedCommand::defprivs, fb(), CollectedCommand::in_extension, lappend(), MemoryContextSwitchTo(), CollectedCommand::objtype, palloc0_object, CollectedCommand::parsetree, SCT_AlterDefaultPrivileges, stmt, and CollectedCommand::type.

Referenced by ProcessUtilitySlow().

◆ EventTriggerCollectAlterOpFam()

void EventTriggerCollectAlterOpFam ( const AlterOpFamilyStmt stmt,
Oid  opfamoid,
List operators,
List procedures 
)

Definition at line 1924 of file event_trigger.c.

1926{
1928 CollectedCommand *command;
1929
1930 /* ignore if event trigger context not set, or collection disabled */
1933 return;
1934
1936
1938 command->type = SCT_AlterOpFamily;
1942 command->d.opfam.operators = operators;
1943 command->d.opfam.procedures = procedures;
1944 command->parsetree = (Node *) copyObject(stmt);
1945
1948
1950}
@ SCT_AlterOpFamily
struct CollectedCommand::@137::@141 opfam
ObjectAddress address

References CollectedCommand::address, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), CollectedCommand::in_extension, lappend(), MemoryContextSwitchTo(), ObjectAddressSet, CollectedCommand::operators, CollectedCommand::opfam, palloc_object, CollectedCommand::parsetree, CollectedCommand::procedures, SCT_AlterOpFamily, stmt, and CollectedCommand::type.

Referenced by AlterOpFamilyAdd(), and AlterOpFamilyDrop().

◆ EventTriggerCollectAlterTableSubcmd()

void EventTriggerCollectAlterTableSubcmd ( const Node subcmd,
ObjectAddress  address 
)

Definition at line 1807 of file event_trigger.c.

1808{
1811
1812 /* ignore if event trigger context not set, or collection disabled */
1815 return;
1816
1820
1822
1824 newsub->address = address;
1825 newsub->parsetree = copyObject(subcmd);
1826
1829
1831}
#define Assert(condition)
Definition c.h:943
#define OidIsValid(objectId)
Definition c.h:858
#define IsA(nodeptr, _type_)
Definition nodes.h:164
static color newsub(struct colormap *cm, color co)
Definition regc_color.c:389

References CollectedCommand::alterTable, Assert, EventTriggerQueryState::commandCollectionInhibited, copyObject, EventTriggerQueryState::currentCommand, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), IsA, lappend(), MemoryContextSwitchTo(), newsub(), CollectedCommand::objectId, OidIsValid, palloc_object, and CollectedCommand::subcmds.

Referenced by ATExecCmd().

◆ EventTriggerCollectAlterTSConfig()

void EventTriggerCollectAlterTSConfig ( const AlterTSConfigurationStmt stmt,
Oid  cfgId,
Oid dictIds,
int  ndicts 
)

Definition at line 1991 of file event_trigger.c.

1993{
1995 CollectedCommand *command;
1996
1997 /* ignore if event trigger context not set, or collection disabled */
2000 return;
2001
2003
2005 command->type = SCT_AlterTSConfig;
2008 TSConfigRelationId, cfgId);
2009 if (ndicts > 0)
2010 {
2011 command->d.atscfg.dictIds = palloc_array(Oid, ndicts);
2012 memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
2013 }
2014 command->d.atscfg.ndicts = ndicts;
2015 command->parsetree = (Node *) copyObject(stmt);
2016
2019
2021}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
@ SCT_AlterTSConfig
#define palloc_array(type, count)
Definition fe_memutils.h:76
struct CollectedCommand::@137::@143 atscfg

References CollectedCommand::address, CollectedCommand::atscfg, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, CollectedCommand::dictIds, fb(), CollectedCommand::in_extension, lappend(), memcpy(), MemoryContextSwitchTo(), CollectedCommand::ndicts, ObjectAddressSet, palloc0_object, palloc_array, CollectedCommand::parsetree, SCT_AlterTSConfig, stmt, and CollectedCommand::type.

Referenced by DropConfigurationMapping(), and MakeConfigurationMapping().

◆ EventTriggerCollectCreateOpClass()

void EventTriggerCollectCreateOpClass ( const CreateOpClassStmt stmt,
Oid  opcoid,
List operators,
List procedures 
)

Definition at line 1957 of file event_trigger.c.

1959{
1961 CollectedCommand *command;
1962
1963 /* ignore if event trigger context not set, or collection disabled */
1966 return;
1967
1969
1971 command->type = SCT_CreateOpClass;
1975 command->d.createopc.operators = operators;
1976 command->d.createopc.procedures = procedures;
1977 command->parsetree = (Node *) copyObject(stmt);
1978
1981
1983}
@ SCT_CreateOpClass
struct CollectedCommand::@137::@142 createopc

References CollectedCommand::address, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, CollectedCommand::createopc, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), CollectedCommand::in_extension, lappend(), MemoryContextSwitchTo(), ObjectAddressSet, CollectedCommand::operators, palloc0_object, CollectedCommand::parsetree, CollectedCommand::procedures, SCT_CreateOpClass, stmt, and CollectedCommand::type.

Referenced by DefineOpClass().

◆ EventTriggerCollectGrant()

void EventTriggerCollectGrant ( InternalGrant istmt)

Definition at line 1880 of file event_trigger.c.

1881{
1883 CollectedCommand *command;
1885 ListCell *cell;
1886
1887 /* ignore if event trigger context not set, or collection disabled */
1890 return;
1891
1893
1894 /*
1895 * This is tedious, but necessary.
1896 */
1898 memcpy(icopy, istmt, sizeof(InternalGrant));
1899 icopy->objects = list_copy(istmt->objects);
1900 icopy->grantees = list_copy(istmt->grantees);
1901 icopy->col_privs = NIL;
1902 foreach(cell, istmt->col_privs)
1903 icopy->col_privs = lappend(icopy->col_privs, copyObject(lfirst(cell)));
1904
1905 /* Now collect it, using the copied InternalGrant */
1907 command->type = SCT_Grant;
1909 command->d.grant.istmt = icopy;
1910 command->parsetree = NULL;
1911
1914
1916}
@ SCT_Grant
List * list_copy(const List *oldlist)
Definition list.c:1573
InternalGrant * istmt
struct CollectedCommand::@137::@140 grant

References InternalGrant::col_privs, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), CollectedCommand::grant, InternalGrant::grantees, CollectedCommand::in_extension, CollectedCommand::istmt, lappend(), lfirst, list_copy(), memcpy(), MemoryContextSwitchTo(), NIL, InternalGrant::objects, palloc_object, CollectedCommand::parsetree, SCT_Grant, and CollectedCommand::type.

Referenced by ExecGrantStmt_oids().

◆ EventTriggerCollectSimpleCommand()

void EventTriggerCollectSimpleCommand ( ObjectAddress  address,
ObjectAddress  secondaryObject,
const Node parsetree 
)

Definition at line 1717 of file event_trigger.c.

1720{
1722 CollectedCommand *command;
1723
1724 /* ignore if event trigger context not set, or collection disabled */
1727 return;
1728
1730
1732
1733 command->type = SCT_Simple;
1735
1736 command->d.simple.address = address;
1737 command->d.simple.secondaryObject = secondaryObject;
1738 command->parsetree = copyObject(parsetree);
1739
1741 command);
1742
1744}
@ SCT_Simple
ObjectAddress secondaryObject
struct CollectedCommand::@137::@138 simple

References CollectedCommand::address, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, fb(), CollectedCommand::in_extension, lappend(), MemoryContextSwitchTo(), palloc_object, CollectedCommand::parsetree, SCT_Simple, CollectedCommand::secondaryObject, CollectedCommand::simple, and CollectedCommand::type.

Referenced by AlterPublicationOptions(), CreateOpFamily(), CreateSchemaCommand(), ProcessUtilitySlow(), PublicationAddSchemas(), PublicationAddTables(), reindex_index(), and ReindexRelationConcurrently().

◆ EventTriggerCommonSetup()

static List * EventTriggerCommonSetup ( Node parsetree,
EventTriggerEvent  event,
const char eventstr,
EventTriggerData trigdata,
bool  unfiltered 
)
static

Definition at line 640 of file event_trigger.c.

643{
644 CommandTag tag;
646 ListCell *lc;
647 List *runlist = NIL;
648
649 /*
650 * We want the list of command tags for which this procedure is actually
651 * invoked to match up exactly with the list that CREATE EVENT TRIGGER
652 * accepts. This debugging cross-check will throw an error if this
653 * function is invoked for a command tag that CREATE EVENT TRIGGER won't
654 * accept. (Unfortunately, there doesn't seem to be any simple, automated
655 * way to verify that CREATE EVENT TRIGGER doesn't accept extra stuff that
656 * never reaches this control point.)
657 *
658 * If this cross-check fails for you, you probably need to either adjust
659 * standard_ProcessUtility() not to invoke event triggers for the command
660 * type in question, or you need to adjust event_trigger_ok to accept the
661 * relevant command tag.
662 */
663#ifdef USE_ASSERT_CHECKING
664 {
666
667 dbgtag = EventTriggerGetTag(parsetree, event);
668
669 if (event == EVT_DDLCommandStart ||
670 event == EVT_DDLCommandEnd ||
671 event == EVT_SQLDrop ||
672 event == EVT_Login)
673 {
675 elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag));
676 }
677 else if (event == EVT_TableRewrite)
678 {
680 elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag));
681 }
682 }
683#endif
684
685 /* Use cache to find triggers for this event; fast exit if none. */
687 if (cachelist == NIL)
688 return NIL;
689
690 /* Get the command tag. */
691 tag = EventTriggerGetTag(parsetree, event);
692
693 /*
694 * Filter list of event triggers by command tag, and copy them into our
695 * memory context. Once we start running the command triggers, or indeed
696 * once we do anything at all that touches the catalogs, an invalidation
697 * might leave cachelist pointing at garbage, so we must do this before we
698 * can do much else.
699 */
700 foreach(lc, cachelist)
701 {
703
704 if (unfiltered || filter_event_trigger(tag, item))
705 {
706 /* We must plan to fire this trigger. */
708 }
709 }
710
711 /* Don't spend any more time on this if no functions to run */
712 if (runlist == NIL)
713 return NIL;
714
715 trigdata->type = T_EventTriggerData;
716 trigdata->event = eventstr;
717 trigdata->parsetree = parsetree;
718 trigdata->tag = tag;
719
720 return runlist;
721}
const char * GetCommandTagName(CommandTag commandTag)
Definition cmdtag.c:47
bool command_tag_event_trigger_ok(CommandTag commandTag)
Definition cmdtag.c:66
bool command_tag_table_rewrite_ok(CommandTag commandTag)
Definition cmdtag.c:72
CommandTag
Definition cmdtag.h:23
#define elog(elevel,...)
Definition elog.h:228
static bool filter_event_trigger(CommandTag tag, EventTriggerCacheItem *item)
static CommandTag EventTriggerGetTag(Node *parsetree, EventTriggerEvent event)
List * EventCacheLookup(EventTriggerEvent event)
Definition evtcache.c:64
@ EVT_SQLDrop
Definition evtcache.h:24
@ EVT_Login
Definition evtcache.h:26
@ EVT_DDLCommandEnd
Definition evtcache.h:23
@ EVT_DDLCommandStart
Definition evtcache.h:22
@ EVT_TableRewrite
Definition evtcache.h:25
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
const char * event

References command_tag_event_trigger_ok(), command_tag_table_rewrite_ok(), elog, ERROR, EventTriggerData::event, EventCacheLookup(), EventTriggerGetTag(), EVT_DDLCommandEnd, EVT_DDLCommandStart, EVT_Login, EVT_SQLDrop, EVT_TableRewrite, fb(), filter_event_trigger(), EventTriggerCacheItem::fnoid, GetCommandTagName(), lappend_oid(), lfirst, NIL, EventTriggerData::parsetree, EventTriggerData::tag, and EventTriggerData::type.

Referenced by EventTriggerDDLCommandEnd(), EventTriggerDDLCommandStart(), EventTriggerOnLogin(), EventTriggerSQLDrop(), and EventTriggerTableRewrite().

◆ EventTriggerDDLCommandEnd()

void EventTriggerDDLCommandEnd ( Node parsetree)

Definition at line 778 of file event_trigger.c.

779{
780 List *runlist;
781 EventTriggerData trigdata;
782
783 /*
784 * See EventTriggerDDLCommandStart for a discussion about why event
785 * triggers are disabled in single user mode or via GUC.
786 */
788 return;
789
790 /*
791 * Also do nothing if our state isn't set up, which it won't be if there
792 * weren't any relevant event triggers at the start of the current DDL
793 * command. This test might therefore seem optional, but it's important
794 * because EventTriggerCommonSetup might find triggers that didn't exist
795 * at the time the command started. Although this function itself
796 * wouldn't crash, the event trigger functions would presumably call
797 * pg_event_trigger_ddl_commands which would fail. Better to do nothing
798 * until the next command.
799 */
801 return;
802
804 EVT_DDLCommandEnd, "ddl_command_end",
805 &trigdata, false);
806 if (runlist == NIL)
807 return;
808
809 /*
810 * Make sure anything the main command did will be visible to the event
811 * triggers.
812 */
814
815 /* Run the triggers. */
816 EventTriggerInvoke(runlist, &trigdata);
817
818 /* Cleanup. */
820}
bool event_triggers
static List * EventTriggerCommonSetup(Node *parsetree, EventTriggerEvent event, const char *eventstr, EventTriggerData *trigdata, bool unfiltered)
static void EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
bool IsUnderPostmaster
Definition globals.c:122
void list_free(List *list)
Definition list.c:1546
void CommandCounterIncrement(void)
Definition xact.c:1130

References CommandCounterIncrement(), currentEventTriggerState, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_DDLCommandEnd, fb(), IsUnderPostmaster, list_free(), and NIL.

Referenced by ProcessUtilitySlow().

◆ EventTriggerDDLCommandStart()

void EventTriggerDDLCommandStart ( Node parsetree)

Definition at line 727 of file event_trigger.c.

728{
729 List *runlist;
730 EventTriggerData trigdata;
731
732 /*
733 * Event Triggers are completely disabled in standalone mode. There are
734 * (at least) two reasons for this:
735 *
736 * 1. A sufficiently broken event trigger might not only render the
737 * database unusable, but prevent disabling itself to fix the situation.
738 * In this scenario, restarting in standalone mode provides an escape
739 * hatch.
740 *
741 * 2. BuildEventTriggerCache relies on systable_beginscan_ordered, and
742 * therefore will malfunction if pg_event_trigger's indexes are damaged.
743 * To allow recovery from a damaged index, we need some operating mode
744 * wherein event triggers are disabled. (Or we could implement
745 * heapscan-and-sort logic for that case, but having disaster recovery
746 * scenarios depend on code that's otherwise untested isn't appetizing.)
747 *
748 * Additionally, event triggers can be disabled with a superuser-only GUC
749 * to make fixing database easier as per 1 above.
750 */
752 return;
753
756 "ddl_command_start",
757 &trigdata, false);
758 if (runlist == NIL)
759 return;
760
761 /* Run the triggers. */
762 EventTriggerInvoke(runlist, &trigdata);
763
764 /* Cleanup. */
766
767 /*
768 * Make sure anything the event triggers did will be visible to the main
769 * command.
770 */
772}

References CommandCounterIncrement(), event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_DDLCommandStart, fb(), IsUnderPostmaster, list_free(), and NIL.

Referenced by ProcessUtilitySlow().

◆ EventTriggerEndCompleteQuery()

void EventTriggerEndCompleteQuery ( void  )

Definition at line 1229 of file event_trigger.c.

1230{
1232
1234
1235 /* this avoids the need for retail pfree of SQLDropList items: */
1237
1239}
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
struct EventTriggerQueryState * previous

References currentEventTriggerState, EventTriggerQueryState::cxt, fb(), MemoryContextDelete(), and EventTriggerQueryState::previous.

Referenced by ProcessUtilitySlow().

◆ EventTriggerGetTag()

static CommandTag EventTriggerGetTag ( Node parsetree,
EventTriggerEvent  event 
)
static

Definition at line 626 of file event_trigger.c.

627{
628 if (event == EVT_Login)
629 return CMDTAG_LOGIN;
630 else
631 return CreateCommandTag(parsetree);
632}
CommandTag CreateCommandTag(Node *parsetree)
Definition utility.c:2384

References CreateCommandTag(), EVT_Login, and fb().

Referenced by EventTriggerCommonSetup().

◆ EventTriggerInhibitCommandCollection()

void EventTriggerInhibitCommandCollection ( void  )

◆ EventTriggerInvoke()

static void EventTriggerInvoke ( List fn_oid_list,
EventTriggerData trigdata 
)
static

Definition at line 1070 of file event_trigger.c.

1071{
1072 MemoryContext context;
1073 MemoryContext oldcontext;
1074 ListCell *lc;
1075 bool first = true;
1076
1077 /* Guard against stack overflow due to recursive event trigger */
1079
1080 /*
1081 * Let's evaluate event triggers in their own memory context, so that any
1082 * leaks get cleaned up promptly.
1083 */
1085 "event trigger context",
1087 oldcontext = MemoryContextSwitchTo(context);
1088
1089 /* Call each event trigger. */
1090 foreach(lc, fn_oid_list)
1091 {
1092 LOCAL_FCINFO(fcinfo, 0);
1093 Oid fnoid = lfirst_oid(lc);
1094 FmgrInfo flinfo;
1096
1097 elog(DEBUG1, "EventTriggerInvoke %u", fnoid);
1098
1099 /*
1100 * We want each event trigger to be able to see the results of the
1101 * previous event trigger's action. Caller is responsible for any
1102 * command-counter increment that is needed between the event trigger
1103 * and anything else in the transaction.
1104 */
1105 if (first)
1106 first = false;
1107 else
1109
1110 /* Look up the function */
1111 fmgr_info(fnoid, &flinfo);
1112
1113 /* Call the function, passing no arguments but setting a context. */
1114 InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
1115 InvalidOid, (Node *) trigdata, NULL);
1117 FunctionCallInvoke(fcinfo);
1119
1120 /* Reclaim memory. */
1121 MemoryContextReset(context);
1122 }
1123
1124 /* Restore old memory context and delete the temporary one. */
1125 MemoryContextSwitchTo(oldcontext);
1126 MemoryContextDelete(context);
1127}
#define DEBUG1
Definition elog.h:31
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define lfirst_oid(lc)
Definition pg_list.h:174
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void check_stack_depth(void)
Definition stack_depth.c:95

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, check_stack_depth(), CommandCounterIncrement(), CurrentMemoryContext, DEBUG1, elog, fb(), fmgr_info(), FunctionCallInvoke, InitFunctionCallInfoData, InvalidOid, lfirst_oid, LOCAL_FCINFO, MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), pgstat_end_function_usage(), and pgstat_init_function_usage().

Referenced by EventTriggerDDLCommandEnd(), EventTriggerDDLCommandStart(), EventTriggerOnLogin(), EventTriggerSQLDrop(), and EventTriggerTableRewrite().

◆ EventTriggerOnLogin()

void EventTriggerOnLogin ( void  )

Definition at line 899 of file event_trigger.c.

900{
901 List *runlist;
902 EventTriggerData trigdata;
903
904 /*
905 * See EventTriggerDDLCommandStart for a discussion about why event
906 * triggers are disabled in single user mode or via a GUC. We also need a
907 * database connection (some background workers don't have it).
908 */
911 return;
912
915 EVT_Login, "login",
916 &trigdata, false);
917
918 if (runlist != NIL)
919 {
920 /*
921 * Event trigger execution may require an active snapshot.
922 */
924
925 /* Run the triggers. */
926 EventTriggerInvoke(runlist, &trigdata);
927
928 /* Cleanup. */
930
932 }
933
934 /*
935 * There is no active login event trigger, but our
936 * pg_database.dathasloginevt is set. Try to unset this flag. We use the
937 * lock to prevent concurrent SetDatabaseHasLoginEventTriggers(), but we
938 * don't want to hang the connection waiting on the lock. Thus, we are
939 * just trying to acquire the lock conditionally.
940 */
943 {
944 /*
945 * The lock is held. Now we need to recheck that login event triggers
946 * list is still empty. Once the list is empty, we know that even if
947 * there is a backend which concurrently inserts/enables a login event
948 * trigger, it will update pg_database.dathasloginevt *afterwards*.
949 */
951 EVT_Login, "login",
952 &trigdata, true);
953
954 if (runlist == NIL)
955 {
957 HeapTuple tuple;
958 void *state;
960 ScanKeyData key[1];
961
962 /* Fetch a copy of the tuple to scribble on */
963 ScanKeyInit(&key[0],
967
969 NULL, 1, key, &tuple, &state);
970
971 if (!HeapTupleIsValid(tuple))
972 elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
973
974 db = (Form_pg_database) GETSTRUCT(tuple);
975 if (db->dathasloginevt)
976 {
977 db->dathasloginevt = false;
978
979 /*
980 * Do an "in place" update of the pg_database tuple. Doing
981 * this instead of regular updates serves two purposes. First,
982 * that avoids possible waiting on the row-level lock. Second,
983 * that avoids dealing with TOAST.
984 */
986 }
987 else
990 heap_freetuple(tuple);
991 }
992 else
993 {
995 }
996 }
998}
void systable_inplace_update_cancel(void *state)
Definition genam.c:913
void systable_inplace_update_begin(Relation relation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, const ScanKeyData *key, HeapTuple *oldtupcopy, void **state)
Definition genam.c:818
void systable_inplace_update_finish(void *state, HeapTuple tuple)
Definition genam.c:894
bool MyDatabaseHasLoginEventTriggers
Definition globals.c:100
Oid MyDatabaseId
Definition globals.c:96
bool ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1112
#define AccessExclusiveLock
Definition lockdefs.h:43
END_CATALOG_STRUCT typedef FormData_pg_database * Form_pg_database
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
#define BTEqualStrategyNumber
Definition stratnum.h:31
void StartTransactionCommand(void)
Definition xact.c:3109
void CommitTransactionCommand(void)
Definition xact.c:3207

References AccessExclusiveLock, BTEqualStrategyNumber, CommitTransactionCommand(), ConditionalLockSharedObject(), elog, ERROR, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_Login, fb(), Form_pg_database, GETSTRUCT(), GetTransactionSnapshot(), heap_freetuple(), HeapTupleIsValid, IsUnderPostmaster, list_free(), MyDatabaseHasLoginEventTriggers, MyDatabaseId, NIL, ObjectIdGetDatum(), OidIsValid, PopActiveSnapshot(), PushActiveSnapshot(), RowExclusiveLock, ScanKeyInit(), StartTransactionCommand(), systable_inplace_update_begin(), systable_inplace_update_cancel(), systable_inplace_update_finish(), table_close(), and table_open().

Referenced by PostgresMain().

◆ EventTriggerSQLDrop()

void EventTriggerSQLDrop ( Node parsetree)

Definition at line 826 of file event_trigger.c.

827{
828 List *runlist;
829 EventTriggerData trigdata;
830
831 /*
832 * See EventTriggerDDLCommandStart for a discussion about why event
833 * triggers are disabled in single user mode or via a GUC.
834 */
836 return;
837
838 /*
839 * Use current state to determine whether this event fires at all. If
840 * there are no triggers for the sql_drop event, then we don't have
841 * anything to do here. Note that dropped object collection is disabled
842 * if this is the case, so even if we were to try to run, the list would
843 * be empty.
844 */
847 return;
848
850 EVT_SQLDrop, "sql_drop",
851 &trigdata, false);
852
853 /*
854 * Nothing to do if run list is empty. Note this typically can't happen,
855 * because if there are no sql_drop events, then objects-to-drop wouldn't
856 * have been collected in the first place and we would have quit above.
857 * But it could occur if event triggers were dropped partway through.
858 */
859 if (runlist == NIL)
860 return;
861
862 /*
863 * Make sure anything the main command did will be visible to the event
864 * triggers.
865 */
867
868 /*
869 * Make sure pg_event_trigger_dropped_objects only works when running
870 * these triggers. Use PG_TRY to ensure in_sql_drop is reset even when
871 * one trigger fails. (This is perhaps not necessary, as the currentState
872 * variable will be removed shortly by our caller, but it seems better to
873 * play safe.)
874 */
876
877 /* Run the triggers. */
878 PG_TRY();
879 {
880 EventTriggerInvoke(runlist, &trigdata);
881 }
882 PG_FINALLY();
883 {
885 }
886 PG_END_TRY();
887
888 /* Cleanup. */
890}
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define PG_FINALLY(...)
Definition elog.h:391
static bool slist_is_empty(const slist_head *head)
Definition ilist.h:995

References CommandCounterIncrement(), currentEventTriggerState, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_SQLDrop, fb(), EventTriggerQueryState::in_sql_drop, IsUnderPostmaster, list_free(), NIL, PG_END_TRY, PG_FINALLY, PG_TRY, slist_is_empty(), and EventTriggerQueryState::SQLDropList.

Referenced by ProcessUtilitySlow().

◆ EventTriggerSQLDropAddObject()

void EventTriggerSQLDropAddObject ( const ObjectAddress object,
bool  original,
bool  normal 
)

Definition at line 1279 of file event_trigger.c.

1280{
1281 SQLDropObject *obj;
1283
1285 return;
1286
1288
1290
1292 obj->address = *object;
1293 obj->original = original;
1294 obj->normal = normal;
1295
1296 if (object->classId == NamespaceRelationId)
1297 {
1298 /* Special handling is needed for temp namespaces */
1299 if (isTempNamespace(object->objectId))
1300 obj->istemp = true;
1301 else if (isAnyTempNamespace(object->objectId))
1302 {
1303 /* don't report temp schemas except my own */
1304 pfree(obj);
1306 return;
1307 }
1308 obj->objname = get_namespace_name(object->objectId);
1309 }
1310 else if (object->classId == AttrDefaultRelationId)
1311 {
1312 /* We treat a column default as temp if its table is temp */
1314
1316 if (OidIsValid(colobject.objectId))
1317 {
1319 {
1320 pfree(obj);
1322 return;
1323 }
1324 }
1325 }
1326 else if (object->classId == TriggerRelationId)
1327 {
1328 /* Similarly, a trigger is temp if its table is temp */
1329 /* Sadly, there's no lsyscache.c support for trigger objects */
1331 ScanKeyData skey[1];
1333 HeapTuple tuple;
1334 Oid relid;
1335
1336 /* Fetch the trigger's table OID the hard way */
1338 ScanKeyInit(&skey[0],
1341 ObjectIdGetDatum(object->objectId));
1343 NULL, 1, skey);
1344 tuple = systable_getnext(sscan);
1345 if (HeapTupleIsValid(tuple))
1346 relid = ((Form_pg_trigger) GETSTRUCT(tuple))->tgrelid;
1347 else
1348 relid = InvalidOid; /* shouldn't happen */
1351 /* Do nothing if we didn't find the trigger */
1352 if (OidIsValid(relid))
1353 {
1355
1357 relobject.objectId = relid;
1358 /* Arbitrarily set objectSubId nonzero so as not to fill objname */
1359 relobject.objectSubId = 1;
1361 {
1362 pfree(obj);
1364 return;
1365 }
1366 }
1367 }
1368 else if (object->classId == PolicyRelationId)
1369 {
1370 /* Similarly, a policy is temp if its table is temp */
1371 /* Sadly, there's no lsyscache.c support for policy objects */
1373 ScanKeyData skey[1];
1375 HeapTuple tuple;
1376 Oid relid;
1377
1378 /* Fetch the policy's table OID the hard way */
1380 ScanKeyInit(&skey[0],
1383 ObjectIdGetDatum(object->objectId));
1385 NULL, 1, skey);
1386 tuple = systable_getnext(sscan);
1387 if (HeapTupleIsValid(tuple))
1388 relid = ((Form_pg_policy) GETSTRUCT(tuple))->polrelid;
1389 else
1390 relid = InvalidOid; /* shouldn't happen */
1393 /* Do nothing if we didn't find the policy */
1394 if (OidIsValid(relid))
1395 {
1397
1399 relobject.objectId = relid;
1400 /* Arbitrarily set objectSubId nonzero so as not to fill objname */
1401 relobject.objectSubId = 1;
1403 {
1404 pfree(obj);
1406 return;
1407 }
1408 }
1409 }
1410 else
1411 {
1412 /* Generic handling for all other object classes */
1413 if (!obtain_object_name_namespace(object, obj))
1414 {
1415 /* don't report temp objects except my own */
1416 pfree(obj);
1418 return;
1419 }
1420 }
1421
1422 /* object identity, objname and objargs */
1423 obj->objidentity =
1425 false);
1426
1427 /* object type */
1428 obj->objecttype = getObjectTypeDescription(&obj->address, false);
1429
1431
1433}
static bool obtain_object_name_namespace(const ObjectAddress *object, SQLDropObject *obj)
bool EventTriggerSupportsObject(const ObjectAddress *object)
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
static void slist_push_head(slist_head *head, slist_node *node)
Definition ilist.h:1006
#define AccessShareLock
Definition lockdefs.h:36
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
bool isTempNamespace(Oid namespaceId)
Definition namespace.c:3721
bool isAnyTempNamespace(Oid namespaceId)
Definition namespace.c:3759
char * getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
char * getObjectIdentityParts(const ObjectAddress *object, List **objname, List **objargs, bool missing_ok)
ObjectAddress GetAttrDefaultColumnAddress(Oid attrdefoid)
Definition pg_attrdef.c:322
END_CATALOG_STRUCT typedef FormData_pg_policy * Form_pg_policy
Definition pg_policy.h:55
END_CATALOG_STRUCT typedef FormData_pg_trigger * Form_pg_trigger
Definition pg_trigger.h:84
ObjectAddress address
slist_node next
const char * objidentity
const char * objecttype
const char * objname

References AccessShareLock, SQLDropObject::addrargs, SQLDropObject::address, SQLDropObject::addrnames, Assert, BTEqualStrategyNumber, ObjectAddress::classId, currentEventTriggerState, EventTriggerQueryState::cxt, EventTriggerSupportsObject(), fb(), Form_pg_policy, Form_pg_trigger, get_namespace_name(), GetAttrDefaultColumnAddress(), getObjectIdentityParts(), getObjectTypeDescription(), GETSTRUCT(), HeapTupleIsValid, InvalidOid, isAnyTempNamespace(), SQLDropObject::istemp, isTempNamespace(), MemoryContextSwitchTo(), SQLDropObject::next, SQLDropObject::normal, ObjectAddress::objectId, ObjectIdGetDatum(), SQLDropObject::objecttype, SQLDropObject::objidentity, SQLDropObject::objname, obtain_object_name_namespace(), OidIsValid, SQLDropObject::original, palloc0_object, pfree(), ScanKeyInit(), slist_push_head(), EventTriggerQueryState::SQLDropList, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by deleteObjectsInList(), and DropSubscription().

◆ EventTriggerSupportsObject()

bool EventTriggerSupportsObject ( const ObjectAddress object)

Definition at line 1159 of file event_trigger.c.

1160{
1161 switch (object->classId)
1162 {
1163 case DatabaseRelationId:
1165 case AuthIdRelationId:
1166 case AuthMemRelationId:
1168 /* no support for global objects (except subscriptions) */
1169 return false;
1171 /* no support for event triggers on event triggers */
1172 return false;
1173 default:
1174 return true;
1175 }
1176}

References ObjectAddress::classId, and fb().

Referenced by deleteObjectsInList(), and EventTriggerSQLDropAddObject().

◆ EventTriggerSupportsObjectType()

bool EventTriggerSupportsObjectType ( ObjectType  obtype)

Definition at line 1135 of file event_trigger.c.

1136{
1137 switch (obtype)
1138 {
1139 case OBJECT_DATABASE:
1140 case OBJECT_TABLESPACE:
1141 case OBJECT_ROLE:
1143 /* no support for global objects (except subscriptions) */
1144 return false;
1146 /* no support for event triggers on event triggers */
1147 return false;
1148 default:
1149 return true;
1150 }
1151}
@ OBJECT_TABLESPACE
@ OBJECT_ROLE
@ OBJECT_DATABASE
@ OBJECT_PARAMETER_ACL

References fb(), OBJECT_DATABASE, OBJECT_EVENT_TRIGGER, OBJECT_PARAMETER_ACL, OBJECT_ROLE, and OBJECT_TABLESPACE.

Referenced by ExecGrantStmt_oids(), and standard_ProcessUtility().

◆ EventTriggerTableRewrite()

void EventTriggerTableRewrite ( Node parsetree,
Oid  tableOid,
int  reason 
)

Definition at line 1005 of file event_trigger.c.

1006{
1007 List *runlist;
1008 EventTriggerData trigdata;
1009
1010 /*
1011 * See EventTriggerDDLCommandStart for a discussion about why event
1012 * triggers are disabled in single user mode or via a GUC.
1013 */
1015 return;
1016
1017 /*
1018 * Also do nothing if our state isn't set up, which it won't be if there
1019 * weren't any relevant event triggers at the start of the current DDL
1020 * command. This test might therefore seem optional, but it's
1021 * *necessary*, because EventTriggerCommonSetup might find triggers that
1022 * didn't exist at the time the command started.
1023 */
1025 return;
1026
1027 runlist = EventTriggerCommonSetup(parsetree,
1029 "table_rewrite",
1030 &trigdata, false);
1031 if (runlist == NIL)
1032 return;
1033
1034 /*
1035 * Make sure pg_event_trigger_table_rewrite_oid only works when running
1036 * these triggers. Use PG_TRY to ensure table_rewrite_oid is reset even
1037 * when one trigger fails. (This is perhaps not necessary, as the
1038 * currentState variable will be removed shortly by our caller, but it
1039 * seems better to play safe.)
1040 */
1043
1044 /* Run the triggers. */
1045 PG_TRY();
1046 {
1047 EventTriggerInvoke(runlist, &trigdata);
1048 }
1049 PG_FINALLY();
1050 {
1053 }
1054 PG_END_TRY();
1055
1056 /* Cleanup. */
1058
1059 /*
1060 * Make sure anything the event triggers did will be visible to the main
1061 * command.
1062 */
1064}

References CommandCounterIncrement(), currentEventTriggerState, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_TableRewrite, fb(), InvalidOid, IsUnderPostmaster, list_free(), NIL, PG_END_TRY, PG_FINALLY, PG_TRY, EventTriggerQueryState::table_rewrite_oid, and EventTriggerQueryState::table_rewrite_reason.

Referenced by ATRewriteTables().

◆ EventTriggerUndoInhibitCommandCollection()

void EventTriggerUndoInhibitCommandCollection ( void  )

Definition at line 1695 of file event_trigger.c.

1696{
1698 return;
1699
1701}

References EventTriggerQueryState::commandCollectionInhibited, and currentEventTriggerState.

Referenced by ProcessUtilitySlow().

◆ filter_event_trigger()

static bool filter_event_trigger ( CommandTag  tag,
EventTriggerCacheItem item 
)
static

Definition at line 600 of file event_trigger.c.

601{
602 /*
603 * Filter by session replication role, knowing that we never see disabled
604 * items down here.
605 */
607 {
608 if (item->enabled == TRIGGER_FIRES_ON_ORIGIN)
609 return false;
610 }
611 else
612 {
614 return false;
615 }
616
617 /* Filter by tags, if any were specified. */
618 if (!bms_is_empty(item->tagset) && !bms_is_member(tag, item->tagset))
619 return false;
620
621 /* if we reach that point, we're not filtering out this item */
622 return true;
623}
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
#define bms_is_empty(a)
Definition bitmapset.h:118
Bitmapset * tagset
Definition evtcache.h:33
int SessionReplicationRole
Definition trigger.c:65
#define SESSION_REPLICATION_ROLE_REPLICA
Definition trigger.h:143
#define TRIGGER_FIRES_ON_ORIGIN
Definition trigger.h:151
#define TRIGGER_FIRES_ON_REPLICA
Definition trigger.h:153

References bms_is_empty, bms_is_member(), EventTriggerCacheItem::enabled, SESSION_REPLICATION_ROLE_REPLICA, SessionReplicationRole, EventTriggerCacheItem::tagset, TRIGGER_FIRES_ON_ORIGIN, and TRIGGER_FIRES_ON_REPLICA.

Referenced by EventTriggerCommonSetup().

◆ filter_list_to_array()

static Datum filter_list_to_array ( List filterlist)
static

Definition at line 362 of file event_trigger.c.

363{
364 ListCell *lc;
365 Datum *data;
366 int i = 0,
368
369 data = palloc_array(Datum, l);
370
371 foreach(lc, filterlist)
372 {
373 const char *value = strVal(lfirst(lc));
374 char *result,
375 *p;
376
378 for (p = result; *p; p++)
379 *p = pg_ascii_toupper((unsigned char) *p);
381 pfree(result);
382 }
383
385}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
uint32 result
static struct @177 value
int i
Definition isn.c:77
char * pstrdup(const char *in)
Definition mcxt.c:1781
const void * data
static int list_length(const List *l)
Definition pg_list.h:152
static unsigned char pg_ascii_toupper(unsigned char ch)
Definition port.h:177
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
#define strVal(v)
Definition value.h:82
text * cstring_to_text(const char *s)
Definition varlena.c:184

References construct_array_builtin(), cstring_to_text(), data, fb(), i, lfirst, list_length(), palloc_array, pfree(), pg_ascii_toupper(), PointerGetDatum(), pstrdup(), result, strVal, and value.

Referenced by insert_event_trigger_tuple().

◆ get_event_trigger_oid()

Oid get_event_trigger_oid ( const char trigname,
bool  missing_ok 
)

Definition at line 581 of file event_trigger.c.

582{
583 Oid oid;
584
586 CStringGetDatum(trigname));
587 if (!OidIsValid(oid) && !missing_ok)
590 errmsg("event trigger \"%s\" does not exist", trigname)));
591 return oid;
592}
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition syscache.h:109

References CStringGetDatum(), ereport, errcode(), errmsg, ERROR, fb(), GetSysCacheOid1, and OidIsValid.

Referenced by get_object_address_unqualified().

◆ insert_event_trigger_tuple()

static Oid insert_event_trigger_tuple ( const char trigname,
const char eventname,
Oid  evtOwner,
Oid  funcoid,
List taglist 
)
static

Definition at line 279 of file event_trigger.c.

281{
283 Oid trigoid;
284 HeapTuple tuple;
286 bool nulls[Natts_pg_event_trigger];
291
292 /* Open pg_event_trigger. */
294
295 /* Build the new pg_trigger tuple. */
299 memset(nulls, false, sizeof(nulls));
300 namestrcpy(&evtnamedata, trigname);
302 namestrcpy(&evteventdata, eventname);
308 if (taglist == NIL)
309 nulls[Anum_pg_event_trigger_evttags - 1] = true;
310 else
313
314 /* Insert heap tuple. */
315 tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
317 heap_freetuple(tuple);
318
319 /*
320 * Login event triggers have an additional flag in pg_database to enable
321 * faster lookups in hot codepaths. Set the flag unless already True.
322 */
323 if (strcmp(eventname, "login") == 0)
325
326 /* Depend on owner. */
328
329 /* Depend on event trigger function. */
331 myself.objectId = trigoid;
332 myself.objectSubId = 0;
334 referenced.objectId = funcoid;
335 referenced.objectSubId = 0;
337
338 /* Depend on extension, if any. */
340
341 /* Post creation hook for new event trigger */
343
344 /* Close pg_event_trigger. */
346
347 return trigoid;
348}
static Datum values[MAXATTR]
Definition bootstrap.c:190
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
@ DEPENDENCY_NORMAL
Definition dependency.h:33
static Datum filter_list_to_array(List *filterlist)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
void namestrcpy(Name name, const char *str)
Definition name.c:233
#define InvokeObjectPostCreateHook(classId, objectId, subId)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition pg_depend.c:195
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:393
static Datum CharGetDatum(char X)
Definition postgres.h:132
Definition c.h:830

References CatalogTupleInsert(), CharGetDatum(), DEPENDENCY_NORMAL, fb(), filter_list_to_array(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, NameGetDatum(), namestrcpy(), NIL, ObjectIdGetDatum(), recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, SetDatabaseHasLoginEventTriggers(), table_close(), table_open(), TRIGGER_FIRES_ON_ORIGIN, and values.

Referenced by CreateEventTrigger().

◆ obtain_object_name_namespace()

static bool obtain_object_name_namespace ( const ObjectAddress object,
SQLDropObject obj 
)
static

Definition at line 1442 of file event_trigger.c.

1443{
1444 /*
1445 * Obtain schema names from the object's catalog tuple, if one exists;
1446 * this lets us skip objects in temp schemas. We trust that
1447 * ObjectProperty contains all object classes that can be
1448 * schema-qualified.
1449 *
1450 * Currently, this function does nothing for object classes that are not
1451 * in ObjectProperty, but we might sometime add special cases for that.
1452 */
1453 if (is_objectclass_supported(object->classId))
1454 {
1456 HeapTuple tuple;
1457
1461 object->objectId);
1462
1463 if (tuple)
1464 {
1466 Datum datum;
1467 bool isnull;
1468
1471 {
1472 datum = heap_getattr(tuple, attnum,
1473 RelationGetDescr(catalog), &isnull);
1474 if (!isnull)
1475 {
1477
1479 /* temp objects are only reported if they are my own */
1481 {
1482 obj->schemaname = "pg_temp";
1483 obj->istemp = true;
1484 }
1486 {
1487 /* no need to fill any fields of *obj */
1489 return false;
1490 }
1491 else
1492 {
1494 obj->istemp = false;
1495 }
1496 }
1497 }
1498
1499 if (get_object_namensp_unique(object->classId) &&
1500 object->objectSubId == 0)
1501 {
1504 {
1505 datum = heap_getattr(tuple, attnum,
1506 RelationGetDescr(catalog), &isnull);
1507 if (!isnull)
1508 obj->objname = pstrdup(NameStr(*DatumGetName(datum)));
1509 }
1510 }
1511 }
1512
1514 }
1515
1516 return true;
1517}
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
bool get_object_namensp_unique(Oid class_id)
HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
AttrNumber get_object_attnum_oid(Oid class_id)
AttrNumber get_object_attnum_namespace(Oid class_id)
AttrNumber get_object_attnum_name(Oid class_id)
bool is_objectclass_supported(Oid class_id)
int16 attnum
static Name DatumGetName(Datum X)
Definition postgres.h:380
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
#define RelationGetDescr(relation)
Definition rel.h:542
const char * schemaname

References AccessShareLock, attnum, ObjectAddress::classId, DatumGetName(), DatumGetObjectId(), fb(), get_catalog_object_by_oid(), get_namespace_name(), get_object_attnum_name(), get_object_attnum_namespace(), get_object_attnum_oid(), get_object_namensp_unique(), heap_getattr(), InvalidAttrNumber, is_objectclass_supported(), isAnyTempNamespace(), SQLDropObject::istemp, isTempNamespace(), NameStr, ObjectAddress::objectId, ObjectAddress::objectSubId, SQLDropObject::objname, pstrdup(), RelationGetDescr, SQLDropObject::schemaname, table_close(), and table_open().

Referenced by EventTriggerSQLDropAddObject().

◆ pg_event_trigger_ddl_commands()

Datum pg_event_trigger_ddl_commands ( PG_FUNCTION_ARGS  )

Definition at line 2057 of file event_trigger.c.

2058{
2059 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2060 ListCell *lc;
2061
2062 /*
2063 * Protect this function from being called out of context
2064 */
2066 ereport(ERROR,
2068 errmsg("%s can only be called in an event trigger function",
2069 "pg_event_trigger_ddl_commands()")));
2070
2071 /* Build tuplestore to hold the result rows */
2072 InitMaterializedSRF(fcinfo, 0);
2073
2075 {
2076 CollectedCommand *cmd = lfirst(lc);
2077 Datum values[9];
2078 bool nulls[9] = {0};
2079 ObjectAddress addr;
2080 int i = 0;
2081
2082 /*
2083 * For IF NOT EXISTS commands that attempt to create an existing
2084 * object, the returned OID is Invalid. Don't return anything.
2085 *
2086 * One might think that a viable alternative would be to look up the
2087 * Oid of the existing object and run the deparse with that. But
2088 * since the parse tree might be different from the one that created
2089 * the object in the first place, we might not end up in a consistent
2090 * state anyway.
2091 */
2092 if (cmd->type == SCT_Simple &&
2094 continue;
2095
2096 switch (cmd->type)
2097 {
2098 case SCT_Simple:
2099 case SCT_AlterTable:
2100 case SCT_AlterOpFamily:
2101 case SCT_CreateOpClass:
2102 case SCT_AlterTSConfig:
2103 {
2104 char *identity;
2105 char *type;
2106 char *schema = NULL;
2107
2108 if (cmd->type == SCT_Simple)
2109 addr = cmd->d.simple.address;
2110 else if (cmd->type == SCT_AlterTable)
2111 ObjectAddressSet(addr,
2112 cmd->d.alterTable.classId,
2113 cmd->d.alterTable.objectId);
2114 else if (cmd->type == SCT_AlterOpFamily)
2115 addr = cmd->d.opfam.address;
2116 else if (cmd->type == SCT_CreateOpClass)
2117 addr = cmd->d.createopc.address;
2118 else if (cmd->type == SCT_AlterTSConfig)
2119 addr = cmd->d.atscfg.address;
2120
2121 /*
2122 * If an object was dropped in the same command we may end
2123 * up in a situation where we generated a message but can
2124 * no longer look for the object information, so skip it
2125 * rather than failing. This can happen for example with
2126 * some subcommand combinations of ALTER TABLE.
2127 */
2128 identity = getObjectIdentity(&addr, true);
2129 if (identity == NULL)
2130 continue;
2131
2132 /* The type can never be NULL. */
2133 type = getObjectTypeDescription(&addr, true);
2134
2135 /*
2136 * Obtain schema name, if any ("pg_temp" if a temp
2137 * object). If the object class is not in the supported
2138 * list here, we assume it's a schema-less object type,
2139 * and thus "schema" remains set to NULL.
2140 */
2142 {
2144
2147 {
2151 bool isnull;
2152
2156 addr.objectId);
2158 elog(ERROR, "cache lookup failed for object %u/%u",
2159 addr.classId, addr.objectId);
2160 schema_oid =
2162 RelationGetDescr(catalog), &isnull));
2163 if (isnull)
2164 elog(ERROR,
2165 "invalid null namespace in object %u/%u/%d",
2166 addr.classId, addr.objectId, addr.objectSubId);
2168
2170 }
2171 }
2172
2173 /* classid */
2174 values[i++] = ObjectIdGetDatum(addr.classId);
2175 /* objid */
2176 values[i++] = ObjectIdGetDatum(addr.objectId);
2177 /* objsubid */
2178 values[i++] = Int32GetDatum(addr.objectSubId);
2179 /* command tag */
2181 /* object_type */
2183 /* schema */
2184 if (schema == NULL)
2185 nulls[i++] = true;
2186 else
2187 values[i++] = CStringGetTextDatum(schema);
2188 /* identity */
2189 values[i++] = CStringGetTextDatum(identity);
2190 /* in_extension */
2191 values[i++] = BoolGetDatum(cmd->in_extension);
2192 /* command */
2193 values[i++] = PointerGetDatum(cmd);
2194 }
2195 break;
2196
2198 /* classid */
2199 nulls[i++] = true;
2200 /* objid */
2201 nulls[i++] = true;
2202 /* objsubid */
2203 nulls[i++] = true;
2204 /* command tag */
2206 /* object_type */
2208 /* schema */
2209 nulls[i++] = true;
2210 /* identity */
2211 nulls[i++] = true;
2212 /* in_extension */
2213 values[i++] = BoolGetDatum(cmd->in_extension);
2214 /* command */
2215 values[i++] = PointerGetDatum(cmd);
2216 break;
2217
2218 case SCT_Grant:
2219 /* classid */
2220 nulls[i++] = true;
2221 /* objid */
2222 nulls[i++] = true;
2223 /* objsubid */
2224 nulls[i++] = true;
2225 /* command tag */
2227 "GRANT" : "REVOKE");
2228 /* object_type */
2230 /* schema */
2231 nulls[i++] = true;
2232 /* identity */
2233 nulls[i++] = true;
2234 /* in_extension */
2235 values[i++] = BoolGetDatum(cmd->in_extension);
2236 /* command */
2237 values[i++] = PointerGetDatum(cmd);
2238 break;
2239 }
2240
2241 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2242 values, nulls);
2243 }
2244
2246}
#define CStringGetTextDatum(s)
Definition builtins.h:98
static const char * stringify_adefprivs_objtype(ObjectType objtype)
static const char * stringify_grant_objtype(ObjectType objtype)
#define PG_RETURN_VOID()
Definition fmgr.h:350
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
char * get_namespace_name_or_temp(Oid nspid)
Definition lsyscache.c:3612
char * getObjectIdentity(const ObjectAddress *object, bool missing_ok)
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
ObjectType objtype
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
static const char * CreateCommandName(Node *parsetree)
Definition utility.h:103
const char * type

References AccessShareLock, CollectedCommand::address, CollectedCommand::alterTable, CollectedCommand::atscfg, BoolGetDatum(), ObjectAddress::classId, CollectedCommand::classId, EventTriggerQueryState::commandList, CreateCommandName(), CollectedCommand::createopc, CStringGetTextDatum, currentEventTriggerState, CollectedCommand::d, DatumGetObjectId(), CollectedCommand::defprivs, elog, ereport, errcode(), errmsg, ERROR, fb(), get_catalog_object_by_oid(), get_namespace_name_or_temp(), get_object_attnum_namespace(), get_object_attnum_oid(), getObjectIdentity(), getObjectTypeDescription(), CollectedCommand::grant, heap_getattr(), HeapTupleIsValid, i, CollectedCommand::in_extension, InitMaterializedSRF(), Int32GetDatum(), InvalidAttrNumber, InternalGrant::is_grant, is_objectclass_supported(), CollectedCommand::istmt, lfirst, ObjectAddressSet, ObjectAddress::objectId, CollectedCommand::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, CollectedCommand::objtype, InternalGrant::objtype, OidIsValid, CollectedCommand::opfam, CollectedCommand::parsetree, PG_RETURN_VOID, PointerGetDatum(), RelationGetDescr, SCT_AlterDefaultPrivileges, SCT_AlterOpFamily, SCT_AlterTable, SCT_AlterTSConfig, SCT_CreateOpClass, SCT_Grant, SCT_Simple, CollectedCommand::simple, stringify_adefprivs_objtype(), stringify_grant_objtype(), table_close(), table_open(), tuplestore_putvalues(), type, CollectedCommand::type, and values.

◆ pg_event_trigger_dropped_objects()

Datum pg_event_trigger_dropped_objects ( PG_FUNCTION_ARGS  )

Definition at line 1526 of file event_trigger.c.

1527{
1528 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1529 slist_iter iter;
1530
1531 /*
1532 * Protect this function from being called out of context
1533 */
1536 ereport(ERROR,
1538 errmsg("%s can only be called in a sql_drop event trigger function",
1539 "pg_event_trigger_dropped_objects()")));
1540
1541 /* Build tuplestore to hold the result rows */
1542 InitMaterializedSRF(fcinfo, 0);
1543
1545 {
1546 SQLDropObject *obj;
1547 int i = 0;
1548 Datum values[12] = {0};
1549 bool nulls[12] = {0};
1550
1551 obj = slist_container(SQLDropObject, next, iter.cur);
1552
1553 /* classid */
1555
1556 /* objid */
1558
1559 /* objsubid */
1561
1562 /* original */
1563 values[i++] = BoolGetDatum(obj->original);
1564
1565 /* normal */
1566 values[i++] = BoolGetDatum(obj->normal);
1567
1568 /* is_temporary */
1569 values[i++] = BoolGetDatum(obj->istemp);
1570
1571 /* object_type */
1573
1574 /* schema_name */
1575 if (obj->schemaname)
1577 else
1578 nulls[i++] = true;
1579
1580 /* object_name */
1581 if (obj->objname)
1583 else
1584 nulls[i++] = true;
1585
1586 /* object_identity */
1587 if (obj->objidentity)
1589 else
1590 nulls[i++] = true;
1591
1592 /* address_names and address_args */
1593 if (obj->addrnames)
1594 {
1596
1597 if (obj->addrargs)
1599 else
1601 }
1602 else
1603 {
1604 nulls[i++] = true;
1605 nulls[i++] = true;
1606 }
1607
1608 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
1609 values, nulls);
1610 }
1611
1612 return (Datum) 0;
1613}
ArrayType * construct_empty_array(Oid elmtype)
static int32 next
Definition blutils.c:225
#define slist_container(type, membername, ptr)
Definition ilist.h:1106
#define slist_foreach(iter, lhead)
Definition ilist.h:1132
ArrayType * strlist_to_textarray(List *list)
slist_node * cur
Definition ilist.h:259

References SQLDropObject::addrargs, SQLDropObject::address, SQLDropObject::addrnames, BoolGetDatum(), ObjectAddress::classId, construct_empty_array(), CStringGetTextDatum, slist_iter::cur, currentEventTriggerState, ereport, errcode(), errmsg, ERROR, fb(), i, EventTriggerQueryState::in_sql_drop, InitMaterializedSRF(), Int32GetDatum(), SQLDropObject::istemp, next, SQLDropObject::normal, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, SQLDropObject::objecttype, SQLDropObject::objidentity, SQLDropObject::objname, SQLDropObject::original, PointerGetDatum(), SQLDropObject::schemaname, slist_container, slist_foreach, EventTriggerQueryState::SQLDropList, strlist_to_textarray(), tuplestore_putvalues(), and values.

◆ pg_event_trigger_table_rewrite_oid()

Datum pg_event_trigger_table_rewrite_oid ( PG_FUNCTION_ARGS  )

Definition at line 1622 of file event_trigger.c.

1623{
1624 /*
1625 * Protect this function from being called out of context
1626 */
1629 ereport(ERROR,
1631 errmsg("%s can only be called in a table_rewrite event trigger function",
1632 "pg_event_trigger_table_rewrite_oid()")));
1633
1635}
#define PG_RETURN_OID(x)
Definition fmgr.h:361

References currentEventTriggerState, ereport, errcode(), errmsg, ERROR, fb(), InvalidOid, PG_RETURN_OID, and EventTriggerQueryState::table_rewrite_oid.

◆ pg_event_trigger_table_rewrite_reason()

Datum pg_event_trigger_table_rewrite_reason ( PG_FUNCTION_ARGS  )

Definition at line 1643 of file event_trigger.c.

1644{
1645 /*
1646 * Protect this function from being called out of context
1647 */
1650 ereport(ERROR,
1652 errmsg("%s can only be called in a table_rewrite event trigger function",
1653 "pg_event_trigger_table_rewrite_reason()")));
1654
1656}
#define PG_RETURN_INT32(x)
Definition fmgr.h:355

References currentEventTriggerState, ereport, errcode(), errmsg, ERROR, fb(), PG_RETURN_INT32, and EventTriggerQueryState::table_rewrite_reason.

◆ SetDatabaseHasLoginEventTriggers()

void SetDatabaseHasLoginEventTriggers ( void  )
static

Definition at line 392 of file event_trigger.c.

393{
394 /* Set dathasloginevt flag in pg_database */
398 HeapTuple tuple;
399
400 /*
401 * Use shared lock to prevent a conflict with EventTriggerOnLogin() trying
402 * to reset pg_database.dathasloginevt flag. Note, this lock doesn't
403 * effectively blocks database or other objection. It's just custom lock
404 * tag used to prevent multiple backends changing
405 * pg_database.dathasloginevt flag.
406 */
408
410 if (!HeapTupleIsValid(tuple))
411 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
412 otid = tuple->t_self;
413 db = (Form_pg_database) GETSTRUCT(tuple);
414 if (!db->dathasloginevt)
415 {
416 db->dathasloginevt = true;
417 CatalogTupleUpdate(pg_db, &otid, tuple);
419 }
422 heap_freetuple(tuple);
423}
void UnlockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
Definition lmgr.c:601
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1088
#define InplaceUpdateTupleLock
Definition lockdefs.h:48
ItemPointerData t_self
Definition htup.h:65
HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:400

References AccessExclusiveLock, CatalogTupleUpdate(), CommandCounterIncrement(), elog, ERROR, fb(), Form_pg_database, GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, InplaceUpdateTupleLock, LockSharedObject(), MyDatabaseId, ObjectIdGetDatum(), RowExclusiveLock, SearchSysCacheLockedCopy1(), HeapTupleData::t_self, table_close(), table_open(), and UnlockTuple().

Referenced by AlterEventTrigger(), and insert_event_trigger_tuple().

◆ stringify_adefprivs_objtype()

static const char * stringify_adefprivs_objtype ( ObjectType  objtype)
static

Definition at line 2339 of file event_trigger.c.

2340{
2341 switch (objtype)
2342 {
2343 case OBJECT_COLUMN:
2344 return "COLUMNS";
2345 case OBJECT_TABLE:
2346 return "TABLES";
2347 case OBJECT_SEQUENCE:
2348 return "SEQUENCES";
2349 case OBJECT_DATABASE:
2350 return "DATABASES";
2351 case OBJECT_DOMAIN:
2352 return "DOMAINS";
2353 case OBJECT_FDW:
2354 return "FOREIGN DATA WRAPPERS";
2356 return "FOREIGN SERVERS";
2357 case OBJECT_FUNCTION:
2358 return "FUNCTIONS";
2359 case OBJECT_LANGUAGE:
2360 return "LANGUAGES";
2361 case OBJECT_LARGEOBJECT:
2362 return "LARGE OBJECTS";
2363 case OBJECT_SCHEMA:
2364 return "SCHEMAS";
2365 case OBJECT_PROCEDURE:
2366 return "PROCEDURES";
2367 case OBJECT_ROUTINE:
2368 return "ROUTINES";
2369 case OBJECT_TABLESPACE:
2370 return "TABLESPACES";
2371 case OBJECT_TYPE:
2372 return "TYPES";
2373 /* these currently aren't used */
2375 case OBJECT_AGGREGATE:
2376 case OBJECT_AMOP:
2377 case OBJECT_AMPROC:
2378 case OBJECT_ATTRIBUTE:
2379 case OBJECT_CAST:
2380 case OBJECT_COLLATION:
2381 case OBJECT_CONVERSION:
2382 case OBJECT_DEFAULT:
2383 case OBJECT_DEFACL:
2386 case OBJECT_EXTENSION:
2388 case OBJECT_INDEX:
2389 case OBJECT_MATVIEW:
2390 case OBJECT_OPCLASS:
2391 case OBJECT_OPERATOR:
2392 case OBJECT_OPFAMILY:
2394 case OBJECT_POLICY:
2395 case OBJECT_PROPGRAPH:
2396 case OBJECT_PUBLICATION:
2399 case OBJECT_ROLE:
2400 case OBJECT_RULE:
2404 case OBJECT_TRANSFORM:
2405 case OBJECT_TRIGGER:
2408 case OBJECT_TSPARSER:
2409 case OBJECT_TSTEMPLATE:
2411 case OBJECT_VIEW:
2412 elog(ERROR, "unsupported object type: %d", (int) objtype);
2413 }
2414
2415 return "???"; /* keep compiler quiet */
2416}
@ OBJECT_FDW
@ OBJECT_TSPARSER
@ OBJECT_COLLATION
@ OBJECT_USER_MAPPING
@ OBJECT_PROPGRAPH
@ OBJECT_ACCESS_METHOD
@ OBJECT_OPCLASS
@ OBJECT_DEFACL
@ OBJECT_AGGREGATE
@ OBJECT_MATVIEW
@ OBJECT_SCHEMA
@ OBJECT_POLICY
@ OBJECT_OPERATOR
@ OBJECT_FOREIGN_TABLE
@ OBJECT_TSCONFIGURATION
@ OBJECT_OPFAMILY
@ OBJECT_DOMAIN
@ OBJECT_COLUMN
@ OBJECT_ROUTINE
@ OBJECT_LARGEOBJECT
@ OBJECT_PUBLICATION_NAMESPACE
@ OBJECT_PROCEDURE
@ OBJECT_EXTENSION
@ OBJECT_INDEX
@ OBJECT_DEFAULT
@ OBJECT_SEQUENCE
@ OBJECT_TSTEMPLATE
@ OBJECT_LANGUAGE
@ OBJECT_AMOP
@ OBJECT_PUBLICATION_REL
@ OBJECT_FOREIGN_SERVER
@ OBJECT_TSDICTIONARY
@ OBJECT_ATTRIBUTE
@ OBJECT_PUBLICATION
@ OBJECT_RULE
@ OBJECT_CONVERSION
@ OBJECT_AMPROC
@ OBJECT_TABLE
@ OBJECT_VIEW
@ OBJECT_TYPE
@ OBJECT_FUNCTION
@ OBJECT_TABCONSTRAINT
@ OBJECT_DOMCONSTRAINT
@ OBJECT_SUBSCRIPTION
@ OBJECT_STATISTIC_EXT
@ OBJECT_CAST
@ OBJECT_TRIGGER
@ OBJECT_TRANSFORM

References elog, ERROR, OBJECT_ACCESS_METHOD, OBJECT_AGGREGATE, OBJECT_AMOP, OBJECT_AMPROC, OBJECT_ATTRIBUTE, OBJECT_CAST, OBJECT_COLLATION, OBJECT_COLUMN, OBJECT_CONVERSION, OBJECT_DATABASE, OBJECT_DEFACL, OBJECT_DEFAULT, OBJECT_DOMAIN, OBJECT_DOMCONSTRAINT, OBJECT_EVENT_TRIGGER, OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FOREIGN_TABLE, OBJECT_FUNCTION, OBJECT_INDEX, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_MATVIEW, OBJECT_OPCLASS, OBJECT_OPERATOR, OBJECT_OPFAMILY, OBJECT_PARAMETER_ACL, OBJECT_POLICY, OBJECT_PROCEDURE, OBJECT_PROPGRAPH, OBJECT_PUBLICATION, OBJECT_PUBLICATION_NAMESPACE, OBJECT_PUBLICATION_REL, OBJECT_ROLE, OBJECT_ROUTINE, OBJECT_RULE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_SUBSCRIPTION, OBJECT_TABCONSTRAINT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, OBJECT_TSDICTIONARY, OBJECT_TSPARSER, OBJECT_TSTEMPLATE, OBJECT_TYPE, OBJECT_USER_MAPPING, and OBJECT_VIEW.

Referenced by pg_event_trigger_ddl_commands().

◆ stringify_grant_objtype()

static const char * stringify_grant_objtype ( ObjectType  objtype)
static

Definition at line 2253 of file event_trigger.c.

2254{
2255 switch (objtype)
2256 {
2257 case OBJECT_COLUMN:
2258 return "COLUMN";
2259 case OBJECT_TABLE:
2260 return "TABLE";
2261 case OBJECT_SEQUENCE:
2262 return "SEQUENCE";
2263 case OBJECT_DATABASE:
2264 return "DATABASE";
2265 case OBJECT_DOMAIN:
2266 return "DOMAIN";
2267 case OBJECT_FDW:
2268 return "FOREIGN DATA WRAPPER";
2270 return "FOREIGN SERVER";
2271 case OBJECT_FUNCTION:
2272 return "FUNCTION";
2273 case OBJECT_LANGUAGE:
2274 return "LANGUAGE";
2275 case OBJECT_LARGEOBJECT:
2276 return "LARGE OBJECT";
2277 case OBJECT_SCHEMA:
2278 return "SCHEMA";
2280 return "PARAMETER";
2281 case OBJECT_PROCEDURE:
2282 return "PROCEDURE";
2283 case OBJECT_ROUTINE:
2284 return "ROUTINE";
2285 case OBJECT_TABLESPACE:
2286 return "TABLESPACE";
2287 case OBJECT_TYPE:
2288 return "TYPE";
2289 /* these currently aren't used */
2291 case OBJECT_AGGREGATE:
2292 case OBJECT_AMOP:
2293 case OBJECT_AMPROC:
2294 case OBJECT_ATTRIBUTE:
2295 case OBJECT_CAST:
2296 case OBJECT_COLLATION:
2297 case OBJECT_CONVERSION:
2298 case OBJECT_DEFAULT:
2299 case OBJECT_DEFACL:
2302 case OBJECT_EXTENSION:
2304 case OBJECT_INDEX:
2305 case OBJECT_MATVIEW:
2306 case OBJECT_OPCLASS:
2307 case OBJECT_OPERATOR:
2308 case OBJECT_OPFAMILY:
2309 case OBJECT_POLICY:
2310 case OBJECT_PROPGRAPH:
2311 case OBJECT_PUBLICATION:
2314 case OBJECT_ROLE:
2315 case OBJECT_RULE:
2319 case OBJECT_TRANSFORM:
2320 case OBJECT_TRIGGER:
2323 case OBJECT_TSPARSER:
2324 case OBJECT_TSTEMPLATE:
2326 case OBJECT_VIEW:
2327 elog(ERROR, "unsupported object type: %d", (int) objtype);
2328 }
2329
2330 return "???"; /* keep compiler quiet */
2331}

References elog, ERROR, OBJECT_ACCESS_METHOD, OBJECT_AGGREGATE, OBJECT_AMOP, OBJECT_AMPROC, OBJECT_ATTRIBUTE, OBJECT_CAST, OBJECT_COLLATION, OBJECT_COLUMN, OBJECT_CONVERSION, OBJECT_DATABASE, OBJECT_DEFACL, OBJECT_DEFAULT, OBJECT_DOMAIN, OBJECT_DOMCONSTRAINT, OBJECT_EVENT_TRIGGER, OBJECT_EXTENSION, OBJECT_FDW, OBJECT_FOREIGN_SERVER, OBJECT_FOREIGN_TABLE, OBJECT_FUNCTION, OBJECT_INDEX, OBJECT_LANGUAGE, OBJECT_LARGEOBJECT, OBJECT_MATVIEW, OBJECT_OPCLASS, OBJECT_OPERATOR, OBJECT_OPFAMILY, OBJECT_PARAMETER_ACL, OBJECT_POLICY, OBJECT_PROCEDURE, OBJECT_PROPGRAPH, OBJECT_PUBLICATION, OBJECT_PUBLICATION_NAMESPACE, OBJECT_PUBLICATION_REL, OBJECT_ROLE, OBJECT_ROUTINE, OBJECT_RULE, OBJECT_SCHEMA, OBJECT_SEQUENCE, OBJECT_STATISTIC_EXT, OBJECT_SUBSCRIPTION, OBJECT_TABCONSTRAINT, OBJECT_TABLE, OBJECT_TABLESPACE, OBJECT_TRANSFORM, OBJECT_TRIGGER, OBJECT_TSCONFIGURATION, OBJECT_TSDICTIONARY, OBJECT_TSPARSER, OBJECT_TSTEMPLATE, OBJECT_TYPE, OBJECT_USER_MAPPING, and OBJECT_VIEW.

Referenced by pg_event_trigger_ddl_commands().

◆ trackDroppedObjectsNeeded()

bool trackDroppedObjectsNeeded ( void  )

Definition at line 1247 of file event_trigger.c.

1248{
1249 /*
1250 * true if any sql_drop, table_rewrite, ddl_command_end event trigger
1251 * exists
1252 */
1253 return (EventCacheLookup(EVT_SQLDrop) != NIL) ||
1256}

References EventCacheLookup(), EVT_DDLCommandEnd, EVT_SQLDrop, EVT_TableRewrite, and NIL.

Referenced by deleteObjectsInList(), and EventTriggerBeginCompleteQuery().

◆ validate_ddl_tags()

static void validate_ddl_tags ( const char filtervar,
List taglist 
)
static

Definition at line 218 of file event_trigger.c.

219{
220 ListCell *lc;
221
222 foreach(lc, taglist)
223 {
224 const char *tagstr = strVal(lfirst(lc));
225 CommandTag commandTag = GetCommandTagEnum(tagstr);
226
227 if (commandTag == CMDTAG_UNKNOWN)
230 errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",
231 tagstr, filtervar)));
232 if (!command_tag_event_trigger_ok(commandTag))
235 /* translator: %s represents an SQL statement name */
236 errmsg("event triggers are not supported for %s",
237 tagstr)));
238 }
239}
CommandTag GetCommandTagEnum(const char *commandname)
Definition cmdtag.c:83

References command_tag_event_trigger_ok(), ereport, errcode(), errmsg, ERROR, fb(), GetCommandTagEnum(), lfirst, and strVal.

Referenced by CreateEventTrigger().

◆ validate_table_rewrite_tags()

static void validate_table_rewrite_tags ( const char filtervar,
List taglist 
)
static

Definition at line 245 of file event_trigger.c.

246{
247 ListCell *lc;
248
249 foreach(lc, taglist)
250 {
251 const char *tagstr = strVal(lfirst(lc));
252 CommandTag commandTag = GetCommandTagEnum(tagstr);
253
254 if (!command_tag_table_rewrite_ok(commandTag))
257 /* translator: %s represents an SQL statement name */
258 errmsg("event triggers are not supported for %s",
259 tagstr)));
260 }
261}

References command_tag_table_rewrite_ok(), ereport, errcode(), errmsg, ERROR, fb(), GetCommandTagEnum(), lfirst, and strVal.

Referenced by CreateEventTrigger().

Variable Documentation

◆ currentEventTriggerState

◆ event_triggers