1 /*-------------------------------------------------------------------------
2  *
3  * event_trigger.c
4  *	  PostgreSQL EVENT TRIGGER support code.
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *	  src/backend/commands/event_trigger.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include "access/htup_details.h"
17 #include "access/table.h"
18 #include "access/xact.h"
19 #include "catalog/catalog.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/objectaccess.h"
23 #include "catalog/pg_event_trigger.h"
24 #include "catalog/pg_namespace.h"
25 #include "catalog/pg_opclass.h"
26 #include "catalog/pg_opfamily.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_trigger.h"
29 #include "catalog/pg_ts_config.h"
30 #include "catalog/pg_type.h"
31 #include "commands/dbcommands.h"
32 #include "commands/event_trigger.h"
33 #include "commands/extension.h"
34 #include "commands/trigger.h"
35 #include "funcapi.h"
36 #include "parser/parse_func.h"
37 #include "pgstat.h"
38 #include "lib/ilist.h"
newInstance(String key)39 #include "miscadmin.h"
40 #include "tcop/deparse_utility.h"
41 #include "utils/acl.h"
42 #include "utils/builtins.h"
43 #include "utils/evtcache.h"
44 #include "utils/fmgroids.h"
45 #include "utils/lsyscache.h"
46 #include "utils/memutils.h"
47 #include "utils/rel.h"
48 #include "utils/syscache.h"
49 #include "tcop/utility.h"
50 
51 typedef struct EventTriggerQueryState
52 {
53 	/* memory context for this state's objects */
54 	MemoryContext cxt;
55 
56 	/* sql_drop */
57 	slist_head	SQLDropList;
58 	bool		in_sql_drop;
59 
60 	/* table_rewrite */
61 	Oid			table_rewrite_oid;	/* InvalidOid, or set for table_rewrite
62 									 * event */
63 	int			table_rewrite_reason;	/* AT_REWRITE reason */
64 
65 	/* Support for command collection */
66 	bool		commandCollectionInhibited;
67 	CollectedCommand *currentCommand;
68 	List	   *commandList;	/* list of CollectedCommand; see
69 								 * deparse_utility.h */
70 	struct EventTriggerQueryState *previous;
71 } EventTriggerQueryState;
72 
73 static EventTriggerQueryState *currentEventTriggerState = NULL;
74 
75 typedef struct
76 {
77 	const char *obtypename;
78 	bool		supported;
onBindDialogView(View view)79 } event_trigger_support_data;
80 
81 typedef enum
82 {
83 	EVENT_TRIGGER_COMMAND_TAG_OK,
84 	EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED,
85 	EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED
86 } event_trigger_command_tag_check_result;
87 
88 /* XXX merge this with ObjectTypeMap? */
89 static const event_trigger_support_data event_trigger_support[] = {
90 	{"ACCESS METHOD", true},
91 	{"AGGREGATE", true},
92 	{"CAST", true},
93 	{"CONSTRAINT", true},
94 	{"COLLATION", true},
95 	{"CONVERSION", true},
onPrepareDialogBuilder(AlertDialog.Builder builder)96 	{"DATABASE", false},
97 	{"DOMAIN", true},
98 	{"EXTENSION", true},
99 	{"EVENT TRIGGER", false},
100 	{"FOREIGN DATA WRAPPER", true},
101 	{"FOREIGN TABLE", true},
102 	{"FUNCTION", true},
103 	{"INDEX", true},
onDialogClosed(boolean positiveResult)104 	{"LANGUAGE", true},
105 	{"MATERIALIZED VIEW", true},
106 	{"OPERATOR", true},
107 	{"OPERATOR CLASS", true},
108 	{"OPERATOR FAMILY", true},
onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)109 	{"POLICY", true},
110 	{"PROCEDURE", true},
111 	{"PUBLICATION", true},
112 	{"ROLE", false},
113 	{"ROUTINE", true},
114 	{"RULE", true},
115 	{"SCHEMA", true},
116 	{"SEQUENCE", true},
onStartTrackingTouch(SeekBar seekBar)117 	{"SERVER", true},
118 	{"STATISTICS", true},
119 	{"SUBSCRIPTION", true},
120 	{"TABLE", true},
121 	{"TABLESPACE", false},
onStopTrackingTouch(SeekBar seekBar)122 	{"TRANSFORM", true},
123 	{"TRIGGER", true},
124 	{"TEXT SEARCH CONFIGURATION", true},
125 	{"TEXT SEARCH DICTIONARY", true},
126 	{"TEXT SEARCH PARSER", true},
onClick(View view)127 	{"TEXT SEARCH TEMPLATE", true},
128 	{"TYPE", true},
129 	{"USER MAPPING", true},
130 	{"VIEW", true},
131 	{NULL, false}
132 };
133 
134 /* Support for dropped objects */
135 typedef struct SQLDropObject
136 {
137 	ObjectAddress address;
138 	const char *schemaname;
139 	const char *objname;
140 	const char *objidentity;
141 	const char *objecttype;
142 	List	   *addrnames;
143 	List	   *addrargs;
144 	bool		original;
145 	bool		normal;
146 	bool		istemp;
syncButtonStates(int progress)147 	slist_node	next;
148 } SQLDropObject;
149 
150 static void AlterEventTriggerOwner_internal(Relation rel,
151 											HeapTuple tup,
152 											Oid newOwnerId);
153 static event_trigger_command_tag_check_result check_ddl_tag(const char *tag);
154 static event_trigger_command_tag_check_result check_table_rewrite_ddl_tag(const char *tag);
155 static void error_duplicate_filter_variable(const char *defname);
156 static Datum filter_list_to_array(List *filterlist);
157 static Oid	insert_event_trigger_tuple(const char *trigname, const char *eventname,
158 									   Oid evtOwner, Oid funcoid, List *tags);
159 static void validate_ddl_tags(const char *filtervar, List *taglist);
160 static void validate_table_rewrite_tags(const char *filtervar, List *taglist);
161 static void EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata);
162 static const char *stringify_grant_objtype(ObjectType objtype);
163 static const char *stringify_adefprivs_objtype(ObjectType objtype);
164 
165 /*
166  * Create an event trigger.
167  */
168 Oid
169 CreateEventTrigger(CreateEventTrigStmt *stmt)
170 {
171 	HeapTuple	tuple;
172 	Oid			funcoid;
173 	Oid			funcrettype;
174 	Oid			fargtypes[1];	/* dummy */
175 	Oid			evtowner = GetUserId();
176 	ListCell   *lc;
177 	List	   *tags = NULL;
178 
179 	/*
180 	 * It would be nice to allow database owners or even regular users to do
181 	 * this, but there are obvious privilege escalation risks which would have
182 	 * to somehow be plugged first.
183 	 */
184 	if (!superuser())
185 		ereport(ERROR,
186 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
187 				 errmsg("permission denied to create event trigger \"%s\"",
188 						stmt->trigname),
189 				 errhint("Must be superuser to create an event trigger.")));
190 
191 	/* Validate event name. */
192 	if (strcmp(stmt->eventname, "ddl_command_start") != 0 &&
193 		strcmp(stmt->eventname, "ddl_command_end") != 0 &&
194 		strcmp(stmt->eventname, "sql_drop") != 0 &&
195 		strcmp(stmt->eventname, "table_rewrite") != 0)
196 		ereport(ERROR,
197 				(errcode(ERRCODE_SYNTAX_ERROR),
198 				 errmsg("unrecognized event name \"%s\"",
199 						stmt->eventname)));
200 
201 	/* Validate filter conditions. */
202 	foreach(lc, stmt->whenclause)
203 	{
204 		DefElem    *def = (DefElem *) lfirst(lc);
205 
206 		if (strcmp(def->defname, "tag") == 0)
207 		{
208 			if (tags != NULL)
209 				error_duplicate_filter_variable(def->defname);
210 			tags = (List *) def->arg;
211 		}
212 		else
213 			ereport(ERROR,
214 					(errcode(ERRCODE_SYNTAX_ERROR),
215 					 errmsg("unrecognized filter variable \"%s\"", def->defname)));
216 	}
217 
218 	/* Validate tag list, if any. */
219 	if ((strcmp(stmt->eventname, "ddl_command_start") == 0 ||
220 		 strcmp(stmt->eventname, "ddl_command_end") == 0 ||
221 		 strcmp(stmt->eventname, "sql_drop") == 0)
222 		&& tags != NULL)
223 		validate_ddl_tags("tag", tags);
224 	else if (strcmp(stmt->eventname, "table_rewrite") == 0
225 			 && tags != NULL)
226 		validate_table_rewrite_tags("tag", tags);
227 
228 	/*
229 	 * Give user a nice error message if an event trigger of the same name
230 	 * already exists.
231 	 */
232 	tuple = SearchSysCache1(EVENTTRIGGERNAME, CStringGetDatum(stmt->trigname));
233 	if (HeapTupleIsValid(tuple))
234 		ereport(ERROR,
235 				(errcode(ERRCODE_DUPLICATE_OBJECT),
236 				 errmsg("event trigger \"%s\" already exists",
237 						stmt->trigname)));
238 
239 	/* Find and validate the trigger function. */
240 	funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
241 	funcrettype = get_func_rettype(funcoid);
242 	if (funcrettype != EVTTRIGGEROID)
243 		ereport(ERROR,
244 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
245 				 errmsg("function %s must return type %s",
246 						NameListToString(stmt->funcname), "event_trigger")));
247 
248 	/* Insert catalog entries. */
249 	return insert_event_trigger_tuple(stmt->trigname, stmt->eventname,
250 									  evtowner, funcoid, tags);
251 }
252 
253 /*
254  * Validate DDL command tags.
255  */
256 static void
257 validate_ddl_tags(const char *filtervar, List *taglist)
258 {
259 	ListCell   *lc;
260 
261 	foreach(lc, taglist)
262 	{
263 		const char *tag = strVal(lfirst(lc));
264 		event_trigger_command_tag_check_result result;
265 
266 		result = check_ddl_tag(tag);
267 		if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED)
268 			ereport(ERROR,
269 					(errcode(ERRCODE_SYNTAX_ERROR),
270 					 errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",
271 							tag, filtervar)));
272 		if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED)
273 			ereport(ERROR,
274 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
275 			/* translator: %s represents an SQL statement name */
276 					 errmsg("event triggers are not supported for %s",
277 							tag)));
278 	}
279 }
280 
281 static event_trigger_command_tag_check_result
282 check_ddl_tag(const char *tag)
283 {
284 	const char *obtypename;
285 	const event_trigger_support_data *etsd;
286 
287 	/*
288 	 * Handle some idiosyncratic special cases.
289 	 */
290 	if (pg_strcasecmp(tag, "CREATE TABLE AS") == 0 ||
291 		pg_strcasecmp(tag, "SELECT INTO") == 0 ||
292 		pg_strcasecmp(tag, "REFRESH MATERIALIZED VIEW") == 0 ||
293 		pg_strcasecmp(tag, "ALTER DEFAULT PRIVILEGES") == 0 ||
294 		pg_strcasecmp(tag, "ALTER LARGE OBJECT") == 0 ||
295 		pg_strcasecmp(tag, "COMMENT") == 0 ||
296 		pg_strcasecmp(tag, "GRANT") == 0 ||
297 		pg_strcasecmp(tag, "REVOKE") == 0 ||
298 		pg_strcasecmp(tag, "DROP OWNED") == 0 ||
299 		pg_strcasecmp(tag, "IMPORT FOREIGN SCHEMA") == 0 ||
300 		pg_strcasecmp(tag, "SECURITY LABEL") == 0)
301 		return EVENT_TRIGGER_COMMAND_TAG_OK;
302 
303 	/*
304 	 * Otherwise, command should be CREATE, ALTER, or DROP.
305 	 */
306 	if (pg_strncasecmp(tag, "CREATE ", 7) == 0)
307 		obtypename = tag + 7;
308 	else if (pg_strncasecmp(tag, "ALTER ", 6) == 0)
309 		obtypename = tag + 6;
310 	else if (pg_strncasecmp(tag, "DROP ", 5) == 0)
311 		obtypename = tag + 5;
312 	else
313 		return EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED;
314 
315 	/*
316 	 * ...and the object type should be something recognizable.
317 	 */
318 	for (etsd = event_trigger_support; etsd->obtypename != NULL; etsd++)
319 		if (pg_strcasecmp(etsd->obtypename, obtypename) == 0)
320 			break;
321 	if (etsd->obtypename == NULL)
322 		return EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED;
323 	if (!etsd->supported)
324 		return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED;
325 	return EVENT_TRIGGER_COMMAND_TAG_OK;
326 }
327 
328 /*
329  * Validate DDL command tags for event table_rewrite.
330  */
331 static void
332 validate_table_rewrite_tags(const char *filtervar, List *taglist)
333 {
334 	ListCell   *lc;
335 
336 	foreach(lc, taglist)
337 	{
338 		const char *tag = strVal(lfirst(lc));
339 		event_trigger_command_tag_check_result result;
340 
341 		result = check_table_rewrite_ddl_tag(tag);
342 		if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED)
343 			ereport(ERROR,
344 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
345 			/* translator: %s represents an SQL statement name */
346 					 errmsg("event triggers are not supported for %s",
347 							tag)));
348 	}
349 }
350 
351 static event_trigger_command_tag_check_result
352 check_table_rewrite_ddl_tag(const char *tag)
353 {
354 	if (pg_strcasecmp(tag, "ALTER TABLE") == 0 ||
355 		pg_strcasecmp(tag, "ALTER TYPE") == 0)
356 		return EVENT_TRIGGER_COMMAND_TAG_OK;
357 
358 	return EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED;
359 }
360 
361 /*
362  * Complain about a duplicate filter variable.
363  */
364 static void
365 error_duplicate_filter_variable(const char *defname)
366 {
367 	ereport(ERROR,
368 			(errcode(ERRCODE_SYNTAX_ERROR),
369 			 errmsg("filter variable \"%s\" specified more than once",
370 					defname)));
371 }
372 
373 /*
374  * Insert the new pg_event_trigger row and record dependencies.
375  */
376 static Oid
377 insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtOwner,
378 						   Oid funcoid, List *taglist)
379 {
380 	Relation	tgrel;
381 	Oid			trigoid;
382 	HeapTuple	tuple;
383 	Datum		values[Natts_pg_trigger];
384 	bool		nulls[Natts_pg_trigger];
385 	NameData	evtnamedata,
386 				evteventdata;
387 	ObjectAddress myself,
388 				referenced;
389 
390 	/* Open pg_event_trigger. */
391 	tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
392 
393 	/* Build the new pg_trigger tuple. */
394 	trigoid = GetNewOidWithIndex(tgrel, EventTriggerOidIndexId,
395 								 Anum_pg_event_trigger_oid);
396 	values[Anum_pg_event_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
397 	memset(nulls, false, sizeof(nulls));
398 	namestrcpy(&evtnamedata, trigname);
399 	values[Anum_pg_event_trigger_evtname - 1] = NameGetDatum(&evtnamedata);
400 	namestrcpy(&evteventdata, eventname);
401 	values[Anum_pg_event_trigger_evtevent - 1] = NameGetDatum(&evteventdata);
402 	values[Anum_pg_event_trigger_evtowner - 1] = ObjectIdGetDatum(evtOwner);
403 	values[Anum_pg_event_trigger_evtfoid - 1] = ObjectIdGetDatum(funcoid);
404 	values[Anum_pg_event_trigger_evtenabled - 1] =
405 		CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
406 	if (taglist == NIL)
407 		nulls[Anum_pg_event_trigger_evttags - 1] = true;
408 	else
409 		values[Anum_pg_event_trigger_evttags - 1] =
410 			filter_list_to_array(taglist);
411 
412 	/* Insert heap tuple. */
413 	tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
414 	CatalogTupleInsert(tgrel, tuple);
415 	heap_freetuple(tuple);
416 
417 	/* Depend on owner. */
418 	recordDependencyOnOwner(EventTriggerRelationId, trigoid, evtOwner);
419 
420 	/* Depend on event trigger function. */
421 	myself.classId = EventTriggerRelationId;
422 	myself.objectId = trigoid;
423 	myself.objectSubId = 0;
424 	referenced.classId = ProcedureRelationId;
425 	referenced.objectId = funcoid;
426 	referenced.objectSubId = 0;
427 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
428 
429 	/* Depend on extension, if any. */
430 	recordDependencyOnCurrentExtension(&myself, false);
431 
432 	/* Post creation hook for new event trigger */
433 	InvokeObjectPostCreateHook(EventTriggerRelationId, trigoid, 0);
434 
435 	/* Close pg_event_trigger. */
436 	table_close(tgrel, RowExclusiveLock);
437 
438 	return trigoid;
439 }
440 
441 /*
442  * In the parser, a clause like WHEN tag IN ('cmd1', 'cmd2') is represented
443  * by a DefElem whose value is a List of String nodes; in the catalog, we
444  * store the list of strings as a text array.  This function transforms the
445  * former representation into the latter one.
446  *
447  * For cleanliness, we store command tags in the catalog as text.  It's
448  * possible (although not currently anticipated) that we might have
449  * a case-sensitive filter variable in the future, in which case this would
450  * need some further adjustment.
451  */
452 static Datum
453 filter_list_to_array(List *filterlist)
454 {
455 	ListCell   *lc;
456 	Datum	   *data;
457 	int			i = 0,
458 				l = list_length(filterlist);
459 
460 	data = (Datum *) palloc(l * sizeof(Datum));
461 
462 	foreach(lc, filterlist)
463 	{
464 		const char *value = strVal(lfirst(lc));
465 		char	   *result,
466 				   *p;
467 
468 		result = pstrdup(value);
469 		for (p = result; *p; p++)
470 			*p = pg_ascii_toupper((unsigned char) *p);
471 		data[i++] = PointerGetDatum(cstring_to_text(result));
472 		pfree(result);
473 	}
474 
475 	return PointerGetDatum(construct_array(data, l, TEXTOID, -1, false, 'i'));
476 }
477 
478 /*
479  * Guts of event trigger deletion.
480  */
481 void
482 RemoveEventTriggerById(Oid trigOid)
483 {
484 	Relation	tgrel;
485 	HeapTuple	tup;
486 
487 	tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
488 
489 	tup = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(trigOid));
490 	if (!HeapTupleIsValid(tup))
491 		elog(ERROR, "cache lookup failed for event trigger %u", trigOid);
492 
493 	CatalogTupleDelete(tgrel, &tup->t_self);
494 
495 	ReleaseSysCache(tup);
496 
497 	table_close(tgrel, RowExclusiveLock);
498 }
499 
500 /*
501  * ALTER EVENT TRIGGER foo ENABLE|DISABLE|ENABLE ALWAYS|REPLICA
502  */
503 Oid
504 AlterEventTrigger(AlterEventTrigStmt *stmt)
505 {
506 	Relation	tgrel;
507 	HeapTuple	tup;
508 	Oid			trigoid;
509 	Form_pg_event_trigger evtForm;
510 	char		tgenabled = stmt->tgenabled;
511 
512 	tgrel = table_open(EventTriggerRelationId, RowExclusiveLock);
513 
514 	tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
515 							  CStringGetDatum(stmt->trigname));
516 	if (!HeapTupleIsValid(tup))
517 		ereport(ERROR,
518 				(errcode(ERRCODE_UNDEFINED_OBJECT),
519 				 errmsg("event trigger \"%s\" does not exist",
520 						stmt->trigname)));
521 
522 	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
523 	trigoid = evtForm->oid;
524 
525 	if (!pg_event_trigger_ownercheck(trigoid, GetUserId()))
526 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
527 					   stmt->trigname);
528 
529 	/* tuple is a copy, so we can modify it below */
530 	evtForm->evtenabled = tgenabled;
531 
532 	CatalogTupleUpdate(tgrel, &tup->t_self, tup);
533 
534 	InvokeObjectPostAlterHook(EventTriggerRelationId,
535 							  trigoid, 0);
536 
537 	/* clean up */
538 	heap_freetuple(tup);
539 	table_close(tgrel, RowExclusiveLock);
540 
541 	return trigoid;
542 }
543 
544 /*
545  * Change event trigger's owner -- by name
546  */
547 ObjectAddress
548 AlterEventTriggerOwner(const char *name, Oid newOwnerId)
549 {
550 	Oid			evtOid;
551 	HeapTuple	tup;
552 	Form_pg_event_trigger evtForm;
553 	Relation	rel;
554 	ObjectAddress address;
555 
556 	rel = table_open(EventTriggerRelationId, RowExclusiveLock);
557 
558 	tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(name));
559 
560 	if (!HeapTupleIsValid(tup))
561 		ereport(ERROR,
562 				(errcode(ERRCODE_UNDEFINED_OBJECT),
563 				 errmsg("event trigger \"%s\" does not exist", name)));
564 
565 	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
566 	evtOid = evtForm->oid;
567 
568 	AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
569 
570 	ObjectAddressSet(address, EventTriggerRelationId, evtOid);
571 
572 	heap_freetuple(tup);
573 
574 	table_close(rel, RowExclusiveLock);
575 
576 	return address;
577 }
578 
579 /*
580  * Change event trigger owner, by OID
581  */
582 void
583 AlterEventTriggerOwner_oid(Oid trigOid, Oid newOwnerId)
584 {
585 	HeapTuple	tup;
586 	Relation	rel;
587 
588 	rel = table_open(EventTriggerRelationId, RowExclusiveLock);
589 
590 	tup = SearchSysCacheCopy1(EVENTTRIGGEROID, ObjectIdGetDatum(trigOid));
591 
592 	if (!HeapTupleIsValid(tup))
593 		ereport(ERROR,
594 				(errcode(ERRCODE_UNDEFINED_OBJECT),
595 				 errmsg("event trigger with OID %u does not exist", trigOid)));
596 
597 	AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
598 
599 	heap_freetuple(tup);
600 
601 	table_close(rel, RowExclusiveLock);
602 }
603 
604 /*
605  * Internal workhorse for changing an event trigger's owner
606  */
607 static void
608 AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
609 {
610 	Form_pg_event_trigger form;
611 
612 	form = (Form_pg_event_trigger) GETSTRUCT(tup);
613 
614 	if (form->evtowner == newOwnerId)
615 		return;
616 
617 	if (!pg_event_trigger_ownercheck(form->oid, GetUserId()))
618 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
619 					   NameStr(form->evtname));
620 
621 	/* New owner must be a superuser */
622 	if (!superuser_arg(newOwnerId))
623 		ereport(ERROR,
624 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
625 				 errmsg("permission denied to change owner of event trigger \"%s\"",
626 						NameStr(form->evtname)),
627 				 errhint("The owner of an event trigger must be a superuser.")));
628 
629 	form->evtowner = newOwnerId;
630 	CatalogTupleUpdate(rel, &tup->t_self, tup);
631 
632 	/* Update owner dependency reference */
633 	changeDependencyOnOwner(EventTriggerRelationId,
634 							form->oid,
635 							newOwnerId);
636 
637 	InvokeObjectPostAlterHook(EventTriggerRelationId,
638 							  form->oid, 0);
639 }
640 
641 /*
642  * get_event_trigger_oid - Look up an event trigger by name to find its OID.
643  *
644  * If missing_ok is false, throw an error if trigger not found.  If
645  * true, just return InvalidOid.
646  */
647 Oid
648 get_event_trigger_oid(const char *trigname, bool missing_ok)
649 {
650 	Oid			oid;
651 
652 	oid = GetSysCacheOid1(EVENTTRIGGERNAME, Anum_pg_event_trigger_oid,
653 						  CStringGetDatum(trigname));
654 	if (!OidIsValid(oid) && !missing_ok)
655 		ereport(ERROR,
656 				(errcode(ERRCODE_UNDEFINED_OBJECT),
657 				 errmsg("event trigger \"%s\" does not exist", trigname)));
658 	return oid;
659 }
660 
661 /*
662  * Return true when we want to fire given Event Trigger and false otherwise,
663  * filtering on the session replication role and the event trigger registered
664  * tags matching.
665  */
666 static bool
667 filter_event_trigger(const char **tag, EventTriggerCacheItem *item)
668 {
669 	/*
670 	 * Filter by session replication role, knowing that we never see disabled
671 	 * items down here.
672 	 */
673 	if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
674 	{
675 		if (item->enabled == TRIGGER_FIRES_ON_ORIGIN)
676 			return false;
677 	}
678 	else
679 	{
680 		if (item->enabled == TRIGGER_FIRES_ON_REPLICA)
681 			return false;
682 	}
683 
684 	/* Filter by tags, if any were specified. */
685 	if (item->ntags != 0 && bsearch(tag, item->tag,
686 									item->ntags, sizeof(char *),
687 									pg_qsort_strcmp) == NULL)
688 		return false;
689 
690 	/* if we reach that point, we're not filtering out this item */
691 	return true;
692 }
693 
694 /*
695  * Setup for running triggers for the given event.  Return value is an OID list
696  * of functions to run; if there are any, trigdata is filled with an
697  * appropriate EventTriggerData for them to receive.
698  */
699 static List *
700 EventTriggerCommonSetup(Node *parsetree,
701 						EventTriggerEvent event, const char *eventstr,
702 						EventTriggerData *trigdata)
703 {
704 	const char *tag;
705 	List	   *cachelist;
706 	ListCell   *lc;
707 	List	   *runlist = NIL;
708 
709 	/*
710 	 * We want the list of command tags for which this procedure is actually
711 	 * invoked to match up exactly with the list that CREATE EVENT TRIGGER
712 	 * accepts.  This debugging cross-check will throw an error if this
713 	 * function is invoked for a command tag that CREATE EVENT TRIGGER won't
714 	 * accept.  (Unfortunately, there doesn't seem to be any simple, automated
715 	 * way to verify that CREATE EVENT TRIGGER doesn't accept extra stuff that
716 	 * never reaches this control point.)
717 	 *
718 	 * If this cross-check fails for you, you probably need to either adjust
719 	 * standard_ProcessUtility() not to invoke event triggers for the command
720 	 * type in question, or you need to adjust check_ddl_tag to accept the
721 	 * relevant command tag.
722 	 */
723 #ifdef USE_ASSERT_CHECKING
724 	{
725 		const char *dbgtag;
726 
727 		dbgtag = CreateCommandTag(parsetree);
728 		if (event == EVT_DDLCommandStart ||
729 			event == EVT_DDLCommandEnd ||
730 			event == EVT_SQLDrop)
731 		{
732 			if (check_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK)
733 				elog(ERROR, "unexpected command tag \"%s\"", dbgtag);
734 		}
735 		else if (event == EVT_TableRewrite)
736 		{
737 			if (check_table_rewrite_ddl_tag(dbgtag) != EVENT_TRIGGER_COMMAND_TAG_OK)
738 				elog(ERROR, "unexpected command tag \"%s\"", dbgtag);
739 		}
740 	}
741 #endif
742 
743 	/* Use cache to find triggers for this event; fast exit if none. */
744 	cachelist = EventCacheLookup(event);
745 	if (cachelist == NIL)
746 		return NIL;
747 
748 	/* Get the command tag. */
749 	tag = CreateCommandTag(parsetree);
750 
751 	/*
752 	 * Filter list of event triggers by command tag, and copy them into our
753 	 * memory context.  Once we start running the command triggers, or indeed
754 	 * once we do anything at all that touches the catalogs, an invalidation
755 	 * might leave cachelist pointing at garbage, so we must do this before we
756 	 * can do much else.
757 	 */
758 	foreach(lc, cachelist)
759 	{
760 		EventTriggerCacheItem *item = lfirst(lc);
761 
762 		if (filter_event_trigger(&tag, item))
763 		{
764 			/* We must plan to fire this trigger. */
765 			runlist = lappend_oid(runlist, item->fnoid);
766 		}
767 	}
768 
769 	/* don't spend any more time on this if no functions to run */
770 	if (runlist == NIL)
771 		return NIL;
772 
773 	trigdata->type = T_EventTriggerData;
774 	trigdata->event = eventstr;
775 	trigdata->parsetree = parsetree;
776 	trigdata->tag = tag;
777 
778 	return runlist;
779 }
780 
781 /*
782  * Fire ddl_command_start triggers.
783  */
784 void
785 EventTriggerDDLCommandStart(Node *parsetree)
786 {
787 	List	   *runlist;
788 	EventTriggerData trigdata;
789 
790 	/*
791 	 * Event Triggers are completely disabled in standalone mode.  There are
792 	 * (at least) two reasons for this:
793 	 *
794 	 * 1. A sufficiently broken event trigger might not only render the
795 	 * database unusable, but prevent disabling itself to fix the situation.
796 	 * In this scenario, restarting in standalone mode provides an escape
797 	 * hatch.
798 	 *
799 	 * 2. BuildEventTriggerCache relies on systable_beginscan_ordered, and
800 	 * therefore will malfunction if pg_event_trigger's indexes are damaged.
801 	 * To allow recovery from a damaged index, we need some operating mode
802 	 * wherein event triggers are disabled.  (Or we could implement
803 	 * heapscan-and-sort logic for that case, but having disaster recovery
804 	 * scenarios depend on code that's otherwise untested isn't appetizing.)
805 	 */
806 	if (!IsUnderPostmaster)
807 		return;
808 
809 	runlist = EventTriggerCommonSetup(parsetree,
810 									  EVT_DDLCommandStart,
811 									  "ddl_command_start",
812 									  &trigdata);
813 	if (runlist == NIL)
814 		return;
815 
816 	/* Run the triggers. */
817 	EventTriggerInvoke(runlist, &trigdata);
818 
819 	/* Cleanup. */
820 	list_free(runlist);
821 
822 	/*
823 	 * Make sure anything the event triggers did will be visible to the main
824 	 * command.
825 	 */
826 	CommandCounterIncrement();
827 }
828 
829 /*
830  * Fire ddl_command_end triggers.
831  */
832 void
833 EventTriggerDDLCommandEnd(Node *parsetree)
834 {
835 	List	   *runlist;
836 	EventTriggerData trigdata;
837 
838 	/*
839 	 * See EventTriggerDDLCommandStart for a discussion about why event
840 	 * triggers are disabled in single user mode.
841 	 */
842 	if (!IsUnderPostmaster)
843 		return;
844 
845 	/*
846 	 * Also do nothing if our state isn't set up, which it won't be if there
847 	 * weren't any relevant event triggers at the start of the current DDL
848 	 * command.  This test might therefore seem optional, but it's important
849 	 * because EventTriggerCommonSetup might find triggers that didn't exist
850 	 * at the time the command started.  Although this function itself
851 	 * wouldn't crash, the event trigger functions would presumably call
852 	 * pg_event_trigger_ddl_commands which would fail.  Better to do nothing
853 	 * until the next command.
854 	 */
855 	if (!currentEventTriggerState)
856 		return;
857 
858 	runlist = EventTriggerCommonSetup(parsetree,
859 									  EVT_DDLCommandEnd, "ddl_command_end",
860 									  &trigdata);
861 	if (runlist == NIL)
862 		return;
863 
864 	/*
865 	 * Make sure anything the main command did will be visible to the event
866 	 * triggers.
867 	 */
868 	CommandCounterIncrement();
869 
870 	/* Run the triggers. */
871 	EventTriggerInvoke(runlist, &trigdata);
872 
873 	/* Cleanup. */
874 	list_free(runlist);
875 }
876 
877 /*
878  * Fire sql_drop triggers.
879  */
880 void
881 EventTriggerSQLDrop(Node *parsetree)
882 {
883 	List	   *runlist;
884 	EventTriggerData trigdata;
885 
886 	/*
887 	 * See EventTriggerDDLCommandStart for a discussion about why event
888 	 * triggers are disabled in single user mode.
889 	 */
890 	if (!IsUnderPostmaster)
891 		return;
892 
893 	/*
894 	 * Use current state to determine whether this event fires at all.  If
895 	 * there are no triggers for the sql_drop event, then we don't have
896 	 * anything to do here.  Note that dropped object collection is disabled
897 	 * if this is the case, so even if we were to try to run, the list would
898 	 * be empty.
899 	 */
900 	if (!currentEventTriggerState ||
901 		slist_is_empty(&currentEventTriggerState->SQLDropList))
902 		return;
903 
904 	runlist = EventTriggerCommonSetup(parsetree,
905 									  EVT_SQLDrop, "sql_drop",
906 									  &trigdata);
907 
908 	/*
909 	 * Nothing to do if run list is empty.  Note this typically can't happen,
910 	 * because if there are no sql_drop events, then objects-to-drop wouldn't
911 	 * have been collected in the first place and we would have quit above.
912 	 * But it could occur if event triggers were dropped partway through.
913 	 */
914 	if (runlist == NIL)
915 		return;
916 
917 	/*
918 	 * Make sure anything the main command did will be visible to the event
919 	 * triggers.
920 	 */
921 	CommandCounterIncrement();
922 
923 	/*
924 	 * Make sure pg_event_trigger_dropped_objects only works when running
925 	 * these triggers.  Use PG_TRY to ensure in_sql_drop is reset even when
926 	 * one trigger fails.  (This is perhaps not necessary, as the currentState
927 	 * variable will be removed shortly by our caller, but it seems better to
928 	 * play safe.)
929 	 */
930 	currentEventTriggerState->in_sql_drop = true;
931 
932 	/* Run the triggers. */
933 	PG_TRY();
934 	{
935 		EventTriggerInvoke(runlist, &trigdata);
936 	}
937 	PG_CATCH();
938 	{
939 		currentEventTriggerState->in_sql_drop = false;
940 		PG_RE_THROW();
941 	}
942 	PG_END_TRY();
943 	currentEventTriggerState->in_sql_drop = false;
944 
945 	/* Cleanup. */
946 	list_free(runlist);
947 }
948 
949 
950 /*
951  * Fire table_rewrite triggers.
952  */
953 void
954 EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason)
955 {
956 	List	   *runlist;
957 	EventTriggerData trigdata;
958 
959 	/*
960 	 * Event Triggers are completely disabled in standalone mode.  There are
961 	 * (at least) two reasons for this:
962 	 *
963 	 * 1. A sufficiently broken event trigger might not only render the
964 	 * database unusable, but prevent disabling itself to fix the situation.
965 	 * In this scenario, restarting in standalone mode provides an escape
966 	 * hatch.
967 	 *
968 	 * 2. BuildEventTriggerCache relies on systable_beginscan_ordered, and
969 	 * therefore will malfunction if pg_event_trigger's indexes are damaged.
970 	 * To allow recovery from a damaged index, we need some operating mode
971 	 * wherein event triggers are disabled.  (Or we could implement
972 	 * heapscan-and-sort logic for that case, but having disaster recovery
973 	 * scenarios depend on code that's otherwise untested isn't appetizing.)
974 	 */
975 	if (!IsUnderPostmaster)
976 		return;
977 
978 	/*
979 	 * Also do nothing if our state isn't set up, which it won't be if there
980 	 * weren't any relevant event triggers at the start of the current DDL
981 	 * command.  This test might therefore seem optional, but it's
982 	 * *necessary*, because EventTriggerCommonSetup might find triggers that
983 	 * didn't exist at the time the command started.
984 	 */
985 	if (!currentEventTriggerState)
986 		return;
987 
988 	runlist = EventTriggerCommonSetup(parsetree,
989 									  EVT_TableRewrite,
990 									  "table_rewrite",
991 									  &trigdata);
992 	if (runlist == NIL)
993 		return;
994 
995 	/*
996 	 * Make sure pg_event_trigger_table_rewrite_oid only works when running
997 	 * these triggers. Use PG_TRY to ensure table_rewrite_oid is reset even
998 	 * when one trigger fails. (This is perhaps not necessary, as the
999 	 * currentState variable will be removed shortly by our caller, but it
1000 	 * seems better to play safe.)
1001 	 */
1002 	currentEventTriggerState->table_rewrite_oid = tableOid;
1003 	currentEventTriggerState->table_rewrite_reason = reason;
1004 
1005 	/* Run the triggers. */
1006 	PG_TRY();
1007 	{
1008 		EventTriggerInvoke(runlist, &trigdata);
1009 	}
1010 	PG_CATCH();
1011 	{
1012 		currentEventTriggerState->table_rewrite_oid = InvalidOid;
1013 		currentEventTriggerState->table_rewrite_reason = 0;
1014 		PG_RE_THROW();
1015 	}
1016 	PG_END_TRY();
1017 
1018 	currentEventTriggerState->table_rewrite_oid = InvalidOid;
1019 	currentEventTriggerState->table_rewrite_reason = 0;
1020 
1021 	/* Cleanup. */
1022 	list_free(runlist);
1023 
1024 	/*
1025 	 * Make sure anything the event triggers did will be visible to the main
1026 	 * command.
1027 	 */
1028 	CommandCounterIncrement();
1029 }
1030 
1031 /*
1032  * Invoke each event trigger in a list of event triggers.
1033  */
1034 static void
1035 EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
1036 {
1037 	MemoryContext context;
1038 	MemoryContext oldcontext;
1039 	ListCell   *lc;
1040 	bool		first = true;
1041 
1042 	/* Guard against stack overflow due to recursive event trigger */
1043 	check_stack_depth();
1044 
1045 	/*
1046 	 * Let's evaluate event triggers in their own memory context, so that any
1047 	 * leaks get cleaned up promptly.
1048 	 */
1049 	context = AllocSetContextCreate(CurrentMemoryContext,
1050 									"event trigger context",
1051 									ALLOCSET_DEFAULT_SIZES);
1052 	oldcontext = MemoryContextSwitchTo(context);
1053 
1054 	/* Call each event trigger. */
1055 	foreach(lc, fn_oid_list)
1056 	{
1057 		LOCAL_FCINFO(fcinfo, 0);
1058 		Oid			fnoid = lfirst_oid(lc);
1059 		FmgrInfo	flinfo;
1060 		PgStat_FunctionCallUsage fcusage;
1061 
1062 		elog(DEBUG1, "EventTriggerInvoke %u", fnoid);
1063 
1064 		/*
1065 		 * We want each event trigger to be able to see the results of the
1066 		 * previous event trigger's action.  Caller is responsible for any
1067 		 * command-counter increment that is needed between the event trigger
1068 		 * and anything else in the transaction.
1069 		 */
1070 		if (first)
1071 			first = false;
1072 		else
1073 			CommandCounterIncrement();
1074 
1075 		/* Look up the function */
1076 		fmgr_info(fnoid, &flinfo);
1077 
1078 		/* Call the function, passing no arguments but setting a context. */
1079 		InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
1080 								 InvalidOid, (Node *) trigdata, NULL);
1081 		pgstat_init_function_usage(fcinfo, &fcusage);
1082 		FunctionCallInvoke(fcinfo);
1083 		pgstat_end_function_usage(&fcusage, true);
1084 
1085 		/* Reclaim memory. */
1086 		MemoryContextReset(context);
1087 	}
1088 
1089 	/* Restore old memory context and delete the temporary one. */
1090 	MemoryContextSwitchTo(oldcontext);
1091 	MemoryContextDelete(context);
1092 }
1093 
1094 /*
1095  * Do event triggers support this object type?
1096  */
1097 bool
1098 EventTriggerSupportsObjectType(ObjectType obtype)
1099 {
1100 	switch (obtype)
1101 	{
1102 		case OBJECT_DATABASE:
1103 		case OBJECT_TABLESPACE:
1104 		case OBJECT_ROLE:
1105 			/* no support for global objects */
1106 			return false;
1107 		case OBJECT_EVENT_TRIGGER:
1108 			/* no support for event triggers on event triggers */
1109 			return false;
1110 		case OBJECT_ACCESS_METHOD:
1111 		case OBJECT_AGGREGATE:
1112 		case OBJECT_AMOP:
1113 		case OBJECT_AMPROC:
1114 		case OBJECT_ATTRIBUTE:
1115 		case OBJECT_CAST:
1116 		case OBJECT_COLUMN:
1117 		case OBJECT_COLLATION:
1118 		case OBJECT_CONVERSION:
1119 		case OBJECT_DEFACL:
1120 		case OBJECT_DEFAULT:
1121 		case OBJECT_DOMAIN:
1122 		case OBJECT_DOMCONSTRAINT:
1123 		case OBJECT_EXTENSION:
1124 		case OBJECT_FDW:
1125 		case OBJECT_FOREIGN_SERVER:
1126 		case OBJECT_FOREIGN_TABLE:
1127 		case OBJECT_FUNCTION:
1128 		case OBJECT_INDEX:
1129 		case OBJECT_LANGUAGE:
1130 		case OBJECT_LARGEOBJECT:
1131 		case OBJECT_MATVIEW:
1132 		case OBJECT_OPCLASS:
1133 		case OBJECT_OPERATOR:
1134 		case OBJECT_OPFAMILY:
1135 		case OBJECT_POLICY:
1136 		case OBJECT_PROCEDURE:
1137 		case OBJECT_PUBLICATION:
1138 		case OBJECT_PUBLICATION_REL:
1139 		case OBJECT_ROUTINE:
1140 		case OBJECT_RULE:
1141 		case OBJECT_SCHEMA:
1142 		case OBJECT_SEQUENCE:
1143 		case OBJECT_SUBSCRIPTION:
1144 		case OBJECT_STATISTIC_EXT:
1145 		case OBJECT_TABCONSTRAINT:
1146 		case OBJECT_TABLE:
1147 		case OBJECT_TRANSFORM:
1148 		case OBJECT_TRIGGER:
1149 		case OBJECT_TSCONFIGURATION:
1150 		case OBJECT_TSDICTIONARY:
1151 		case OBJECT_TSPARSER:
1152 		case OBJECT_TSTEMPLATE:
1153 		case OBJECT_TYPE:
1154 		case OBJECT_USER_MAPPING:
1155 		case OBJECT_VIEW:
1156 			return true;
1157 
1158 			/*
1159 			 * There's intentionally no default: case here; we want the
1160 			 * compiler to warn if a new ObjectType hasn't been handled above.
1161 			 */
1162 	}
1163 
1164 	/* Shouldn't get here, but if we do, say "no support" */
1165 	return false;
1166 }
1167 
1168 /*
1169  * Do event triggers support this object class?
1170  */
1171 bool
1172 EventTriggerSupportsObjectClass(ObjectClass objclass)
1173 {
1174 	switch (objclass)
1175 	{
1176 		case OCLASS_DATABASE:
1177 		case OCLASS_TBLSPACE:
1178 		case OCLASS_ROLE:
1179 			/* no support for global objects */
1180 			return false;
1181 		case OCLASS_EVENT_TRIGGER:
1182 			/* no support for event triggers on event triggers */
1183 			return false;
1184 		case OCLASS_CLASS:
1185 		case OCLASS_PROC:
1186 		case OCLASS_TYPE:
1187 		case OCLASS_CAST:
1188 		case OCLASS_COLLATION:
1189 		case OCLASS_CONSTRAINT:
1190 		case OCLASS_CONVERSION:
1191 		case OCLASS_DEFAULT:
1192 		case OCLASS_LANGUAGE:
1193 		case OCLASS_LARGEOBJECT:
1194 		case OCLASS_OPERATOR:
1195 		case OCLASS_OPCLASS:
1196 		case OCLASS_OPFAMILY:
1197 		case OCLASS_AM:
1198 		case OCLASS_AMOP:
1199 		case OCLASS_AMPROC:
1200 		case OCLASS_REWRITE:
1201 		case OCLASS_TRIGGER:
1202 		case OCLASS_SCHEMA:
1203 		case OCLASS_STATISTIC_EXT:
1204 		case OCLASS_TSPARSER:
1205 		case OCLASS_TSDICT:
1206 		case OCLASS_TSTEMPLATE:
1207 		case OCLASS_TSCONFIG:
1208 		case OCLASS_FDW:
1209 		case OCLASS_FOREIGN_SERVER:
1210 		case OCLASS_USER_MAPPING:
1211 		case OCLASS_DEFACL:
1212 		case OCLASS_EXTENSION:
1213 		case OCLASS_POLICY:
1214 		case OCLASS_PUBLICATION:
1215 		case OCLASS_PUBLICATION_REL:
1216 		case OCLASS_SUBSCRIPTION:
1217 		case OCLASS_TRANSFORM:
1218 			return true;
1219 
1220 			/*
1221 			 * There's intentionally no default: case here; we want the
1222 			 * compiler to warn if a new OCLASS hasn't been handled above.
1223 			 */
1224 	}
1225 
1226 	/* Shouldn't get here, but if we do, say "no support" */
1227 	return false;
1228 }
1229 
1230 /*
1231  * Prepare event trigger state for a new complete query to run, if necessary;
1232  * returns whether this was done.  If it was, EventTriggerEndCompleteQuery must
1233  * be called when the query is done, regardless of whether it succeeds or fails
1234  * -- so use of a PG_TRY block is mandatory.
1235  */
1236 bool
1237 EventTriggerBeginCompleteQuery(void)
1238 {
1239 	EventTriggerQueryState *state;
1240 	MemoryContext cxt;
1241 
1242 	/*
1243 	 * Currently, sql_drop, table_rewrite, ddl_command_end events are the only
1244 	 * reason to have event trigger state at all; so if there are none, don't
1245 	 * install one.
1246 	 */
1247 	if (!trackDroppedObjectsNeeded())
1248 		return false;
1249 
1250 	cxt = AllocSetContextCreate(TopMemoryContext,
1251 								"event trigger state",
1252 								ALLOCSET_DEFAULT_SIZES);
1253 	state = MemoryContextAlloc(cxt, sizeof(EventTriggerQueryState));
1254 	state->cxt = cxt;
1255 	slist_init(&(state->SQLDropList));
1256 	state->in_sql_drop = false;
1257 	state->table_rewrite_oid = InvalidOid;
1258 
1259 	state->commandCollectionInhibited = currentEventTriggerState ?
1260 		currentEventTriggerState->commandCollectionInhibited : false;
1261 	state->currentCommand = NULL;
1262 	state->commandList = NIL;
1263 	state->previous = currentEventTriggerState;
1264 	currentEventTriggerState = state;
1265 
1266 	return true;
1267 }
1268 
1269 /*
1270  * Query completed (or errored out) -- clean up local state, return to previous
1271  * one.
1272  *
1273  * Note: it's an error to call this routine if EventTriggerBeginCompleteQuery
1274  * returned false previously.
1275  *
1276  * Note: this might be called in the PG_CATCH block of a failing transaction,
1277  * so be wary of running anything unnecessary.  (In particular, it's probably
1278  * unwise to try to allocate memory.)
1279  */
1280 void
1281 EventTriggerEndCompleteQuery(void)
1282 {
1283 	EventTriggerQueryState *prevstate;
1284 
1285 	prevstate = currentEventTriggerState->previous;
1286 
1287 	/* this avoids the need for retail pfree of SQLDropList items: */
1288 	MemoryContextDelete(currentEventTriggerState->cxt);
1289 
1290 	currentEventTriggerState = prevstate;
1291 }
1292 
1293 /*
1294  * Do we need to keep close track of objects being dropped?
1295  *
1296  * This is useful because there is a cost to running with them enabled.
1297  */
1298 bool
1299 trackDroppedObjectsNeeded(void)
1300 {
1301 	/*
1302 	 * true if any sql_drop, table_rewrite, ddl_command_end event trigger
1303 	 * exists
1304 	 */
1305 	return list_length(EventCacheLookup(EVT_SQLDrop)) > 0 ||
1306 		list_length(EventCacheLookup(EVT_TableRewrite)) > 0 ||
1307 		list_length(EventCacheLookup(EVT_DDLCommandEnd)) > 0;
1308 }
1309 
1310 /*
1311  * Support for dropped objects information on event trigger functions.
1312  *
1313  * We keep the list of objects dropped by the current command in current
1314  * state's SQLDropList (comprising SQLDropObject items).  Each time a new
1315  * command is to start, a clean EventTriggerQueryState is created; commands
1316  * that drop objects do the dependency.c dance to drop objects, which
1317  * populates the current state's SQLDropList; when the event triggers are
1318  * invoked they can consume the list via pg_event_trigger_dropped_objects().
1319  * When the command finishes, the EventTriggerQueryState is cleared, and
1320  * the one from the previous command is restored (when no command is in
1321  * execution, the current state is NULL).
1322  *
1323  * All this lets us support the case that an event trigger function drops
1324  * objects "reentrantly".
1325  */
1326 
1327 /*
1328  * Register one object as being dropped by the current command.
1329  */
1330 void
1331 EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool normal)
1332 {
1333 	SQLDropObject *obj;
1334 	MemoryContext oldcxt;
1335 
1336 	if (!currentEventTriggerState)
1337 		return;
1338 
1339 	Assert(EventTriggerSupportsObjectClass(getObjectClass(object)));
1340 
1341 	/* don't report temp schemas except my own */
1342 	if (object->classId == NamespaceRelationId &&
1343 		(isAnyTempNamespace(object->objectId) &&
1344 		 !isTempNamespace(object->objectId)))
1345 		return;
1346 
1347 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1348 
1349 	obj = palloc0(sizeof(SQLDropObject));
1350 	obj->address = *object;
1351 	obj->original = original;
1352 	obj->normal = normal;
1353 
1354 	/*
1355 	 * Obtain schema names from the object's catalog tuple, if one exists;
1356 	 * this lets us skip objects in temp schemas.  We trust that
1357 	 * ObjectProperty contains all object classes that can be
1358 	 * schema-qualified.
1359 	 */
1360 	if (is_objectclass_supported(object->classId))
1361 	{
1362 		Relation	catalog;
1363 		HeapTuple	tuple;
1364 
1365 		catalog = table_open(obj->address.classId, AccessShareLock);
1366 		tuple = get_catalog_object_by_oid(catalog,
1367 										  get_object_attnum_oid(object->classId),
1368 										  obj->address.objectId);
1369 
1370 		if (tuple)
1371 		{
1372 			AttrNumber	attnum;
1373 			Datum		datum;
1374 			bool		isnull;
1375 
1376 			attnum = get_object_attnum_namespace(obj->address.classId);
1377 			if (attnum != InvalidAttrNumber)
1378 			{
1379 				datum = heap_getattr(tuple, attnum,
1380 									 RelationGetDescr(catalog), &isnull);
1381 				if (!isnull)
1382 				{
1383 					Oid			namespaceId;
1384 
1385 					namespaceId = DatumGetObjectId(datum);
1386 					/* temp objects are only reported if they are my own */
1387 					if (isTempNamespace(namespaceId))
1388 					{
1389 						obj->schemaname = "pg_temp";
1390 						obj->istemp = true;
1391 					}
1392 					else if (isAnyTempNamespace(namespaceId))
1393 					{
1394 						pfree(obj);
1395 						table_close(catalog, AccessShareLock);
1396 						MemoryContextSwitchTo(oldcxt);
1397 						return;
1398 					}
1399 					else
1400 					{
1401 						obj->schemaname = get_namespace_name(namespaceId);
1402 						obj->istemp = false;
1403 					}
1404 				}
1405 			}
1406 
1407 			if (get_object_namensp_unique(obj->address.classId) &&
1408 				obj->address.objectSubId == 0)
1409 			{
1410 				attnum = get_object_attnum_name(obj->address.classId);
1411 				if (attnum != InvalidAttrNumber)
1412 				{
1413 					datum = heap_getattr(tuple, attnum,
1414 										 RelationGetDescr(catalog), &isnull);
1415 					if (!isnull)
1416 						obj->objname = pstrdup(NameStr(*DatumGetName(datum)));
1417 				}
1418 			}
1419 		}
1420 
1421 		table_close(catalog, AccessShareLock);
1422 	}
1423 	else
1424 	{
1425 		if (object->classId == NamespaceRelationId &&
1426 			isTempNamespace(object->objectId))
1427 			obj->istemp = true;
1428 	}
1429 
1430 	/* object identity, objname and objargs */
1431 	obj->objidentity =
1432 		getObjectIdentityParts(&obj->address, &obj->addrnames, &obj->addrargs);
1433 
1434 	/* object type */
1435 	obj->objecttype = getObjectTypeDescription(&obj->address);
1436 
1437 	slist_push_head(&(currentEventTriggerState->SQLDropList), &obj->next);
1438 
1439 	MemoryContextSwitchTo(oldcxt);
1440 }
1441 
1442 /*
1443  * pg_event_trigger_dropped_objects
1444  *
1445  * Make the list of dropped objects available to the user function run by the
1446  * Event Trigger.
1447  */
1448 Datum
1449 pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
1450 {
1451 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1452 	TupleDesc	tupdesc;
1453 	Tuplestorestate *tupstore;
1454 	MemoryContext per_query_ctx;
1455 	MemoryContext oldcontext;
1456 	slist_iter	iter;
1457 
1458 	/*
1459 	 * Protect this function from being called out of context
1460 	 */
1461 	if (!currentEventTriggerState ||
1462 		!currentEventTriggerState->in_sql_drop)
1463 		ereport(ERROR,
1464 				(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1465 				 errmsg("%s can only be called in a sql_drop event trigger function",
1466 						"pg_event_trigger_dropped_objects()")));
1467 
1468 	/* check to see if caller supports us returning a tuplestore */
1469 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1470 		ereport(ERROR,
1471 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1472 				 errmsg("set-valued function called in context that cannot accept a set")));
1473 	if (!(rsinfo->allowedModes & SFRM_Materialize))
1474 		ereport(ERROR,
1475 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1476 				 errmsg("materialize mode required, but it is not allowed in this context")));
1477 
1478 	/* Build a tuple descriptor for our result type */
1479 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1480 		elog(ERROR, "return type must be a row type");
1481 
1482 	/* Build tuplestore to hold the result rows */
1483 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1484 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
1485 
1486 	tupstore = tuplestore_begin_heap(true, false, work_mem);
1487 	rsinfo->returnMode = SFRM_Materialize;
1488 	rsinfo->setResult = tupstore;
1489 	rsinfo->setDesc = tupdesc;
1490 
1491 	MemoryContextSwitchTo(oldcontext);
1492 
1493 	slist_foreach(iter, &(currentEventTriggerState->SQLDropList))
1494 	{
1495 		SQLDropObject *obj;
1496 		int			i = 0;
1497 		Datum		values[12];
1498 		bool		nulls[12];
1499 
1500 		obj = slist_container(SQLDropObject, next, iter.cur);
1501 
1502 		MemSet(values, 0, sizeof(values));
1503 		MemSet(nulls, 0, sizeof(nulls));
1504 
1505 		/* classid */
1506 		values[i++] = ObjectIdGetDatum(obj->address.classId);
1507 
1508 		/* objid */
1509 		values[i++] = ObjectIdGetDatum(obj->address.objectId);
1510 
1511 		/* objsubid */
1512 		values[i++] = Int32GetDatum(obj->address.objectSubId);
1513 
1514 		/* original */
1515 		values[i++] = BoolGetDatum(obj->original);
1516 
1517 		/* normal */
1518 		values[i++] = BoolGetDatum(obj->normal);
1519 
1520 		/* is_temporary */
1521 		values[i++] = BoolGetDatum(obj->istemp);
1522 
1523 		/* object_type */
1524 		values[i++] = CStringGetTextDatum(obj->objecttype);
1525 
1526 		/* schema_name */
1527 		if (obj->schemaname)
1528 			values[i++] = CStringGetTextDatum(obj->schemaname);
1529 		else
1530 			nulls[i++] = true;
1531 
1532 		/* object_name */
1533 		if (obj->objname)
1534 			values[i++] = CStringGetTextDatum(obj->objname);
1535 		else
1536 			nulls[i++] = true;
1537 
1538 		/* object_identity */
1539 		if (obj->objidentity)
1540 			values[i++] = CStringGetTextDatum(obj->objidentity);
1541 		else
1542 			nulls[i++] = true;
1543 
1544 		/* address_names and address_args */
1545 		if (obj->addrnames)
1546 		{
1547 			values[i++] = PointerGetDatum(strlist_to_textarray(obj->addrnames));
1548 
1549 			if (obj->addrargs)
1550 				values[i++] = PointerGetDatum(strlist_to_textarray(obj->addrargs));
1551 			else
1552 				values[i++] = PointerGetDatum(construct_empty_array(TEXTOID));
1553 		}
1554 		else
1555 		{
1556 			nulls[i++] = true;
1557 			nulls[i++] = true;
1558 		}
1559 
1560 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1561 	}
1562 
1563 	/* clean up and return the tuplestore */
1564 	tuplestore_donestoring(tupstore);
1565 
1566 	return (Datum) 0;
1567 }
1568 
1569 /*
1570  * pg_event_trigger_table_rewrite_oid
1571  *
1572  * Make the Oid of the table going to be rewritten available to the user
1573  * function run by the Event Trigger.
1574  */
1575 Datum
1576 pg_event_trigger_table_rewrite_oid(PG_FUNCTION_ARGS)
1577 {
1578 	/*
1579 	 * Protect this function from being called out of context
1580 	 */
1581 	if (!currentEventTriggerState ||
1582 		currentEventTriggerState->table_rewrite_oid == InvalidOid)
1583 		ereport(ERROR,
1584 				(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1585 				 errmsg("%s can only be called in a table_rewrite event trigger function",
1586 						"pg_event_trigger_table_rewrite_oid()")));
1587 
1588 	PG_RETURN_OID(currentEventTriggerState->table_rewrite_oid);
1589 }
1590 
1591 /*
1592  * pg_event_trigger_table_rewrite_reason
1593  *
1594  * Make the rewrite reason available to the user.
1595  */
1596 Datum
1597 pg_event_trigger_table_rewrite_reason(PG_FUNCTION_ARGS)
1598 {
1599 	/*
1600 	 * Protect this function from being called out of context
1601 	 */
1602 	if (!currentEventTriggerState ||
1603 		currentEventTriggerState->table_rewrite_reason == 0)
1604 		ereport(ERROR,
1605 				(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
1606 				 errmsg("%s can only be called in a table_rewrite event trigger function",
1607 						"pg_event_trigger_table_rewrite_reason()")));
1608 
1609 	PG_RETURN_INT32(currentEventTriggerState->table_rewrite_reason);
1610 }
1611 
1612 /*-------------------------------------------------------------------------
1613  * Support for DDL command deparsing
1614  *
1615  * The routines below enable an event trigger function to obtain a list of
1616  * DDL commands as they are executed.  There are three main pieces to this
1617  * feature:
1618  *
1619  * 1) Within ProcessUtilitySlow, or some sub-routine thereof, each DDL command
1620  * adds a struct CollectedCommand representation of itself to the command list,
1621  * using the routines below.
1622  *
1623  * 2) Some time after that, ddl_command_end fires and the command list is made
1624  * available to the event trigger function via pg_event_trigger_ddl_commands();
1625  * the complete command details are exposed as a column of type pg_ddl_command.
1626  *
1627  * 3) An extension can install a function capable of taking a value of type
1628  * pg_ddl_command and transform it into some external, user-visible and/or
1629  * -modifiable representation.
1630  *-------------------------------------------------------------------------
1631  */
1632 
1633 /*
1634  * Inhibit DDL command collection.
1635  */
1636 void
1637 EventTriggerInhibitCommandCollection(void)
1638 {
1639 	if (!currentEventTriggerState)
1640 		return;
1641 
1642 	currentEventTriggerState->commandCollectionInhibited = true;
1643 }
1644 
1645 /*
1646  * Re-establish DDL command collection.
1647  */
1648 void
1649 EventTriggerUndoInhibitCommandCollection(void)
1650 {
1651 	if (!currentEventTriggerState)
1652 		return;
1653 
1654 	currentEventTriggerState->commandCollectionInhibited = false;
1655 }
1656 
1657 /*
1658  * EventTriggerCollectSimpleCommand
1659  *		Save data about a simple DDL command that was just executed
1660  *
1661  * address identifies the object being operated on.  secondaryObject is an
1662  * object address that was related in some way to the executed command; its
1663  * meaning is command-specific.
1664  *
1665  * For instance, for an ALTER obj SET SCHEMA command, objtype is the type of
1666  * object being moved, objectId is its OID, and secondaryOid is the OID of the
1667  * old schema.  (The destination schema OID can be obtained by catalog lookup
1668  * of the object.)
1669  */
1670 void
1671 EventTriggerCollectSimpleCommand(ObjectAddress address,
1672 								 ObjectAddress secondaryObject,
1673 								 Node *parsetree)
1674 {
1675 	MemoryContext oldcxt;
1676 	CollectedCommand *command;
1677 
1678 	/* ignore if event trigger context not set, or collection disabled */
1679 	if (!currentEventTriggerState ||
1680 		currentEventTriggerState->commandCollectionInhibited)
1681 		return;
1682 
1683 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1684 
1685 	command = palloc(sizeof(CollectedCommand));
1686 
1687 	command->type = SCT_Simple;
1688 	command->in_extension = creating_extension;
1689 
1690 	command->d.simple.address = address;
1691 	command->d.simple.secondaryObject = secondaryObject;
1692 	command->parsetree = copyObject(parsetree);
1693 
1694 	currentEventTriggerState->commandList = lappend(currentEventTriggerState->commandList,
1695 													command);
1696 
1697 	MemoryContextSwitchTo(oldcxt);
1698 }
1699 
1700 /*
1701  * EventTriggerAlterTableStart
1702  *		Prepare to receive data on an ALTER TABLE command about to be executed
1703  *
1704  * Note we don't collect the command immediately; instead we keep it in
1705  * currentCommand, and only when we're done processing the subcommands we will
1706  * add it to the command list.
1707  */
1708 void
1709 EventTriggerAlterTableStart(Node *parsetree)
1710 {
1711 	MemoryContext oldcxt;
1712 	CollectedCommand *command;
1713 
1714 	/* ignore if event trigger context not set, or collection disabled */
1715 	if (!currentEventTriggerState ||
1716 		currentEventTriggerState->commandCollectionInhibited)
1717 		return;
1718 
1719 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1720 
1721 	command = palloc(sizeof(CollectedCommand));
1722 
1723 	command->type = SCT_AlterTable;
1724 	command->in_extension = creating_extension;
1725 
1726 	command->d.alterTable.classId = RelationRelationId;
1727 	command->d.alterTable.objectId = InvalidOid;
1728 	command->d.alterTable.subcmds = NIL;
1729 	command->parsetree = copyObject(parsetree);
1730 
1731 	command->parent = currentEventTriggerState->currentCommand;
1732 	currentEventTriggerState->currentCommand = command;
1733 
1734 	MemoryContextSwitchTo(oldcxt);
1735 }
1736 
1737 /*
1738  * Remember the OID of the object being affected by an ALTER TABLE.
1739  *
1740  * This is needed because in some cases we don't know the OID until later.
1741  */
1742 void
1743 EventTriggerAlterTableRelid(Oid objectId)
1744 {
1745 	if (!currentEventTriggerState ||
1746 		currentEventTriggerState->commandCollectionInhibited)
1747 		return;
1748 
1749 	currentEventTriggerState->currentCommand->d.alterTable.objectId = objectId;
1750 }
1751 
1752 /*
1753  * EventTriggerCollectAlterTableSubcmd
1754  *		Save data about a single part of an ALTER TABLE.
1755  *
1756  * Several different commands go through this path, but apart from ALTER TABLE
1757  * itself, they are all concerned with AlterTableCmd nodes that are generated
1758  * internally, so that's all that this code needs to handle at the moment.
1759  */
1760 void
1761 EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
1762 {
1763 	MemoryContext oldcxt;
1764 	CollectedATSubcmd *newsub;
1765 
1766 	/* ignore if event trigger context not set, or collection disabled */
1767 	if (!currentEventTriggerState ||
1768 		currentEventTriggerState->commandCollectionInhibited)
1769 		return;
1770 
1771 	Assert(IsA(subcmd, AlterTableCmd));
1772 	Assert(currentEventTriggerState->currentCommand != NULL);
1773 	Assert(OidIsValid(currentEventTriggerState->currentCommand->d.alterTable.objectId));
1774 
1775 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1776 
1777 	newsub = palloc(sizeof(CollectedATSubcmd));
1778 	newsub->address = address;
1779 	newsub->parsetree = copyObject(subcmd);
1780 
1781 	currentEventTriggerState->currentCommand->d.alterTable.subcmds =
1782 		lappend(currentEventTriggerState->currentCommand->d.alterTable.subcmds, newsub);
1783 
1784 	MemoryContextSwitchTo(oldcxt);
1785 }
1786 
1787 /*
1788  * EventTriggerAlterTableEnd
1789  *		Finish up saving an ALTER TABLE command, and add it to command list.
1790  *
1791  * FIXME this API isn't considering the possibility that an xact/subxact is
1792  * aborted partway through.  Probably it's best to add an
1793  * AtEOSubXact_EventTriggers() to fix this.
1794  */
1795 void
1796 EventTriggerAlterTableEnd(void)
1797 {
1798 	CollectedCommand *parent;
1799 
1800 	/* ignore if event trigger context not set, or collection disabled */
1801 	if (!currentEventTriggerState ||
1802 		currentEventTriggerState->commandCollectionInhibited)
1803 		return;
1804 
1805 	parent = currentEventTriggerState->currentCommand->parent;
1806 
1807 	/* If no subcommands, don't collect */
1808 	if (list_length(currentEventTriggerState->currentCommand->d.alterTable.subcmds) != 0)
1809 	{
1810 		MemoryContext oldcxt;
1811 
1812 		oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1813 
1814 		currentEventTriggerState->commandList =
1815 			lappend(currentEventTriggerState->commandList,
1816 					currentEventTriggerState->currentCommand);
1817 
1818 		MemoryContextSwitchTo(oldcxt);
1819 	}
1820 	else
1821 		pfree(currentEventTriggerState->currentCommand);
1822 
1823 	currentEventTriggerState->currentCommand = parent;
1824 }
1825 
1826 /*
1827  * EventTriggerCollectGrant
1828  *		Save data about a GRANT/REVOKE command being executed
1829  *
1830  * This function creates a copy of the InternalGrant, as the original might
1831  * not have the right lifetime.
1832  */
1833 void
1834 EventTriggerCollectGrant(InternalGrant *istmt)
1835 {
1836 	MemoryContext oldcxt;
1837 	CollectedCommand *command;
1838 	InternalGrant *icopy;
1839 	ListCell   *cell;
1840 
1841 	/* ignore if event trigger context not set, or collection disabled */
1842 	if (!currentEventTriggerState ||
1843 		currentEventTriggerState->commandCollectionInhibited)
1844 		return;
1845 
1846 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1847 
1848 	/*
1849 	 * This is tedious, but necessary.
1850 	 */
1851 	icopy = palloc(sizeof(InternalGrant));
1852 	memcpy(icopy, istmt, sizeof(InternalGrant));
1853 	icopy->objects = list_copy(istmt->objects);
1854 	icopy->grantees = list_copy(istmt->grantees);
1855 	icopy->col_privs = NIL;
1856 	foreach(cell, istmt->col_privs)
1857 		icopy->col_privs = lappend(icopy->col_privs, copyObject(lfirst(cell)));
1858 
1859 	/* Now collect it, using the copied InternalGrant */
1860 	command = palloc(sizeof(CollectedCommand));
1861 	command->type = SCT_Grant;
1862 	command->in_extension = creating_extension;
1863 	command->d.grant.istmt = icopy;
1864 	command->parsetree = NULL;
1865 
1866 	currentEventTriggerState->commandList =
1867 		lappend(currentEventTriggerState->commandList, command);
1868 
1869 	MemoryContextSwitchTo(oldcxt);
1870 }
1871 
1872 /*
1873  * EventTriggerCollectAlterOpFam
1874  *		Save data about an ALTER OPERATOR FAMILY ADD/DROP command being
1875  *		executed
1876  */
1877 void
1878 EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
1879 							  List *operators, List *procedures)
1880 {
1881 	MemoryContext oldcxt;
1882 	CollectedCommand *command;
1883 
1884 	/* ignore if event trigger context not set, or collection disabled */
1885 	if (!currentEventTriggerState ||
1886 		currentEventTriggerState->commandCollectionInhibited)
1887 		return;
1888 
1889 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1890 
1891 	command = palloc(sizeof(CollectedCommand));
1892 	command->type = SCT_AlterOpFamily;
1893 	command->in_extension = creating_extension;
1894 	ObjectAddressSet(command->d.opfam.address,
1895 					 OperatorFamilyRelationId, opfamoid);
1896 	command->d.opfam.operators = operators;
1897 	command->d.opfam.procedures = procedures;
1898 	command->parsetree = (Node *) copyObject(stmt);
1899 
1900 	currentEventTriggerState->commandList =
1901 		lappend(currentEventTriggerState->commandList, command);
1902 
1903 	MemoryContextSwitchTo(oldcxt);
1904 }
1905 
1906 /*
1907  * EventTriggerCollectCreateOpClass
1908  *		Save data about a CREATE OPERATOR CLASS command being executed
1909  */
1910 void
1911 EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt, Oid opcoid,
1912 								 List *operators, List *procedures)
1913 {
1914 	MemoryContext oldcxt;
1915 	CollectedCommand *command;
1916 
1917 	/* ignore if event trigger context not set, or collection disabled */
1918 	if (!currentEventTriggerState ||
1919 		currentEventTriggerState->commandCollectionInhibited)
1920 		return;
1921 
1922 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1923 
1924 	command = palloc0(sizeof(CollectedCommand));
1925 	command->type = SCT_CreateOpClass;
1926 	command->in_extension = creating_extension;
1927 	ObjectAddressSet(command->d.createopc.address,
1928 					 OperatorClassRelationId, opcoid);
1929 	command->d.createopc.operators = operators;
1930 	command->d.createopc.procedures = procedures;
1931 	command->parsetree = (Node *) copyObject(stmt);
1932 
1933 	currentEventTriggerState->commandList =
1934 		lappend(currentEventTriggerState->commandList, command);
1935 
1936 	MemoryContextSwitchTo(oldcxt);
1937 }
1938 
1939 /*
1940  * EventTriggerCollectAlterTSConfig
1941  *		Save data about an ALTER TEXT SEARCH CONFIGURATION command being
1942  *		executed
1943  */
1944 void
1945 EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt, Oid cfgId,
1946 								 Oid *dictIds, int ndicts)
1947 {
1948 	MemoryContext oldcxt;
1949 	CollectedCommand *command;
1950 
1951 	/* ignore if event trigger context not set, or collection disabled */
1952 	if (!currentEventTriggerState ||
1953 		currentEventTriggerState->commandCollectionInhibited)
1954 		return;
1955 
1956 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1957 
1958 	command = palloc0(sizeof(CollectedCommand));
1959 	command->type = SCT_AlterTSConfig;
1960 	command->in_extension = creating_extension;
1961 	ObjectAddressSet(command->d.atscfg.address,
1962 					 TSConfigRelationId, cfgId);
1963 	command->d.atscfg.dictIds = palloc(sizeof(Oid) * ndicts);
1964 	memcpy(command->d.atscfg.dictIds, dictIds, sizeof(Oid) * ndicts);
1965 	command->d.atscfg.ndicts = ndicts;
1966 	command->parsetree = (Node *) copyObject(stmt);
1967 
1968 	currentEventTriggerState->commandList =
1969 		lappend(currentEventTriggerState->commandList, command);
1970 
1971 	MemoryContextSwitchTo(oldcxt);
1972 }
1973 
1974 /*
1975  * EventTriggerCollectAlterDefPrivs
1976  *		Save data about an ALTER DEFAULT PRIVILEGES command being
1977  *		executed
1978  */
1979 void
1980 EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
1981 {
1982 	MemoryContext oldcxt;
1983 	CollectedCommand *command;
1984 
1985 	/* ignore if event trigger context not set, or collection disabled */
1986 	if (!currentEventTriggerState ||
1987 		currentEventTriggerState->commandCollectionInhibited)
1988 		return;
1989 
1990 	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
1991 
1992 	command = palloc0(sizeof(CollectedCommand));
1993 	command->type = SCT_AlterDefaultPrivileges;
1994 	command->d.defprivs.objtype = stmt->action->objtype;
1995 	command->in_extension = creating_extension;
1996 	command->parsetree = (Node *) copyObject(stmt);
1997 
1998 	currentEventTriggerState->commandList =
1999 		lappend(currentEventTriggerState->commandList, command);
2000 	MemoryContextSwitchTo(oldcxt);
2001 }
2002 
2003 /*
2004  * In a ddl_command_end event trigger, this function reports the DDL commands
2005  * being run.
2006  */
2007 Datum
2008 pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
2009 {
2010 	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2011 	TupleDesc	tupdesc;
2012 	Tuplestorestate *tupstore;
2013 	MemoryContext per_query_ctx;
2014 	MemoryContext oldcontext;
2015 	ListCell   *lc;
2016 
2017 	/*
2018 	 * Protect this function from being called out of context
2019 	 */
2020 	if (!currentEventTriggerState)
2021 		ereport(ERROR,
2022 				(errcode(ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED),
2023 				 errmsg("%s can only be called in an event trigger function",
2024 						"pg_event_trigger_ddl_commands()")));
2025 
2026 	/* check to see if caller supports us returning a tuplestore */
2027 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2028 		ereport(ERROR,
2029 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2030 				 errmsg("set-valued function called in context that cannot accept a set")));
2031 	if (!(rsinfo->allowedModes & SFRM_Materialize))
2032 		ereport(ERROR,
2033 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2034 				 errmsg("materialize mode required, but it is not allowed in this context")));
2035 
2036 	/* Build a tuple descriptor for our result type */
2037 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2038 		elog(ERROR, "return type must be a row type");
2039 
2040 	/* Build tuplestore to hold the result rows */
2041 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2042 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
2043 
2044 	tupstore = tuplestore_begin_heap(true, false, work_mem);
2045 	rsinfo->returnMode = SFRM_Materialize;
2046 	rsinfo->setResult = tupstore;
2047 	rsinfo->setDesc = tupdesc;
2048 
2049 	MemoryContextSwitchTo(oldcontext);
2050 
2051 	foreach(lc, currentEventTriggerState->commandList)
2052 	{
2053 		CollectedCommand *cmd = lfirst(lc);
2054 		Datum		values[9];
2055 		bool		nulls[9];
2056 		ObjectAddress addr;
2057 		int			i = 0;
2058 
2059 		/*
2060 		 * For IF NOT EXISTS commands that attempt to create an existing
2061 		 * object, the returned OID is Invalid.  Don't return anything.
2062 		 *
2063 		 * One might think that a viable alternative would be to look up the
2064 		 * Oid of the existing object and run the deparse with that.  But
2065 		 * since the parse tree might be different from the one that created
2066 		 * the object in the first place, we might not end up in a consistent
2067 		 * state anyway.
2068 		 */
2069 		if (cmd->type == SCT_Simple &&
2070 			!OidIsValid(cmd->d.simple.address.objectId))
2071 			continue;
2072 
2073 		MemSet(nulls, 0, sizeof(nulls));
2074 
2075 		switch (cmd->type)
2076 		{
2077 			case SCT_Simple:
2078 			case SCT_AlterTable:
2079 			case SCT_AlterOpFamily:
2080 			case SCT_CreateOpClass:
2081 			case SCT_AlterTSConfig:
2082 				{
2083 					char	   *identity;
2084 					char	   *type;
2085 					char	   *schema = NULL;
2086 
2087 					if (cmd->type == SCT_Simple)
2088 						addr = cmd->d.simple.address;
2089 					else if (cmd->type == SCT_AlterTable)
2090 						ObjectAddressSet(addr,
2091 										 cmd->d.alterTable.classId,
2092 										 cmd->d.alterTable.objectId);
2093 					else if (cmd->type == SCT_AlterOpFamily)
2094 						addr = cmd->d.opfam.address;
2095 					else if (cmd->type == SCT_CreateOpClass)
2096 						addr = cmd->d.createopc.address;
2097 					else if (cmd->type == SCT_AlterTSConfig)
2098 						addr = cmd->d.atscfg.address;
2099 
2100 					type = getObjectTypeDescription(&addr);
2101 					identity = getObjectIdentity(&addr);
2102 
2103 					/*
2104 					 * Obtain schema name, if any ("pg_temp" if a temp
2105 					 * object). If the object class is not in the supported
2106 					 * list here, we assume it's a schema-less object type,
2107 					 * and thus "schema" remains set to NULL.
2108 					 */
2109 					if (is_objectclass_supported(addr.classId))
2110 					{
2111 						AttrNumber	nspAttnum;
2112 
2113 						nspAttnum = get_object_attnum_namespace(addr.classId);
2114 						if (nspAttnum != InvalidAttrNumber)
2115 						{
2116 							Relation	catalog;
2117 							HeapTuple	objtup;
2118 							Oid			schema_oid;
2119 							bool		isnull;
2120 
2121 							catalog = table_open(addr.classId, AccessShareLock);
2122 							objtup = get_catalog_object_by_oid(catalog,
2123 															   get_object_attnum_oid(addr.classId),
2124 															   addr.objectId);
2125 							if (!HeapTupleIsValid(objtup))
2126 								elog(ERROR, "cache lookup failed for object %u/%u",
2127 									 addr.classId, addr.objectId);
2128 							schema_oid =
2129 								heap_getattr(objtup, nspAttnum,
2130 											 RelationGetDescr(catalog), &isnull);
2131 							if (isnull)
2132 								elog(ERROR,
2133 									 "invalid null namespace in object %u/%u/%d",
2134 									 addr.classId, addr.objectId, addr.objectSubId);
2135 							/* XXX not quite get_namespace_name_or_temp */
2136 							if (isAnyTempNamespace(schema_oid))
2137 								schema = pstrdup("pg_temp");
2138 							else
2139 								schema = get_namespace_name(schema_oid);
2140 
2141 							table_close(catalog, AccessShareLock);
2142 						}
2143 					}
2144 
2145 					/* classid */
2146 					values[i++] = ObjectIdGetDatum(addr.classId);
2147 					/* objid */
2148 					values[i++] = ObjectIdGetDatum(addr.objectId);
2149 					/* objsubid */
2150 					values[i++] = Int32GetDatum(addr.objectSubId);
2151 					/* command tag */
2152 					values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree));
2153 					/* object_type */
2154 					values[i++] = CStringGetTextDatum(type);
2155 					/* schema */
2156 					if (schema == NULL)
2157 						nulls[i++] = true;
2158 					else
2159 						values[i++] = CStringGetTextDatum(schema);
2160 					/* identity */
2161 					values[i++] = CStringGetTextDatum(identity);
2162 					/* in_extension */
2163 					values[i++] = BoolGetDatum(cmd->in_extension);
2164 					/* command */
2165 					values[i++] = PointerGetDatum(cmd);
2166 				}
2167 				break;
2168 
2169 			case SCT_AlterDefaultPrivileges:
2170 				/* classid */
2171 				nulls[i++] = true;
2172 				/* objid */
2173 				nulls[i++] = true;
2174 				/* objsubid */
2175 				nulls[i++] = true;
2176 				/* command tag */
2177 				values[i++] = CStringGetTextDatum(CreateCommandTag(cmd->parsetree));
2178 				/* object_type */
2179 				values[i++] = CStringGetTextDatum(stringify_adefprivs_objtype(
2180 																			  cmd->d.defprivs.objtype));
2181 				/* schema */
2182 				nulls[i++] = true;
2183 				/* identity */
2184 				nulls[i++] = true;
2185 				/* in_extension */
2186 				values[i++] = BoolGetDatum(cmd->in_extension);
2187 				/* command */
2188 				values[i++] = PointerGetDatum(cmd);
2189 				break;
2190 
2191 			case SCT_Grant:
2192 				/* classid */
2193 				nulls[i++] = true;
2194 				/* objid */
2195 				nulls[i++] = true;
2196 				/* objsubid */
2197 				nulls[i++] = true;
2198 				/* command tag */
2199 				values[i++] = CStringGetTextDatum(cmd->d.grant.istmt->is_grant ?
2200 												  "GRANT" : "REVOKE");
2201 				/* object_type */
2202 				values[i++] = CStringGetTextDatum(stringify_grant_objtype(
2203 																		  cmd->d.grant.istmt->objtype));
2204 				/* schema */
2205 				nulls[i++] = true;
2206 				/* identity */
2207 				nulls[i++] = true;
2208 				/* in_extension */
2209 				values[i++] = BoolGetDatum(cmd->in_extension);
2210 				/* command */
2211 				values[i++] = PointerGetDatum(cmd);
2212 				break;
2213 		}
2214 
2215 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2216 	}
2217 
2218 	/* clean up and return the tuplestore */
2219 	tuplestore_donestoring(tupstore);
2220 
2221 	PG_RETURN_VOID();
2222 }
2223 
2224 /*
2225  * Return the ObjectType as a string, as it would appear in GRANT and
2226  * REVOKE commands.
2227  */
2228 static const char *
2229 stringify_grant_objtype(ObjectType objtype)
2230 {
2231 	switch (objtype)
2232 	{
2233 		case OBJECT_COLUMN:
2234 			return "COLUMN";
2235 		case OBJECT_TABLE:
2236 			return "TABLE";
2237 		case OBJECT_SEQUENCE:
2238 			return "SEQUENCE";
2239 		case OBJECT_DATABASE:
2240 			return "DATABASE";
2241 		case OBJECT_DOMAIN:
2242 			return "DOMAIN";
2243 		case OBJECT_FDW:
2244 			return "FOREIGN DATA WRAPPER";
2245 		case OBJECT_FOREIGN_SERVER:
2246 			return "FOREIGN SERVER";
2247 		case OBJECT_FUNCTION:
2248 			return "FUNCTION";
2249 		case OBJECT_LANGUAGE:
2250 			return "LANGUAGE";
2251 		case OBJECT_LARGEOBJECT:
2252 			return "LARGE OBJECT";
2253 		case OBJECT_SCHEMA:
2254 			return "SCHEMA";
2255 		case OBJECT_PROCEDURE:
2256 			return "PROCEDURE";
2257 		case OBJECT_ROUTINE:
2258 			return "ROUTINE";
2259 		case OBJECT_TABLESPACE:
2260 			return "TABLESPACE";
2261 		case OBJECT_TYPE:
2262 			return "TYPE";
2263 			/* these currently aren't used */
2264 		case OBJECT_ACCESS_METHOD:
2265 		case OBJECT_AGGREGATE:
2266 		case OBJECT_AMOP:
2267 		case OBJECT_AMPROC:
2268 		case OBJECT_ATTRIBUTE:
2269 		case OBJECT_CAST:
2270 		case OBJECT_COLLATION:
2271 		case OBJECT_CONVERSION:
2272 		case OBJECT_DEFAULT:
2273 		case OBJECT_DEFACL:
2274 		case OBJECT_DOMCONSTRAINT:
2275 		case OBJECT_EVENT_TRIGGER:
2276 		case OBJECT_EXTENSION:
2277 		case OBJECT_FOREIGN_TABLE:
2278 		case OBJECT_INDEX:
2279 		case OBJECT_MATVIEW:
2280 		case OBJECT_OPCLASS:
2281 		case OBJECT_OPERATOR:
2282 		case OBJECT_OPFAMILY:
2283 		case OBJECT_POLICY:
2284 		case OBJECT_PUBLICATION:
2285 		case OBJECT_PUBLICATION_REL:
2286 		case OBJECT_ROLE:
2287 		case OBJECT_RULE:
2288 		case OBJECT_STATISTIC_EXT:
2289 		case OBJECT_SUBSCRIPTION:
2290 		case OBJECT_TABCONSTRAINT:
2291 		case OBJECT_TRANSFORM:
2292 		case OBJECT_TRIGGER:
2293 		case OBJECT_TSCONFIGURATION:
2294 		case OBJECT_TSDICTIONARY:
2295 		case OBJECT_TSPARSER:
2296 		case OBJECT_TSTEMPLATE:
2297 		case OBJECT_USER_MAPPING:
2298 		case OBJECT_VIEW:
2299 			elog(ERROR, "unsupported object type: %d", (int) objtype);
2300 	}
2301 
2302 	return "???";				/* keep compiler quiet */
2303 }
2304 
2305 /*
2306  * Return the ObjectType as a string; as above, but use the spelling
2307  * in ALTER DEFAULT PRIVILEGES commands instead.  Generally this is just
2308  * the plural.
2309  */
2310 static const char *
2311 stringify_adefprivs_objtype(ObjectType objtype)
2312 {
2313 	switch (objtype)
2314 	{
2315 		case OBJECT_COLUMN:
2316 			return "COLUMNS";
2317 		case OBJECT_TABLE:
2318 			return "TABLES";
2319 		case OBJECT_SEQUENCE:
2320 			return "SEQUENCES";
2321 		case OBJECT_DATABASE:
2322 			return "DATABASES";
2323 		case OBJECT_DOMAIN:
2324 			return "DOMAINS";
2325 		case OBJECT_FDW:
2326 			return "FOREIGN DATA WRAPPERS";
2327 		case OBJECT_FOREIGN_SERVER:
2328 			return "FOREIGN SERVERS";
2329 		case OBJECT_FUNCTION:
2330 			return "FUNCTIONS";
2331 		case OBJECT_LANGUAGE:
2332 			return "LANGUAGES";
2333 		case OBJECT_LARGEOBJECT:
2334 			return "LARGE OBJECTS";
2335 		case OBJECT_SCHEMA:
2336 			return "SCHEMAS";
2337 		case OBJECT_PROCEDURE:
2338 			return "PROCEDURES";
2339 		case OBJECT_ROUTINE:
2340 			return "ROUTINES";
2341 		case OBJECT_TABLESPACE:
2342 			return "TABLESPACES";
2343 		case OBJECT_TYPE:
2344 			return "TYPES";
2345 			/* these currently aren't used */
2346 		case OBJECT_ACCESS_METHOD:
2347 		case OBJECT_AGGREGATE:
2348 		case OBJECT_AMOP:
2349 		case OBJECT_AMPROC:
2350 		case OBJECT_ATTRIBUTE:
2351 		case OBJECT_CAST:
2352 		case OBJECT_COLLATION:
2353 		case OBJECT_CONVERSION:
2354 		case OBJECT_DEFAULT:
2355 		case OBJECT_DEFACL:
2356 		case OBJECT_DOMCONSTRAINT:
2357 		case OBJECT_EVENT_TRIGGER:
2358 		case OBJECT_EXTENSION:
2359 		case OBJECT_FOREIGN_TABLE:
2360 		case OBJECT_INDEX:
2361 		case OBJECT_MATVIEW:
2362 		case OBJECT_OPCLASS:
2363 		case OBJECT_OPERATOR:
2364 		case OBJECT_OPFAMILY:
2365 		case OBJECT_POLICY:
2366 		case OBJECT_PUBLICATION:
2367 		case OBJECT_PUBLICATION_REL:
2368 		case OBJECT_ROLE:
2369 		case OBJECT_RULE:
2370 		case OBJECT_STATISTIC_EXT:
2371 		case OBJECT_SUBSCRIPTION:
2372 		case OBJECT_TABCONSTRAINT:
2373 		case OBJECT_TRANSFORM:
2374 		case OBJECT_TRIGGER:
2375 		case OBJECT_TSCONFIGURATION:
2376 		case OBJECT_TSDICTIONARY:
2377 		case OBJECT_TSPARSER:
2378 		case OBJECT_TSTEMPLATE:
2379 		case OBJECT_USER_MAPPING:
2380 		case OBJECT_VIEW:
2381 			elog(ERROR, "unsupported object type: %d", (int) objtype);
2382 	}
2383 
2384 	return "???";				/* keep compiler quiet */
2385 }
2386