Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Extend object access hook framework to support arguments, and DROP.
authorRobert Haas <rhaas@postgresql.org>
Fri, 9 Mar 2012 19:34:56 +0000 (14:34 -0500)
committerRobert Haas <rhaas@postgresql.org>
Fri, 9 Mar 2012 19:34:56 +0000 (14:34 -0500)
This allows loadable modules to get control at drop time, perhaps for the
purpose of performing additional security checks or to log the event.
The initial purpose of this code is to support sepgsql, but other
applications should be possible as well.

KaiGai Kohei, reviewed by me.

23 files changed:
src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/catalog/pg_collation.c
src/backend/catalog/pg_constraint.c
src/backend/catalog/pg_conversion.c
src/backend/catalog/pg_namespace.c
src/backend/catalog/pg_operator.c
src/backend/catalog/pg_proc.c
src/backend/catalog/pg_type.c
src/backend/commands/dbcommands.c
src/backend/commands/extension.c
src/backend/commands/foreigncmds.c
src/backend/commands/functioncmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/proclang.c
src/backend/commands/tablecmds.c
src/backend/commands/tablespace.c
src/backend/commands/trigger.c
src/backend/commands/tsearchcmds.c
src/backend/commands/user.c
src/backend/rewrite/rewriteDefine.c
src/backend/storage/large_object/inv_api.c
src/include/catalog/objectaccess.h

index eca064f0cdef7ee6367b76a4da785e29a9cfdbc6..1b92f5c38a1efa97dc644cb769ba1feae55e35a5 100644 (file)
@@ -20,6 +20,7 @@
 #include "catalog/heap.h"
 #include "catalog/index.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_attrdef.h"
@@ -991,6 +992,15 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
    SysScanDesc scan;
    HeapTuple   tup;
 
+   /* DROP hook of the objects being removed */
+   if (object_access_hook)
+   {
+       ObjectAccessDrop    drop_arg;
+       drop_arg.dropflags = flags;
+       InvokeObjectAccessHook(OAT_DROP, object->classId, object->objectId,
+                              object->objectSubId, &drop_arg);
+   }
+
    /*
     * First remove any pg_depend records that link from this object to
     * others.  (Any records linking to this object should be gone already.)
index d1d458d7fa485606f1c0e877fdd558b42f6ea273..8bd5a9296e1be06bbfc944c08c1d42863a7dc142 100644 (file)
@@ -1286,7 +1286,8 @@ heap_create_with_catalog(const char *relname,
    }
 
    /* Post creation hook for new relation */
-   InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          RelationRelationId, relid, 0, NULL);
 
    /*
     * Store any supplied constraints and defaults.
index 511d70c044d6ba18c809296befb5035e8bc19493..18c7acf0e81ffe2582cea769dfe2b8122a2fab4d 100644 (file)
@@ -136,7 +136,7 @@ CollationCreate(const char *collname, Oid collnamespace,
 
    /* Post creation hook for new collation */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          CollationRelationId, oid, 0);
+                          CollationRelationId, oid, 0, NULL);
 
    heap_freetuple(tup);
    heap_close(rel, RowExclusiveLock);
index 0bad4d99cb42f5018578d124856605f2116992a0..342cf75270a3f4b6b19d35d4394d27ca06708055 100644 (file)
@@ -366,7 +366,8 @@ CreateConstraintEntry(const char *constraintName,
    }
 
    /* Post creation hook for new constraint */
-   InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          ConstraintRelationId, conOid, 0, NULL);
 
    return conOid;
 }
index 8194cd6c2671f9131d581aa8e5a6c03293ac76a0..f86c84fc4bb239e7cf83844794d86e51bb43711b 100644 (file)
@@ -134,8 +134,8 @@ ConversionCreate(const char *conname, Oid connamespace,
    recordDependencyOnCurrentExtension(&myself, false);
 
    /* Post creation hook for new conversion */
-   InvokeObjectAccessHook(OAT_POST_CREATE,
-                          ConversionRelationId, HeapTupleGetOid(tup), 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE, ConversionRelationId,
+                          HeapTupleGetOid(tup), 0, NULL);
 
    heap_freetuple(tup);
    heap_close(rel, RowExclusiveLock);
index be812a246c09dbc92f762fb50f1a6fac0e074f73..de856760f08b37427bbdda04dd12306a0d629e0f 100644 (file)
@@ -95,7 +95,8 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
        recordDependencyOnCurrentExtension(&myself, false);
 
    /* Post creation hook for new schema */
-   InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          NamespaceRelationId, nspoid, 0, NULL);
 
    return nspoid;
 }
