aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-11-11 19:22:49 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-11-11 19:22:49 +0000
commit0bd4da23a4bee4fb3b6b61cb0fadc43c054c5ddb (patch)
tree2a37c084e71feafe8e502758e7e01446192d9529 /src/backend/commands/functioncmds.c
parent6b8cc88268fcf33b5e2d3c230f097dff0541398f (diff)
downloadpostgresql-0bd4da23a4bee4fb3b6b61cb0fadc43c054c5ddb.tar.gz
postgresql-0bd4da23a4bee4fb3b6b61cb0fadc43c054c5ddb.zip
Ensure that typmod decoration on a datatype name is validated in all cases,
even in code paths where we don't pay any subsequent attention to the typmod value. This seems needed in view of the fact that 8.3's generalized typmod support will accept a lot of bogus syntax, such as "timestamp(foo)" or "record(int, 42)" --- if we allow such things to pass without comment, users will get confused. Per a recent example from Greg Stark. To implement this in a way that's not very vulnerable to future bugs-of-omission, refactor the API of parse_type.c's TypeName lookup routines so that typmod validation is folded into the base lookup operation. Callers can still choose not to receive the encoded typmod, but we'll check the decoration anyway if it's present.
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9e5d0b1095b..3a556615026 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.85 2007/09/03 18:46:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.86 2007/11/11 19:22:48 tgl Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -76,12 +76,13 @@ compute_return_type(TypeName *returnType, Oid languageOid,
Oid *prorettype_p, bool *returnsSet_p)
{
Oid rettype;
+ Type typtup;
- rettype = LookupTypeName(NULL, returnType);
+ typtup = LookupTypeName(NULL, returnType, NULL);
- if (OidIsValid(rettype))
+ if (typtup)
{
- if (!get_typisdefined(rettype))
+ if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
{
if (languageOid == SQLlanguageId)
ereport(ERROR,
@@ -94,6 +95,8 @@ compute_return_type(TypeName *returnType, Oid languageOid,
errmsg("return type %s is only a shell",
TypeNameToString(returnType))));
}
+ rettype = typeTypeId(typtup);
+ ReleaseSysCache(typtup);
}
else
{
@@ -114,6 +117,13 @@ compute_return_type(TypeName *returnType, Oid languageOid,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", typnam)));
+ /* Reject if there's typmod decoration, too */
+ if (returnType->typmods != NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("type modifier cannot be specified for shell type \"%s\"",
+ typnam)));
+
/* Otherwise, go ahead and make a shell type */
ereport(NOTICE,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -175,11 +185,12 @@ examine_parameter_list(List *parameters, Oid languageOid,
FunctionParameter *fp = (FunctionParameter *) lfirst(x);
TypeName *t = fp->argType;
Oid toid;
+ Type typtup;
- toid = LookupTypeName(NULL, t);
- if (OidIsValid(toid))
+ typtup = LookupTypeName(NULL, t, NULL);
+ if (typtup)
{
- if (!get_typisdefined(toid))
+ if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
{
/* As above, hard error if language is SQL */
if (languageOid == SQLlanguageId)
@@ -193,6 +204,8 @@ examine_parameter_list(List *parameters, Oid languageOid,
errmsg("argument type %s is only a shell",
TypeNameToString(t))));
}
+ toid = typeTypeId(typtup);
+ ReleaseSysCache(typtup);
}
else
{
@@ -200,6 +213,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type %s does not exist",
TypeNameToString(t))));
+ toid = InvalidOid; /* keep compiler quiet */
}
if (t->setof)
@@ -1341,8 +1355,8 @@ CreateCast(CreateCastStmt *stmt)
ObjectAddress myself,
referenced;
- sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
- targettypeid = typenameTypeId(NULL, stmt->targettype);
+ sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
+ targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
/* No pseudo-types allowed */
if (get_typtype(sourcetypeid) == TYPTYPE_PSEUDO)
@@ -1567,8 +1581,8 @@ DropCast(DropCastStmt *stmt)
ObjectAddress object;
/* when dropping a cast, the types must exist even if you use IF EXISTS */
- sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
- targettypeid = typenameTypeId(NULL, stmt->targettype);
+ sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
+ targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid),