diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index d0a0e92..fc4970d 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -248,7 +248,8 @@ Boot_CreateStmt:
 													  ONCOMMIT_NOOP,
 													  (Datum) 0,
 													  false,
-													  true);
+													  true,
+													  0);
 						elog(DEBUG4, "relation created with OID %u", id);
 					}
 					do_end();
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index e11d896..1a6a0bc 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -89,7 +89,8 @@ static Oid AddNewRelationType(const char *typeName,
 				   char new_rel_kind,
 				   Oid ownerid,
 				   Oid new_row_type,
-				   Oid new_array_type);
+				   Oid new_array_type,
+				   Datum hook_private);
 static void RelationRemoveInheritance(Oid relid);
 static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
 			  bool is_validated, bool is_local, int inhcount);
@@ -910,7 +911,8 @@ AddNewRelationType(const char *typeName,
 				   char new_rel_kind,
 				   Oid ownerid,
 				   Oid new_row_type,
-				   Oid new_array_type)
+				   Oid new_array_type,
+				   Datum hook_private)
 {
 	return
 		TypeCreate(new_row_type,	/* optional predetermined OID */
@@ -943,7 +945,8 @@ AddNewRelationType(const char *typeName,
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
 				   false,		/* Type NOT NULL */
-				   InvalidOid); /* rowtypes never have a collation */
+				   InvalidOid,	/* rowtypes never have a collation */
+				   hook_private);	/* opaque of object_access_hook */
 }
 
 /* --------------------------------
@@ -993,7 +996,8 @@ heap_create_with_catalog(const char *relname,
 						 OnCommitAction oncommit,
 						 Datum reloptions,
 						 bool use_user_acl,
-						 bool allow_system_table_mods)
+						 bool allow_system_table_mods,
+						 Datum hook_private)
 {
 	Relation	pg_class_desc;
 	Relation	new_rel_desc;
@@ -1154,7 +1158,8 @@ heap_create_with_catalog(const char *relname,
 									  relkind,
 									  ownerid,
 									  reltypeid,
-									  new_array_oid);
+									  new_array_oid,
+									  hook_private);
 
 	/*
 	 * Now make the array type if wanted.
@@ -1195,7 +1200,8 @@ heap_create_with_catalog(const char *relname,
 				   -1,			/* typmod */
 				   0,			/* array dimensions for typBaseType */
 				   false,		/* Type NOT NULL */
-				   InvalidOid); /* rowtypes never have a collation */
+				   InvalidOid,	/* rowtypes never have a collation */
+				   hook_private);	/* opaque of the object_access_hook */
 
 		pfree(relarrayname);
 	}
@@ -1279,7 +1285,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, hook_private);
 
 	/*
 	 * Store any supplied constraints and defaults.
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index fcc90fe..acbce90 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -21,6 +21,7 @@
 
 #include "access/xact.h"
 #include "catalog/dependency.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_authid.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_conversion.h"
@@ -3384,9 +3385,12 @@ InitTempTableNamespace(void)
 	char		namespaceName[NAMEDATALEN];
 	Oid			namespaceId;
 	Oid			toastspaceId;
+	Datum		hook_private = 0;
 
 	Assert(!OidIsValid(myTempNamespace));
 
+	snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
+
 	/*
 	 * First, do permission check to see if we are authorized to make temp
 	 * tables.	We use a nonstandard error message here since "databasename:
@@ -3404,6 +3408,10 @@ InitTempTableNamespace(void)
 				 errmsg("permission denied to create temporary tables in database \"%s\"",
 						get_database_name(MyDatabaseId))));
 
+	/* Prep-creation hook for new temp-schema */
+	InvokeObjectPrepCreateHook(NamespaceRelationId,
+							   &hook_private, namespaceName);
+
 	/*
 	 * Do not allow a Hot Standby slave session to make temp tables.  Aside
 	 * from problems with modifying the system catalogs, there is a naming
@@ -3419,8 +3427,6 @@ InitTempTableNamespace(void)
 				(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
 				 errmsg("cannot create temporary tables during recovery")));
 
-	snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
-
 	namespaceId = get_namespace_oid(namespaceName, true);
 	if (!OidIsValid(namespaceId))
 	{
@@ -3432,7 +3438,9 @@ InitTempTableNamespace(void)
 		 * temp tables.  This works because the places that access the temp
 		 * namespace for my own backend skip permissions checks on it.
 		 */
-		namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
+		namespaceId = NamespaceCreate(namespaceName,
+									  BOOTSTRAP_SUPERUSERID,
+									  hook_private);
 		/* Advance command counter to make namespace visible */
 		CommandCounterIncrement();
 	}