index 3b727222413ac8e6467723a770904f478660239e..4fd55ae570607d97c538762f1ba0955257741e14 100644 (file)
@@ -275,7 +275,7 @@ OperatorShellMake(const char *operatorName,
 
    /* Post creation hook for new shell operator */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          OperatorRelationId, operatorObjectId, 0);
+                          OperatorRelationId, operatorObjectId, 0, NULL);
 
    /*
     * Make sure the tuple is visible for subsequent lookups/updates.
@@ -544,7 +544,7 @@ OperatorCreate(const char *operatorName,
 
    /* Post creation hook for new operator */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          OperatorRelationId, operatorObjectId, 0);
+                          OperatorRelationId, operatorObjectId, 0, NULL);
 
    heap_close(pg_operator_desc, RowExclusiveLock);
 
index 91ead4cb9d266d2be520c0838e7fcc2a482b85b2..1fffe1c6ac313717191fd9427dbcb2ba8af2da15 100644 (file)
@@ -655,7 +655,8 @@ ProcedureCreate(const char *procedureName,
    heap_freetuple(tup);
 
    /* Post creation hook for new function */
-   InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          ProcedureRelationId, retval, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 
index 2c2e3b3e7cf95f201f6b0760c749a1b79fff7013..5b2ad6bfe0d41d1bf60e2df0aa7cb905e4be0896 100644 (file)
@@ -162,7 +162,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
                                 false);
 
    /* Post creation hook for new shell type */
-   InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TypeRelationId, typoid, 0, NULL);
 
    /*
     * clean up and return the type-oid
@@ -474,7 +475,8 @@ TypeCreate(Oid newTypeOid,
                                 rebuildDeps);
 
    /* Post creation hook for new type */
-   InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TypeRelationId, typeObjectId, 0, NULL);
 
    /*
     * finish up
index 42a8b31b2a8263dad3a548a046f1e1999bfabbea..91d74815287c1f6d46359b1a0ad0bddd0fd763be 100644 (file)
@@ -515,7 +515,8 @@ createdb(const CreatedbStmt *stmt)
    copyTemplateDependencies(src_dboid, dboid);
 
    /* Post creation hook for new database */
-   InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          DatabaseRelationId, dboid, 0, NULL);
 
    /*
     * Force a checkpoint before starting the copy. This will force dirty
@@ -777,6 +778,15 @@ dropdb(const char *dbname, bool missing_ok)
        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
                       dbname);
 
+   /* DROP hook for the database being removed */
+   if (object_access_hook)
+   {
+       ObjectAccessDrop    drop_arg;
+       memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+       InvokeObjectAccessHook(OAT_DROP,
+                              DatabaseRelationId, db_id, 0, &drop_arg);
+   }
+
    /*
     * Disallow dropping a DB that is marked istemplate.  This is just to
     * prevent people from accidentally dropping template0 or template1; they
index a9963ac93b939479617581669377696e56fca1c2..732791cc41366fa9770765d8b24f2b8b74203a97 100644 (file)
@@ -1558,7 +1558,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
    }
    /* Post creation hook for new extension */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          ExtensionRelationId, extensionOid, 0);
+                          ExtensionRelationId, extensionOid, 0, NULL);
 
    return extensionOid;
 }
index 5d18bdcf0a972b7da4cd334d584ceab1f9269776..30135e6de8b027b7b932c188f146f545e9af5d89 100644 (file)
@@ -666,7 +666,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 
    /* Post creation hook for new foreign data wrapper */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          ForeignDataWrapperRelationId, fdwId, 0);
+                          ForeignDataWrapperRelationId, fdwId, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 }
@@ -962,7 +962,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
    recordDependencyOnCurrentExtension(&myself, false);
 
    /* Post creation hook for new foreign server */
-   InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          ForeignServerRelationId, srvId, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 }
@@ -1202,7 +1203,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
    recordDependencyOnCurrentExtension(&myself, false);
 
    /* Post creation hook for new user mapping */
