Object access hook framework, with post-creation hook.
authorRobert Haas <[email protected]>
Thu, 25 Nov 2010 16:48:49 +0000 (11:48 -0500)
committerRobert Haas <[email protected]>
Thu, 25 Nov 2010 16:50:13 +0000 (11:50 -0500)
After a SQL object is created, we provide an opportunity for security
or logging plugins to get control; for example, a security label provider
could use this to assign an initial security label to newly created
objects.  The basic infrastructure is (hopefully) reusable for other types
of events that might require similar treatment.

KaiGai Kohei, with minor adjustments.

21 files changed:
src/backend/catalog/heap.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/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/backend/utils/init/globals.c
src/include/catalog/objectaccess.h [new file with mode: 0644]

index dcc53e13a1a7523128aa7622c47df5c283f9374b..9b7668c133ef8dba82450e74ef37d9a13ea11061 100644 (file)
@@ -40,6 +40,7 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_inherits.h"
@@ -1188,6 +1189,9 @@ heap_create_with_catalog(const char *relname,
        }
    }
 
+   /* Post creation hook for new relation */
+   InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0);
+
    /*
     * Store any supplied constraints and defaults.
     *
index 8b4f8c636fc1d32c015e3ea399c7f6b603d48c4f..db0507b8c7332c3462b5c561f47138bc6ec73900 100644 (file)
@@ -18,6 +18,7 @@
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
@@ -360,6 +361,9 @@ CreateConstraintEntry(const char *constraintName,
                                        DEPENDENCY_NORMAL);
    }
 
+   /* Post creation hook for new constraint */
+   InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0);
+
    return conOid;
 }
 
index 957818403ff2775f3e44592e657029b3c71d3f54..5f1f1de45180c10926026914b99c30f894d833b6 100644 (file)
@@ -18,6 +18,7 @@
 #include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_conversion_fn.h"
 #include "catalog/pg_namespace.h"
@@ -131,6 +132,10 @@ ConversionCreate(const char *conname, Oid connamespace,
    recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
                            conowner);
 
+   /* Post creation hook for new conversion */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          ConversionRelationId, HeapTupleGetOid(tup), 0);
+
    heap_freetuple(tup);
    heap_close(rel, RowExclusiveLock);
 
index 71ebd7aa8278deb48af930fe9b938ff4f0bc5280..0387423d9fb117ac0016ca655efe5e82706be68b 100644 (file)
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "utils/builtins.h"
 #include "utils/rel.h"
@@ -75,5 +76,8 @@ NamespaceCreate(const char *nspName, Oid ownerId)
    /* Record dependency on owner */
    recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
 
+   /* Post creation hook for new schema */
+   InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0);
+
    return nspoid;
 }
index 73de67252003783ced5c929b718e2280c4f90636..3e9737437160a9969f49e6517f460a66c5b7ba29 100644 (file)
@@ -22,6 +22,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
@@ -273,6 +274,10 @@ OperatorShellMake(const char *operatorName,
 
    heap_freetuple(tup);
 
+   /* Post creation hook for new shell operator */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          OperatorRelationId, operatorObjectId, 0);
+
    /*
     * Make sure the tuple is visible for subsequent lookups/updates.
     */
@@ -539,6 +544,10 @@ OperatorCreate(const char *operatorName,
    /* Add dependencies for the entry */
    makeOperatorDependencies(tup);
 
+   /* Post creation hook for new operator */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          OperatorRelationId, operatorObjectId, 0);
+
    heap_close(pg_operator_desc, RowExclusiveLock);
 
    /*
index 34cd862d27e7f9992c840bb031673da8ce8193b6..d464979bc744877d875c846803d44a34551093b6 100644 (file)
@@ -18,6 +18,7 @@
 #include "access/xact.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_proc.h"
@@ -616,6 +617,9 @@ ProcedureCreate(const char *procedureName,
 
    heap_freetuple(tup);
 
+   /* Post creation hook for new function */
+   InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0);
+
    heap_close(rel, RowExclusiveLock);
 
    /* Verify function body */
index d7fccdf07b1b3ad69dd2e731e03becf27f4e6499..85368202d8d7b11bb303060b520c9f912973ce85 100644 (file)
@@ -18,6 +18,7 @@
 #include "access/xact.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
@@ -155,6 +156,9 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
                                 NULL,
                                 false);
 
+   /* Post creation hook for new shell type */
+   InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0);
+
    /*
     * clean up and return the type-oid
     */
@@ -455,6 +459,9 @@ TypeCreate(Oid newTypeOid,
                                  NULL),
                                 rebuildDeps);
 
+   /* Post creation hook for new type */
+   InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0);
+
    /*
     * finish up
     */
index 8cbd7548f97a303ffcf2ad01e65b6f4cb78c59b0..09c6632a3b773a9b05641aa05e9e25112694bfb3 100644 (file)
@@ -32,6 +32,7 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_db_role_setting.h"
@@ -572,6 +573,9 @@ createdb(const CreatedbStmt *stmt)
    /* Create pg_shdepend entries for objects within database */
    copyTemplateDependencies(src_dboid, dboid);
 
