diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c index 549fac4539..38922294e2 100644 --- a/src/backend/catalog/objectaccess.c +++ b/src/backend/catalog/objectaccess.c @@ -20,11 +20,13 @@ * and logging plugins. */ object_access_hook_type object_access_hook = NULL; +object_access_hook_type_str object_access_hook_str = NULL; + /* * RunObjectPostCreateHook * - * It is entrypoint of OAT_POST_CREATE event + * OAT_POST_CREATE object ID based event hook entrypoint */ void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, @@ -46,7 +48,7 @@ RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, /* * RunObjectDropHook * - * It is entrypoint of OAT_DROP event + * OAT_DROP object ID based event hook entrypoint */ void RunObjectDropHook(Oid classId, Oid objectId, int subId, @@ -68,7 +70,7 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId, /* * RunObjectTruncateHook * - * It is the entrypoint of OAT_TRUNCATE event + * OAT_TRUNCATE object ID based event hook entrypoint */ void RunObjectTruncateHook(Oid objectId) @@ -84,7 +86,7 @@ RunObjectTruncateHook(Oid objectId) /* * RunObjectPostAlterHook * - * It is entrypoint of OAT_POST_ALTER event + * OAT_POST_ALTER object ID based event hook entrypoint */ void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, @@ -107,7 +109,7 @@ RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, /* * RunNamespaceSearchHook * - * It is entrypoint of OAT_NAMESPACE_SEARCH event + * OAT_NAMESPACE_SEARCH object ID based event hook entrypoint */ bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation) @@ -131,7 +133,7 @@ RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation) /* * RunFunctionExecuteHook * - * It is entrypoint of OAT_FUNCTION_EXECUTE event + * OAT_FUNCTION_EXECUTE object ID based event hook entrypoint */ void RunFunctionExecuteHook(Oid objectId) @@ -143,3 +145,129 @@ RunFunctionExecuteHook(Oid objectId) ProcedureRelationId, objectId, 0, NULL); } + +/* String versions */ + + +/* + * RunObjectPostCreateHookStr + * + * OAT_POST_CREATE object name based event hook entrypoint + */ +void +RunObjectPostCreateHookStr(Oid classId, const char *objectName, int subId, + bool is_internal) +{ + ObjectAccessPostCreate pc_arg; + + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + memset(&pc_arg, 0, sizeof(ObjectAccessPostCreate)); + pc_arg.is_internal = is_internal; + + (*object_access_hook_str) (OAT_POST_CREATE, + classId, objectName, subId, + (void *) &pc_arg); +} + +/* + * RunObjectDropHookStr + * + * OAT_DROP object name based event hook entrypoint + */ +void +RunObjectDropHookStr(Oid classId, const char *objectName, int subId, + int dropflags) +{ + ObjectAccessDrop drop_arg; + + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + memset(&drop_arg, 0, sizeof(ObjectAccessDrop)); + drop_arg.dropflags = dropflags; + + (*object_access_hook_str) (OAT_DROP, + classId, objectName, subId, + (void *) &drop_arg); +} + +/* + * RunObjectTruncateHookStr + * + * OAT_TRUNCATE object name based event hook entrypoint + */ +void +RunObjectTruncateHookStr(const char *objectName) +{ + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + (*object_access_hook_str) (OAT_TRUNCATE, + RelationRelationId, objectName, 0, + NULL); +} + +/* + * RunObjectPostAlterHookStr + * + * OAT_POST_ALTER object name based event hook entrypoint + */ +void +RunObjectPostAlterHookStr(Oid classId, const char *objectName, int subId, + Oid auxiliaryId, bool is_internal) +{ + ObjectAccessPostAlter pa_arg; + + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + memset(&pa_arg, 0, sizeof(ObjectAccessPostAlter)); + pa_arg.auxiliary_id = auxiliaryId; + pa_arg.is_internal = is_internal; + + (*object_access_hook_str) (OAT_POST_ALTER, + classId, objectName, subId, + (void *) &pa_arg); +} + +/* + * RunNamespaceSearchHookStr + * + * OAT_NAMESPACE_SEARCH object name based event hook entrypoint + */ +bool +RunNamespaceSearchHookStr(const char *objectName, bool ereport_on_violation) +{ + ObjectAccessNamespaceSearch ns_arg; + + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + memset(&ns_arg, 0, sizeof(ObjectAccessNamespaceSearch)); + ns_arg.ereport_on_violation = ereport_on_violation; + ns_arg.result = true; + + (*object_access_hook_str) (OAT_NAMESPACE_SEARCH, + NamespaceRelationId, objectName, 0, + (void *) &ns_arg); + + return ns_arg.result; +} + +/* + * RunFunctionExecuteHookStr + * + * OAT_FUNCTION_EXECUTE object name based event hook entrypoint + */ +void +RunFunctionExecuteHookStr(const char *objectName) +{ + /* caller should check, but just in case... */ + Assert(object_access_hook_str != NULL); + + (*object_access_hook_str) (OAT_FUNCTION_EXECUTE, + ProcedureRelationId, objectName, 0, + NULL); +} diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index e7f0a380e6..932aefc777 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -43,6 +43,7 @@ #include "access/xlog_internal.h" #include "access/xlogrecovery.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_authid.h" #include "catalog/storage.h" #include "commands/async.h" @@ -8736,6 +8737,18 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) replace_auto_config_value(&head, &tail, name, value); } + /* + * Invoke the post-alter hook for altering this GUC variable. + * + * We do this here rather than at the end, because ALTER SYSTEM is not + * transactional. If the hook aborts our transaction, it will be cleaner + * to do so before we touch any files. + */ + InvokeObjectPostAlterHookArgStr(InvalidOid, name, + ACL_ALTER_SYSTEM, + altersysstmt->setstmt->kind, + false); + /* * To ensure crash safety, first write the new file data to a temp file, * then atomically rename it into place. @@ -8907,6 +8920,10 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel) ResetAllOptions(); break; } + + /* Invoke the post-alter hook for setting this GUC variable. */ + InvokeObjectPostAlterHookArgStr(InvalidOid, stmt->name, + ACL_SET_VALUE, stmt->kind, false); } /* diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h index 508dfd0a6b..4d54ae2a7d 100644 --- a/src/include/catalog/objectaccess.h +++ b/src/include/catalog/objectaccess.h @@ -121,15 +121,23 @@ typedef struct bool result; } ObjectAccessNamespaceSearch; -/* Plugin provides a hook function matching this signature. */ +/* Plugin provides a hook function matching one or both of these signatures. */ typedef void (*object_access_hook_type) (ObjectAccessType access, Oid classId, Oid objectId, int subId, void *arg); +typedef void (*object_access_hook_type_str) (ObjectAccessType access, + Oid classId, + const char *objectStr, + int subId, + void *arg); + /* Plugin sets this variable to a suitable hook function. */ extern PGDLLIMPORT object_access_hook_type object_access_hook; +extern PGDLLIMPORT object_access_hook_type_str object_access_hook_str; + /* Core code uses these functions to call the hook (see macros below). */ extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId, @@ -142,6 +150,18 @@ extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId, extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation); extern void RunFunctionExecuteHook(Oid objectId); +/* String versions */ +extern void RunObjectPostCreateHookStr(Oid classId, const char *objectStr, int subId, + bool is_internal); +extern void RunObjectDropHookStr(Oid classId, const char *objectStr, int subId, + int dropflags); +extern void RunObjectTruncateHookStr(const char *objectStr); +extern void RunObjectPostAlterHookStr(Oid classId, const char *objectStr, int subId, + Oid auxiliaryId, bool is_internal); +extern bool RunNamespaceSearchHookStr(const char *objectStr, bool ereport_on_violation); +extern void RunFunctionExecuteHookStr(const char *objectStr); + + /* * The following macros are wrappers around the functions above; these should * normally be used to invoke the hook in lieu of calling the above functions @@ -194,4 +214,52 @@ extern void RunFunctionExecuteHook(Oid objectId); RunFunctionExecuteHook(objectId); \ } while(0) + +#define InvokeObjectPostCreateHookStr(classId,objectName,subId) \ + InvokeObjectPostCreateHookArgStr((classId),(objectName),(subId),false) +#define InvokeObjectPostCreateHookArgStr(classId,objectName,subId,is_internal) \ + do { \ + if (object_access_hook_str) \ + RunObjectPostCreateHookStr((classId),(objectName),(subId), \ + (is_internal)); \ + } while(0) + +#define InvokeObjectDropHookStr(classId,objectName,subId) \ + InvokeObjectDropHookArgStr((classId),(objectName),(subId),0) +#define InvokeObjectDropHookArgStr(classId,objectName,subId,dropflags) \ + do { \ + if (object_access_hook_str) \ + RunObjectDropHookStr((classId),(objectName),(subId), \ + (dropflags)); \ + } while(0) + +#define InvokeObjectTruncateHookStr(objectName) \ + do { \ + if (object_access_hook_str) \ + RunObjectTruncateHookStr(objectName); \ + } while(0) + +#define InvokeObjectPostAlterHookStr(className,objectName,subId) \ + InvokeObjectPostAlterHookArgStr((classId),(objectName),(subId), \ + InvalidOid,false) +#define InvokeObjectPostAlterHookArgStr(classId,objectName,subId, \ + auxiliaryId,is_internal) \ + do { \ + if (object_access_hook_str) \ + RunObjectPostAlterHookStr((classId),(objectName),(subId), \ + (auxiliaryId),(is_internal)); \ + } while(0) + +#define InvokeNamespaceSearchHookStr(objectName, ereport_on_violation) \ + (!object_access_hook_str \ + ? true \ + : RunNamespaceSearchHookStr((objectName), (ereport_on_violation))) + +#define InvokeFunctionExecuteHookStr(objectName) \ + do { \ + if (object_access_hook_str) \ + RunFunctionExecuteHookStr(objectName); \ + } while(0) + + #endif /* OBJECTACCESS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 6f83a79a96..2f618cb229 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -92,7 +92,9 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */ #define ACL_CREATE (1<<9) /* for namespaces and databases */ #define ACL_CREATE_TEMP (1<<10) /* for databases */ #define ACL_CONNECT (1<<11) /* for databases */ -#define N_ACL_RIGHTS 12 /* 1 plus the last 1<