PostgreSQL Source Code  git master
event_trigger.h File Reference
Include dependency graph for event_trigger.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  EventTriggerData
 

Macros

#define AT_REWRITE_ALTER_PERSISTENCE   0x01
 
#define AT_REWRITE_DEFAULT_VAL   0x02
 
#define AT_REWRITE_COLUMN_REWRITE   0x04
 
#define AT_REWRITE_ACCESS_METHOD   0x08
 
#define CALLED_AS_EVENT_TRIGGER(fcinfo)    ((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))
 

Typedefs

typedef struct EventTriggerData EventTriggerData
 

Functions

Oid CreateEventTrigger (CreateEventTrigStmt *stmt)
 
Oid get_event_trigger_oid (const char *trigname, bool missing_ok)
 
Oid AlterEventTrigger (AlterEventTrigStmt *stmt)
 
ObjectAddress AlterEventTriggerOwner (const char *name, Oid newOwnerId)
 
void AlterEventTriggerOwner_oid (Oid, Oid newOwnerId)
 
bool EventTriggerSupportsObjectType (ObjectType obtype)
 
bool EventTriggerSupportsObject (const ObjectAddress *object)
 
void EventTriggerDDLCommandStart (Node *parsetree)
 
void EventTriggerDDLCommandEnd (Node *parsetree)
 
void EventTriggerSQLDrop (Node *parsetree)
 
void EventTriggerTableRewrite (Node *parsetree, Oid tableOid, int reason)
 
void EventTriggerOnLogin (void)
 
bool EventTriggerBeginCompleteQuery (void)
 
void EventTriggerEndCompleteQuery (void)
 
bool trackDroppedObjectsNeeded (void)
 
void EventTriggerSQLDropAddObject (const ObjectAddress *object, bool original, bool normal)
 
void EventTriggerInhibitCommandCollection (void)
 
void EventTriggerUndoInhibitCommandCollection (void)
 
void EventTriggerCollectSimpleCommand (ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
 
void EventTriggerAlterTableStart (Node *parsetree)
 
void EventTriggerAlterTableRelid (Oid objectId)
 
void EventTriggerCollectAlterTableSubcmd (Node *subcmd, ObjectAddress address)
 
void EventTriggerAlterTableEnd (void)
 
void EventTriggerCollectGrant (InternalGrant *istmt)
 
void EventTriggerCollectAlterOpFam (AlterOpFamilyStmt *stmt, Oid opfamoid, List *operators, List *procedures)
 
void EventTriggerCollectCreateOpClass (CreateOpClassStmt *stmt, Oid opcoid, List *operators, List *procedures)
 
void EventTriggerCollectAlterTSConfig (AlterTSConfigurationStmt *stmt, Oid cfgId, Oid *dictIds, int ndicts)
 
void EventTriggerCollectAlterDefPrivs (AlterDefaultPrivilegesStmt *stmt)
 

Variables

PGDLLIMPORT bool event_triggers
 

Macro Definition Documentation

◆ AT_REWRITE_ACCESS_METHOD

#define AT_REWRITE_ACCESS_METHOD   0x08

Definition at line 37 of file event_trigger.h.

◆ AT_REWRITE_ALTER_PERSISTENCE

#define AT_REWRITE_ALTER_PERSISTENCE   0x01

Definition at line 34 of file event_trigger.h.

◆ AT_REWRITE_COLUMN_REWRITE

#define AT_REWRITE_COLUMN_REWRITE   0x04

Definition at line 36 of file event_trigger.h.

◆ AT_REWRITE_DEFAULT_VAL

#define AT_REWRITE_DEFAULT_VAL   0x02

Definition at line 35 of file event_trigger.h.

◆ CALLED_AS_EVENT_TRIGGER

#define CALLED_AS_EVENT_TRIGGER (   fcinfo)     ((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))

Definition at line 43 of file event_trigger.h.

Typedef Documentation

◆ EventTriggerData

Function Documentation

◆ AlterEventTrigger()

Oid AlterEventTrigger ( AlterEventTrigStmt stmt)

Definition at line 420 of file event_trigger.c.

421 {
422  Relation tgrel;
423  HeapTuple tup;
424  Oid trigoid;
425  Form_pg_event_trigger evtForm;
426  char tgenabled = stmt->tgenabled;
427 
428  tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
429 
430  tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
431  CStringGetDatum(stmt->trigname));
432  if (!HeapTupleIsValid(tup))
433  ereport(ERROR,
434  (errcode(ERRCODE_UNDEFINED_OBJECT),
435  errmsg("event trigger \"%s\" does not exist",
436  stmt->trigname)));
437 
438  evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
439  trigoid = evtForm->oid;
440 
441  if (!object_ownercheck(EventTriggerRelationId, trigoid, GetUserId()))
443  stmt->trigname);
444 
445  /* tuple is a copy, so we can modify it below */
446  evtForm->evtenabled = tgenabled;
447 
448  CatalogTupleUpdate(tgrel, &tup->t_self, tup);
449 
450  /*
451  * Login event triggers have an additional flag in pg_database to enable
452  * faster lookups in hot codepaths. Set the flag unless already True.
453  */
454  if (namestrcmp(&evtForm->evtevent, "login") == 0 &&
455  tgenabled != TRIGGER_DISABLED)
457 
458  InvokeObjectPostAlterHook(EventTriggerRelationId,
459  trigoid, 0);
460 
461  /* clean up */
462  heap_freetuple(tup);
464 
465  return trigoid;
466 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2688
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4130
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static void SetDatabaseHasLoginEventTriggers(void)
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:514
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
@ OBJECT_EVENT_TRIGGER
Definition: parsenodes.h:2277
FormData_pg_event_trigger * Form_pg_event_trigger
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
unsigned int Oid
Definition: postgres_ext.h:31
ItemPointerData t_self
Definition: htup.h:65
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
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:152

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

