diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 7934a1263e..6f3094656c 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17729,6 +17729,19 @@ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); int32 Object sub-id (e.g. attribute number for columns) + + original + bool + Flag used to identify the root object(s) of the deletion + + + normal + bool + + Flag indicating that there's a normal dependency relationship + in the dependency graph leading to this object + + object_type text diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 8ba5123c10..3027259a3a 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -206,16 +206,25 @@ deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel, /* * Keep track of objects for event triggers, if necessary. */ - if (trackDroppedObjectsNeeded()) + if (trackDroppedObjectsNeeded() && !(flags & PERFORM_DELETION_INTERNAL)) { for (i = 0; i < targetObjects->numrefs; i++) { - ObjectAddress *thisobj = targetObjects->refs + i; + const ObjectAddress *thisobj = &targetObjects->refs[i]; + const ObjectAddressExtra *extra = &targetObjects->extras[i]; + bool original = false; + bool normal = false; - if ((!(flags & PERFORM_DELETION_INTERNAL)) && - EventTriggerSupportsObjectClass(getObjectClass(thisobj))) + if (extra->flags & DEPFLAG_ORIGINAL) + original = true; + if (extra->flags & DEPFLAG_NORMAL) + normal = true; + if (extra->flags & DEPFLAG_REVERSE) + normal = true; + + if (EventTriggerSupportsObjectClass(getObjectClass(thisobj))) { - EventTriggerSQLDropAddObject(thisobj); + EventTriggerSQLDropAddObject(thisobj, original, normal); } } } diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 6fb4817845..8b88ecb359 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -117,6 +117,8 @@ typedef struct SQLDropObject const char *objname; const char *objidentity; const char *objecttype; + bool original; + bool normal; slist_node next; } SQLDropObject; @@ -1238,7 +1240,7 @@ trackDroppedObjectsNeeded(void) * Register one object as being dropped by the current command. */ void -EventTriggerSQLDropAddObject(ObjectAddress *object) +EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool normal) { SQLDropObject *obj; MemoryContext oldcxt; @@ -1257,6 +1259,8 @@ EventTriggerSQLDropAddObject(ObjectAddress *object) obj = palloc0(sizeof(SQLDropObject)); obj->address = *object; + obj->original = original; + obj->normal = normal; /* * Obtain schema names from the object's catalog tuple, if one exists; @@ -1384,8 +1388,8 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS) { SQLDropObject *obj; int i = 0; - Datum values[7]; - bool nulls[7]; + Datum values[9]; + bool nulls[9]; obj = slist_container(SQLDropObject, next, iter.cur); @@ -1401,6 +1405,12 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS) /* objsubid */ values[i++] = Int32GetDatum(obj->address.objectSubId); + /* original */ + values[i++] = BoolGetDatum(obj->original); + + /* normal */ + values[i++] = BoolGetDatum(obj->normal); + /* object_type */ values[i++] = CStringGetTextDatum(obj->objecttype); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index bedab8b658..5e9961af69 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201412122 +#define CATALOG_VERSION_NO 201412191 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index eace352ec0..f766ed791f 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5075,7 +5075,7 @@ DATA(insert OID = 3785 ( pg_logical_slot_peek_binary_changes PGNSP PGUID 12 100 DESCR("peek at binary changes from replication slot"); /* event triggers */ -DATA(insert OID = 3566 ( pg_event_trigger_dropped_objects PGNSP PGUID 12 10 100 0 0 f f f f t t s 0 0 2249 "" "{26,26,23,25,25,25,25}" "{o,o,o,o,o,o,o}" "{classid, objid, objsubid, object_type, schema_name, object_name, object_identity}" _null_ pg_event_trigger_dropped_objects _null_ _null_ _null_ )); +DATA(insert OID = 3566 ( pg_event_trigger_dropped_objects PGNSP PGUID 12 10 100 0 0 f f f f t t s 0 0 2249 "" "{26,26,23,16,16,25,25,25,25}" "{o,o,o,o,o,o,o,o,o}" "{classid, objid, objsubid, original, normal, object_type, schema_name, object_name, object_identity}" _null_ pg_event_trigger_dropped_objects _null_ _null_ _null_ )); DESCR("list objects dropped by the current command"); DATA(insert OID = 4566 ( pg_event_trigger_table_rewrite_oid PGNSP PGUID 12 1 0 0 0 f f f f t f s 0 0 26 "" "{26}" "{o}" "{oid}" _null_ pg_event_trigger_table_rewrite_oid _null_ _null_ _null_ )); DESCR("return Oid of the table getting rewritten"); diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index bcd656b72d..b402547739 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -56,6 +56,7 @@ extern void EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason); extern bool EventTriggerBeginCompleteQuery(void); extern void EventTriggerEndCompleteQuery(void); extern bool trackDroppedObjectsNeeded(void); -extern void EventTriggerSQLDropAddObject(ObjectAddress *object); +extern void EventTriggerSQLDropAddObject(const ObjectAddress *object, + bool original, bool normal); #endif /* EVENT_TRIGGER_H */ diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out index 5934cf74b1..72e1660d6b 100644 --- a/src/test/regress/expected/event_trigger.out +++ b/src/test/regress/expected/event_trigger.out @@ -294,6 +294,46 @@ SELECT * FROM dropped_objects WHERE type = 'schema'; DROP ROLE regression_bob; DROP EVENT TRIGGER regress_event_trigger_drop_objects; DROP EVENT TRIGGER undroppable; +CREATE OR REPLACE FUNCTION event_trigger_report_dropped() + RETURNS event_trigger + LANGUAGE plpgsql +AS $$ +DECLARE r record; +BEGIN + FOR r IN SELECT * from pg_event_trigger_dropped_objects() + LOOP + IF NOT r.normal AND NOT r.original THEN + CONTINUE; + END IF; + RAISE NOTICE 'NORMAL: orig=% normal=% type=% identity=%', + r.original, r.normal, r.object_type, r.object_identity; + END LOOP; +END; $$; +CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop + EXECUTE PROCEDURE event_trigger_report_dropped(); +CREATE SCHEMA evttrig + CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two') + CREATE INDEX one_idx ON one (col_b) + CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42); +ALTER TABLE evttrig.two DROP COLUMN col_c; +NOTICE: NORMAL: orig=t normal=f type=table column identity=evttrig.two.col_c +NOTICE: NORMAL: orig=f normal=t type=table constraint identity=two_col_c_check on evttrig.two +ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT; +NOTICE: NORMAL: orig=t normal=f type=default value identity=for evttrig.one.col_b +ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey; +NOTICE: NORMAL: orig=t normal=f type=table constraint identity=one_pkey on evttrig.one +DROP INDEX evttrig.one_idx; +NOTICE: NORMAL: orig=t normal=f type=index identity=evttrig.one_idx +DROP SCHEMA evttrig CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to table evttrig.one +drop cascades to table evttrig.two +NOTICE: NORMAL: orig=t normal=f type=schema identity=evttrig +NOTICE: NORMAL: orig=f normal=t type=table identity=evttrig.one +NOTICE: NORMAL: orig=f normal=t type=sequence identity=evttrig.one_col_a_seq +NOTICE: NORMAL: orig=f normal=t type=default value identity=for evttrig.one.col_a +NOTICE: NORMAL: orig=f normal=t type=table identity=evttrig.two +DROP EVENT TRIGGER regress_event_trigger_report_dropped; -- only allowed from within an event trigger function, should fail select pg_event_trigger_table_rewrite_oid(); ERROR: pg_event_trigger_table_rewrite_oid() can only be called in a table_rewrite event trigger function diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql index 02b93c9e1f..7987fde50b 100644 --- a/src/test/regress/sql/event_trigger.sql +++ b/src/test/regress/sql/event_trigger.sql @@ -207,6 +207,36 @@ DROP ROLE regression_bob; DROP EVENT TRIGGER regress_event_trigger_drop_objects; DROP EVENT TRIGGER undroppable; +CREATE OR REPLACE FUNCTION event_trigger_report_dropped() + RETURNS event_trigger + LANGUAGE plpgsql +AS $$ +DECLARE r record; +BEGIN + FOR r IN SELECT * from pg_event_trigger_dropped_objects() + LOOP + IF NOT r.normal AND NOT r.original THEN + CONTINUE; + END IF; + RAISE NOTICE 'NORMAL: orig=% normal=% type=% identity=%', + r.original, r.normal, r.object_type, r.object_identity; + END LOOP; +END; $$; +CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop + EXECUTE PROCEDURE event_trigger_report_dropped(); +CREATE SCHEMA evttrig + CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two') + CREATE INDEX one_idx ON one (col_b) + CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42); + +ALTER TABLE evttrig.two DROP COLUMN col_c; +ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT; +ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey; +DROP INDEX evttrig.one_idx; +DROP SCHEMA evttrig CASCADE; + +DROP EVENT TRIGGER regress_event_trigger_report_dropped; + -- only allowed from within an event trigger function, should fail select pg_event_trigger_table_rewrite_oid();