diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 53f31b51f54..5f7bf6aa13e 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17877,6 +17877,13 @@ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); in the dependency graph leading to this object + + is_temporary + bool + + Flag indicating that the object was a temporary object. + + object_type text diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index cf79ea5cc93..30cb6990726 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -3687,7 +3687,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for collation %u", object->objectId); coll = (Form_pg_collation) GETSTRUCT(collTup); - schema = get_namespace_name(coll->collnamespace); + schema = get_namespace_name_or_temp(coll->collnamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(coll->collname))); @@ -3751,7 +3751,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for conversion %u", object->objectId); conForm = (Form_pg_conversion) GETSTRUCT(conTup); - schema = get_namespace_name(conForm->connamespace); + schema = get_namespace_name_or_temp(conForm->connamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(conForm->conname))); @@ -3849,7 +3849,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for opclass %u", object->objectId); opcForm = (Form_pg_opclass) GETSTRUCT(opcTup); - schema = get_namespace_name(opcForm->opcnamespace); + schema = get_namespace_name_or_temp(opcForm->opcnamespace); amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opcForm->opcmethod)); @@ -4066,7 +4066,7 @@ getObjectIdentityParts(const ObjectAddress *object, { char *nspname; - nspname = get_namespace_name(object->objectId); + nspname = get_namespace_name_or_temp(object->objectId); if (!nspname) elog(ERROR, "cache lookup failed for namespace %u", object->objectId); @@ -4089,7 +4089,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for text search parser %u", object->objectId); formParser = (Form_pg_ts_parser) GETSTRUCT(tup); - schema = get_namespace_name(formParser->prsnamespace); + schema = get_namespace_name_or_temp(formParser->prsnamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(formParser->prsname))); @@ -4112,7 +4112,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for text search dictionary %u", object->objectId); formDict = (Form_pg_ts_dict) GETSTRUCT(tup); - schema = get_namespace_name(formDict->dictnamespace); + schema = get_namespace_name_or_temp(formDict->dictnamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(formDict->dictname))); @@ -4135,7 +4135,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for text search template %u", object->objectId); formTmpl = (Form_pg_ts_template) GETSTRUCT(tup); - schema = get_namespace_name(formTmpl->tmplnamespace); + schema = get_namespace_name_or_temp(formTmpl->tmplnamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(formTmpl->tmplname))); @@ -4158,7 +4158,7 @@ getObjectIdentityParts(const ObjectAddress *object, elog(ERROR, "cache lookup failed for text search configuration %u", object->objectId); formCfg = (Form_pg_ts_config) GETSTRUCT(tup); - schema = get_namespace_name(formCfg->cfgnamespace); + schema = get_namespace_name_or_temp(formCfg->cfgnamespace); appendStringInfoString(&buffer, quote_qualified_identifier(schema, NameStr(formCfg->cfgname))); @@ -4305,7 +4305,7 @@ getObjectIdentityParts(const ObjectAddress *object, if (OidIsValid(defacl->defaclnamespace)) { - schema = get_namespace_name(defacl->defaclnamespace); + schema = get_namespace_name_or_temp(defacl->defaclnamespace); appendStringInfo(&buffer, " in schema %s", quote_identifier(schema)); @@ -4421,7 +4421,7 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname) opfForm->opfmethod); amForm = (Form_pg_am) GETSTRUCT(amTup); - schema = get_namespace_name(opfForm->opfnamespace); + schema = get_namespace_name_or_temp(opfForm->opfnamespace); appendStringInfo(buffer, "%s USING %s", quote_qualified_identifier(schema, NameStr(opfForm->opfname)), @@ -4453,7 +4453,7 @@ getRelationIdentity(StringInfo buffer, Oid relid, List **objname) elog(ERROR, "cache lookup failed for relation %u", relid); relForm = (Form_pg_class) GETSTRUCT(relTup); - schema = get_namespace_name(relForm->relnamespace); + schema = get_namespace_name_or_temp(relForm->relnamespace); appendStringInfoString(buffer, quote_qualified_identifier(schema, NameStr(relForm->relname))); diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 4bcc327a2b5..0026e53e842 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -121,6 +121,7 @@ typedef struct SQLDropObject List *addrargs; bool original; bool normal; + bool istemp; slist_node next; } SQLDropObject; @@ -1294,9 +1295,10 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no Assert(EventTriggerSupportsObjectClass(getObjectClass(object))); - /* don't report temp schemas */ + /* don't report temp schemas except my own */ if (object->classId == NamespaceRelationId && - isAnyTempNamespace(object->objectId)) + (isAnyTempNamespace(object->objectId) && + !isTempNamespace(object->objectId))) return; oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt); @@ -1336,16 +1338,24 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no Oid namespaceId; namespaceId = DatumGetObjectId(datum); - /* Don't report objects in temp namespaces */ - if (isAnyTempNamespace(namespaceId)) + /* temp objects are only reported if they are my own */ + if (isTempNamespace(namespaceId)) + { + obj->schemaname = "pg_temp"; + obj->istemp = true; + } + else if (isAnyTempNamespace(namespaceId)) { pfree(obj); heap_close(catalog, AccessShareLock); MemoryContextSwitchTo(oldcxt); return; } - - obj->schemaname = get_namespace_name(namespaceId); + else + { + obj->schemaname = get_namespace_name(namespaceId); + obj->istemp = false; + } } } @@ -1365,6 +1375,12 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no heap_close(catalog, AccessShareLock); } + else + { + if (object->classId == NamespaceRelationId && + isTempNamespace(object->objectId)) + obj->istemp = true; + } /* object identity, objname and objargs */ obj->objidentity = @@ -1433,8 +1449,8 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS) { SQLDropObject *obj; int i = 0; - Datum values[11]; - bool nulls[11]; + Datum values[12]; + bool nulls[12]; obj = slist_container(SQLDropObject, next, iter.cur); @@ -1456,6 +1472,9 @@ pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS) /* normal */ values[i++] = BoolGetDatum(obj->normal); + /* is_temporary */ + values[i++] = BoolGetDatum(obj->istemp); + /* object_type */ values[i++] = CStringGetTextDatum(obj->objecttype); diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index fc816cef852..2f0f0a1d895 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -305,7 +305,7 @@ format_type_internal(Oid type_oid, int32 typemod, if (!force_qualify && TypeIsVisible(type_oid)) nspname = NULL; else - nspname = get_namespace_name(typeform->typnamespace); + nspname = get_namespace_name_or_temp(typeform->typnamespace); typname = NameStr(typeform->typname); diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 3d1bb32030e..11d663b295d 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -460,7 +460,7 @@ format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs) procform = (Form_pg_proc) GETSTRUCT(proctup); nargs = procform->pronargs; - *objnames = list_make2(get_namespace_name(procform->pronamespace), + *objnames = list_make2(get_namespace_name_or_temp(procform->pronamespace), pstrdup(NameStr(procform->proname))); *objargs = NIL; for (i = 0; i < nargs; i++) @@ -922,7 +922,7 @@ format_operator_parts(Oid operator_oid, List **objnames, List **objargs) operator_oid); oprForm = (Form_pg_operator) GETSTRUCT(opertup); - *objnames = list_make2(get_namespace_name(oprForm->oprnamespace), + *objnames = list_make2(get_namespace_name_or_temp(oprForm->oprnamespace), pstrdup(NameStr(oprForm->oprname))); *objargs = NIL; if (oprForm->oprleft) diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 818c2f619ba..6a398638906 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -19,6 +19,7 @@ #include "access/htup_details.h" #include "access/nbtree.h" #include "bootstrap/bootstrap.h" +#include "catalog/namespace.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_collation.h" @@ -2884,6 +2885,20 @@ get_namespace_name(Oid nspid) return NULL; } +/* + * get_namespace_name_or_temp + * As above, but if it is this backend's temporary namespace, return + * "pg_temp" instead. + */ +char * +get_namespace_name_or_temp(Oid nspid) +{ + if (isTempNamespace(nspid)) + return "pg_temp"; + else + return get_namespace_name(nspid); +} + /* ---------- PG_RANGE CACHE ---------- */ /* diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c20c634367a..5191526bef7 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201504021 +#define CATALOG_VERSION_NO 201504061 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index d90ecc53964..62187fb2741 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -5120,8 +5120,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,16,16,25,25,25,25,1009,1009}" "{o,o,o,o,o,o,o,o,o,o,o}" "{classid, objid, objsubid, original, normal, object_type, schema_name, object_name, object_identity, address_names, address_args}" _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,16,25,25,25,25,1009,1009}" "{o,o,o,o,o,o,o,o,o,o,o,o}" "{classid, objid, objsubid, original, normal, is_temporary, object_type, schema_name, object_name, object_identity, address_names, address_args}" _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/utils/lsyscache.h b/src/include/utils/lsyscache.h index 2f5ede1843b..15bb6d94f58 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -151,6 +151,7 @@ extern void free_attstatsslot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers); extern char *get_namespace_name(Oid nspid); +extern char *get_namespace_name_or_temp(Oid nspid); extern Oid get_range_subtype(Oid rangeOid); #define type_is_array(typid) (get_element_type(typid) != InvalidOid) diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out index 1dace02782f..24335df88c4 100644 --- a/src/test/regress/expected/event_trigger.out +++ b/src/test/regress/expected/event_trigger.out @@ -151,6 +151,7 @@ drop event trigger regress_event_trigger_end; CREATE SCHEMA schema_one authorization regression_bob; CREATE SCHEMA schema_two authorization regression_bob; CREATE SCHEMA audit_tbls authorization regression_bob; +CREATE TEMP TABLE a_temp_tbl (); SET SESSION AUTHORIZATION regression_bob; CREATE TABLE schema_one.table_one(a int); CREATE TABLE schema_one."table two"(a int); @@ -352,9 +353,9 @@ BEGIN IF NOT r.normal AND NOT r.original THEN CONTINUE; END IF; - RAISE NOTICE 'NORMAL: orig=% normal=% type=% identity=% name=% args=%', - r.original, r.normal, r.object_type, r.object_identity, - r.address_names, r.address_args; + RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% name=% args=%', + r.original, r.normal, r.is_temporary, r.object_type, + r.object_identity, r.address_names, r.address_args; END LOOP; END; $$; CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop @@ -364,23 +365,25 @@ CREATE SCHEMA evttrig 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 name={evttrig,two,col_c} args={} -NOTICE: NORMAL: orig=f normal=t type=table constraint identity=two_col_c_check on evttrig.two name={evttrig,two,two_col_c_check} args={} +NOTICE: NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.two.col_c name={evttrig,two,col_c} args={} +NOTICE: NORMAL: orig=f normal=t istemp=f type=table constraint identity=two_col_c_check on evttrig.two name={evttrig,two,two_col_c_check} args={} 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 name={evttrig,one,col_b} args={} +NOTICE: NORMAL: orig=t normal=f istemp=f type=default value identity=for evttrig.one.col_b name={evttrig,one,col_b} args={} ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey; -NOTICE: NORMAL: orig=t normal=f type=table constraint identity=one_pkey on evttrig.one name={evttrig,one,one_pkey} args={} +NOTICE: NORMAL: orig=t normal=f istemp=f type=table constraint identity=one_pkey on evttrig.one name={evttrig,one,one_pkey} args={} DROP INDEX evttrig.one_idx; -NOTICE: NORMAL: orig=t normal=f type=index identity=evttrig.one_idx name={evttrig,one_idx} args={} +NOTICE: NORMAL: orig=t normal=f istemp=f type=index identity=evttrig.one_idx name={evttrig,one_idx} args={} 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 name={evttrig} args={} -NOTICE: NORMAL: orig=f normal=t type=table identity=evttrig.one name={evttrig,one} args={} -NOTICE: NORMAL: orig=f normal=t type=sequence identity=evttrig.one_col_a_seq name={evttrig,one_col_a_seq} args={} -NOTICE: NORMAL: orig=f normal=t type=default value identity=for evttrig.one.col_a name={evttrig,one,col_a} args={} -NOTICE: NORMAL: orig=f normal=t type=table identity=evttrig.two name={evttrig,two} args={} +NOTICE: NORMAL: orig=t normal=f istemp=f type=schema identity=evttrig name={evttrig} args={} +NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.one name={evttrig,one} args={} +NOTICE: NORMAL: orig=f normal=t istemp=f type=sequence identity=evttrig.one_col_a_seq name={evttrig,one_col_a_seq} args={} +NOTICE: NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_a name={evttrig,one,col_a} args={} +NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.two name={evttrig,two} args={} +DROP TABLE a_temp_tbl; +NOTICE: NORMAL: orig=t normal=f istemp=t type=table identity=pg_temp.a_temp_tbl name={pg_temp,a_temp_tbl} args={} 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(); diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql index 1b7346409c8..9f9646c4dc8 100644 --- a/src/test/regress/sql/event_trigger.sql +++ b/src/test/regress/sql/event_trigger.sql @@ -143,6 +143,7 @@ drop event trigger regress_event_trigger_end; CREATE SCHEMA schema_one authorization regression_bob; CREATE SCHEMA schema_two authorization regression_bob; CREATE SCHEMA audit_tbls authorization regression_bob; +CREATE TEMP TABLE a_temp_tbl (); SET SESSION AUTHORIZATION regression_bob; CREATE TABLE schema_one.table_one(a int); @@ -253,9 +254,9 @@ BEGIN IF NOT r.normal AND NOT r.original THEN CONTINUE; END IF; - RAISE NOTICE 'NORMAL: orig=% normal=% type=% identity=% name=% args=%', - r.original, r.normal, r.object_type, r.object_identity, - r.address_names, r.address_args; + RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% name=% args=%', + r.original, r.normal, r.is_temporary, r.object_type, + r.object_identity, r.address_names, r.address_args; END LOOP; END; $$; CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop @@ -270,6 +271,7 @@ 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 TABLE a_temp_tbl; DROP EVENT TRIGGER regress_event_trigger_report_dropped;