diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index 1205605ca36..a39c244c6c7 100644
--- a/doc/src/sgml/ref/create_type.sgml
+++ b/doc/src/sgml/ref/create_type.sgml
@@ -1,5 +1,5 @@
@@ -446,6 +446,17 @@ CREATE TYPE name (
internally-created array type names.
+
+ Because there are no restrictions on use of a data type once it's been
+ created, creating a base type is tantamount to granting public execute
+ permission on the functions mentioned in the type definition. (The creator
+ of the type is therefore required to own these functions.) This is usually
+ not an issue for the sorts of functions that are useful in a type
+ definition. But you might want to think twice before designing a type
+ in a way that would require secret> information to be used
+ while converting it to or from external form.
+
+
In PostgreSQL versions before 7.3, it
was customary to avoid creating a shell type by replacing the
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 389fe133a58..143695252f4 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.85 2005/11/22 18:17:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.86 2006/01/13 18:06:45 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -330,6 +330,30 @@ DefineType(List *names, List *parameters)
if (analyzeName)
analyzeOid = findTypeAnalyzeFunction(analyzeName, typoid);
+ /*
+ * Check permissions on functions. We choose to require the creator/owner
+ * of a type to also own the underlying functions. Since creating a type
+ * is tantamount to granting public execute access on the functions, the
+ * minimum sane check would be for execute-with-grant-option. But we don't
+ * have a way to make the type go away if the grant option is revoked, so
+ * ownership seems better.
+ */
+ if (inputOid && !pg_proc_ownercheck(inputOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameListToString(inputName));
+ if (outputOid && !pg_proc_ownercheck(outputOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameListToString(outputName));
+ if (receiveOid && !pg_proc_ownercheck(receiveOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameListToString(receiveName));
+ if (sendOid && !pg_proc_ownercheck(sendOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameListToString(sendName));
+ if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameListToString(analyzeName));
+
/*
* now have TypeCreate do all the real work.
*/