PostgreSQL Source Code  git master
event_trigger.c File Reference
#include "postgres.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_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_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 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 const char * stringify_grant_objtype (ObjectType objtype)
 
static const char * stringify_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, 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)
 
Datum pg_event_trigger_ddl_commands (PG_FUNCTION_ARGS)
 

Variables

static EventTriggerQueryStatecurrentEventTriggerState = NULL
 
bool event_triggers = true
 

Typedef Documentation

◆ EventTriggerQueryState

◆ SQLDropObject

typedef struct SQLDropObject SQLDropObject

Function Documentation

◆ AlterEventTrigger()

Oid AlterEventTrigger ( AlterEventTrigStmt stmt)

Definition at line 423 of file event_trigger.c.

424 {
425  Relation tgrel;
426  HeapTuple tup;
427  Oid trigoid;
428  Form_pg_event_trigger evtForm;
429  char tgenabled = stmt->tgenabled;
430 
431  tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
432 
433  tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
434  CStringGetDatum(stmt->trigname));
435  if (!HeapTupleIsValid(tup))
436  ereport(ERROR,
437  (errcode(ERRCODE_UNDEFINED_OBJECT),
438  errmsg("event trigger \"%s\" does not exist",
439  stmt->trigname)));
440 
441  evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
442  trigoid = evtForm->oid;
443 
444  if (!object_ownercheck(EventTriggerRelationId, trigoid, GetUserId()))
446  stmt->trigname);
447 
448  /* tuple is a copy, so we can modify it below */
449  evtForm->evtenabled = tgenabled;
450 
451  CatalogTupleUpdate(tgrel, &tup->t_self, tup);
452 
453  /*
454  * Login event triggers have an additional flag in pg_database to enable
455  * faster lookups in hot codepaths. Set the flag unless already True.
456  */
457  if (namestrcmp(&evtForm->evtevent, "login") == 0 &&
458  tgenabled != TRIGGER_DISABLED)
460 
461  InvokeObjectPostAlterHook(EventTriggerRelationId,
462  trigoid, 0);
463 
464  /* clean up */
465  heap_freetuple(tup);
467 
468  return trigoid;
469 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2703
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4145
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#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:2272
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: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: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 475 of file event_trigger.c.

476 {
477  Oid evtOid;
478  HeapTuple tup;
479  Form_pg_event_trigger evtForm;
480  Relation rel;
481  ObjectAddress address;
482 
483  rel = table_open(EventTriggerRelationId, RowExclusiveLock);
484 
485  tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(name));
486 
487  if (!HeapTupleIsValid(tup))
488  ereport(ERROR,
489  (errcode(ERRCODE_UNDEFINED_OBJECT),
490  errmsg("event trigger \"%s\" does not exist", name)));
491 
492  evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
493  evtOid = evtForm->oid;
494 
495  AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
496 
497  ObjectAddressSet(address, EventTriggerRelationId, evtOid);
498 
499  heap_freetuple(tup);
500 
502 
503  return address;
504 }
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_internal()

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

Definition at line 535 of file event_trigger.c.

536 {
538 
539  form = (Form_pg_event_trigger) GETSTRUCT(tup);
540 
541  if (form->evtowner == newOwnerId)
542  return;
543 
544  if (!object_ownercheck(EventTriggerRelationId, form->oid, GetUserId()))
546  NameStr(form->evtname));
547 
548  /* New owner must be a superuser */
549  if (!superuser_arg(newOwnerId))
550  ereport(ERROR,
551  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
552  errmsg("permission denied to change owner of event trigger \"%s\"",
553  NameStr(form->evtname)),
554  errhint("The owner of an event trigger must be a superuser.")));
555 
556  form->evtowner = newOwnerId;
557  CatalogTupleUpdate(rel, &tup->t_self, tup);
558 
559  /* Update owner dependency reference */
560  changeDependencyOnOwner(EventTriggerRelationId,
561  form->oid,
562  newOwnerId);
563 
564  InvokeObjectPostAlterHook(EventTriggerRelationId,
565  form->oid, 0);
566 }
#define NameStr(name)
Definition: c.h:737
int errhint(const char *fmt,...)
Definition: elog.c:1317
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:316
bool superuser_arg(Oid roleid)
Definition: superuser.c:56

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

Referenced by AlterEventTriggerOwner(), and AlterEventTriggerOwner_oid().

◆ AlterEventTriggerOwner_oid()

void AlterEventTriggerOwner_oid ( Oid  trigOid,
Oid  newOwnerId 
)

Definition at line 510 of file event_trigger.c.

511 {
512  HeapTuple tup;
513  Relation rel;
514 
515  rel = table_open(EventTriggerRelationId, RowExclusiveLock);
516 
517  tup = SearchSysCacheCopy1(EVENTTRIGGEROID, ObjectIdGetDatum(trigOid));
518 
519  if (!HeapTupleIsValid(tup))
520  ereport(ERROR,
521  (errcode(ERRCODE_UNDEFINED_OBJECT),
522  errmsg("event trigger with OID %u does not exist", trigOid)));
523 
524  AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
525 
526  heap_freetuple(tup);
527 
529 }
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_Owner().

