diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index eca064f0cde..1b92f5c38a1 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -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.) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index d1d458d7fa4..8bd5a9296e1 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -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. diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c index 511d70c044d..18c7acf0e81 100644 --- a/src/backend/catalog/pg_collation.c +++ b/src/backend/catalog/pg_collation.c @@ -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); diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 0bad4d99cb4..342cf75270a 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -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; } diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 8194cd6c267..f86c84fc4bb 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -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); diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index be812a246c0..de856760f08 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -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; } diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 3b727222413..4fd55ae5706 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -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); diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 91ead4cb9d2..1fffe1c6ac3 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -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); diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 2c2e3b3e7cf..5b2ad6bfe0d 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -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 diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 42a8b31b2a8..91d74815287 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -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 diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index a9963ac93b9..732791cc413 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -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; } diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 5d18bdcf0a9..30135e6de8b 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -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); } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index ce866a20a99..4125b97e89e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -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); diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 5dc131a50e2..87c889604e2 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -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); } diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 8d6a0416d5f..41775fd8674 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -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); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index cd4490a1c24..25ca356b867 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 5e10f8c9a33..d66ea3b6c12 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -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) */ diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index caae2dafab1..a98d1b884ee 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -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); diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index fe500a6d7f9..86cb8704da8 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -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); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 9a88c907894..2edbabe7549 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -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. diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 8c87ac599f9..645182dbfa4 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -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); diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index a14ce442c1c..3adfb159b8b 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -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. diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h index 5c7a40a31cb..9763280177b 100644 --- a/src/include/catalog/objectaccess.h +++ b/src/include/catalog/objectaccess.h @@ -19,28 +19,45 @@ * 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; +/* + * 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 */