@@ -3456,7 +3464,9 @@ InitTempTableNamespace(void)
 	toastspaceId = get_namespace_oid(namespaceName, true);
 	if (!OidIsValid(toastspaceId))
 	{
-		toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
+		toastspaceId = NamespaceCreate(namespaceName,
+									   BOOTSTRAP_SUPERUSERID,
+									   hook_private);
 		/* Advance command counter to make namespace visible */
 		CommandCounterIncrement();
 	}
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 86e8c6b..38b661d 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -50,7 +50,8 @@ AggregateCreate(const char *aggName,
 				List *aggfinalfnName,
 				List *aggsortopName,
 				Oid aggTransType,
-				const char *agginitval)
+				const char *agginitval,
+				Datum hook_private)
 {
 	Relation	aggdesc;
 	HeapTuple	tup;
@@ -229,7 +230,8 @@ AggregateCreate(const char *aggName,
 							  NIL,		/* parameterDefaults */
 							  PointerGetDatum(NULL),	/* proconfig */
 							  1,	/* procost */
-							  0);		/* prorows */
+							  0,	/* prorows */
+							  hook_private);	/* opaque of hook */
 
 	/*
 	 * Okay to create the pg_aggregate entry.
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
index ce9bfae..1cdc006 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, 0);
 
 	heap_freetuple(tup);
 	heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 6997994..8be45b6 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -364,7 +364,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, 0);
 
 	return conOid;
 }
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index e480aeb..ce87f06 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -135,7 +135,7 @@ ConversionCreate(const char *conname, Oid connamespace,
 
 	/* Post creation hook for new conversion */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   ConversionRelationId, HeapTupleGetOid(tup), 0);
+						   ConversionRelationId, HeapTupleGetOid(tup), 0, 0);
 
 	heap_freetuple(tup);
 	heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index ceebac2..5d76ecf 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -29,7 +29,7 @@
  * ---------------
  */
 Oid
-NamespaceCreate(const char *nspName, Oid ownerId)
+NamespaceCreate(const char *nspName, Oid ownerId, Datum hook_private)
 {
 	Relation	nspdesc;
 	HeapTuple	tup;
@@ -86,7 +86,8 @@ NamespaceCreate(const char *nspName, Oid ownerId)
 	recordDependencyOnCurrentExtension(&myself, false);
 
 	/* Post creation hook for new schema */
-	InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0);
+	InvokeObjectAccessHook(OAT_POST_CREATE,
+						   NamespaceRelationId, nspoid, 0, hook_private);
 
 	return nspoid;
 }
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 1440464..98e3921 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, 0);
 
 	/*
 	 * 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, 0);
 
 	heap_close(pg_operator_desc, RowExclusiveLock);
 
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 8378c36..f7866fc 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -85,7 +85,8 @@ ProcedureCreate(const char *procedureName,
 				List *parameterDefaults,
 				Datum proconfig,
 				float4 procost,
-				float4 prorows)
+				float4 prorows,
+				Datum hook_private)
 {
 	Oid			retval;
 	int			parameterCount;
@@ -646,7 +647,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, hook_private);
 
 	heap_close(rel, RowExclusiveLock);
 
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 21d1ef3..cd7afa3 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -51,7 +51,8 @@ Oid			binary_upgrade_next_pg_type_oid = InvalidOid;
  * ----------------------------------------------------------------
  */
 Oid
-TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
+TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId,
+			  Datum hook_private)
 {
 	Relation	pg_type_desc;
 	TupleDesc	tupDesc;
@@ -161,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, hook_private);
 
 	/*
 	 * clean up and return the type-oid
@@ -213,7 +215,8 @@ TypeCreate(Oid newTypeOid,
 		   int32 typeMod,
 		   int32 typNDims,		/* Array dimensions for baseType */
 		   bool typeNotNull,
-		   Oid typeCollation)
+		   Oid typeCollation,
+		   Datum hook_private)
 {
 	Relation	pg_type_desc;
 	Oid			typeObjectId;
@@ -465,7 +468,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, hook_private);
 
 	/*
 	 * finish up
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 3a40e8b..148b100 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -228,7 +228,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
 										   ONCOMMIT_NOOP,
 										   reloptions,
 										   false,
-										   true);
+										   true,
+										   0);
 	Assert(toast_relid != InvalidOid);
 
 	/* make the toast relation visible, else heap_open will fail */
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index a2122c1..35a622f 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -25,7 +25,9 @@
 #include "access/heapam.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_aggregate.h"
+#include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -51,6 +53,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
 	char	   *aggName;
 	Oid			aggNamespace;
 	AclResult	aclresult;
+	Datum		hook_private = 0;
 	List	   *transfuncName = NIL;
 	List	   *finalfuncName = NIL;
 	List	   *sortoperatorName = NIL;
@@ -192,6 +195,11 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
 							format_type_be(transTypeId))));
 	}
 
+	/* Prep-creation hook for new aggregate function */
+	InvokeProcedurePrepCreateHook(&hook_private, aggName,
+								  buildoidvector(aggArgTypes, numArgs),
+								  aggNamespace, INTERNALlanguageId, false);
+
 	/*
 	 * Most of the argument-checking is done inside of AggregateCreate
 	 */