◆ 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 }
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:3594
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2144
#define lfirst(lc)
Definition: pg_list.h:172
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
char * defname
Definition: parsenodes.h:817
Node * arg
Definition: parsenodes.h:818
Definition: pg_list.h:54
bool superuser(void)
Definition: superuser.c:46
HeapTuple SearchSysCache1(int 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(), 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 261 of file event_trigger.c.

262 {
263  ereport(ERROR,
264  (errcode(ERRCODE_SYNTAX_ERROR),
265  errmsg("filter variable \"%s\" specified more than once",
266  defname)));
267 }

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

Referenced by CreateEventTrigger().

◆ EventTriggerAlterTableEnd()

void EventTriggerAlterTableEnd ( void  )

Definition at line 1713 of file event_trigger.c.

1714 {
1715  CollectedCommand *parent;
1716 
1717  /* ignore if event trigger context not set, or collection disabled */
1718  if (!currentEventTriggerState ||
1720  return;
1721 
1723 
1724  /* If no subcommands, don't collect */
1726  {
1727  MemoryContext oldcxt;
1728 
1730 
1734 
1735  MemoryContextSwitchTo(oldcxt);
1736  }
1737  else
1739 
1741 }
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:1521
#define NIL
Definition: pg_list.h:68
MemoryContextSwitchTo(old_ctx)
struct CollectedCommand * parent
union CollectedCommand::@120 d
struct CollectedCommand::@120::@122 alterTable
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 1626 of file event_trigger.c.

1627 {
1628  MemoryContext oldcxt;
1629  CollectedCommand *command;
1630 
1631  /* ignore if event trigger context not set, or collection disabled */
1632  if (!currentEventTriggerState ||
1634  return;
1635 
1637 
1638  command = palloc(sizeof(CollectedCommand));
1639 
1640  command->type = SCT_AlterTable;
1641  command->in_extension = creating_extension;
1642 
1643  command->d.alterTable.classId = RelationRelationId;
1644  command->d.alterTable.objectId = InvalidOid;
1645  command->d.alterTable.subcmds = NIL;
1646  command->parsetree = copyObject(parsetree);
1647 
1650 
1651  MemoryContextSwitchTo(oldcxt);
1652 }
@ SCT_AlterTable
bool creating_extension
Definition: extension.c:73
void * palloc(Size size)
Definition: mcxt.c:1317
#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 1184 of file event_trigger.c.

1185 {
1187  MemoryContext cxt;
1188 
1189  /*
1190  * Currently, sql_drop, table_rewrite, ddl_command_end events are the only
1191  * reason to have event trigger state at all; so if there are none, don't
1192  * install one.
1193  */
1195  return false;
1196 
1198  "event trigger state",
1201  state->cxt = cxt;
1202  slist_init(&(state->SQLDropList));
1203  state->in_sql_drop = false;
1204  state->table_rewrite_oid = InvalidOid;
1205 
1206  state->commandCollectionInhibited = currentEventTriggerState ?
1208  state->currentCommand = NULL;
1209  state->commandList = NIL;
1210  state->previous = currentEventTriggerState;
1212 
1213  return true;
1214 }
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:1181
#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 1897 of file event_trigger.c.

1898 {
1899  MemoryContext oldcxt;
1900  CollectedCommand *command;
1901 
1902  /* ignore if event trigger context not set, or collection disabled */
1903  if (!currentEventTriggerState ||
1905  return;
1906 
1908 
1909  command = palloc0(sizeof(CollectedCommand));
1910  command->type = SCT_AlterDefaultPrivileges;
1911  command->d.defprivs.objtype = stmt->action->objtype;
1912  command->in_extension = creating_extension;
1913  command->parsetree = (Node *) copyObject(stmt);
1914 
1917  MemoryContextSwitchTo(oldcxt);
1918 }
@ SCT_AlterDefaultPrivileges
void * palloc0(Size size)
Definition: mcxt.c:1347
struct CollectedCommand::@120::@127 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 1795 of file event_trigger.c.

1797 {
1798  MemoryContext oldcxt;
1799  CollectedCommand *command;
1800 
1801  /* ignore if event trigger context not set, or collection disabled */
1802  if (!currentEventTriggerState ||
1804  return;
1805 
1807 
1808  command = palloc(sizeof(CollectedCommand));
1809  command->type = SCT_AlterOpFamily;
1810  command->in_extension = creating_extension;
1811  ObjectAddressSet(command->d.opfam.address,
1812  OperatorFamilyRelationId, opfamoid);
1813  command->d.opfam.operators = operators;
1814  command->d.opfam.procedures = procedures;
1815  command->parsetree = (Node *) copyObject(stmt);
1816 
1819 
1820  MemoryContextSwitchTo(oldcxt);
1821 }
@ SCT_AlterOpFamily
struct CollectedCommand::@120::@124 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 1678 of file event_trigger.c.

1679 {
1680  MemoryContext oldcxt;
1682 
1683  /* ignore if event trigger context not set, or collection disabled */
1684  if (!currentEventTriggerState ||
1686  return;
1687 
1688  Assert(IsA(subcmd, AlterTableCmd));
1691 
1693 
1694  newsub = palloc(sizeof(CollectedATSubcmd));
1695  newsub->address = address;
1696  newsub->parsetree = copyObject(subcmd);
1697 
1700 
1701  MemoryContextSwitchTo(oldcxt);
1702 }
#define Assert(condition)
Definition: c.h:849
#define OidIsValid(objectId)
Definition: c.h:766
#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 1862 of file event_trigger.c.

1864 {
1865  MemoryContext oldcxt;
1866  CollectedCommand *command;
1867 
1868  /* ignore if event trigger context not set, or collection disabled */
1869  if (!currentEventTriggerState ||
1871  return;
1872 
1874 
1875  command = palloc0(sizeof(CollectedCommand));
1876  command->type = SCT_AlterTSConfig;
1877  command->in_extension = creating_extension;
1878  ObjectAddressSet(command->d.atscfg.address,
1879  TSConfigRelationId, cfgId);
1880  command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
1881  memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
1882  command->d.atscfg.ndicts = ndicts;
1883  command->parsetree = (Node *) copyObject(stmt);
1884 
1887 
1888  MemoryContextSwitchTo(oldcxt);
1889 }
@ SCT_AlterTSConfig
struct CollectedCommand::@120::@126 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 1828 of file event_trigger.c.

1830 {
1831  MemoryContext oldcxt;
1832  CollectedCommand *command;
1833 
1834  /* ignore if event trigger context not set, or collection disabled */
1835  if (!currentEventTriggerState ||
1837  return;
1838 
1840 
1841  command = palloc0(sizeof(CollectedCommand));
1842  command->type = SCT_CreateOpClass;
1843  command->in_extension = creating_extension;
1844  ObjectAddressSet(command->d.createopc.address,
1845  OperatorClassRelationId, opcoid);
1846  command->d.createopc.operators = operators;
1847  command->d.createopc.procedures = procedures;
1848  command->parsetree = (Node *) copyObject(stmt);
1849 
1852 
1853  MemoryContextSwitchTo(oldcxt);
1854 }
@ SCT_CreateOpClass
struct CollectedCommand::@120::@125 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 1751 of file event_trigger.c.

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

1591 {
1592  MemoryContext oldcxt;
1593  CollectedCommand *command;
1594 
1595  /* ignore if event trigger context not set, or collection disabled */
1596  if (!currentEventTriggerState ||
1598  return;
1599 
1601 
1602  command = palloc(sizeof(CollectedCommand));
1603 
1604  command->type = SCT_Simple;
1605  command->in_extension = creating_extension;
1606 
1607  command->d.simple.address = address;
1608  command->d.simple.secondaryObject = secondaryObject;
1609  command->parsetree = copyObject(parsetree);
1610 
1612  command);
1613 
1614  MemoryContextSwitchTo(oldcxt);
1615 }
@ SCT_Simple
struct CollectedCommand::@120::@121 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().

◆ EventTriggerCommonSetup()

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

Definition at line 634 of file event_trigger.c.

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

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, 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 772 of file event_trigger.c.

773 {
774  List *runlist;
775  EventTriggerData trigdata;
776 
777  /*
778  * See EventTriggerDDLCommandStart for a discussion about why event
779  * triggers are disabled in single user mode or via GUC.
780  */
782  return;
783 
784  /*
785  * Also do nothing if our state isn't set up, which it won't be if there
786  * weren't any relevant event triggers at the start of the current DDL
787  * command. This test might therefore seem optional, but it's important
788  * because EventTriggerCommonSetup might find triggers that didn't exist
789  * at the time the command started. Although this function itself
790  * wouldn't crash, the event trigger functions would presumably call
791  * pg_event_trigger_ddl_commands which would fail. Better to do nothing
792  * until the next command.
793  */
795  return;
796 
797  runlist = EventTriggerCommonSetup(parsetree,
798  EVT_DDLCommandEnd, "ddl_command_end",
799  &trigdata, false);
800  if (runlist == NIL)
801  return;
802 
803  /*
804  * Make sure anything the main command did will be visible to the event
805  * triggers.
806  */
808 
809  /* Run the triggers. */
810  EventTriggerInvoke(runlist, &trigdata);
811 
812  /* Cleanup. */
813  list_free(runlist);
814 }
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)
bool IsUnderPostmaster
Definition: globals.c:119
void list_free(List *list)
Definition: list.c:1546
void CommandCounterIncrement(void)
Definition: xact.c:1099

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

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

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

Referenced by ProcessUtilitySlow().

◆ EventTriggerEndCompleteQuery()

void EventTriggerEndCompleteQuery ( void  )

Definition at line 1228 of file event_trigger.c.

1229 {
1230  EventTriggerQueryState *prevstate;
1231 
1232  prevstate = currentEventTriggerState->previous;
1233 
1234  /* this avoids the need for retail pfree of SQLDropList items: */
1236 
1237  currentEventTriggerState = prevstate;
1238 }
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().

◆ EventTriggerGetTag()

static CommandTag EventTriggerGetTag ( Node parsetree,
EventTriggerEvent  event 
)
static

Definition at line 620 of file event_trigger.c.

621 {
622  if (event == EVT_Login)
623  return CMDTAG_LOGIN;
624  else
625  return CreateCommandTag(parsetree);
626 }
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2359

References CreateCommandTag(), and EVT_Login.

Referenced by EventTriggerCommonSetup().

◆ EventTriggerInhibitCommandCollection()

void EventTriggerInhibitCommandCollection ( void  )

Definition at line 1554 of file event_trigger.c.

1555 {
1557  return;
1558 
1560 }

References EventTriggerQueryState::commandCollectionInhibited, and currentEventTriggerState.

Referenced by ProcessUtilitySlow().

◆ EventTriggerInvoke()

static void EventTriggerInvoke ( List fn_oid_list,
EventTriggerData trigdata 
)
static

Definition at line 1069 of file event_trigger.c.

1070 {
1072  MemoryContext oldcontext;
1073  ListCell *lc;
1074  bool first = true;
1075 
1076  /* Guard against stack overflow due to recursive event trigger */
1078 
1079  /*
1080  * Let's evaluate event triggers in their own memory context, so that any
1081  * leaks get cleaned up promptly.
1082  */
1084  "event trigger context",
1086  oldcontext = MemoryContextSwitchTo(context);
1087 
1088  /* Call each event trigger. */
1089  foreach(lc, fn_oid_list)
1090  {
1091  LOCAL_FCINFO(fcinfo, 0);
1092  Oid fnoid = lfirst_oid(lc);
1093  FmgrInfo flinfo;
1094  PgStat_FunctionCallUsage fcusage;
1095 
1096  elog(DEBUG1, "EventTriggerInvoke %u", fnoid);
1097 
1098  /*
1099  * We want each event trigger to be able to see the results of the
1100  * previous event trigger's action. Caller is responsible for any
1101  * command-counter increment that is needed between the event trigger
1102  * and anything else in the transaction.
1103  */
1104  if (first)
1105  first = false;
1106  else
1108 
1109  /* Look up the function */
1110  fmgr_info(fnoid, &flinfo);
1111 
1112  /* Call the function, passing no arguments but setting a context. */
1113  InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
1114  InvalidOid, (Node *) trigdata, NULL);
1115  pgstat_init_function_usage(fcinfo, &fcusage);
1116  FunctionCallInvoke(fcinfo);
1117  pgstat_end_function_usage(&fcusage, true);
1118 
1119  /* Reclaim memory. */
1121  }
1122 
1123  /* Restore old memory context and delete the temporary one. */
1124  MemoryContextSwitchTo(oldcontext);
1126 }
#define DEBUG1
Definition: elog.h:30
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#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:383
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#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: postgres.c:3564
tree context
Definition: radixtree.h:1835
Definition: fmgr.h:57

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, check_stack_depth(), CommandCounterIncrement(), context, CurrentMemoryContext, DEBUG1, elog, 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 893 of file event_trigger.c.

894 {
895  List *runlist;
896  EventTriggerData trigdata;
897 
898  /*
899  * See EventTriggerDDLCommandStart for a discussion about why event
900  * triggers are disabled in single user mode or via a GUC. We also need a
901  * database connection (some background workers don't have it).
902  */
905  return;
906 
908  runlist = EventTriggerCommonSetup(NULL,
909  EVT_Login, "login",
910  &trigdata, false);
911 
912  if (runlist != NIL)
913  {
914  /*
915  * Event trigger execution may require an active snapshot.
916  */
918 
919  /* Run the triggers. */
920  EventTriggerInvoke(runlist, &trigdata);
921 
922  /* Cleanup. */
923  list_free(runlist);
924 
926  }
927 
928  /*
929  * There is no active login event trigger, but our
930  * pg_database.dathasloginevt is set. Try to unset this flag. We use the
931  * lock to prevent concurrent SetDatabaseHasLoginEventTriggers(), but we
932  * don't want to hang the connection waiting on the lock. Thus, we are
933  * just trying to acquire the lock conditionally.
934  */
935  else if (ConditionalLockSharedObject(DatabaseRelationId, MyDatabaseId,
937  {
938  /*
939  * The lock is held. Now we need to recheck that login event triggers
940  * list is still empty. Once the list is empty, we know that even if
941  * there is a backend which concurrently inserts/enables a login event
942  * trigger, it will update pg_database.dathasloginevt *afterwards*.
943  */
944  runlist = EventTriggerCommonSetup(NULL,
945  EVT_Login, "login",
946  &trigdata, true);
947 
948  if (runlist == NIL)
949  {
950  Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
951  HeapTuple tuple;
952  void *state;
953  Form_pg_database db;
954  ScanKeyData key[1];
955 
956  /* Fetch a copy of the tuple to scribble on */
957  ScanKeyInit(&key[0],
958  Anum_pg_database_oid,
959  BTEqualStrategyNumber, F_OIDEQ,
961 
962  systable_inplace_update_begin(pg_db, DatabaseOidIndexId, true,
963  NULL, 1, key, &tuple, &state);
964 
965  if (!HeapTupleIsValid(tuple))
966  elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
967 
968  db = (Form_pg_database) GETSTRUCT(tuple);
969  if (db->dathasloginevt)
970  {
971  db->dathasloginevt = false;
972 
973  /*
974  * Do an "in place" update of the pg_database tuple. Doing
975  * this instead of regular updates serves two purposes. First,
976  * that avoids possible waiting on the row-level lock. Second,
977  * that avoids dealing with TOAST.
978  *
979  * Changes made by inplace update may be lost due to
980  * concurrent normal updates; see inplace-inval.spec. However,
981  * we are OK with that. The subsequent connections will still
982  * have a chance to set "dathasloginevt" to false.
983  */
985  }
986  else
989  heap_freetuple(tuple);
990  }
991  else
992  {
993  list_free(runlist);
994  }
995  }
997 }
void systable_inplace_update_cancel(void *state)
Definition: genam.c:903
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:806
void systable_inplace_update_finish(void *state, HeapTuple tuple)
Definition: genam.c:884
bool MyDatabaseHasLoginEventTriggers
Definition: globals.c:97
Oid MyDatabaseId
Definition: globals.c:93
bool ConditionalLockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1097
#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:3039
void CommitTransactionCommand(void)
Definition: xact.c:3137

References AccessExclusiveLock, BTEqualStrategyNumber, CommitTransactionCommand(), ConditionalLockSharedObject(), elog, ERROR, event_triggers, EventTriggerCommonSetup(), EventTriggerInvoke(), EVT_Login, GETSTRUCT, GetTransactionSnapshot(), heap_freetuple(), HeapTupleIsValid, IsUnderPostmaster, sort-test::key, 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 820 of file event_trigger.c.

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

1279 {
1280  SQLDropObject *obj;
1281  MemoryContext oldcxt;
1282 
1284  return;
1285 
1287 
1288  /* don't report temp schemas except my own */
1289  if (object->classId == NamespaceRelationId &&
1290  (isAnyTempNamespace(object->objectId) &&
1291  !isTempNamespace(object->objectId)))
1292  return;
1293 
1295 
1296  obj = palloc0(sizeof(SQLDropObject));
1297  obj->address = *object;
1298  obj->original = original;
1299  obj->normal = normal;
1300 
1301  /*
1302  * Obtain schema names from the object's catalog tuple, if one exists;
1303  * this lets us skip objects in temp schemas. We trust that
1304  * ObjectProperty contains all object classes that can be
1305  * schema-qualified.
1306  */
1307  if (is_objectclass_supported(object->classId))
1308  {
1309  Relation catalog;
1310  HeapTuple tuple;
1311 
1312  catalog = table_open(obj->address.classId, AccessShareLock);
1313  tuple = get_catalog_object_by_oid(catalog,
1314  get_object_attnum_oid(object->classId),
1315  obj->address.objectId);
1316 
1317  if (tuple)
1318  {
1320  Datum datum;
1321  bool isnull;
1322 
1324  if (attnum != InvalidAttrNumber)
1325  {
1326  datum = heap_getattr(tuple, attnum,
1327  RelationGetDescr(catalog), &isnull);
1328  if (!isnull)
1329  {
1330  Oid namespaceId;
1331 
1332  namespaceId = DatumGetObjectId(datum);
1333  /* temp objects are only reported if they are my own */
1334  if (isTempNamespace(namespaceId))
1335  {
1336  obj->schemaname = "pg_temp";
1337  obj->istemp = true;
1338  }
1339  else if (isAnyTempNamespace(namespaceId))
1340  {
1341  pfree(obj);
1342  table_close(catalog, AccessShareLock);
1343  MemoryContextSwitchTo(oldcxt);
1344  return;
1345  }
1346  else
1347  {
1348  obj->schemaname = get_namespace_name(namespaceId);
1349  obj->istemp = false;
1350  }
1351  }
1352  }
1353 
1355  obj->address.objectSubId == 0)
1356  {
1358  if (attnum != InvalidAttrNumber)
1359  {
1360  datum = heap_getattr(tuple, attnum,
1361  RelationGetDescr(catalog), &isnull);
1362  if (!isnull)
1363  obj->objname = pstrdup(NameStr(*DatumGetName(datum)));
1364  }
1365  }
1366  }
1367 
1368  table_close(catalog, AccessShareLock);
1369  }
1370  else
1371  {
1372  if (object->classId == NamespaceRelationId &&
1373  isTempNamespace(object->objectId))
1374  obj->istemp = true;
1375  }
1376 
1377  /* object identity, objname and objargs */
1378  obj->objidentity =
1379  getObjectIdentityParts(&obj->address, &obj->addrnames, &obj->addrargs,
1380  false);
1381 
1382  /* object type */
1383  obj->objecttype = getObjectTypeDescription(&obj->address, false);
1384 
1386 
1387  MemoryContextSwitchTo(oldcxt);
1388 }
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
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:1696
bool isTempNamespace(Oid namespaceId)
Definition: namespace.c:3649
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3687
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 1158 of file event_trigger.c.

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

References ObjectAddress::classId.

Referenced by deleteObjectsInList(), and EventTriggerSQLDropAddObject().

◆ EventTriggerSupportsObjectType()

bool EventTriggerSupportsObjectType ( ObjectType  obtype)

Definition at line 1134 of file event_trigger.c.

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

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

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

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

1567 {
1569  return;
1570 
1572 }

References EventTriggerQueryState::commandCollectionInhibited, and currentEventTriggerState.

Referenced by ProcessUtilitySlow().

◆ filter_event_trigger()

static bool filter_event_trigger ( CommandTag  tag,
EventTriggerCacheItem item 
)
static

Definition at line 594 of file event_trigger.c.

595 {
596  /*
597  * Filter by session replication role, knowing that we never see disabled
598  * items down here.
599  */
601  {
602  if (item->enabled == TRIGGER_FIRES_ON_ORIGIN)
603  return false;
604  }
605  else
606  {
607  if (item->enabled == TRIGGER_FIRES_ON_REPLICA)
608  return false;
609  }
610 
611  /* Filter by tags, if any were specified. */
612  if (!bms_is_empty(item->tagset) && !bms_is_member(tag, item->tagset))
613  return false;
614 
615  /* if we reach that point, we're not filtering out this item */
616  return true;
617 }
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:63
#define SESSION_REPLICATION_ROLE_REPLICA
Definition: trigger.h:141
#define TRIGGER_FIRES_ON_ORIGIN
Definition: trigger.h:149
#define TRIGGER_FIRES_ON_REPLICA
Definition: trigger.h:151

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

357 {
358  ListCell *lc;
359  Datum *data;
360  int i = 0,
361  l = list_length(filterlist);
362 
363  data = (Datum *) palloc(l * sizeof(Datum));
364 
365  foreach(lc, filterlist)
366  {
367  const char *value = strVal(lfirst(lc));
368  char *result,
369  *p;
370 
371  result = pstrdup(value);
372  for (p = result; *p; p++)
373  *p = pg_ascii_toupper((unsigned char) *p);
374  data[i++] = PointerGetDatum(cstring_to_text(result));
375  pfree(result);
376  }
377 
378  return PointerGetDatum(construct_array_builtin(data, l, TEXTOID));
379 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
static struct @157 value
int i
Definition: isn.c:73
const void * data
static int list_length(const List *l)
Definition: pg_list.h:152
unsigned char pg_ascii_toupper(unsigned char ch)
Definition: pgstrcasecmp.c:135
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
#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, i, lfirst, list_length(), palloc(), pfree(), pg_ascii_toupper(), PointerGetDatum(), pstrdup(), 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 575 of file event_trigger.c.

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

References CStringGetDatum(), ereport, errcode(), errmsg(), ERROR, 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 273 of file event_trigger.c.

275 {
276  Relation tgrel;
277  Oid trigoid;
278  HeapTuple tuple;
279  Datum values[Natts_pg_trigger];
280  bool nulls[Natts_pg_trigger];
281  NameData evtnamedata,
282  evteventdata;
283  ObjectAddress myself,
284  referenced;
285 
286  /* Open pg_event_trigger. */
287  tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
288 
289  /* Build the new pg_trigger tuple. */
290  trigoid = GetNewOidWithIndex(tgrel, EventTriggerOidIndexId,
291  Anum_pg_event_trigger_oid);
292  values[Anum_pg_event_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
293  memset(nulls, false, sizeof(nulls));
294  namestrcpy(&evtnamedata, trigname);
295  values[Anum_pg_event_trigger_evtname - 1] = NameGetDatum(&evtnamedata);
296  namestrcpy(&evteventdata, eventname);
297  values[Anum_pg_event_trigger_evtevent - 1] = NameGetDatum(&evteventdata);
298  values[Anum_pg_event_trigger_evtowner - 1] = ObjectIdGetDatum(evtOwner);
299  values[Anum_pg_event_trigger_evtfoid - 1] = ObjectIdGetDatum(funcoid);
300  values[Anum_pg_event_trigger_evtenabled - 1] =
302  if (taglist == NIL)
303  nulls[Anum_pg_event_trigger_evttags - 1] = true;
304  else
305  values[Anum_pg_event_trigger_evttags - 1] =
306  filter_list_to_array(taglist);
307 
308  /* Insert heap tuple. */
309  tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
310  CatalogTupleInsert(tgrel, tuple);
311  heap_freetuple(tuple);
312 
313  /*
314  * Login event triggers have an additional flag in pg_database to enable
315  * faster lookups in hot codepaths. Set the flag unless already True.
316  */
317  if (strcmp(eventname, "login") == 0)
319 
320  /* Depend on owner. */
321  recordDependencyOnOwner(EventTriggerRelationId, trigoid, evtOwner);
322 
323  /* Depend on event trigger function. */
324  myself.classId = EventTriggerRelationId;
325  myself.objectId = trigoid;
326  myself.objectSubId = 0;
327  referenced.classId = ProcedureRelationId;
328  referenced.objectId = funcoid;
329  referenced.objectSubId = 0;
330  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
331 
332  /* Depend on extension, if any. */
333  recordDependencyOnCurrentExtension(&myself, false);
334 
335  /* Post creation hook for new event trigger */
336  InvokeObjectPostCreateHook(EventTriggerRelationId, trigoid, 0);
337 
338  /* Close pg_event_trigger. */
340 
341  return trigoid;
342 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
@ 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:1116
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)
Definition: objectaccess.h:173
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:194
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:168
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
static Datum CharGetDatum(char X)
Definition: postgres.h:122
TupleDesc rd_att
Definition: rel.h:112
Definition: c.h:732

References CatalogTupleInsert(), CharGetDatum(), ObjectAddress::classId, DEPENDENCY_NORMAL, filter_list_to_array(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), InvokeObjectPostCreateHook, NameGetDatum(), namestrcpy(), NIL, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), RowExclusiveLock, SetDatabaseHasLoginEventTriggers(), table_close(), table_open(), TRIGGER_FIRES_ON_ORIGIN, and values.

Referenced by CreateEventTrigger().

◆ pg_event_trigger_ddl_commands()

Datum pg_event_trigger_ddl_commands ( PG_FUNCTION_ARGS  )

Definition at line 1925 of file event_trigger.c.

1926 {
1927  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1928  ListCell *lc;
1929 
1930  /*
1931  * Protect this function from being called out of context
1932  */
1934  ereport(ERROR,
1935  (errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1936  errmsg("%s can only be called in an event trigger function",
1937  "pg_event_trigger_ddl_commands()")));
1938 
1939  /* Build tuplestore to hold the result rows */
1940  InitMaterializedSRF(fcinfo, 0);
1941 
1943  {
1944  CollectedCommand *cmd = lfirst(lc);
1945  Datum values[9];
1946  bool nulls[9] = {0};
1947  ObjectAddress addr;
1948  int i = 0;
1949 
1950  /*
1951  * For IF NOT EXISTS commands that attempt to create an existing
1952  * object, the returned OID is Invalid. Don't return anything.
1953  *
1954  * One might think that a viable alternative would be to look up the
1955  * Oid of the existing object and run the deparse with that. But
1956  * since the parse tree might be different from the one that created
1957  * the object in the first place, we might not end up in a consistent
1958  * state anyway.
1959  */
1960  if (cmd->type == SCT_Simple &&
1961  !OidIsValid(cmd->d.simple.address.objectId))
1962  continue;
1963 
1964  switch (cmd->type)
1965  {
1966  case SCT_Simple:
1967  case SCT_AlterTable:
1968  case SCT_AlterOpFamily:
1969  case SCT_CreateOpClass:
1970  case SCT_AlterTSConfig:
1971  {
1972  char *identity;
1973  char *type;
1974  char *schema = NULL;
1975 
1976  if (cmd->type == SCT_Simple)
1977  addr = cmd->d.simple.address;
1978  else if (cmd->type == SCT_AlterTable)
1979  ObjectAddressSet(addr,
1980  cmd->d.alterTable.classId,
1981  cmd->d.alterTable.objectId);
1982  else if (cmd->type == SCT_AlterOpFamily)
1983  addr = cmd->d.opfam.address;
1984  else if (cmd->type == SCT_CreateOpClass)
1985  addr = cmd->d.createopc.address;
1986  else if (cmd->type == SCT_AlterTSConfig)
1987  addr = cmd->d.atscfg.address;
1988 
1989  /*
1990  * If an object was dropped in the same command we may end
1991  * up in a situation where we generated a message but can
1992  * no longer look for the object information, so skip it
1993  * rather than failing. This can happen for example with
1994  * some subcommand combinations of ALTER TABLE.
1995  */
1996  identity = getObjectIdentity(&addr, true);
1997  if (identity == NULL)
1998  continue;
1999 
2000  /* The type can never be NULL. */
2001  type = getObjectTypeDescription(&addr, true);
2002 
2003  /*
2004  * Obtain schema name, if any ("pg_temp" if a temp
2005  * object). If the object class is not in the supported
2006  * list here, we assume it's a schema-less object type,
2007  * and thus "schema" remains set to NULL.
2008  */
2010  {
2011  AttrNumber nspAttnum;
2012 
2013  nspAttnum = get_object_attnum_namespace(addr.classId);
2014  if (nspAttnum != InvalidAttrNumber)
2015  {
2016  Relation catalog;
2017  HeapTuple objtup;
2018  Oid schema_oid;
2019  bool isnull;
2020 
2021  catalog = table_open(addr.classId, AccessShareLock);
2022  objtup = get_catalog_object_by_oid(catalog,
2024  addr.objectId);
2025  if (!HeapTupleIsValid(objtup))
2026  elog(ERROR, "cache lookup failed for object %u/%u",
2027  addr.classId, addr.objectId);
2028  schema_oid =
2029  heap_getattr(objtup, nspAttnum,
2030  RelationGetDescr(catalog), &isnull);
2031  if (isnull)
2032  elog(ERROR,
2033  "invalid null namespace in object %u/%u/%d",
2034  addr.classId, addr.objectId, addr.objectSubId);
2035  schema = get_namespace_name_or_temp(schema_oid);
2036 
2037  table_close(catalog, AccessShareLock);
2038  }
2039  }
2040 
2041  /* classid */
2042  values[i++] = ObjectIdGetDatum(addr.classId);
2043  /* objid */
2044  values[i++] = ObjectIdGetDatum(addr.objectId);
2045  /* objsubid */
2046  values[i++] = Int32GetDatum(addr.objectSubId);
2047  /* command tag */
2049  /* object_type */
2051  /* schema */
2052  if (schema == NULL)
2053  nulls[i++] = true;
2054  else
2055  values[i++] = CStringGetTextDatum(schema);
2056  /* identity */
2057  values[i++] = CStringGetTextDatum(identity);
2058  /* in_extension */
2059  values[i++] = BoolGetDatum(cmd->in_extension);
2060  /* command */
2061  values[i++] = PointerGetDatum(cmd);
2062  }
2063  break;
2064 
2066  /* classid */
2067  nulls[i++] = true;
2068  /* objid */
2069  nulls[i++] = true;
2070  /* objsubid */
2071  nulls[i++] = true;
2072  /* command tag */
2074  /* object_type */
2076  /* schema */
2077  nulls[i++] = true;
2078  /* identity */
2079  nulls[i++] = true;
2080  /* in_extension */
2081  values[i++] = BoolGetDatum(cmd->in_extension);
2082  /* command */
2083  values[i++] = PointerGetDatum(cmd);
2084  break;
2085 
2086  case SCT_Grant:
2087  /* classid */
2088  nulls[i++] = true;
2089  /* objid */
2090  nulls[i++] = true;
2091  /* objsubid */
2092  nulls[i++] = true;
2093  /* command tag */
2094  values[i++] = CStringGetTextDatum(cmd->d.grant.istmt->is_grant ?
2095  "GRANT" : "REVOKE");
2096  /* object_type */
2097  values[i++] = CStringGetTextDatum(stringify_grant_objtype(cmd->d.grant.istmt->objtype));
2098  /* schema */
2099  nulls[i++] = true;
2100  /* identity */
2101  nulls[i++] = true;
2102  /* in_extension */
2103  values[i++] = BoolGetDatum(cmd->in_extension);
2104  /* command */
2105  values[i++] = PointerGetDatum(cmd);
2106  break;
2107  }
2108 
2109  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2110  values, nulls);
2111  }
2112 
2113  PG_RETURN_VOID();
2114 }
#define CStringGetTextDatum(s)
Definition: builtins.h:97
static const char * stringify_adefprivs_objtype(ObjectType objtype)
static const char * stringify_grant_objtype(ObjectType objtype)
#define PG_RETURN_VOID()
Definition: fmgr.h:349
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
char * get_namespace_name_or_temp(Oid nspid)
Definition: lsyscache.c:3390
char * getObjectIdentity(const ObjectAddress *object, bool missing_ok)
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:103
const char * type

References AccessShareLock, CollectedCommand::alterTable, CollectedCommand::atscfg, BoolGetDatum(), ObjectAddress::classId, EventTriggerQueryState::commandList, CreateCommandName(), CollectedCommand::createopc, CStringGetTextDatum, currentEventTriggerState, CollectedCommand::d, CollectedCommand::defprivs, elog, ereport, errcode(), errmsg(), ERROR, 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, if(), CollectedCommand::in_extension, InitMaterializedSRF(), Int32GetDatum(), InvalidAttrNumber, is_objectclass_supported(), lfirst, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, OidIsValid, CollectedCommand::opfam, CollectedCommand::parsetree, PG_RETURN_VOID, PointerGetDatum(), RelationGetDescr, SCT_AlterDefaultPrivileges, SCT_AlterOpFamily, SCT_AlterTable, SCT_AlterTSConfig, SCT_CreateOpClass, SCT_Grant, SCT_Simple, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, 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 1397 of file event_trigger.c.

1398 {
1399  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1400  slist_iter iter;
1401 
1402  /*
1403  * Protect this function from being called out of context
1404  */
1407  ereport(ERROR,
1408  (errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1409  errmsg("%s can only be called in a sql_drop event trigger function",
1410  "pg_event_trigger_dropped_objects()")));
1411 
1412  /* Build tuplestore to hold the result rows */
1413  InitMaterializedSRF(fcinfo, 0);
1414 
1416  {
1417  SQLDropObject *obj;
1418  int i = 0;
1419  Datum values[12] = {0};
1420  bool nulls[12] = {0};
1421 
1422  obj = slist_container(SQLDropObject, next, iter.cur);
1423 
1424  /* classid */
1426 
1427  /* objid */
1429 
1430  /* objsubid */
1432 
1433  /* original */
1434  values[i++] = BoolGetDatum(obj->original);
1435 
1436  /* normal */
1437  values[i++] = BoolGetDatum(obj->normal);
1438 
1439  /* is_temporary */
1440  values[i++] = BoolGetDatum(obj->istemp);
1441 
1442  /* object_type */
1444 
1445  /* schema_name */
1446  if (obj->schemaname)
1448  else
1449  nulls[i++] = true;
1450 
1451  /* object_name */
1452  if (obj->objname)
1453  values[i++] = CStringGetTextDatum(obj->objname);
1454  else
1455  nulls[i++] = true;
1456 
1457  /* object_identity */
1458  if (obj->objidentity)
1460  else
1461  nulls[i++] = true;
1462 
1463  /* address_names and address_args */
1464  if (obj->addrnames)
1465  {
1467 
1468  if (obj->addrargs)
1470  else
1472  }
1473  else
1474  {
1475  nulls[i++] = true;
1476  nulls[i++] = true;
1477  }
1478 
1479  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
1480  values, nulls);
1481  }
1482 
1483  return (Datum) 0;
1484 }
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3580
static int32 next
Definition: blutils.c:222
#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)

References SQLDropObject::addrargs, SQLDropObject::address, SQLDropObject::addrnames, BoolGetDatum(), ObjectAddress::classId, construct_empty_array(), CStringGetTextDatum, currentEventTriggerState, ereport, errcode(), errmsg(), ERROR, i, if(), 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, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, 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 1493 of file event_trigger.c.

1494 {
1495  /*
1496  * Protect this function from being called out of context
1497  */
1498  if (!currentEventTriggerState ||
1500  ereport(ERROR,
1501  (errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1502  errmsg("%s can only be called in a table_rewrite event trigger function",
1503  "pg_event_trigger_table_rewrite_oid()")));
1504 
1506 }
#define PG_RETURN_OID(x)
Definition: fmgr.h:360

References currentEventTriggerState, ereport, errcode(), errmsg(), ERROR, 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 1514 of file event_trigger.c.

1515 {
1516  /*
1517  * Protect this function from being called out of context
1518  */
1519  if (!currentEventTriggerState ||
1521  ereport(ERROR,
1522  (errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1523  errmsg("%s can only be called in a table_rewrite event trigger function",
1524  "pg_event_trigger_table_rewrite_reason()")));
1525 
1527 }
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354

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

◆ SetDatabaseHasLoginEventTriggers()

void SetDatabaseHasLoginEventTriggers ( void  )
static

Definition at line 386 of file event_trigger.c.

387 {
388  /* Set dathasloginevt flag in pg_database */
389  Form_pg_database db;
390  Relation pg_db = table_open(DatabaseRelationId, RowExclusiveLock);
391  ItemPointerData otid;
392  HeapTuple tuple;
393 
394  /*
395  * Use shared lock to prevent a conflict with EventTriggerOnLogin() trying
396  * to reset pg_database.dathasloginevt flag. Note, this lock doesn't
397  * effectively blocks database or other objection. It's just custom lock
398  * tag used to prevent multiple backends changing
399  * pg_database.dathasloginevt flag.
400  */
401  LockSharedObject(DatabaseRelationId, MyDatabaseId, 0, AccessExclusiveLock);
402 
404  if (!HeapTupleIsValid(tuple))
405  elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
406  otid = tuple->t_self;
407  db = (Form_pg_database) GETSTRUCT(tuple);
408  if (!db->dathasloginevt)
409  {
410  db->dathasloginevt = true;
411  CatalogTupleUpdate(pg_db, &otid, tuple);
413  }
414  UnlockTuple(pg_db, &otid, InplaceUpdateTupleLock);
416  heap_freetuple(tuple);
417 }
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1073
void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
Definition: lmgr.c:595
#define InplaceUpdateTupleLock
Definition: lockdefs.h:48
HeapTuple SearchSysCacheLockedCopy1(int cacheId, Datum key1)
Definition: syscache.c:400

References AccessExclusiveLock, CatalogTupleUpdate(), CommandCounterIncrement(), elog, ERROR, 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 2206 of file event_trigger.c.

2207 {
2208  switch (objtype)
2209  {
2210  case OBJECT_COLUMN:
2211  return "COLUMNS";
2212  case OBJECT_TABLE:
2213  return "TABLES";
2214  case OBJECT_SEQUENCE:
2215  return "SEQUENCES";
2216  case OBJECT_DATABASE:
2217  return "DATABASES";
2218  case OBJECT_DOMAIN:
2219  return "DOMAINS";
2220  case OBJECT_FDW:
2221  return "FOREIGN DATA WRAPPERS";
2222  case OBJECT_FOREIGN_SERVER:
2223  return "FOREIGN SERVERS";
2224  case OBJECT_FUNCTION:
2225  return "FUNCTIONS";
2226  case OBJECT_LANGUAGE:
2227  return "LANGUAGES";
2228  case OBJECT_LARGEOBJECT:
2229  return "LARGE OBJECTS";
2230  case OBJECT_SCHEMA:
2231  return "SCHEMAS";
2232  case OBJECT_PROCEDURE:
2233  return "PROCEDURES";
2234  case OBJECT_ROUTINE:
2235  return "ROUTINES";
2236  case OBJECT_TABLESPACE:
2237  return "TABLESPACES";
2238  case OBJECT_TYPE:
2239  return "TYPES";
2240  /* these currently aren't used */
2241  case OBJECT_ACCESS_METHOD:
2242  case OBJECT_AGGREGATE:
2243  case OBJECT_AMOP:
2244  case OBJECT_AMPROC:
2245  case OBJECT_ATTRIBUTE:
2246  case OBJECT_CAST:
2247  case OBJECT_COLLATION:
2248  case OBJECT_CONVERSION:
2249  case OBJECT_DEFAULT:
2250  case OBJECT_DEFACL:
2251  case OBJECT_DOMCONSTRAINT:
2252  case OBJECT_EVENT_TRIGGER:
2253  case OBJECT_EXTENSION:
2254  case OBJECT_FOREIGN_TABLE:
2255  case OBJECT_INDEX:
2256  case OBJECT_MATVIEW:
2257  case OBJECT_OPCLASS:
2258  case OBJECT_OPERATOR:
2259  case OBJECT_OPFAMILY:
2260  case OBJECT_PARAMETER_ACL:
2261  case OBJECT_POLICY:
2262  case OBJECT_PUBLICATION:
2265  case OBJECT_ROLE:
2266  case OBJECT_RULE:
2267  case OBJECT_STATISTIC_EXT:
2268  case OBJECT_SUBSCRIPTION:
2269  case OBJECT_TABCONSTRAINT:
2270  case OBJECT_TRANSFORM:
2271  case OBJECT_TRIGGER:
2273  case OBJECT_TSDICTIONARY:
2274  case OBJECT_TSPARSER:
2275  case OBJECT_TSTEMPLATE:
2276  case OBJECT_USER_MAPPING:
2277  case OBJECT_VIEW:
2278  elog(ERROR, "unsupported object type: %d", (int) objtype);
2279  }
2280 
2281  return "???"; /* keep compiler quiet */
2282 }
@ OBJECT_FDW
Definition: parsenodes.h:2274
@ OBJECT_TSPARSER
Definition: parsenodes.h:2305
@ OBJECT_COLLATION
Definition: parsenodes.h:2265
@ OBJECT_USER_MAPPING
Definition: parsenodes.h:2308
@ OBJECT_ACCESS_METHOD
Definition: parsenodes.h:2258
@ OBJECT_OPCLASS
Definition: parsenodes.h:2282
@ OBJECT_DEFACL
Definition: parsenodes.h:2269
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2259
@ OBJECT_MATVIEW
Definition: parsenodes.h:2281
@ OBJECT_SCHEMA
Definition: parsenodes.h:2294
@ OBJECT_POLICY
Definition: parsenodes.h:2286
@ OBJECT_OPERATOR
Definition: parsenodes.h:2283
@ OBJECT_FOREIGN_TABLE
Definition: parsenodes.h:2276
@ OBJECT_TSCONFIGURATION
Definition: parsenodes.h:2303
@ OBJECT_OPFAMILY
Definition: parsenodes.h:2284
@ OBJECT_DOMAIN
Definition: parsenodes.h:2270
@ OBJECT_COLUMN
Definition: parsenodes.h:2264
@ OBJECT_ROUTINE
Definition: parsenodes.h:2292
@ OBJECT_LARGEOBJECT
Definition: parsenodes.h:2280
@ OBJECT_PUBLICATION_NAMESPACE
Definition: parsenodes.h:2289
@ OBJECT_PROCEDURE
Definition: parsenodes.h:2287
@ OBJECT_EXTENSION
Definition: parsenodes.h:2273
@ OBJECT_INDEX
Definition: parsenodes.h:2278
@ OBJECT_DEFAULT
Definition: parsenodes.h:2268
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2295
@ OBJECT_TSTEMPLATE
Definition: parsenodes.h:2306
@ OBJECT_LANGUAGE
Definition: parsenodes.h:2279
@ OBJECT_AMOP
Definition: parsenodes.h:2260
@ OBJECT_PUBLICATION_REL
Definition: parsenodes.h:2290
@ OBJECT_FOREIGN_SERVER
Definition: parsenodes.h:2275
@ OBJECT_TSDICTIONARY
Definition: parsenodes.h:2304
@ OBJECT_ATTRIBUTE
Definition: parsenodes.h:2262
@ OBJECT_PUBLICATION
Definition: parsenodes.h:2288
@ OBJECT_RULE
Definition: parsenodes.h:2293
@ OBJECT_CONVERSION
Definition: parsenodes.h:2266
@ OBJECT_AMPROC
Definition: parsenodes.h:2261
@ OBJECT_TABLE
Definition: parsenodes.h:2299
@ OBJECT_VIEW
Definition: parsenodes.h:2309
@ OBJECT_TYPE
Definition: parsenodes.h:2307
@ OBJECT_FUNCTION
Definition: parsenodes.h:2277
@ OBJECT_TABCONSTRAINT
Definition: parsenodes.h:2298
@ OBJECT_DOMCONSTRAINT
Definition: parsenodes.h:2271
@ OBJECT_SUBSCRIPTION
Definition: parsenodes.h:2296
@ OBJECT_STATISTIC_EXT
Definition: parsenodes.h:2297
@ OBJECT_CAST
Definition: parsenodes.h:2263
@ OBJECT_TRIGGER
Definition: parsenodes.h:2302
@ OBJECT_TRANSFORM
Definition: parsenodes.h:2301

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_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 2121 of file event_trigger.c.

2122 {
2123  switch (objtype)
2124  {
2125  case OBJECT_COLUMN:
2126  return "COLUMN";
2127  case OBJECT_TABLE:
2128  return "TABLE";
2129  case OBJECT_SEQUENCE:
2130  return "SEQUENCE";
2131  case OBJECT_DATABASE:
2132  return "DATABASE";
2133  case OBJECT_DOMAIN:
2134  return "DOMAIN";
2135  case OBJECT_FDW:
2136  return "FOREIGN DATA WRAPPER";
2137  case OBJECT_FOREIGN_SERVER:
2138  return "FOREIGN SERVER";
2139  case OBJECT_FUNCTION:
2140  return "FUNCTION";
2141  case OBJECT_LANGUAGE:
2142  return "LANGUAGE";
2143  case OBJECT_LARGEOBJECT:
2144  return "LARGE OBJECT";
2145  case OBJECT_SCHEMA:
2146  return "SCHEMA";
2147  case OBJECT_PARAMETER_ACL:
2148  return "PARAMETER";
2149  case OBJECT_PROCEDURE:
2150  return "PROCEDURE";
2151  case OBJECT_ROUTINE:
2152  return "ROUTINE";
2153  case OBJECT_TABLESPACE:
2154  return "TABLESPACE";
2155  case OBJECT_TYPE:
2156  return "TYPE";
2157  /* these currently aren't used */
2158  case OBJECT_ACCESS_METHOD:
2159  case OBJECT_AGGREGATE:
2160  case OBJECT_AMOP:
2161  case OBJECT_AMPROC:
2162  case OBJECT_ATTRIBUTE:
2163  case OBJECT_CAST:
2164  case OBJECT_COLLATION:
2165  case OBJECT_CONVERSION:
2166  case OBJECT_DEFAULT:
2167  case OBJECT_DEFACL:
2168  case OBJECT_DOMCONSTRAINT:
2169  case OBJECT_EVENT_TRIGGER:
2170  case OBJECT_EXTENSION:
2171  case OBJECT_FOREIGN_TABLE:
2172  case OBJECT_INDEX:
2173  case OBJECT_MATVIEW:
2174  case OBJECT_OPCLASS:
2175  case OBJECT_OPERATOR:
2176  case OBJECT_OPFAMILY:
2177  case OBJECT_POLICY:
2178  case OBJECT_PUBLICATION:
2181  case OBJECT_ROLE:
2182  case OBJECT_RULE:
2183  case OBJECT_STATISTIC_EXT:
2184  case OBJECT_SUBSCRIPTION:
2185  case OBJECT_TABCONSTRAINT:
2186  case OBJECT_TRANSFORM:
2187  case OBJECT_TRIGGER:
2189  case OBJECT_TSDICTIONARY:
2190  case OBJECT_TSPARSER:
2191  case OBJECT_TSTEMPLATE:
2192  case OBJECT_USER_MAPPING:
2193  case OBJECT_VIEW:
2194  elog(ERROR, "unsupported object type: %d", (int) objtype);
2195  }
2196 
2197  return "???"; /* keep compiler quiet */
2198 }

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_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 1246 of file event_trigger.c.

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

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

213 {
214  ListCell *lc;
215 
216  foreach(lc, taglist)
217  {
218  const char *tagstr = strVal(lfirst(lc));
219  CommandTag commandTag = GetCommandTagEnum(tagstr);
220 
221  if (commandTag == CMDTAG_UNKNOWN)
222  ereport(ERROR,
223  (errcode(ERRCODE_SYNTAX_ERROR),
224  errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",
225  tagstr, filtervar)));
226  if (!command_tag_event_trigger_ok(commandTag))
227  ereport(ERROR,
228  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
229  /* translator: %s represents an SQL statement name */
230  errmsg("event triggers are not supported for %s",
231  tagstr)));
232  }
233 }
CommandTag GetCommandTagEnum(const char *commandname)
Definition: cmdtag.c:83

References command_tag_event_trigger_ok(), ereport, errcode(), errmsg(), ERROR, 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 239 of file event_trigger.c.

240 {
241  ListCell *lc;
242 
243  foreach(lc, taglist)
244  {
245  const char *tagstr = strVal(lfirst(lc));
246  CommandTag commandTag = GetCommandTagEnum(tagstr);
247 
248  if (!command_tag_table_rewrite_ok(commandTag))
249  ereport(ERROR,
250  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
251  /* translator: %s represents an SQL statement name */
252  errmsg("event triggers are not supported for %s",
253  tagstr)));
254  }
255 }

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

Referenced by CreateEventTrigger().

Variable Documentation

◆ currentEventTriggerState

◆ event_triggers