pg_event_trigger_dropped_objects: add is_temp column
authorAlvaro Herrera <[email protected]>
Mon, 6 Apr 2015 14:40:55 +0000 (11:40 -0300)
committerAlvaro Herrera <[email protected]>
Mon, 6 Apr 2015 14:40:55 +0000 (11:40 -0300)
It now also reports temporary objects dropped that are local to the
backend.  Previously we weren't reporting any temp objects because it
was deemed unnecessary; but as it turns out, it is necessary if we want
to keep close track of DDL command execution inside one session.  Temp
objects are reported as living in schema pg_temp, which works because
such a schema-qualification always refers to the temp objects of the
current session.

doc/src/sgml/func.sgml
src/backend/catalog/objectaddress.c
src/backend/commands/event_trigger.c
src/backend/utils/adt/format_type.c
src/backend/utils/adt/regproc.c
src/backend/utils/cache/lsyscache.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/lsyscache.h
src/test/regress/expected/event_trigger.out
src/test/regress/sql/event_trigger.sql

index 53f31b51f54adfb82a7bb46579de9d45bfdb1ee3..5f7bf6aa13e83fcb3afd00bffe8776f236a7d928 100644 (file)
@@ -17877,6 +17877,13 @@ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
          in the dependency graph leading to this object
         </entry>
        </row>
+       <row>
+        <entry><literal>is_temporary</literal></entry>
+        <entry><type>bool</type></entry>
+        <entry>
+         Flag indicating that the object was a temporary object.
+        </entry>
+       </row>
        <row>
         <entry><literal>object_type</literal></entry>
         <entry><type>text</type></entry>
index cf79ea5cc937cdcc8dc929116f75174f0b4203b0..30cb6990726945d4aa81e6424a0c51f7d5db5526 100644 (file)
@@ -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)));
index 4bcc327a2b592a6f8d1ed6b35c14da6fb2f2ba88..0026e53e8425342d0cf230a7ef0ddabfc415ed65 100644 (file)
@@ -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);
 
index fc816cef8521d62b185e3aba7872c04ecca87b59..2f0f0a1d8952587b7f34913c465cf78aaedba208 100644 (file)
@@ -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);
 
index 3d1bb32030e443ee690d33b2abbc8166f9d2d769..11d663b295d1467a760e6c14d251a7c176bb9d3e 100644 (file)
@@ -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)
index 818c2f619ba1c96a0fee2cffbabde8b90369ba8a..6a3986389065f4b6f8d146b598ddec82b22591a7 100644 (file)
@@ -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 ----------                             */
 
 /*
index c20c634367a92147ef0431a6930e94655730fa21..5191526bef7ee2cee7a9af3ec2d9f3fb3eb9a620 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201504021
+#define CATALOG_VERSION_NO     201504061
 
 #endif
index d90ecc539645c0fe7dcb8c5a7a924e0782465e00..62187fb27415f3bd0b58f00607ed7fa3f6caff7b 100644 (file)
@@ -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");
index 2f5ede1843bae3bebed259f3a0c7fa02bb7f2b01..15bb6d94f5821ce1e2a678b90e00f2e7e3a88cc4 100644 (file)
@@ -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)
index 1dace02782fd98c26dcd37780b4cb16650c25510..24335df88c4c9b79a34e5496425a6f92787aa0ee 100644 (file)
@@ -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();
index 1b7346409c8a124fe773aa6eab0bf56f2c6b50db..9f9646c4dc862273d58864d3f22d594644f8f515 100644 (file)
@@ -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;