@@ -203,7 +211,8 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
 					finalfuncName,		/* final function name */
 					sortoperatorName,	/* sort operator name */
 					transTypeId,	/* transition data type */
-					initval);	/* initial condition */
+					initval,		/* initial condition */
+					hook_private);	/* opaque of object_access_hook */
 }
 
 
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index edec44d..93e7177 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -645,7 +645,8 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
 										  ONCOMMIT_NOOP,
 										  reloptions,
 										  false,
-										  true);
+										  true,
+										  0);
 	Assert(OIDNewHeap != InvalidOid);
 
 	ReleaseSysCache(tuple);
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 4551db7..58a1fd6 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -127,6 +127,7 @@ createdb(const CreatedbStmt *stmt)
 	int			dbconnlimit = -1;
 	int			notherbackends;
 	int			npreparedxacts;
+	Datum		hook_private = 0;
 	createdb_failure_params fparms;
 
 	/* Extract options from the statement node tree */
@@ -424,6 +425,10 @@ createdb(const CreatedbStmt *stmt)
 		/* Note there is no additional permission check in this path */
 	}
 
+	/* Prep-creation hook for new database */
+	InvokeDatabasePrepCreateHook(&hook_private, dbname,
+								 src_dboid, dst_deftablespace);
+
 	/*
 	 * Check for db name conflict.	This is just to give a more friendly error
 	 * message than "unique index violation".  There's a race condition but
@@ -515,7 +520,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, hook_private);
 
 	/*
 	 * Force a checkpoint before starting the copy. This will force dirty
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index c334ca9..253141b 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, 0);
 
 	return extensionOid;
 }
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index d9c27d1..60aba65 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -518,7 +518,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 
 	/* Post creation hook for new foreign data wrapper */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   ForeignDataWrapperRelationId, fdwId, 0);
+						   ForeignDataWrapperRelationId, fdwId, 0, 0);
 
 	heap_close(rel, RowExclusiveLock);
 }
@@ -858,7 +858,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, 0);
 
 	heap_close(rel, RowExclusiveLock);
 }
@@ -1137,7 +1138,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, 0);
 
 	heap_close(rel, RowExclusiveLock);
 }
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 92abd44..8c65025 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -113,6 +113,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
 		char	   *typnam = TypeNameToString(returnType);
 		Oid			namespaceId;
 		AclResult	aclresult;
+		Datum		hook_private = 0;
 		char	   *typname;
 
 		/*
@@ -146,7 +147,11 @@ compute_return_type(TypeName *returnType, Oid languageOid,
 		if (aclresult != ACLCHECK_OK)
 			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 						   get_namespace_name(namespaceId));
-		rettype = TypeShellMake(typname, namespaceId, GetUserId());
+		/* Prep-creation hook for new range type */
+		InvokeSchemaObjectPrepCreateHook(TypeRelationId, &hook_private,
+										 typname, namespaceId);
+		rettype = TypeShellMake(typname, namespaceId,
+								GetUserId(), hook_private);
 		Assert(OidIsValid(rettype));
 	}
 
@@ -798,6 +803,7 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
 	ArrayType  *proconfig;
 	float4		procost;
 	float4		prorows;
+	Datum		hook_private = 0;
 	HeapTuple	languageTuple;
 	Form_pg_language languageStruct;
 	List	   *as_clause;
@@ -877,6 +883,10 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
 						   &parameterDefaults,
 						   &requiredResultType);
 
+	/* Prep-creation hook for new function */
+	InvokeProcedurePrepCreateHook(&hook_private, funcname, parameterTypes,
+								  namespaceId, languageOid, false);
+
 	if (stmt->returnType)
 	{
 		/* explicit RETURNS clause */
@@ -960,7 +970,8 @@ CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
 					parameterDefaults,
 					PointerGetDatum(proconfig),
 					procost,
-					prorows);
+					prorows,
+					hook_private);
 }
 
 
@@ -1769,7 +1780,7 @@ 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, 0);
 
 	heap_freetuple(tuple);
 
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index af0de05..08ab307 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -313,7 +313,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, 0);
 
 	heap_close(rel, RowExclusiveLock);
 
@@ -716,7 +716,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 
 	/* Post creation hook for new operator class */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   OperatorClassRelationId, opclassoid, 0);
+						   OperatorClassRelationId, opclassoid, 0, 0);
 
 	heap_close(rel, RowExclusiveLock);
 }
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 98770c5..10758aa 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -51,7 +51,7 @@ typedef struct
 
 static void create_proc_lang(const char *languageName, bool replace,
 				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
-				 Oid valOid, bool trusted);
+				 Oid valOid, bool trusted, Datum hook_private);
 static PLTemplate *find_language_template(const char *languageName);
 static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
 							Oid newOwnerId);
@@ -71,6 +71,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 				valOid;
 	Oid			funcrettype;
 	Oid			funcargtypes[1];