Referenced by standard_ProcessUtility().

◆ AlterEventTriggerOwner()

ObjectAddress AlterEventTriggerOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 472 of file event_trigger.c.

473 {
474  Oid evtOid;
475  HeapTuple tup;
476  Form_pg_event_trigger evtForm;
477  Relation rel;
478  ObjectAddress address;
479 
480  rel = table_open(EventTriggerRelationId, RowExclusiveLock);
481 
482  tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(name));
483 
484  if (!HeapTupleIsValid(tup))
485  ereport(ERROR,
486  (errcode(ERRCODE_UNDEFINED_OBJECT),
487  errmsg("event trigger \"%s\" does not exist", name)));
488 
489  evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
490  evtOid = evtForm->oid;
491 
492  AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
493 
494  ObjectAddressSet(address, EventTriggerRelationId, evtOid);
495 
496  heap_freetuple(tup);
497 
499 
500  return address;
501 }
static void AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
const char * name

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

Referenced by ExecAlterOwnerStmt().

◆ AlterEventTriggerOwner_oid()

void AlterEventTriggerOwner_oid ( Oid  trigOid,
Oid  newOwnerId 
)

Definition at line 507 of file event_trigger.c.

508 {
509  HeapTuple tup;
510  Relation rel;
511 
512  rel = table_open(EventTriggerRelationId, RowExclusiveLock);
513 
514  tup = SearchSysCacheCopy1(EVENTTRIGGEROID, ObjectIdGetDatum(trigOid));
515 
516  if (!HeapTupleIsValid(tup))
517  ereport(ERROR,
518  (errcode(ERRCODE_UNDEFINED_OBJECT),
519  errmsg("event trigger with OID %u does not exist", trigOid)));
520 
521  AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
522 
523  heap_freetuple(tup);
524 
526 }
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252

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

Referenced by shdepReassignOwned().

◆ CreateEventTrigger()

Oid CreateEventTrigger ( CreateEventTrigStmt stmt)

Definition at line 120 of file event_trigger.c.