-   InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          UserMappingRelationId, umId, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 }
index ce866a20a990c664f525908a1eff90c12a1b08d3..4125b97e89eb24e00b95f100024ff2b36b0f94ec 100644 (file)
@@ -1759,7 +1759,8 @@ CreateCast(CreateCastStmt *stmt)
    recordDependencyOnCurrentExtension(&myself, false);
 
    /* Post creation hook for new cast */
-   InvokeObjectAccessHook(OAT_POST_CREATE, CastRelationId, castid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          CastRelationId, castid, 0, NULL);
 
    heap_freetuple(tuple);
 
index 5dc131a50e2221d01804ee2a57cf6de68e86bdfd..87c889604e2ad0d40da4a550438c7d203de642b9 100644 (file)
@@ -314,7 +314,7 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
 
    /* Post creation hook for new operator family */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          OperatorFamilyRelationId, opfamilyoid, 0);
+                          OperatorFamilyRelationId, opfamilyoid, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 
@@ -717,7 +717,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 
    /* Post creation hook for new operator class */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          OperatorClassRelationId, opclassoid, 0);
+                          OperatorClassRelationId, opclassoid, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 }
index 8d6a0416d5ff9ea1d7fe457a3a7c9b6e032f1166..41775fd86745a4538c2e26689e7cbf5ef56f8c26 100644 (file)
@@ -428,7 +428,7 @@ create_proc_lang(const char *languageName, bool replace,
 
    /* Post creation hook for new procedural language */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          LanguageRelationId, myself.objectId, 0);
+                          LanguageRelationId, myself.objectId, 0, NULL);
 
    heap_close(rel, RowExclusiveLock);
 }
index cd4490a1c24e5954213d075d768cb5021cdc11a9..25ca356b867ec799625cae5b215151a0284472f0 100644 (file)
@@ -4382,7 +4382,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
    /* Post creation hook for new attribute */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          RelationRelationId, myrelid, newattnum);
+                          RelationRelationId, myrelid, newattnum, NULL);
 
    heap_close(pgclass, RowExclusiveLock);
 
index 5e10f8c9a33b7055ad47566a10ca141dd76a72d8..d66ea3b6c12a953a74e6e5696535ac0e306c5ccd 100644 (file)
@@ -330,7 +330,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 
    /* Post creation hook for new tablespace */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          TableSpaceRelationId, tablespaceoid, 0);
+                          TableSpaceRelationId, tablespaceoid, 0, NULL);
 
    create_tablespace_directories(location, tablespaceoid);
 
@@ -434,6 +434,15 @@ DropTableSpace(DropTableSpaceStmt *stmt)
        aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
                       tablespacename);
 
+   /* DROP hook for the tablespace being removed */
+   if (object_access_hook)
+   {
+       ObjectAccessDrop    drop_arg;
+       memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+       InvokeObjectAccessHook(OAT_DROP, TableSpaceRelationId,
+                              tablespaceoid, 0, &drop_arg);
+   }
+
    /*
     * Remove the pg_tablespace tuple (this will roll back if we fail below)
     */
index caae2dafab159e8adda4ba1b1d02117cb3eb5873..a98d1b884ee5268f0c9b1bf9eef42489877e4a91 100644 (file)
@@ -756,7 +756,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 
    /* Post creation hook for new trigger */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          TriggerRelationId, trigoid, 0);
+                          TriggerRelationId, trigoid, 0, NULL);
 
    /* Keep lock on target rel until end of xact */
    heap_close(rel, NoLock);
index fe500a6d7f97fd6e44b40dee9c8371696d0e245d..86cb8704da811ed9cd3bd2bbd5e2d7dae1a70c70 100644 (file)
@@ -271,7 +271,8 @@ DefineTSParser(List *names, List *parameters)
    makeParserDependencies(tup);
 
    /* Post creation hook for new text search parser */
-   InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TSParserRelationId, prsOid, 0, NULL);
 
    heap_freetuple(tup);
 
@@ -565,7 +566,7 @@ DefineTSDictionary(List *names, List *parameters)
 
    /* Post creation hook for new text search dictionary */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          TSDictionaryRelationId, dictOid, 0);
+                          TSDictionaryRelationId, dictOid, 0, NULL);
 
    heap_freetuple(tup);
 
@@ -1036,7 +1037,8 @@ DefineTSTemplate(List *names, List *parameters)
    makeTSTemplateDependencies(tup);
 
    /* Post creation hook for new text search template */