+	Datum		hook_private = 0;
 
 	/*
 	 * Translate the language name to lower case
@@ -107,6 +108,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 							   get_database_name(MyDatabaseId));
 		}
 
+		/* Prep-creation hook for new language */
+		InvokeObjectPrepCreateHook(LanguageRelationId,
+								   &hook_private, languageName);
+
 		/*
 		 * Find or create the handler function, which we force to be in the
 		 * pg_catalog schema.  If already present, it must have the correct
@@ -146,7 +151,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 										 NIL,
 										 PointerGetDatum(NULL),
 										 1,
-										 0);
+										 0,
+										 hook_private);
 		}
 
 		/*
@@ -181,7 +187,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 											NIL,
 											PointerGetDatum(NULL),
 											1,
-											0);
+											0,
+											hook_private);
 			}
 		}
 		else
@@ -219,7 +226,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 										 NIL,
 										 PointerGetDatum(NULL),
 										 1,
-										 0);
+										 0,
+										 hook_private);
 			}
 		}
 		else
@@ -228,7 +236,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		/* ok, create it */
 		create_proc_lang(languageName, stmt->replace, GetUserId(),
 						 handlerOid, inlineOid,
-						 valOid, pltemplate->tmpltrusted);
+						 valOid, pltemplate->tmpltrusted, hook_private);
 	}
 	else
 	{
@@ -252,6 +260,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("must be superuser to create custom procedural language")));
 
+		/* Prep-creation hook for new language */
+		InvokeObjectPrepCreateHook(LanguageRelationId,
+								   &hook_private, languageName);
+
 		/*
 		 * Lookup the PL handler function and check that it is of the expected
 		 * return type
@@ -303,7 +315,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		/* ok, create it */
 		create_proc_lang(languageName, stmt->replace, GetUserId(),
 						 handlerOid, inlineOid,
-						 valOid, stmt->pltrusted);
+						 valOid, stmt->pltrusted, hook_private);
 	}
 }
 
@@ -313,7 +325,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 static void
 create_proc_lang(const char *languageName, bool replace,
 				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
-				 Oid valOid, bool trusted)
+				 Oid valOid, bool trusted, Datum hook_private)
 {
 	Relation	rel;
 	TupleDesc	tupDesc;
@@ -431,7 +443,8 @@ 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,
+						   hook_private);
 
 	heap_close(rel, RowExclusiveLock);
 }
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 8daa9d0..a59aa68 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -19,6 +19,7 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_namespace.h"
 #include "commands/dbcommands.h"
 #include "commands/schemacmds.h"
@@ -48,6 +49,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
 	Oid			owner_uid;
 	Oid			saved_uid;
 	int			save_sec_context;
+	Datum		hook_private = 0;
 	AclResult	aclresult;
 
 	GetUserIdAndSecContext(&saved_uid, &save_sec_context);
@@ -74,6 +76,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
 
 	check_is_member_of_role(saved_uid, owner_uid);
 
+	/* Prep-creation hook for new schema */
+	InvokeObjectPrepCreateHook(NamespaceRelationId,
+							   &hook_private, schemaName);
+
 	/* Additional check to protect reserved schema names */
 	if (!allowSystemTableMods && IsReservedName(schemaName))
 		ereport(ERROR,
@@ -94,7 +100,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
 							save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
 
 	/* Create the schema's namespace */
-	namespaceId = NamespaceCreate(schemaName, owner_uid);
+	namespaceId = NamespaceCreate(schemaName, owner_uid, hook_private);
 
 	/* Advance cmd counter to make the namespace visible */
 	CommandCounterIncrement();
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c4622c0..a3053d6 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -413,6 +413,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 	ListCell   *listptr;
 	AttrNumber	attnum;
 	static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
+	Datum		hook_private = 0;
 	Oid			ofTypeId;
 
 	/*
@@ -575,6 +576,10 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 		}
 	}
 
+	/* Prep-creation hook for new relation */
+	InvokeRelationPrepCreateHook(&hook_private, relname, relkind,
+								 namespaceId, tablespaceId, descriptor);
+
 	/*
 	 * Create the relation.  Inherited defaults and constraints are passed in
 	 * for immediate handling --- since they don't need parsing, they can be
@@ -599,7 +604,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 										  stmt->oncommit,
 										  reloptions,
 										  true,
-										  allowSystemTableMods);
+										  allowSystemTableMods,
+										  hook_private);
 
 	/* Store inheritance information for new rel. */
 	StoreCatalogInheritance(relationId, inheritOids);
@@ -4381,7 +4387,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
 	/* Post creation hook for new attribute */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   RelationRelationId, myrelid, newattnum);
+						   RelationRelationId, myrelid, newattnum, 0);
 
 	heap_close(pgclass, RowExclusiveLock);
 
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index d223f8c..b0672e1 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -332,7 +332,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 
 	/* Post creation hook for new tablespace */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   TableSpaceRelationId, tablespaceoid, 0);
