mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
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.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.197 2007/06/06 23:00:37 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.198 2007/11/11 19:22:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,6 +33,7 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
static Oid FuncNameAsType(List *funcname);
|
||||
static Node *ParseComplexProjection(ParseState *pstate, char *funcname,
|
||||
Node *first_arg, int location);
|
||||
static void unknown_attribute(ParseState *pstate, Node *relref, char *attname,
|
||||
@ -752,12 +753,9 @@ func_get_detail(List *funcname,
|
||||
*/
|
||||
if (nargs == 1 && fargs != NIL)
|
||||
{
|
||||
Oid targetType;
|
||||
Oid targetType = FuncNameAsType(funcname);
|
||||
|
||||
targetType = LookupTypeName(NULL,
|
||||
makeTypeNameFromNameList(funcname));
|
||||
if (OidIsValid(targetType) &&
|
||||
!ISCOMPLEX(targetType))
|
||||
if (OidIsValid(targetType))
|
||||
{
|
||||
Oid sourceType = argtypes[0];
|
||||
Node *arg1 = linitial(fargs);
|
||||
@ -985,6 +983,33 @@ make_fn_arguments(ParseState *pstate,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FuncNameAsType -
|
||||
* convenience routine to see if a function name matches a type name
|
||||
*
|
||||
* Returns the OID of the matching type, or InvalidOid if none. We ignore
|
||||
* shell types and complex types.
|
||||
*/
|
||||
static Oid
|
||||
FuncNameAsType(List *funcname)
|
||||
{
|
||||
Oid result;
|
||||
Type typtup;
|
||||
|
||||
typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL);
|
||||
if (typtup == NULL)
|
||||
return InvalidOid;
|
||||
|
||||
if (((Form_pg_type) GETSTRUCT(typtup))->typisdefined &&
|
||||
!OidIsValid(typeTypeRelid(typtup)))
|
||||
result = typeTypeId(typtup);
|
||||
else
|
||||
result = InvalidOid;
|
||||
|
||||
ReleaseSysCache(typtup);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* ParseComplexProjection -
|
||||
* handles function calls with a single argument that is of complex type.
|
||||
@ -1180,6 +1205,27 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupTypeNameOid
|
||||
* Convenience routine to look up a type, silently accepting shell types
|
||||
*/
|
||||
static Oid
|
||||
LookupTypeNameOid(const TypeName *typename)
|
||||
{
|
||||
Oid result;
|
||||
Type typtup;
|
||||
|
||||
typtup = LookupTypeName(NULL, typename, NULL);
|
||||
if (typtup == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
result = typeTypeId(typtup);
|
||||
ReleaseSysCache(typtup);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* LookupFuncNameTypeNames
|
||||
* Like LookupFuncName, but the argument types are specified by a
|
||||
@ -1205,14 +1251,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
|
||||
{
|
||||
TypeName *t = (TypeName *) lfirst(args_item);
|
||||
|
||||
argoids[i] = LookupTypeName(NULL, t);
|
||||
|
||||
if (!OidIsValid(argoids[i]))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(t))));
|
||||
|
||||
argoids[i] = LookupTypeNameOid(t);
|
||||
args_item = lnext(args_item);
|
||||
}
|
||||
|
||||
@ -1250,12 +1289,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
|
||||
{
|
||||
TypeName *t = (TypeName *) lfirst(lc);
|
||||
|
||||
argoids[i] = LookupTypeName(NULL, t);
|
||||
if (!OidIsValid(argoids[i]))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(t))));
|
||||
argoids[i] = LookupTypeNameOid(t);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user