-   InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TSTemplateRelationId, dictOid, 0, NULL);
 
    heap_freetuple(tup);
 
@@ -1419,7 +1421,8 @@ DefineTSConfiguration(List *names, List *parameters)
    makeConfigurationDependencies(tup, false, mapRel);
 
    /* Post creation hook for new text search configuration */
-   InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TSConfigRelationId, cfgOid, 0, NULL);
 
    heap_freetuple(tup);
 
index 9a88c907894b6b8ac1d9a11c47c7c5cfb9e414f0..2edbabe7549ba15fad63d85b0f913638c2c82da1 100644 (file)
@@ -425,7 +425,8 @@ CreateRole(CreateRoleStmt *stmt)
                GetUserId(), false);
 
    /* Post creation hook for new role */
-   InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0);
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          AuthIdRelationId, roleid, 0, NULL);
 
    /*
     * Close pg_authid, but keep lock till commit.
@@ -932,6 +933,15 @@ DropRole(DropRoleStmt *stmt)
                    (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                     errmsg("must be superuser to drop superusers")));
 
+       /* DROP hook for the role being removed */
+       if (object_access_hook)
+       {
+           ObjectAccessDrop    drop_arg;
+           memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+           InvokeObjectAccessHook(OAT_DROP,
+                                  AuthIdRelationId, roleid, 0, &drop_arg);
+       }
+
        /*
         * Lock the role, so nobody can add dependencies to her while we drop
         * her.  We keep the lock until the end of transaction.
index 8c87ac599f958804bee25f174273e228b822ad51..645182dbfa4668450b35e3ba73bd2f3167e1eb52 100644 (file)
@@ -178,7 +178,7 @@ InsertRule(char *rulname,
 
    /* Post creation hook for new rule */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          RewriteRelationId, rewriteObjectId, 0);
+                          RewriteRelationId, rewriteObjectId, 0, NULL);
 
    heap_close(pg_rewrite_desc, RowExclusiveLock);
 
index a14ce442c1c35d3ab2d5e297060491206cc1dd84..3adfb159b8baa49939951da0cecf789575652dbe 100644 (file)
@@ -217,7 +217,7 @@ inv_create(Oid lobjId)
 
    /* Post creation hook for new large object */
    InvokeObjectAccessHook(OAT_POST_CREATE,
-                          LargeObjectRelationId, lobjId_new, 0);
+                          LargeObjectRelationId, lobjId_new, 0, NULL);
 
    /*
     * Advance command counter to make new tuple visible to later operations.
index 5c7a40a31cb77d1f298c09d59e679418050b3ae0..9763280177b81c744c89cb7ff1b8922acaf0dced 100644 (file)
  * Typically, this is done after inserting the primary catalog records and
  * associated dependencies.
  *
+ * OAT_DROP should be invoked just before deletion of objects; typically
+ * deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
+ *
  * Other types may be added in the future.
  */
 typedef enum ObjectAccessType
 {
    OAT_POST_CREATE,
+   OAT_DROP,
 } ObjectAccessType;
 
 /*
- * Hook, and a macro to invoke it.
+ * Arguments of OAT_DROP event
  */
+typedef struct
+{
+   /*
+    * Flags to inform extensions the context of this deletion.
+    * Also see PERFORM_DELETION_* in dependency.h
+    */
+   int     dropflags;
+} ObjectAccessDrop;
 
+/*
+ * Hook, and a macro to invoke it.
+ */
 typedef void (*object_access_hook_type) (ObjectAccessType access,
                                                     Oid classId,
                                                     Oid objectId,
-                                                    int subId);
+                                                    int subId,
+                                                    void *arg);
 
 extern PGDLLIMPORT object_access_hook_type object_access_hook;
 
-#define InvokeObjectAccessHook(access,classId,objectId,subId)          \
-   do {                                                                \
-       if (object_access_hook)                                         \
-           (*object_access_hook)((access),(classId),(objectId),(subId)); \
+#define InvokeObjectAccessHook(access,classId,objectId,subId,arg)  \
+   do {                                                            \
+       if (object_access_hook)                                     \
+           (*object_access_hook)((access),(classId),               \
+                                 (objectId),(subId),(arg));        \
    } while(0)
 
 #endif   /* OBJECTACCESS_H */