+						   TableSpaceRelationId, tablespaceoid, 0, 0);
 
 	create_tablespace_directories(location, tablespaceoid);
 
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a6e7268..daeb0a1 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -747,7 +747,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 
 	/* Post creation hook for new trigger */
 	InvokeObjectAccessHook(OAT_POST_CREATE,
-						   TriggerRelationId, trigoid, 0);
+						   TriggerRelationId, trigoid, 0, 0);
 
 	/* 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 5f206d8..2fb7304 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, 0);
 
 	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, 0);
 
 	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, 0);
 
 	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, 0);
 
 	heap_freetuple(tup);
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 91488bb..f91cc02 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -38,6 +38,7 @@
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
 #include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_depend.h"
@@ -104,7 +105,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
 					int typMod, Constraint *constr,
 					char *domainName);
 static void makeRangeConstructor(char *name, Oid namespace, Oid rettype,
-								 Oid subtype);
+								 Oid subtype, Datum hook_private);
 
 
 /*
@@ -162,6 +163,7 @@ DefineType(List *names, List *parameters)
 	Oid			array_oid;
 	Oid			typoid;
 	Oid			resulttype;
+	Datum		hook_private = 0;
 	ListCell   *pl;
 
 	/*
@@ -192,6 +194,11 @@ DefineType(List *names, List *parameters)
 					   get_namespace_name(typeNamespace));
 #endif
 
+	/* Prep-creation hook for new type */
+	InvokeSchemaObjectPrepCreateHook(TypeRelationId,
+									 &hook_private,
+									 typeName, typeNamespace);
+
 	/*
 	 * Look to see if type already exists (presumably as a shell; if not,
 	 * TypeCreate will complain).
@@ -216,7 +223,8 @@ DefineType(List *names, List *parameters)
 	 */
 	if (!OidIsValid(typoid))
 	{
-		typoid = TypeShellMake(typeName, typeNamespace, GetUserId());
+		typoid = TypeShellMake(typeName, typeNamespace,
+							   GetUserId(), hook_private);
 		/* Make new shell type visible for modification below */
 		CommandCounterIncrement();
 
@@ -583,7 +591,8 @@ DefineType(List *names, List *parameters)
 				   -1,			/* typMod (Domains only) */
 				   0,			/* Array Dimensions of typbasetype */
 				   false,		/* Type NOT NULL */
-				   collation);	/* type's collation */
+				   collation,	/* type's collation */
+				   hook_private);	/* opaque to post-creation hook */
 
 	/*
 	 * Create the array type that goes with it.
@@ -623,7 +632,8 @@ DefineType(List *names, List *parameters)
 			   -1,				/* typMod (Domains only) */
 			   0,				/* Array dimensions of typbasetype */
 			   false,			/* Type NOT NULL */
-			   collation);		/* type's collation */
+			   collation,		/* type's collation */
+			   hook_private);	/* opaque to post-creation hook */
 
 	pfree(array_type);
 }
@@ -677,6 +687,7 @@ DefineDomain(CreateDomainStmt *stmt)
 	char	   *domainName;
 	Oid			domainNamespace;
 	AclResult	aclresult;
+	Datum		hook_private = 0;
 	int16		internalLength;
 	Oid			inputProcedure;
 	Oid			outputProcedure;
@@ -719,6 +730,10 @@ DefineDomain(CreateDomainStmt *stmt)
 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 					   get_namespace_name(domainNamespace));
 
+	/* Prep-creation hook for new domain */
+	InvokeSchemaObjectPrepCreateHook(TypeRelationId, &hook_private,
+									 domainName, domainNamespace);
+
 	/*
 	 * Check for collision with an existing type name.	If there is one and
 	 * it's an autogenerated array, we can rename it out of the way.
@@ -998,7 +1013,8 @@ DefineDomain(CreateDomainStmt *stmt)
 				   basetypeMod, /* typeMod value */
 				   typNDims,	/* Array dimensions for base type */
 				   typNotNull,	/* Type NOT NULL */
-				   domaincoll); /* type's collation */
+				   domaincoll,	/* type's collation */
+				   hook_private);	/* opaque to post-creation hook */
 
 	/*
 	 * Process constraints which refer to the domain ID returned by TypeCreate
@@ -1046,6 +1062,7 @@ DefineEnum(CreateEnumStmt *stmt)
 	Oid			enumNamespace;
 	Oid			enumTypeOid;
 	AclResult	aclresult;
+	Datum		hook_private = 0;
 	Oid			old_type_oid;
 	Oid			enumArrayOid;
 
@@ -1059,6 +1076,10 @@ DefineEnum(CreateEnumStmt *stmt)
 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 					   get_namespace_name(enumNamespace));
 
+	/* Prep-creation hook for new enum type */
+	InvokeSchemaObjectPrepCreateHook(TypeRelationId, &hook_private,
+									 enumName, enumNamespace);
+
 	/*
 	 * Check for collision with an existing type name.	If there is one and
 	 * it's an autogenerated array, we can rename it out of the way.
@@ -1108,7 +1129,8 @@ DefineEnum(CreateEnumStmt *stmt)
 				   -1,			/* typMod (Domains only) */
 				   0,			/* Array dimensions of typbasetype */
 				   false,		/* Type NOT NULL */