121 {
122  HeapTuple tuple;
123  Oid funcoid;
124  Oid funcrettype;
125  Oid evtowner = GetUserId();
126  ListCell *lc;
127  List *tags = NULL;
128 
129  /*
130  * It would be nice to allow database owners or even regular users to do
131  * this, but there are obvious privilege escalation risks which would have
132  * to somehow be plugged first.
133  */
134  if (!superuser())
135  ereport(ERROR,
136  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
137  errmsg("permission denied to create event trigger \"%s\"",
138  stmt->trigname),
139  errhint("Must be superuser to create an event trigger.")));
140 
141  /* Validate event name. */
142  if (strcmp(stmt->eventname, "ddl_command_start") != 0 &&
143  strcmp(stmt->eventname, "ddl_command_end") != 0 &&
144  strcmp(stmt->eventname, "sql_drop") != 0 &&
145  strcmp(stmt->eventname, "login") != 0 &&
146  strcmp(stmt->eventname, "table_rewrite") != 0)
147  ereport(ERROR,
148  (errcode(ERRCODE_SYNTAX_ERROR),
149  errmsg("unrecognized event name \"%s\"",
150  stmt->eventname)));
151 
152  /* Validate filter conditions. */
153  foreach(lc, stmt->whenclause)
154  {
155  DefElem *def = (DefElem *) lfirst(lc);
156 
157  if (strcmp(def->defname, "tag") == 0)
158  {
159  if (tags != NULL)
161  tags = (List *) def->arg;
162  }
163  else
164  ereport(ERROR,
165  (errcode(ERRCODE_SYNTAX_ERROR),
166  errmsg("unrecognized filter variable \"%s\"", def->defname)));
167  }
168 
169  /* Validate tag list, if any. */
170  if ((strcmp(stmt->eventname, "ddl_command_start") == 0 ||
171  strcmp(stmt->eventname, "ddl_command_end") == 0 ||
172  strcmp(stmt->eventname, "sql_drop") == 0)
173  && tags != NULL)
174  validate_ddl_tags("tag", tags);
175  else if (strcmp(stmt->eventname, "table_rewrite") == 0
176  && tags != NULL)
177  validate_table_rewrite_tags("tag", tags);
178  else if (strcmp(stmt->eventname, "login") == 0 && tags != NULL)
179  ereport(ERROR,
180  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
181  errmsg("tag filtering is not supported for login event triggers")));
182 
183  /*
184  * Give user a nice error message if an event trigger of the same name
185  * already exists.
186  */
187  tuple = SearchSysCache1(EVENTTRIGGERNAME, CStringGetDatum(stmt->trigname));
188  if (HeapTupleIsValid(tuple))
189  ereport(ERROR,
191  errmsg("event trigger \"%s\" already exists",
192  stmt->trigname)));
193 
194  /* Find and validate the trigger function. */
195  funcoid = LookupFuncName(stmt->funcname, 0, NULL, false);
196  funcrettype = get_func_rettype(funcoid);
197  if (funcrettype != EVENT_TRIGGEROID)
198  ereport(ERROR,
199  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
200  errmsg("function %s must return type %s",
201  NameListToString(stmt->funcname), "event_trigger")));
202 
203  /* Insert catalog entries. */
204  return insert_event_trigger_tuple(stmt->trigname, stmt->eventname,
205  evtowner, funcoid, tags);
206 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
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:1655
char * NameListToString(const List *names)
Definition: namespace.c:3579
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2143
#define lfirst(lc)
Definition: pg_list.h:172
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
char * defname
Definition: parsenodes.h:815
Node * arg
Definition: parsenodes.h:816
Definition: pg_list.h:54
bool superuser(void)
Definition: superuser.c:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

References DefElem::arg, CStringGetDatum(), DefElem::defname, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, error_duplicate_filter_variable(), 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().

◆ EventTriggerAlterTableEnd()

void EventTriggerAlterTableEnd ( void  )

Definition at line 1715 of file event_trigger.c.

