aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-08-22 00:01:51 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-08-22 00:01:51 +0000
commitb663f3443ba096a06970214c3e83e79f6e570b84 (patch)
tree049e26c1b02535c12bee6e60ba89cf1d42a41a72 /src/backend/commands/functioncmds.c
parent606c9b9d4fafe9300d039c044edc9727c0ed43c9 (diff)
downloadpostgresql-b663f3443ba096a06970214c3e83e79f6e570b84.tar.gz
postgresql-b663f3443ba096a06970214c3e83e79f6e570b84.zip
Add a bunch of pseudo-types to replace the behavior formerly associated
with OPAQUE, as per recent pghackers discussion. I still want to do some more work on the 'cstring' pseudo-type, but I'm going to commit the bulk of the changes now before the tree starts shifting under me ...
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c101
1 files changed, 61 insertions, 40 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 51d003600bb..6d6ad94a4ed 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.17 2002/08/11 17:44:12 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.18 2002/08/22 00:01:42 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -61,7 +61,9 @@
* allow a shell type to be used, or even created if the specified return type
* doesn't exist yet. (Without this, there's no way to define the I/O procs
* for a new type.) But SQL function creation won't cope, so error out if
- * the target language is SQL.
+ * the target language is SQL. (We do this here, not in the SQL-function
+ * validator, so as not to produce a WARNING and then an ERROR for the same
+ * condition.)
*/
static void
compute_return_type(TypeName *returnType, Oid languageOid,
@@ -76,7 +78,8 @@ compute_return_type(TypeName *returnType, Oid languageOid,
if (!get_typisdefined(rettype))
{
if (languageOid == SQLlanguageId)
- elog(ERROR, "SQL functions cannot return shell types");
+ elog(ERROR, "SQL function cannot return shell type \"%s\"",
+ TypeNameToString(returnType));
else
elog(WARNING, "Return type \"%s\" is only a shell",
TypeNameToString(returnType));
@@ -85,29 +88,32 @@ compute_return_type(TypeName *returnType, Oid languageOid,
else
{
char *typnam = TypeNameToString(returnType);
+ Oid namespaceId;
+ AclResult aclresult;
+ char *typname;
- if (strcmp(typnam, "opaque") == 0)
- rettype = InvalidOid;
- else
- {
- Oid namespaceId;
- AclResult aclresult;
- char *typname;
-
- if (languageOid == SQLlanguageId)
- elog(ERROR, "Type \"%s\" does not exist", typnam);
- elog(WARNING, "ProcedureCreate: type %s is not yet defined",
- typnam);
- namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
- &typname);
- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
- ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, get_namespace_name(namespaceId));
- rettype = TypeShellMake(typname, namespaceId);
- if (!OidIsValid(rettype))
- elog(ERROR, "could not create type %s", typnam);
- }
+ /*
+ * Only C-coded functions can be I/O functions. We enforce this
+ * restriction here mainly to prevent littering the catalogs with
+ * shell types due to simple typos in user-defined function
+ * definitions.
+ */
+ if (languageOid != INTERNALlanguageId &&
+ languageOid != ClanguageId)
+ elog(ERROR, "Type \"%s\" does not exist", typnam);
+
+ /* Otherwise, go ahead and make a shell type */
+ elog(WARNING, "ProcedureCreate: type %s is not yet defined",
+ typnam);
+ namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
+ &typname);
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(namespaceId));
+ rettype = TypeShellMake(typname, namespaceId);
+ if (!OidIsValid(rettype))
+ elog(ERROR, "could not create type %s", typnam);
}
*prorettype_p = rettype;
@@ -138,25 +144,24 @@ compute_parameter_types(List *argTypes, Oid languageOid,
if (OidIsValid(toid))
{
if (!get_typisdefined(toid))
- elog(WARNING, "Argument type \"%s\" is only a shell",
- TypeNameToString(t));
- }
- else
- {
- char *typnam = TypeNameToString(t);
-
- if (strcmp(typnam, "opaque") == 0)
{
+ /* As above, hard error if language is SQL */
if (languageOid == SQLlanguageId)
- elog(ERROR, "SQL functions cannot have arguments of type \"opaque\"");
- toid = InvalidOid;
+ elog(ERROR, "SQL function cannot accept shell type \"%s\"",
+ TypeNameToString(t));
+ else
+ elog(WARNING, "Argument type \"%s\" is only a shell",
+ TypeNameToString(t));
}
- else
- elog(ERROR, "Type \"%s\" does not exist", typnam);
+ }
+ else
+ {
+ elog(ERROR, "Type \"%s\" does not exist",
+ TypeNameToString(t));
}
if (t->setof)
- elog(ERROR, "functions cannot accept set arguments");
+ elog(ERROR, "Functions cannot accept set arguments");
parameterTypes[parameterCount++] = toid;
}
@@ -492,7 +497,7 @@ RemoveFunction(RemoveFuncStmt *stmt)
* Find the function, do permissions and validity checks
*/
funcOid = LookupFuncNameTypeNames(functionName, argTypes,
- true, "RemoveFunction");
+ "RemoveFunction");
tup = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcOid),
@@ -621,6 +626,23 @@ CreateCast(CreateCastStmt *stmt)
if (sourcetypeid == targettypeid)
elog(ERROR, "source data type and target data type are the same");
+ /* No shells, no pseudo-types allowed */
+ if (!get_typisdefined(sourcetypeid))
+ elog(ERROR, "source data type %s is only a shell",
+ TypeNameToString(stmt->sourcetype));
+
+ if (!get_typisdefined(targettypeid))
+ elog(ERROR, "target data type %s is only a shell",
+ TypeNameToString(stmt->targettype));
+
+ if (get_typtype(sourcetypeid) == 'p')
+ elog(ERROR, "source data type %s is a pseudo-type",
+ TypeNameToString(stmt->sourcetype));
+
+ if (get_typtype(targettypeid) == 'p')
+ elog(ERROR, "target data type %s is a pseudo-type",
+ TypeNameToString(stmt->targettype));
+
if (!pg_type_ownercheck(sourcetypeid, GetUserId())
&& !pg_type_ownercheck(targettypeid, GetUserId()))
elog(ERROR, "must be owner of type %s or type %s",
@@ -642,7 +664,6 @@ CreateCast(CreateCastStmt *stmt)
{
funcid = LookupFuncNameTypeNames(stmt->func->funcname,
stmt->func->funcargs,
- false,
"CreateCast");
tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0);