-				   InvalidOid); /* type's collation */
+				   InvalidOid,	/* type's collation */
+				   hook_private);	/* opaque to post-creation hook */
 
 	/* Enter the enum's values into pg_enum */
 	EnumValuesCreate(enumTypeOid, stmt->vals);
@@ -1148,7 +1170,8 @@ DefineEnum(CreateEnumStmt *stmt)
 			   -1,				/* typMod (Domains only) */
 			   0,				/* Array dimensions of typbasetype */
 			   false,			/* Type NOT NULL */
-			   InvalidOid);		/* type's collation */
+			   InvalidOid,		/* type's collation */
+			   hook_private);	/* opaque to post-creation hook */
 
 	pfree(enumArrayName);
 }
@@ -1179,6 +1202,7 @@ DefineRange(CreateRangeStmt *stmt)
 	regproc		 rangeSubtypeDiff	  = InvalidOid;
 
 	AclResult	 aclresult;
+	Datum		 hook_private = 0;
 
 	/* Convert list of names to a name and namespace */
 	typeNamespace = QualifiedNameGetCreationNamespace(stmt->typeName,
@@ -1190,6 +1214,10 @@ DefineRange(CreateRangeStmt *stmt)
 		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
 					   get_namespace_name(typeNamespace));
 
+	/* Prep-creation hook for new range type */
+	InvokeSchemaObjectPrepCreateHook(TypeRelationId, &hook_private,
+									 typeName, typeNamespace);
+
 	/*
 	 * Look to see if type already exists (presumably as a shell; if not,
 	 * TypeCreate will complain).
@@ -1214,7 +1242,8 @@ DefineRange(CreateRangeStmt *stmt)
 	 */
 	if (!OidIsValid(typoid))
 	{
-		typoid = TypeShellMake(typeName, typeNamespace, GetUserId());
+		typoid = TypeShellMake(typeName, typeNamespace,
+							   GetUserId(), hook_private);
 		/* Make new shell type visible for modification below */
 		CommandCounterIncrement();
 
@@ -1355,7 +1384,8 @@ DefineRange(CreateRangeStmt *stmt)
 				   -1,			/* typMod (Domains only) */
 				   0,			/* Array dimensions of typbasetype */
 				   false,		/* Type NOT NULL */
-				   InvalidOid);	/* typcollation */
+				   InvalidOid,	/* typcollation */
+				   hook_private);	/* opaque to post-creation hook */
 
 	/* create the entry in pg_range */
 	RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
@@ -1396,11 +1426,13 @@ DefineRange(CreateRangeStmt *stmt)
 			   -1,				/* typMod (Domains only) */
 			   0,				/* Array dimensions of typbasetype */
 			   false,			/* Type NOT NULL */
-			   InvalidOid);		/* typcollation */
+			   InvalidOid,		/* typcollation */
+			   hook_private);	/* opaque to post-creation hook */
 
 	pfree(rangeArrayName);
 
-	makeRangeConstructor(typeName, typeNamespace, typoid, rangeSubtype);
+	makeRangeConstructor(typeName, typeNamespace, typoid,
+						 rangeSubtype, hook_private);
 }
 
 /*
@@ -1413,7 +1445,8 @@ DefineRange(CreateRangeStmt *stmt)
  * offer more convenience for the user.
  */
 static void