1716 {
1717  CollectedCommand *parent;
1718 
1719  /* ignore if event trigger context not set, or collection disabled */
1720  if (!currentEventTriggerState ||
1722  return;
1723 
1725 
1726  /* If no subcommands, don't collect */
1728  {
1729  MemoryContext oldcxt;
1730 
1732 
1736 
1737  MemoryContextSwitchTo(oldcxt);
1738  }
1739  else
1741 
1743 }
static EventTriggerQueryState * currentEventTriggerState
Definition: event_trigger.c:81
List * lappend(List *list, void *datum)
Definition: list.c:339
void pfree(void *pointer)
Definition: mcxt.c:1520
#define NIL
Definition: pg_list.h:68
MemoryContextSwitchTo(old_ctx)
union CollectedCommand::@118 d
struct CollectedCommand::@118::@120 alterTable
struct CollectedCommand * parent
CollectedCommand * currentCommand
Definition: event_trigger.c:75

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

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

◆ EventTriggerAlterTableRelid()

◆ EventTriggerAlterTableStart()

void EventTriggerAlterTableStart ( Node parsetree)

Definition at line 1628 of file event_trigger.c.

1629 {
1630  MemoryContext oldcxt;
1631  CollectedCommand *command;
1632 
1633  /* ignore if event trigger context not set, or collection disabled */
1634  if (!currentEventTriggerState ||
1636  return;
1637 
1639 
1640  command = palloc(sizeof(CollectedCommand));
1641 
1642  command->type = SCT_AlterTable;
1643  command->in_extension = creating_extension;
1644 
1645  command->d.alterTable.classId = RelationRelationId;
1646  command->d.alterTable.objectId = InvalidOid;
1647  command->d.alterTable.subcmds = NIL;
1648  command->parsetree = copyObject(parsetree);
1649 
1652 
1653  MemoryContextSwitchTo(oldcxt);
1654 }
@ SCT_AlterTable
bool creating_extension
Definition: extension.c:71
void * palloc(Size size)
Definition: mcxt.c:1316
#define copyObject(obj)
Definition: nodes.h:224
#define InvalidOid
Definition: postgres_ext.h:36
CollectedCommandType type

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

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

◆ EventTriggerBeginCompleteQuery()

bool EventTriggerBeginCompleteQuery ( void  )

Definition at line 1186 of file event_trigger.c.

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

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerCollectAlterDefPrivs()

void EventTriggerCollectAlterDefPrivs ( AlterDefaultPrivilegesStmt stmt)

Definition at line 1899 of file event_trigger.c.

1900 {
1901  MemoryContext oldcxt;
1902  CollectedCommand *command;
1903 
1904  /* ignore if event trigger context not set, or collection disabled */
1905  if (!currentEventTriggerState ||
1907  return;
1908 
1910 
1911  command = palloc0(sizeof(CollectedCommand));
1912  command->type = SCT_AlterDefaultPrivileges;
1913  command->d.defprivs.objtype = stmt->action->objtype;
1914  command->in_extension = creating_extension;
1915  command->parsetree = (Node *) copyObject(stmt);
1916 
1919  MemoryContextSwitchTo(oldcxt);
1920 }
@ SCT_AlterDefaultPrivileges
void * palloc0(Size size)
Definition: mcxt.c:1346
struct CollectedCommand::@118::@125 defprivs
Definition: nodes.h:129

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerCollectAlterOpFam()

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

Definition at line 1797 of file event_trigger.c.

1799 {
1800  MemoryContext oldcxt;
1801  CollectedCommand *command;
1802 
1803  /* ignore if event trigger context not set, or collection disabled */
1804  if (!currentEventTriggerState ||
1806  return;
1807 
1809 
1810  command = palloc(sizeof(CollectedCommand));
1811  command->type = SCT_AlterOpFamily;
1812  command->in_extension = creating_extension;
1813  ObjectAddressSet(command->d.opfam.address,
1814  OperatorFamilyRelationId, opfamoid);
1815  command->d.opfam.operators = operators;
1816  command->d.opfam.procedures = procedures;
1817  command->parsetree = (Node *) copyObject(stmt);
1818 
1821 
1822  MemoryContextSwitchTo(oldcxt);
1823 }
@ SCT_AlterOpFamily
struct CollectedCommand::@118::@122 opfam

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

Referenced by AlterOpFamilyAdd(), and AlterOpFamilyDrop().

◆ EventTriggerCollectAlterTableSubcmd()

void EventTriggerCollectAlterTableSubcmd ( Node subcmd,
ObjectAddress  address 
)

Definition at line 1680 of file event_trigger.c.

1681 {
1682  MemoryContext oldcxt;
1684 
1685  /* ignore if event trigger context not set, or collection disabled */
1686  if (!currentEventTriggerState ||
1688  return;
1689 
1690  Assert(IsA(subcmd, AlterTableCmd));
1693 
1695 
1696  newsub = palloc(sizeof(CollectedATSubcmd));
1697  newsub->address = address;
1698  newsub->parsetree = copyObject(subcmd);
1699 
1702 
1703  MemoryContextSwitchTo(oldcxt);
1704 }
#define Assert(condition)
Definition: c.h:858
#define OidIsValid(objectId)
Definition: c.h:775
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
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, IsA, lappend(), MemoryContextSwitchTo(), newsub(), OidIsValid, and palloc().

Referenced by ATExecCmd().

◆ EventTriggerCollectAlterTSConfig()

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

Definition at line 1864 of file event_trigger.c.

1866 {
1867  MemoryContext oldcxt;
1868  CollectedCommand *command;
1869 
1870  /* ignore if event trigger context not set, or collection disabled */
1871  if (!currentEventTriggerState ||
1873  return;
1874 
1876 
1877  command = palloc0(sizeof(CollectedCommand));
1878  command->type = SCT_AlterTSConfig;
1879  command->in_extension = creating_extension;
1880  ObjectAddressSet(command->d.atscfg.address,
1881  TSConfigRelationId, cfgId);
1882  command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
1883  memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
1884  command->d.atscfg.ndicts = ndicts;
1885  command->parsetree = (Node *) copyObject(stmt);
1886 
1889 
1890  MemoryContextSwitchTo(oldcxt);
1891 }
@ SCT_AlterTSConfig
struct CollectedCommand::@118::@124 atscfg

References CollectedCommand::atscfg, EventTriggerQueryState::commandCollectionInhibited, EventTriggerQueryState::commandList, copyObject, creating_extension, currentEventTriggerState, EventTriggerQueryState::cxt, CollectedCommand::d, CollectedCommand::in_extension, lappend(), MemoryContextSwitchTo(), ObjectAddressSet, palloc(), palloc0(), CollectedCommand::parsetree, SCT_AlterTSConfig, stmt, and CollectedCommand::type.

Referenced by DropConfigurationMapping(), and MakeConfigurationMapping().

◆ EventTriggerCollectCreateOpClass()

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

Definition at line 1830 of file event_trigger.c.

1832 {
1833  MemoryContext oldcxt;
1834  CollectedCommand *command;
1835 
1836  /* ignore if event trigger context not set, or collection disabled */
1837  if (!currentEventTriggerState ||
1839  return;
1840 
1842 
1843  command = palloc0(sizeof(CollectedCommand));
1844  command->type = SCT_CreateOpClass;
1845  command->in_extension = creating_extension;
1846  ObjectAddressSet(command->d.createopc.address,
1847  OperatorClassRelationId, opcoid);
1848  command->d.createopc.operators = operators;
1849  command->d.createopc.procedures = procedures;
1850  command->parsetree = (Node *) copyObject(stmt);
1851 
1854 
1855  MemoryContextSwitchTo(oldcxt);
1856 }
@ SCT_CreateOpClass
struct CollectedCommand::@118::@123 createopc

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

Referenced by DefineOpClass().

◆ EventTriggerCollectGrant()

void EventTriggerCollectGrant ( InternalGrant istmt)

Definition at line 1753 of file event_trigger.c.

1754 {
1755  MemoryContext oldcxt;
1756  CollectedCommand *command;
1757  InternalGrant *icopy;
1758  ListCell *cell;
1759 
1760  /* ignore if event trigger context not set, or collection disabled */
1761  if (!currentEventTriggerState ||
1763  return;
1764 
1766 
1767  /*
1768  * This is tedious, but necessary.
1769  */
1770  icopy = palloc(sizeof(InternalGrant));
1771  memcpy(icopy, istmt, sizeof(InternalGrant));
1772  icopy->objects = list_copy(istmt->objects);
1773  icopy->grantees = list_copy(istmt->grantees);
1774  icopy->col_privs = NIL;
1775  foreach(cell, istmt->col_privs)
1776  icopy->col_privs = lappend(icopy->col_privs, copyObject(lfirst(cell)));
1777 
1778  /* Now collect it, using the copied InternalGrant */
1779  command = palloc(sizeof(CollectedCommand));
1780  command->type = SCT_Grant;
1781  command->in_extension = creating_extension;
1782  command->d.grant.istmt = icopy;
1783  command->parsetree = NULL;
1784 
1787 
1788  MemoryContextSwitchTo(oldcxt);
1789 }
@ SCT_Grant
List * list_copy(const List *oldlist)
Definition: list.c:1573
struct CollectedCommand::@118::@121 grant

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

Referenced by ExecGrantStmt_oids().

◆ EventTriggerCollectSimpleCommand()

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

Definition at line 1590 of file event_trigger.c.

1593 {
1594  MemoryContext oldcxt;
1595  CollectedCommand *command;
1596 
1597  /* ignore if event trigger context not set, or collection disabled */
1598  if (!currentEventTriggerState ||
1600  return;
1601 
1603 
1604  command = palloc(sizeof(CollectedCommand));
1605 
1606  command->type = SCT_Simple;
1607  command->in_extension = creating_extension;
1608 
1609  command->d.simple.address = address;
1610  command->d.simple.secondaryObject = secondaryObject;
1611  command->parsetree = copyObject(parsetree);
1612 
1614  command);
1615 
1616  MemoryContextSwitchTo(oldcxt);
1617 }
@ SCT_Simple
struct CollectedCommand::@118::@119 simple

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

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

◆ EventTriggerDDLCommandEnd()

void EventTriggerDDLCommandEnd ( Node parsetree)

Definition at line 769 of file event_trigger.c.

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

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerDDLCommandStart()

void EventTriggerDDLCommandStart ( Node parsetree)

Definition at line 718 of file event_trigger.c.

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

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerEndCompleteQuery()

void EventTriggerEndCompleteQuery ( void  )

Definition at line 1230 of file event_trigger.c.

1231 {
1232  EventTriggerQueryState *prevstate;
1233 
1234  prevstate = currentEventTriggerState->previous;
1235 
1236  /* this avoids the need for retail pfree of SQLDropList items: */
1238 
1239  currentEventTriggerState = prevstate;
1240 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
struct EventTriggerQueryState * previous
Definition: event_trigger.c:78

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerInhibitCommandCollection()

void EventTriggerInhibitCommandCollection ( void  )

Definition at line 1556 of file event_trigger.c.

1557 {
1559  return;
1560 
1562 }

References EventTriggerQueryState::commandCollectionInhibited, and currentEventTriggerState.

Referenced by ProcessUtilitySlow().

◆ EventTriggerOnLogin()

void EventTriggerOnLogin ( void  )

Definition at line 890 of file event_trigger.c.

891 {
892  List *runlist;
893  EventTriggerData trigdata;
894 
895  /*
896  * See EventTriggerDDLCommandStart for a discussion about why event
897  * triggers are disabled in single user mode or via a GUC. We also need a
898  * database connection (some background workers don't have it).
899  */
902  return;
903 
905  runlist = EventTriggerCommonSetup(NULL,
906  EVT_Login, "login",
907  &trigdata, false);
908 
909  if (runlist != NIL)
910  {
911  /*
912  * Event trigger execution may require an active snapshot.
913  */
915 
916  /* Run the triggers. */
917  EventTriggerInvoke(runlist, &trigdata);
918 
919  /* Cleanup. */
920  list_free(runlist);
921 
923  }
924 
925  /*
926  * There is no active login event trigger, but our
927  * pg_database.dathasloginevt is set. Try to unset this flag. We use the
928  * lock to prevent concurrent SetDatabaseHasLoginEventTriggers(), but we
929  * don't want to hang the connection waiting on the lock. Thus, we are
930  * just trying to acquire the lock conditionally.
931  */
932  else if (ConditionalLockSharedObject(DatabaseRelationId, MyDatabaseId,
934  {
935  /*
936  * The lock is held. Now we need to recheck that login event triggers
937  * list is still empty. Once the list is empty, we know that even if
938  * there is a backend which concurrently inserts/enables a login event
939  * trigger, it will update pg_database.dathasloginevt *afterwards*.
940  */
941  runlist = EventTriggerCommonSetup(NULL,
942  EVT_Login, "login",
943  &trigdata, true);
944 
945  if (runlist == NIL)
946  {
947  Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
948  HeapTuple tuple;
949  Form_pg_database db;
950  ScanKeyData key[1];
951  SysScanDesc scan;
952 
953  /*
954  * Get the pg_database tuple to scribble on. Note that this does
955  * not directly rely on the syscache to avoid issues with
956  * flattened toast values for the in-place update.
957  */
958  ScanKeyInit(&key[0],
959  Anum_pg_database_oid,
960  BTEqualStrategyNumber, F_OIDEQ,
962 
963  scan = systable_beginscan(pg_db, DatabaseOidIndexId, true,
964  NULL, 1, key);
965  tuple = systable_getnext(scan);
966  tuple = heap_copytuple(tuple);
967  systable_endscan(scan);
968 
969  if (!HeapTupleIsValid(tuple))
970  elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
971 
972  db = (Form_pg_database) GETSTRUCT(tuple);
973  if (db->dathasloginevt)
974  {
975  db->dathasloginevt = false;
976 
977  /*
978  * Do an "in place" update of the pg_database tuple. Doing
979  * this instead of regular updates serves two purposes. First,
980  * that avoids possible waiting on the row-level lock. Second,
981  * that avoids dealing with TOAST.
982  *
983  * It's known that changes made by heap_inplace_update() may
984  * be lost due to concurrent normal updates. However, we are
985  * OK with that. The subsequent connections will still have a
986  * chance to set "dathasloginevt" to false.
987  */
988  heap_inplace_update(pg_db, tuple);
989  }
991  heap_freetuple(tuple);
992  }
993  else
994  {
995  list_free(runlist);
996  }
997  }
999 }
#define elog(elevel,...)
Definition: elog.h:224
@ EVT_Login
Definition: evtcache.h:26
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:95
Oid MyDatabaseId
Definition: globals.c:91
void heap_inplace_update(Relation relation, HeapTuple tuple)
Definition: heapam.c:6055
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
bool ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1107
#define AccessExclusiveLock
Definition: lockdefs.h:43
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void StartTransactionCommand(void)
Definition: xact.c:2995
void CommitTransactionCommand(void)
Definition: xact.c:3093

References AccessExclusiveLock, BTEqualStrategyNumber, CommitTransactionCommand(), ConditionalLockSharedObject(), elog, ERROR, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_Login, GETSTRUCT, GetTransactionSnapshot(), heap_copytuple(), heap_freetuple(), heap_inplace_update(), HeapTupleIsValid, IsUnderPostmaster, sort-test::key, list_free(), MyDatabaseHasLoginEventTriggers, MyDatabaseId, NIL, ObjectIdGetDatum(), OidIsValid, PopActiveSnapshot(), PushActiveSnapshot(), RowExclusiveLock, ScanKeyInit(), StartTransactionCommand(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by PostgresMain().

◆ EventTriggerSQLDrop()

void EventTriggerSQLDrop ( Node parsetree)

Definition at line 817 of file event_trigger.c.

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

References CommandCounterIncrement(), currentEventTriggerState, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_SQLDrop, 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 1280 of file event_trigger.c.

1281 {
1282  SQLDropObject *obj;
1283  MemoryContext oldcxt;
1284 
1286  return;
1287 
1289 
1290  /* don't report temp schemas except my own */
1291  if (object->classId == NamespaceRelationId &&
1292  (isAnyTempNamespace(object->objectId) &&
1293  !isTempNamespace(object->objectId)))
1294  return;
1295 
1297 
1298  obj = palloc0(sizeof(SQLDropObject));
1299  obj->address = *object;
1300  obj->original = original;
1301  obj->normal = normal;
1302 
1303  /*
1304  * Obtain schema names from the object's catalog tuple, if one exists;
1305  * this lets us skip objects in temp schemas. We trust that
1306  * ObjectProperty contains all object classes that can be
1307  * schema-qualified.
1308  */
1309  if (is_objectclass_supported(object->classId))
1310  {
1311  Relation catalog;
1312  HeapTuple tuple;
1313 
1314  catalog = table_open(obj->address.classId, AccessShareLock);
1315  tuple = get_catalog_object_by_oid(catalog,
1316  get_object_attnum_oid(object->classId),
1317  obj->address.objectId);
1318 
1319  if (tuple)
1320  {
1322  Datum datum;
1323  bool isnull;
1324 
1326  if (attnum != InvalidAttrNumber)
1327  {
1328  datum = heap_getattr(tuple, attnum,
1329  RelationGetDescr(catalog), &isnull);
1330  if (!isnull)
1331  {
1332  Oid namespaceId;
1333 
1334  namespaceId = DatumGetObjectId(datum);
1335  /* temp objects are only reported if they are my own */
1336  if (isTempNamespace(namespaceId))
1337  {
1338  obj->schemaname = "pg_temp";
1339  obj->istemp = true;
1340  }
1341  else if (isAnyTempNamespace(namespaceId))
1342  {
1343  pfree(obj);
1344  table_close(catalog, AccessShareLock);
1345  MemoryContextSwitchTo(oldcxt);
1346  return;
1347  }
1348  else
1349  {
1350  obj->schemaname = get_namespace_name(namespaceId);
1351  obj->istemp = false;
1352  }
1353  }
1354  }
1355 
1357  obj->address.objectSubId == 0)
1358  {
1360  if (attnum != InvalidAttrNumber)
1361  {
1362  datum = heap_getattr(tuple, attnum,
1363  RelationGetDescr(catalog), &isnull);
1364  if (!isnull)
1365  obj->objname = pstrdup(NameStr(*DatumGetName(datum)));
1366  }
1367  }
1368  }
1369 
1370  table_close(catalog, AccessShareLock);
1371  }
1372  else
1373  {
1374  if (object->classId == NamespaceRelationId &&
1375  isTempNamespace(object->objectId))
1376  obj->istemp = true;
1377  }
1378 
1379  /* object identity, objname and objargs */
1380  obj->objidentity =
1381  getObjectIdentityParts(&obj->address, &obj->addrnames, &obj->addrargs,
1382  false);
1383 
1384  /* object type */
1385  obj->objecttype = getObjectTypeDescription(&obj->address, false);
1386 
1388 
1389  MemoryContextSwitchTo(oldcxt);
1390 }
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
#define NameStr(name)
Definition: c.h:746
bool EventTriggerSupportsObject(const ObjectAddress *object)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
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:3366
char * pstrdup(const char *in)
Definition: mcxt.c:1695
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3634
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3672
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)
char * getObjectTypeDescription(const ObjectAddress *object, bool missing_ok)
char * getObjectIdentityParts(const ObjectAddress *object, List **objname, List **objargs, bool missing_ok)
bool is_objectclass_supported(Oid class_id)
int16 attnum
Definition: pg_attribute.h:74
static Name DatumGetName(Datum X)
Definition: postgres.h:360
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
#define RelationGetDescr(relation)
Definition: rel.h:531
ObjectAddress address
Definition: event_trigger.c:89
const char * schemaname
Definition: event_trigger.c:90
slist_node next
Definition: event_trigger.c:99
const char * objidentity
Definition: event_trigger.c:92
const char * objecttype
Definition: event_trigger.c:93
List * addrnames
Definition: event_trigger.c:94
const char * objname
Definition: event_trigger.c:91

References AccessShareLock, SQLDropObject::addrargs, SQLDropObject::address, SQLDropObject::addrnames, Assert, attnum, ObjectAddress::classId, currentEventTriggerState, EventTriggerQueryState::cxt, DatumGetName(), DatumGetObjectId(), EventTriggerSupportsObject(), get_catalog_object_by_oid(), get_namespace_name(), get_object_attnum_name(), get_object_attnum_namespace(), get_object_attnum_oid(), get_object_namensp_unique(), getObjectIdentityParts(), getObjectTypeDescription(), heap_getattr(), InvalidAttrNumber, is_objectclass_supported(), isAnyTempNamespace(), SQLDropObject::istemp, isTempNamespace(), MemoryContextSwitchTo(), NameStr, SQLDropObject::next, SQLDropObject::normal, ObjectAddress::objectId, ObjectAddress::objectSubId, SQLDropObject::objecttype, SQLDropObject::objidentity, SQLDropObject::objname, SQLDropObject::original, palloc0(), pfree(), pstrdup(), RelationGetDescr, SQLDropObject::schemaname, slist_push_head(), EventTriggerQueryState::SQLDropList, table_close(), and table_open().

Referenced by deleteObjectsInList(), and DropSubscription().

◆ EventTriggerSupportsObject()

bool EventTriggerSupportsObject ( const ObjectAddress object)

Definition at line 1160 of file event_trigger.c.

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

References ObjectAddress::classId.

Referenced by deleteObjectsInList(), and EventTriggerSQLDropAddObject().

◆ EventTriggerSupportsObjectType()

bool EventTriggerSupportsObjectType ( ObjectType  obtype)

Definition at line 1136 of file event_trigger.c.

1137 {
1138  switch (obtype)
1139  {
1140  case OBJECT_DATABASE:
1141  case OBJECT_TABLESPACE:
1142  case OBJECT_ROLE:
1143  case OBJECT_PARAMETER_ACL:
1144  /* no support for global objects (except subscriptions) */
1145  return false;
1146  case OBJECT_EVENT_TRIGGER:
1147  /* no support for event triggers on event triggers */
1148  return false;
1149  default:
1150  return true;
1151  }
1152 }
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2305
@ OBJECT_ROLE
Definition: parsenodes.h:2296
@ OBJECT_DATABASE
Definition: parsenodes.h:2272
@ OBJECT_PARAMETER_ACL
Definition: parsenodes.h:2290

References 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 1006 of file event_trigger.c.

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

References CommandCounterIncrement(), currentEventTriggerState, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_TableRewrite, 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 1568 of file event_trigger.c.

1569 {
1571  return;
1572 
1574 }

References EventTriggerQueryState::commandCollectionInhibited, and currentEventTriggerState.

Referenced by ProcessUtilitySlow().

◆ get_event_trigger_oid()

Oid get_event_trigger_oid ( const char *  trigname,
bool  missing_ok 
)

Definition at line 572 of file event_trigger.c.

573 {
574  Oid oid;
575 
576  oid = GetSysCacheOid1(EVENTTRIGGERNAME, Anum_pg_event_trigger_oid,
577  CStringGetDatum(trigname));
578  if (!OidIsValid(oid) && !missing_ok)
579  ereport(ERROR,
580  (errcode(ERRCODE_UNDEFINED_OBJECT),
581  errmsg("event trigger \"%s\" does not exist", trigname)));
582  return oid;
583 }
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition: syscache.h:104

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

Referenced by get_object_address_unqualified().

◆ trackDroppedObjectsNeeded()

bool trackDroppedObjectsNeeded ( void  )

Definition at line 1248 of file event_trigger.c.

1249 {
1250  /*
1251  * true if any sql_drop, table_rewrite, ddl_command_end event trigger
1252  * exists
1253  */
1254  return (EventCacheLookup(EVT_SQLDrop) != NIL) ||
1257 }
List * EventCacheLookup(EventTriggerEvent event)
Definition: evtcache.c:63

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

Referenced by deleteObjectsInList(), and EventTriggerBeginCompleteQuery().

Variable Documentation

◆ event_triggers