+   /* Post creation hook for new database */
+   InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0);
+
    /*
     * Force a checkpoint before starting the copy. This will force dirty
     * buffers out to disk, to ensure source database is up-to-date on disk
index 4e6367c5268c05a36a707a0781e30799a3469833..71ba806851bbe2b565dd0a7446e80d40acfd4325 100644 (file)
@@ -18,6 +18,7 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_foreign_data_wrapper.h"
 #include "catalog/pg_foreign_server.h"
 #include "catalog/pg_proc.h"
@@ -415,6 +416,10 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 
    recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
 
+   /* Post creation hook for new foreign data wrapper */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          ForeignDataWrapperRelationId, fdwId, 0);
+
    heap_close(rel, NoLock);
 }
 
@@ -696,6 +701,9 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
 
    recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);
 
+   /* Post creation hook for new foreign server */
+   InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0);
+
    heap_close(rel, NoLock);
 }
 
@@ -967,6 +975,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
        /* Record the mapped user dependency */
        recordDependencyOnOwner(UserMappingRelationId, umId, useId);
 
+   /* Post creation hook for new user mapping */
+   InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0);
+
    heap_close(rel, NoLock);
 }
 
index 62a21102512a324b44244f903e70fc198cf83112..2347cad69417eb0f2db4c3ee47a86f4374f4b29c 100644 (file)
@@ -37,6 +37,7 @@
 #include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_cast.h"
 #include "catalog/pg_language.h"
@@ -1761,6 +1762,10 @@ CreateCast(CreateCastStmt *stmt)
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    }
 
+   /* Post creation hook for new cast */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          CastRelationId, myself.objectId, 0);
+
    heap_freetuple(tuple);
 
    heap_close(relation, RowExclusiveLock);
index 132c4ee1e539892ea8de8b0c54561ba810dbf695..5055fb17cde0964c26b12a4917de2e9af0f42875 100644 (file)
@@ -22,6 +22,7 @@
 #include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_namespace.h"
@@ -307,6 +308,10 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
    /* dependency on owner */
    recordDependencyOnOwner(OperatorFamilyRelationId, opfamilyoid, GetUserId());
 
+   /* Post creation hook for new operator family */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          OperatorFamilyRelationId, opfamilyoid, 0);
+
    heap_close(rel, RowExclusiveLock);
 
    return opfamilyoid;
@@ -703,6 +708,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
    /* dependency on owner */
    recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId());
 
+   /* Post creation hook for new operator class */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          OperatorClassRelationId, opclassoid, 0);
+
    heap_close(rel, RowExclusiveLock);
 }
 
index a2e653af80a1a141e223674a3593a6e3da082acd..9d0d3b215466cef6284c87b2354557cedcdd1cc3 100644 (file)
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_pltemplate.h"
@@ -425,6 +426,10 @@ create_proc_lang(const char *languageName, bool replace,
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    }
 
+   /* Post creation hook for new procedural language */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          LanguageRelationId, myself.objectId, 0);
+
    heap_close(rel, RowExclusiveLock);
 }
 
index e8808e28c68ce397d0e87ce73122d94efe924570..937992ba585e41751bcaed784dcce4ee75819910 100644 (file)
@@ -26,6 +26,7 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_depend.h"
 #include "catalog/pg_inherits.h"
@@ -4080,6 +4081,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
 
    heap_freetuple(reltup);
 
+   /* Post creation hook for new attribute */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          RelationRelationId, myrelid, newattnum);
+
    heap_close(pgclass, RowExclusiveLock);
 
    /* Make the attribute's catalog entry visible */
index 305ac46b4071ca73a9058c200813400982a5d187..5ba0f1ca9da6081a7bafb63ac14817f6f7df61ef 100644 (file)
@@ -59,6 +59,7 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_tablespace.h"
 #include "commands/comment.h"
 #include "commands/defrem.h"
@@ -333,6 +334,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
    /* Record dependency on owner */
    recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
 
+   /* Post creation hook for new tablespace */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TableSpaceRelationId, tablespaceoid, 0);
+
    create_tablespace_directories(location, tablespaceoid);
 
    /* Record the filesystem change in XLOG */
index d69fdcf410a3f6b83a85e88a5b59a86af786bb56..8195392f16939004526dafa7e6b178c42ec628bf 100644 (file)
@@ -20,6 +20,7 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_trigger.h"
@@ -735,6 +736,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
        recordDependencyOnExpr(&myself, whenClause, whenRtable,
                               DEPENDENCY_NORMAL);
 
+   /* Post creation hook for new trigger */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TriggerRelationId, trigoid, 0);
+
    /* Keep lock on target rel until end of xact */
    heap_close(rel, NoLock);
 