-makeRangeConstructor(char *name, Oid namespace, Oid rangeOid, Oid subtype)
+makeRangeConstructor(char *name, Oid namespace, Oid rangeOid,
+					 Oid subtype, Datum hook_private)
 {
 	ObjectAddress		referenced;
 	Oid					constructorArgTypes[3];
@@ -1461,7 +1494,8 @@ makeRangeConstructor(char *name, Oid namespace, Oid rangeOid, Oid subtype)
 			NIL, /* parameterDefaults */
 			PointerGetDatum(NULL), /* proconfig */
 			1.0, /* procost */
-			0.0); /* prorows */
+			0.0, /* prorows */
+			hook_private);
 
 		/*
 		 * Make the constructor internally-dependent on the range type so that
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index fa312cb..cc29acb 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -434,7 +434,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, 0);
 
 	/*
 	 * Close pg_authid, but keep lock till commit.
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index fd7a9ed..b31eea4 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -43,6 +43,7 @@
 #include "access/xact.h"
 #include "catalog/heap.h"
 #include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
 #include "catalog/toasting.h"
 #include "commands/tablespace.h"
 #include "commands/trigger.h"
@@ -2393,6 +2394,7 @@ OpenIntoRel(QueryDesc *queryDesc)
 	Oid			namespaceId;
 	Oid			tablespaceId;
 	Datum		reloptions;
+	Datum		hook_private = 0;
 	Oid			intoRelationId;
 	DR_intorel *myState;
 	static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
@@ -2467,6 +2469,12 @@ OpenIntoRel(QueryDesc *queryDesc)
 									 false);
 	(void) heap_reloptions(RELKIND_RELATION, reloptions, true);
 
+	/* Prep-creation hook for new table */
+	InvokeRelationPrepCreateHook(&hook_private, intoName,
+								 RELKIND_RELATION,
+								 namespaceId, tablespaceId,
+								 queryDesc->tupDesc);
+
 	/* Now we can actually create the new relation */
 	intoRelationId = heap_create_with_catalog(intoName,
 											  namespaceId,
@@ -2486,7 +2494,8 @@ OpenIntoRel(QueryDesc *queryDesc)
 											  into->onCommit,
 											  reloptions,
 											  true,
-											  allowSystemTableMods);
+											  allowSystemTableMods,
+											  hook_private);
 	Assert(intoRelationId != InvalidOid);
 
 	/*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 17db70e..f0c0e31 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, 0);
 
 	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 fed6d2e..1cdfa5c 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, 0);
 
 	/*
 	 * Advance command counter to make new tuple visible to later operations.
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index aee2d88..ca4d6a1 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -65,7 +65,8 @@ extern Oid heap_create_with_catalog(const char *relname,
 						 OnCommitAction oncommit,
 						 Datum reloptions,
 						 bool use_user_acl,
-						 bool allow_system_table_mods);
+						 bool allow_system_table_mods,
+						 Datum hook_private);
 
 extern void heap_drop_with_catalog(Oid relid);
 
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 2925475..30bdc75 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -10,11 +10,17 @@
 #ifndef OBJECTACCESS_H
 #define OBJECTACCESS_H
 
+#include "access/tupdesc.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_PREP_CREATE should be invoked around the permission check of object
+ * creation; with arguments that informs properties of the object being
+ * constructed.
+ *
  * 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.
@@ -23,24 +29,158 @@
  */
 typedef enum ObjectAccessType
 {
+	OAT_PREP_CREATE,
 	OAT_POST_CREATE,
 } ObjectAccessType;
 
 /*
+ * ObjectAccessPrepCreateInfo
+ *
+ * A set of contextual information on prep object events; reuired data
+ * is depending on object classes. So, module should check classId prior
+ * to reference this structure.
+ */
+typedef union
+{
+	struct {
+		Datum	   *private;
+		const char *objname;
+		Oid			namespaceId;	/* only objects under schema */
+	} common;
+
+	struct {
+		Datum	   *private;
+		const char *datname;
+		Oid			datsourceId;
+		Oid			tablespaceId;
+	} pg_database;
+
+	struct {
+		Datum	   *private;
+		const char *relname;
+		char		relkind;
+		Oid			namespaceId;
+		Oid			tablespaceId;
+		TupleDesc	tupdesc;
+	} pg_class;
+
+	struct {
+		Datum	   *private;
+		const char *proname;
+		oidvector  *proargs;
+		Oid			namespaceId;
+		Oid			languageId;
+		bool		leakproof;
+	} pg_proc;
+} ObjectAccessPrepCreateInfo;
+
+/*
  * Hook, and a macro to invoke it.
  */
 
 typedef void (*object_access_hook_type) (ObjectAccessType access,
-													 Oid classId,
-													 Oid objectId,
-													 int subId);
+										 Oid classId,
+										 Oid objectId,
+										 int subId,
+										 Datum argument);
 
 extern PGDLLIMPORT object_access_hook_type object_access_hook;
 