index 73b8c9248b04f73050e1e59a09e2718bdf449e39..412b1d278d5876cd90958478dc4740e361cfd776 100644 (file)
@@ -23,6 +23,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_ts_config.h"
@@ -263,6 +264,9 @@ DefineTSParser(List *names, List *parameters)
 
    makeParserDependencies(tup);
 
+   /* Post creation hook for new text search parser */
+   InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0);
+
    heap_freetuple(tup);
 
    heap_close(prsRel, RowExclusiveLock);
@@ -563,6 +567,10 @@ DefineTSDictionary(List *names, List *parameters)
 
    makeDictionaryDependencies(tup);
 
+   /* Post creation hook for new text search dictionary */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          TSDictionaryRelationId, dictOid, 0);
+
    heap_freetuple(tup);
 
    heap_close(dictRel, RowExclusiveLock);
@@ -1050,6 +1058,9 @@ DefineTSTemplate(List *names, List *parameters)
 
    makeTSTemplateDependencies(tup);
 
+   /* Post creation hook for new text search template */
+   InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0);
+
    heap_freetuple(tup);
 
    heap_close(tmplRel, RowExclusiveLock);
@@ -1440,6 +1451,9 @@ DefineTSConfiguration(List *names, List *parameters)
 
    makeConfigurationDependencies(tup, false, mapRel);
 
+   /* Post creation hook for new text search configuration */
+   InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0);
+
    heap_freetuple(tup);
 
    if (mapRel)
index f1ff83987732d6b0fd914056045c7b182af514cd..2634ca10e6460b126ffc8e8ecb16f0fdf93b8126 100644 (file)
@@ -17,6 +17,7 @@
 #include "access/xact.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_auth_members.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_database.h"
@@ -402,6 +403,9 @@ CreateRole(CreateRoleStmt *stmt)
                rolemembers, roleNamesToIds(rolemembers),
                GetUserId(), false);
 
+   /* Post creation hook for new role */
+   InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0);
+
    /*
     * Close pg_authid, but keep lock till commit.
     */
index 029a2888a72871ef3203bd1d3d5ce9efdf27ca68..4354897981a8d6f15064b4031728297f3d7a85ee 100644 (file)
@@ -19,6 +19,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/storage.h"
 #include "miscadmin.h"
@@ -177,6 +178,10 @@ InsertRule(char *rulname,
                               DEPENDENCY_NORMAL);
    }
 
+   /* Post creation hook for new rule */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          RewriteRelationId, rewriteObjectId, 0);
+
    heap_close(pg_rewrite_desc, RowExclusiveLock);
 
    return rewriteObjectId;
index e2faf95d9355a1d95b816b2aa1640cb2f74a93b6..686770cd45e988aa1bb6040e18a668d52cebc894 100644 (file)
@@ -38,6 +38,7 @@
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_largeobject.h"
 #include "catalog/pg_largeobject_metadata.h"
 #include "commands/comment.h"
@@ -218,6 +219,10 @@ inv_create(Oid lobjId)
    recordDependencyOnOwner(LargeObjectRelationId,
                            lobjId_new, GetUserId());
 
+   /* Post creation hook for new large object */
+   InvokeObjectAccessHook(OAT_POST_CREATE,
+                          LargeObjectRelationId, lobjId_new, 0);
+
    /*
     * Advance command counter to make new tuple visible to later operations.
     */
index 9aa2c0a498fae0b2e87521dd923adcfefb837969..5855fe466632400f3123e109c10231d2a275b57f 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include "postgres.h"
 
+#include "catalog/objectaccess.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"
 #include "storage/backendid.h"
@@ -117,3 +118,9 @@ int         VacuumCostBalance = 0;      /* working state for vacuum */
 bool       VacuumCostActive = false;
 
 int            GinFuzzySearchLimit = 0;
+
+/*
+ * Hook on object accesses.  This is intended as infrastructure for security
+ * and logging plugins.
+ */
+PGDLLIMPORT object_access_hook_type object_access_hook = NULL;
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
new file mode 100644 (file)
index 0000000..88508b0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * objectaccess.h
+ *
+ *     Object access hooks.
+ *
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+
+#ifndef OBJECTACCESS_H
+#define OBJECTACCESS_H
+
+/*
+ * Object access hooks are intended to be called just before or just after
+ * performing certain actions on a SQL object.  This is intended as
+ * infrastructure for security or logging pluggins.
+ *
+ * OAT_POST_CREATE should be invoked just after the the object is created.
+ * Typically, this is done after inserting the primary catalog records and
+ * associated dependencies.
+ *
+ * Other types may be added in the future.
+ */
+typedef enum ObjectAccessType
+{
+   OAT_POST_CREATE,
+} ObjectAccessType;
+
+/*
+ * Hook, and a macro to invoke it.
+ */
+
+typedef void (*object_access_hook_type)(ObjectAccessType access,
+                                       Oid classId,
+                                       Oid objectId,
+                                       int subId);
+
+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)); \
+   } while(0)
+
+#endif /* OBJECTACCESS_H */