-#define InvokeObjectAccessHook(access,classId,objectId,subId)			\
+#define InvokeObjectPrepCreateHook(classId,_private,_objname)	\
+	do {														\
+		if (object_access_hook)									\
+		{														\
+			ObjectAccessPrepCreateInfo	__info;					\
+																\
+			__info.common.private = (_private);					\
+			__info.common.objname = (_objname);					\
+			__info.common.namespaceId = InvalidOid;				\
+																\
+			(*object_access_hook)(OAT_PREP_CREATE,				\
+								  (classId),InvalidOid,0,		\
+								  PointerGetDatum(&__info));	\
+		}														\
+	} while(0)
+
+#define InvokeSchemaObjectPrepCreateHook(classId,_private,		\
+										 _objname,_namespace)	\
+	do {														\
+		if (object_access_hook)									\
+		{														\
+			ObjectAccessPrepCreateInfo	__info;					\
+																\
+			__info.common.private = (_private);					\
+			__info.common.objname = (_objname);					\
+			__info.common.namespaceId = (_namespace);			\
+																\
+			(*object_access_hook)(OAT_PREP_CREATE,				\
+								  (classId),InvalidOid,0,		\
+								  PointerGetDatum(&__info));	\
+		}														\
+	} while(0)
+
+#define InvokeDatabasePrepCreateHook(_private,_datname,_source,_tablespace) \
+	do {																\
+		if (object_access_hook)											\
+		{																\
+			ObjectAccessPrepCreateInfo	__info;							\
+																		\
+			__info.pg_database.private = (_private);					\
+			__info.pg_database.datname = (_datname);					\
+			__info.pg_database.datsourceId = (_source);					\
+			__info.pg_database.tablespaceId = (_tablespace);			\
+																		\
+			(*object_access_hook)(OAT_PREP_CREATE,						\
+								  DatabaseRelationId,InvalidOid,0,		\
+								  PointerGetDatum(&__info));			\
+		}																\
+	} while (0)
+
+#define InvokeRelationPrepCreateHook(_private,_relname,_relkind,		\
+									 _namespace,_tablespace,_tupdesc)	\
 	do {																\
 		if (object_access_hook)											\
-			(*object_access_hook)((access),(classId),(objectId),(subId)); \
+		{																\
+			ObjectAccessPrepCreateInfo	__info;							\
+																		\
+			__info.pg_class.private = (_private);						\
+			__info.pg_class.relname = (_relname);						\
+			__info.pg_class.relkind = (_relkind);						\
+			__info.pg_class.namespaceId = (_namespace);					\
+			__info.pg_class.tablespaceId = (_tablespace);				\
+			__info.pg_class.tupdesc = (_tupdesc);						\
+																		\
+			(*object_access_hook)(OAT_PREP_CREATE,						\
+								  RelationRelationId,InvalidOid,0,		\
+								  PointerGetDatum(&__info));			\
+		}																\
+	} while(0)
+
+#define InvokeProcedurePrepCreateHook(_private,_proname,_proargs,		\
+									  _namespace,_language,_leakproof)	\
+	do {																\
+		if (object_access_hook)											\
+		{																\
+			ObjectAccessPrepCreateInfo	__info;							\
+																		\
+			__info.pg_proc.private = (_private);						\
+			__info.pg_proc.proname = (_proname);						\
+			__info.pg_proc.proargs = (_proargs);						\
+			__info.pg_proc.namespaceId = (_namespace);					\
+			__info.pg_proc.languageId = (_language);					\
+			__info.pg_proc.leakproof = (_leakproof);					\
+																		\
+			(*object_access_hook)(OAT_PREP_CREATE,						\
+								  ProcedureRelationId, InvalidOid, 0,	\
+								  PointerGetDatum(&__info));			\
+		}																\
+	} while(0)
+
+#define InvokeObjectAccessHook(access,classId,objectId,subId,argment) \
+	do {															  \
+		if (object_access_hook)										  \
+			(*object_access_hook)((access),(classId),				  \
+								  (objectId),(subId),(argment));	  \
 	} while(0)
 
 #endif   /* OBJECTACCESS_H */
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 26966d2..7b2d172 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -237,6 +237,7 @@ extern void AggregateCreate(const char *aggName,
 				List *aggfinalfnName,
 				List *aggsortopName,
 				Oid aggTransType,
-				const char *agginitval);
+				const char *agginitval,
+				Datum hook_private);
 
 #endif   /* PG_AGGREGATE_H */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 680802d7..eedcf1b 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -77,6 +77,7 @@ DESCR("standard public schema");
 /*
  * prototypes for functions in pg_namespace.c
  */
-extern Oid	NamespaceCreate(const char *nspName, Oid ownerId);
+extern Oid	NamespaceCreate(const char *nspName, Oid ownerId,
+							Datum hook_private);
 
 #endif   /* PG_NAMESPACE_H */
diff --git a/src/include/catalog/pg_proc_fn.h b/src/include/catalog/pg_proc_fn.h
index 09d779f..a28786f 100644
--- a/src/include/catalog/pg_proc_fn.h
+++ b/src/include/catalog/pg_proc_fn.h
@@ -37,7 +37,8 @@ extern Oid ProcedureCreate(const char *procedureName,
 				List *parameterDefaults,
 				Datum proconfig,
 				float4 procost,
-				float4 prorows);
+				float4 prorows,
+				Datum hook_private);
 
 extern bool function_parse_error_transpose(const char *prosrc);
 
diff --git a/src/include/catalog/pg_type_fn.h b/src/include/catalog/pg_type_fn.h
index 81e7d7f..f47c7b6 100644
--- a/src/include/catalog/pg_type_fn.h
+++ b/src/include/catalog/pg_type_fn.h
@@ -19,7 +19,8 @@
 
 extern Oid TypeShellMake(const char *typeName,
 			  Oid typeNamespace,
-			  Oid ownerId);
+			  Oid ownerId,
+			  Datum hook_private);
 
 extern Oid TypeCreate(Oid newTypeOid,
 		   const char *typeName,
@@ -51,7 +52,8 @@ extern Oid TypeCreate(Oid newTypeOid,
 		   int32 typeMod,
 		   int32 typNDims,
 		   bool typeNotNull,
-		   Oid typeCollation);
+		   Oid typeCollation,
+		   Datum hook_private);
 
 extern void GenerateTypeDependencies(Oid typeNamespace,
 						 Oid typeObjectId,
