Commit 0bd4da23 authored by Tom Lane's avatar Tom Lane

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.
parent 6b8cc882
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.120 2007/01/05 22:19:21 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.121 2007/11/11 19:22:48 tgl Exp $
* *
* NOTES * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
...@@ -534,8 +534,7 @@ BuildDescForRelation(List *schema) ...@@ -534,8 +534,7 @@ BuildDescForRelation(List *schema)
attnum++; attnum++;
attname = entry->colname; attname = entry->colname;
atttypid = typenameTypeId(NULL, entry->typename); atttypid = typenameTypeId(NULL, entry->typename, &atttypmod);
atttypmod = typenameTypeMod(NULL, entry->typename, atttypid);
attdim = list_length(entry->typename->arrayBounds); attdim = list_length(entry->typename->arrayBounds);
if (entry->typename->setof) if (entry->typename->setof)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.43 2007/04/02 03:49:37 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.44 2007/11/11 19:22:48 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -142,7 +142,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -142,7 +142,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
{ {
numArgs = 1; numArgs = 1;
aggArgTypes = (Oid *) palloc(sizeof(Oid)); aggArgTypes = (Oid *) palloc(sizeof(Oid));
aggArgTypes[0] = typenameTypeId(NULL, baseType); aggArgTypes[0] = typenameTypeId(NULL, baseType, NULL);
} }
} }
else else
...@@ -164,7 +164,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -164,7 +164,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
{ {
TypeName *curTypeName = (TypeName *) lfirst(lc); TypeName *curTypeName = (TypeName *) lfirst(lc);
aggArgTypes[i++] = typenameTypeId(NULL, curTypeName); aggArgTypes[i++] = typenameTypeId(NULL, curTypeName, NULL);
} }
} }
...@@ -175,7 +175,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters) ...@@ -175,7 +175,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
* values of the transtype. However, we can allow polymorphic transtype * values of the transtype. However, we can allow polymorphic transtype
* in some cases (AggregateCreate will check). * in some cases (AggregateCreate will check).
*/ */
transTypeId = typenameTypeId(NULL, transType); transTypeId = typenameTypeId(NULL, transType, NULL);
if (get_typtype(transTypeId) == TYPTYPE_PSEUDO && if (get_typtype(transTypeId) == TYPTYPE_PSEUDO &&
!IsPolymorphicType(transTypeId)) !IsPolymorphicType(transTypeId))
ereport(ERROR, ereport(ERROR,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 1996-2007, PostgreSQL Global Development Group * Copyright (c) 1996-2007, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.97 2007/08/21 01:11:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.98 2007/11/11 19:22:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -874,7 +874,7 @@ CommentType(List *typename, char *comment) ...@@ -874,7 +874,7 @@ CommentType(List *typename, char *comment)
/* Find the type's oid */ /* Find the type's oid */
oid = typenameTypeId(NULL, tname); oid = typenameTypeId(NULL, tname, NULL);
/* Check object security */ /* Check object security */
...@@ -1451,8 +1451,8 @@ CommentCast(List *qualname, List *arguments, char *comment) ...@@ -1451,8 +1451,8 @@ CommentCast(List *qualname, List *arguments, char *comment)
targettype = (TypeName *) linitial(arguments); targettype = (TypeName *) linitial(arguments);
Assert(IsA(targettype, TypeName)); Assert(IsA(targettype, TypeName));
sourcetypeid = typenameTypeId(NULL, sourcetype); sourcetypeid = typenameTypeId(NULL, sourcetype, NULL);
targettypeid = typenameTypeId(NULL, targettype); targettypeid = typenameTypeId(NULL, targettype, NULL);
tuple = SearchSysCache(CASTSOURCETARGET, tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(sourcetypeid),
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* These routines take the parse tree and pick out the * These routines take the parse tree and pick out the
...@@ -76,12 +76,13 @@ compute_return_type(TypeName *returnType, Oid languageOid, ...@@ -76,12 +76,13 @@ compute_return_type(TypeName *returnType, Oid languageOid,
Oid *prorettype_p, bool *returnsSet_p) Oid *prorettype_p, bool *returnsSet_p)
{ {
Oid rettype; 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) if (languageOid == SQLlanguageId)
ereport(ERROR, ereport(ERROR,
...@@ -94,6 +95,8 @@ compute_return_type(TypeName *returnType, Oid languageOid, ...@@ -94,6 +95,8 @@ compute_return_type(TypeName *returnType, Oid languageOid,
errmsg("return type %s is only a shell", errmsg("return type %s is only a shell",
TypeNameToString(returnType)))); TypeNameToString(returnType))));
} }
rettype = typeTypeId(typtup);
ReleaseSysCache(typtup);
} }
else else
{ {
...@@ -114,6 +117,13 @@ compute_return_type(TypeName *returnType, Oid languageOid, ...@@ -114,6 +117,13 @@ compute_return_type(TypeName *returnType, Oid languageOid,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", typnam))); 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 */ /* Otherwise, go ahead and make a shell type */
ereport(NOTICE, ereport(NOTICE,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
...@@ -175,11 +185,12 @@ examine_parameter_list(List *parameters, Oid languageOid, ...@@ -175,11 +185,12 @@ examine_parameter_list(List *parameters, Oid languageOid,
FunctionParameter *fp = (FunctionParameter *) lfirst(x); FunctionParameter *fp = (FunctionParameter *) lfirst(x);
TypeName *t = fp->argType; TypeName *t = fp->argType;
Oid toid; Oid toid;
Type typtup;
toid = LookupTypeName(NULL, t); typtup = LookupTypeName(NULL, t, NULL);
if (OidIsValid(toid)) if (typtup)
{ {
if (!get_typisdefined(toid)) if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined)
{ {
/* As above, hard error if language is SQL */ /* As above, hard error if language is SQL */
if (languageOid == SQLlanguageId) if (languageOid == SQLlanguageId)
...@@ -193,6 +204,8 @@ examine_parameter_list(List *parameters, Oid languageOid, ...@@ -193,6 +204,8 @@ examine_parameter_list(List *parameters, Oid languageOid,
errmsg("argument type %s is only a shell", errmsg("argument type %s is only a shell",
TypeNameToString(t)))); TypeNameToString(t))));
} }
toid = typeTypeId(typtup);
ReleaseSysCache(typtup);
} }
else else
{ {
...@@ -200,6 +213,7 @@ examine_parameter_list(List *parameters, Oid languageOid, ...@@ -200,6 +213,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type %s does not exist", errmsg("type %s does not exist",
TypeNameToString(t)))); TypeNameToString(t))));
toid = InvalidOid; /* keep compiler quiet */
} }
if (t->setof) if (t->setof)
...@@ -1341,8 +1355,8 @@ CreateCast(CreateCastStmt *stmt) ...@@ -1341,8 +1355,8 @@ CreateCast(CreateCastStmt *stmt)
ObjectAddress myself, ObjectAddress myself,
referenced; referenced;
sourcetypeid = typenameTypeId(NULL, stmt->sourcetype); sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
targettypeid = typenameTypeId(NULL, stmt->targettype); targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
/* No pseudo-types allowed */ /* No pseudo-types allowed */
if (get_typtype(sourcetypeid) == TYPTYPE_PSEUDO) if (get_typtype(sourcetypeid) == TYPTYPE_PSEUDO)
...@@ -1567,8 +1581,8 @@ DropCast(DropCastStmt *stmt) ...@@ -1567,8 +1581,8 @@ DropCast(DropCastStmt *stmt)
ObjectAddress object; ObjectAddress object;
/* when dropping a cast, the types must exist even if you use IF EXISTS */ /* when dropping a cast, the types must exist even if you use IF EXISTS */
sourcetypeid = typenameTypeId(NULL, stmt->sourcetype); sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
targettypeid = typenameTypeId(NULL, stmt->targettype); targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
tuple = SearchSysCache(CASTSOURCETARGET, tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(sourcetypeid),
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.54 2007/02/01 19:10:26 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.55 2007/11/11 19:22:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -327,7 +327,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -327,7 +327,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
errmsg("must be superuser to create an operator class"))); errmsg("must be superuser to create an operator class")));
/* Look up the datatype */ /* Look up the datatype */
typeoid = typenameTypeId(NULL, stmt->datatype); typeoid = typenameTypeId(NULL, stmt->datatype, NULL);
#ifdef NOT_USED #ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */
...@@ -481,7 +481,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -481,7 +481,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("storage type specified more than once"))); errmsg("storage type specified more than once")));
storageoid = typenameTypeId(NULL, item->storedtype); storageoid = typenameTypeId(NULL, item->storedtype, NULL);
#ifdef NOT_USED #ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */ /* XXX this is unnecessary given the superuser check above */
...@@ -1035,12 +1035,12 @@ processTypesSpec(List *args, Oid *lefttype, Oid *righttype) ...@@ -1035,12 +1035,12 @@ processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Assert(args != NIL); Assert(args != NIL);
typeName = (TypeName *) linitial(args); typeName = (TypeName *) linitial(args);
*lefttype = typenameTypeId(NULL, typeName); *lefttype = typenameTypeId(NULL, typeName, NULL);
if (list_length(args) > 1) if (list_length(args) > 1)
{ {
typeName = (TypeName *) lsecond(args); typeName = (TypeName *) lsecond(args);
*righttype = typenameTypeId(NULL, typeName); *righttype = typenameTypeId(NULL, typeName, NULL);
} }
else else
*righttype = *lefttype; *righttype = *lefttype;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.36 2007/06/02 23:36:35 petere Exp $ * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.37 2007/11/11 19:22:48 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -149,9 +149,9 @@ DefineOperator(List *names, List *parameters) ...@@ -149,9 +149,9 @@ DefineOperator(List *names, List *parameters)
/* Transform type names to type OIDs */ /* Transform type names to type OIDs */
if (typeName1) if (typeName1)
typeId1 = typenameTypeId(NULL, typeName1); typeId1 = typenameTypeId(NULL, typeName1, NULL);
if (typeName2) if (typeName2)
typeId2 = typenameTypeId(NULL, typeName2); typeId2 = typenameTypeId(NULL, typeName2, NULL);
/* /*
* now have OperatorCreate do all the work.. * now have OperatorCreate do all the work..
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Copyright (c) 2002-2007, PostgreSQL Global Development Group * Copyright (c) 2002-2007, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.77 2007/06/23 22:12:50 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.78 2007/11/11 19:22:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -90,7 +90,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString) ...@@ -90,7 +90,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
foreach(l, stmt->argtypes) foreach(l, stmt->argtypes)
{ {
TypeName *tn = lfirst(l); TypeName *tn = lfirst(l);
Oid toid = typenameTypeId(pstate, tn); Oid toid = typenameTypeId(pstate, tn, NULL);
argtypes[i++] = toid; argtypes[i++] = toid;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.234 2007/10/12 18:55:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.235 2007/11/11 19:22:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -899,8 +899,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -899,8 +899,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
(errmsg("merging multiple inherited definitions of column \"%s\"", (errmsg("merging multiple inherited definitions of column \"%s\"",
attributeName))); attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
defTypeId = typenameTypeId(NULL, def->typename); defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
deftypmod = typenameTypeMod(NULL, def->typename, defTypeId);
if (defTypeId != attribute->atttypid || if (defTypeId != attribute->atttypid ||
deftypmod != attribute->atttypmod) deftypmod != attribute->atttypmod)
ereport(ERROR, ereport(ERROR,
...@@ -1044,10 +1043,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -1044,10 +1043,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
(errmsg("merging column \"%s\" with inherited definition", (errmsg("merging column \"%s\" with inherited definition",
attributeName))); attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
defTypeId = typenameTypeId(NULL, def->typename); defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
deftypmod = typenameTypeMod(NULL, def->typename, defTypeId); newTypeId = typenameTypeId(NULL, newdef->typename, &newtypmod);
newTypeId = typenameTypeId(NULL, newdef->typename);
newtypmod = typenameTypeMod(NULL, newdef->typename, newTypeId);
if (defTypeId != newTypeId || deftypmod != newtypmod) if (defTypeId != newTypeId || deftypmod != newtypmod)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
...@@ -3018,8 +3015,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, ...@@ -3018,8 +3015,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
int32 ctypmod; int32 ctypmod;
/* Okay if child matches by type */ /* Okay if child matches by type */
ctypeId = typenameTypeId(NULL, colDef->typename); ctypeId = typenameTypeId(NULL, colDef->typename, &ctypmod);
ctypmod = typenameTypeMod(NULL, colDef->typename, ctypeId);
if (ctypeId != childatt->atttypid || if (ctypeId != childatt->atttypid ||
ctypmod != childatt->atttypmod) ctypmod != childatt->atttypmod)
ereport(ERROR, ereport(ERROR,
...@@ -3074,10 +3070,9 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, ...@@ -3074,10 +3070,9 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
MaxHeapAttributeNumber))); MaxHeapAttributeNumber)));
i = minattnum + 1; i = minattnum + 1;
typeTuple = typenameType(NULL, colDef->typename); typeTuple = typenameType(NULL, colDef->typename, &typmod);
tform = (Form_pg_type) GETSTRUCT(typeTuple); tform = (Form_pg_type) GETSTRUCT(typeTuple);
typeOid = HeapTupleGetOid(typeTuple); typeOid = HeapTupleGetOid(typeTuple);
typmod = typenameTypeMod(NULL, colDef->typename, typeOid);
/* make sure datatype is legal for a column */ /* make sure datatype is legal for a column */
CheckAttributeType(colDef->colname, typeOid); CheckAttributeType(colDef->colname, typeOid);
...@@ -4777,8 +4772,7 @@ ATPrepAlterColumnType(List **wqueue, ...@@ -4777,8 +4772,7 @@ ATPrepAlterColumnType(List **wqueue,
colName))); colName)));
/* Look up the target type */ /* Look up the target type */
targettype = typenameTypeId(NULL, typename); targettype = typenameTypeId(NULL, typename, &targettypmod);
targettypmod = typenameTypeMod(NULL, typename, targettype);
/* make sure datatype is legal for a column */ /* make sure datatype is legal for a column */
CheckAttributeType(colName, targettype); CheckAttributeType(colName, targettype);
...@@ -4905,10 +4899,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, ...@@ -4905,10 +4899,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
colName))); colName)));
/* Look up the target type (should not fail, since prep found it) */ /* Look up the target type (should not fail, since prep found it) */
typeTuple = typenameType(NULL, typename); typeTuple = typenameType(NULL, typename, &targettypmod);
tform = (Form_pg_type) GETSTRUCT(typeTuple); tform = (Form_pg_type) GETSTRUCT(typeTuple);
targettype = HeapTupleGetOid(typeTuple); targettype = HeapTupleGetOid(typeTuple);
targettypmod = typenameTypeMod(NULL, typename, targettype);
/* /*
* If there is a default expression for the column, get it and ensure we * If there is a default expression for the column, get it and ensure we
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.109 2007/10/29 19:40:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.110 2007/11/11 19:22:48 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -211,7 +211,7 @@ DefineType(List *names, List *parameters) ...@@ -211,7 +211,7 @@ DefineType(List *names, List *parameters)
} }
else if (pg_strcasecmp(defel->defname, "element") == 0) else if (pg_strcasecmp(defel->defname, "element") == 0)
{ {
elemType = typenameTypeId(NULL, defGetTypeName(defel)); elemType = typenameTypeId(NULL, defGetTypeName(defel), NULL);
/* disallow arrays of pseudotypes */ /* disallow arrays of pseudotypes */
if (get_typtype(elemType) == TYPTYPE_PSEUDO) if (get_typtype(elemType) == TYPTYPE_PSEUDO)
ereport(ERROR, ereport(ERROR,
...@@ -497,8 +497,8 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok) ...@@ -497,8 +497,8 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok)
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */ /* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(NULL, typename); tup = LookupTypeName(NULL, typename, NULL);
if (!OidIsValid(typeoid)) if (tup == NULL)
{ {
if (!missing_ok) if (!missing_ok)
{ {
...@@ -517,11 +517,7 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok) ...@@ -517,11 +517,7 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok)
return; return;
} }
tup = SearchSysCache(TYPEOID, typeoid = typeTypeId(tup);
ObjectIdGetDatum(typeoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", typeoid);
typ = (Form_pg_type) GETSTRUCT(tup); typ = (Form_pg_type) GETSTRUCT(tup);
/* Permission check: must own type or its namespace */ /* Permission check: must own type or its namespace */
...@@ -650,10 +646,9 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -650,10 +646,9 @@ DefineDomain(CreateDomainStmt *stmt)
/* /*
* Look up the base type. * Look up the base type.
*/ */
typeTup = typenameType(NULL, stmt->typename); typeTup = typenameType(NULL, stmt->typename, &basetypeMod);
baseType = (Form_pg_type) GETSTRUCT(typeTup); baseType = (Form_pg_type) GETSTRUCT(typeTup);
basetypeoid = HeapTupleGetOid(typeTup); basetypeoid = HeapTupleGetOid(typeTup);
basetypeMod = typenameTypeMod(NULL, stmt->typename, basetypeoid);
/* /*
* Base type must be a plain base type, another domain or an enum. * Base type must be a plain base type, another domain or an enum.
...@@ -946,8 +941,8 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok) ...@@ -946,8 +941,8 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */ /* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(NULL, typename); tup = LookupTypeName(NULL, typename, NULL);
if (!OidIsValid(typeoid)) if (tup == NULL)
{ {
if (!missing_ok) if (!missing_ok)
{ {
...@@ -966,11 +961,7 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok) ...@@ -966,11 +961,7 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
return; return;
} }
tup = SearchSysCache(TYPEOID, typeoid = typeTypeId(tup);
ObjectIdGetDatum(typeoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", typeoid);
/* Permission check: must own type or its namespace */ /* Permission check: must own type or its namespace */
if (!pg_type_ownercheck(typeoid, GetUserId()) && if (!pg_type_ownercheck(typeoid, GetUserId()) &&
...@@ -1443,7 +1434,7 @@ AlterDomainDefault(List *names, Node *defaultRaw) ...@@ -1443,7 +1434,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
domainoid = typenameTypeId(NULL, typename); domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */ /* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock); rel = heap_open(TypeRelationId, RowExclusiveLock);
...@@ -1573,7 +1564,7 @@ AlterDomainNotNull(List *names, bool notNull) ...@@ -1573,7 +1564,7 @@ AlterDomainNotNull(List *names, bool notNull)
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
domainoid = typenameTypeId(NULL, typename); domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */ /* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock); typrel = heap_open(TypeRelationId, RowExclusiveLock);
...@@ -1675,7 +1666,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, ...@@ -1675,7 +1666,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
domainoid = typenameTypeId(NULL, typename); domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */ /* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock); rel = heap_open(TypeRelationId, RowExclusiveLock);
...@@ -1750,7 +1741,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1750,7 +1741,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
domainoid = typenameTypeId(NULL, typename); domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */ /* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock); typrel = heap_open(TypeRelationId, RowExclusiveLock);
...@@ -2358,28 +2349,28 @@ AlterTypeOwner(List *names, Oid newOwnerId) ...@@ -2358,28 +2349,28 @@ AlterTypeOwner(List *names, Oid newOwnerId)
Oid typeOid; Oid typeOid;
Relation rel; Relation rel;
HeapTuple tup; HeapTuple tup;
HeapTuple newtup;
Form_pg_type typTup; Form_pg_type typTup;
AclResult aclresult; AclResult aclresult;
rel = heap_open(TypeRelationId, RowExclusiveLock);
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be processed */ /* Use LookupTypeName here so that shell types can be processed */
typeOid = LookupTypeName(NULL, typename); tup = LookupTypeName(NULL, typename, NULL);
if (!OidIsValid(typeOid)) if (tup == NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist", errmsg("type \"%s\" does not exist",
TypeNameToString(typename)))); TypeNameToString(typename))));
typeOid = typeTypeId(tup);
/* Look up the type in the type table */ /* Copy the syscache entry so we can scribble on it below */
rel = heap_open(TypeRelationId, RowExclusiveLock); newtup = heap_copytuple(tup);
ReleaseSysCache(tup);
tup = SearchSysCacheCopy(TYPEOID, tup = newtup;
ObjectIdGetDatum(typeOid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for type %u", typeOid);
typTup = (Form_pg_type) GETSTRUCT(tup); typTup = (Form_pg_type) GETSTRUCT(tup);
/* /*
...@@ -2526,7 +2517,7 @@ AlterTypeNamespace(List *names, const char *newschema) ...@@ -2526,7 +2517,7 @@ AlterTypeNamespace(List *names, const char *newschema)
/* Make a TypeName so we can use standard type lookup machinery */ /* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names); typename = makeTypeNameFromNameList(names);
typeOid = typenameTypeId(NULL, typename); typeOid = typenameTypeId(NULL, typename, NULL);
/* check permissions on type */ /* check permissions on type */
if (!pg_type_ownercheck(typeOid, GetUserId())) if (!pg_type_ownercheck(typeOid, GetUserId()))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.222 2007/10/29 19:40:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.223 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -829,7 +829,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a) ...@@ -829,7 +829,7 @@ transformAExprOf(ParseState *pstate, A_Expr *a)
ltype = exprType(lexpr); ltype = exprType(lexpr);
foreach(telem, (List *) a->rexpr) foreach(telem, (List *) a->rexpr)
{ {
rtype = typenameTypeId(pstate, lfirst(telem)); rtype = typenameTypeId(pstate, lfirst(telem), NULL);
matched = (rtype == ltype); matched = (rtype == ltype);
if (matched) if (matched)
break; break;
...@@ -1550,8 +1550,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs) ...@@ -1550,8 +1550,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
XMLOID, XMLOID,
"XMLSERIALIZE")); "XMLSERIALIZE"));
targetType = typenameTypeId(pstate, xs->typename); targetType = typenameTypeId(pstate, xs->typename, &targetTypmod);
targetTypmod = typenameTypeMod(pstate, xs->typename, targetType);
xexpr->xmloption = xs->xmloption; xexpr->xmloption = xs->xmloption;
/* We actually only need these to be able to parse back the expression. */ /* We actually only need these to be able to parse back the expression. */
...@@ -2227,8 +2226,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) ...@@ -2227,8 +2226,7 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
Oid targetType; Oid targetType;
int32 targetTypmod; int32 targetTypmod;
targetType = typenameTypeId(pstate, typename); targetType = typenameTypeId(pstate, typename, &targetTypmod);
targetTypmod = typenameTypeMod(pstate, typename, targetType);
if (inputType == InvalidOid) if (inputType == InvalidOid)
return expr; /* do nothing if NULL input */ return expr; /* do nothing if NULL input */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -33,6 +33,7 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static Oid FuncNameAsType(List *funcname);
static Node *ParseComplexProjection(ParseState *pstate, char *funcname, static Node *ParseComplexProjection(ParseState *pstate, char *funcname,
Node *first_arg, int location); Node *first_arg, int location);
static void unknown_attribute(ParseState *pstate, Node *relref, char *attname, static void unknown_attribute(ParseState *pstate, Node *relref, char *attname,
...@@ -752,12 +753,9 @@ func_get_detail(List *funcname, ...@@ -752,12 +753,9 @@ func_get_detail(List *funcname,
*/ */
if (nargs == 1 && fargs != NIL) if (nargs == 1 && fargs != NIL)
{ {
Oid targetType; Oid targetType = FuncNameAsType(funcname);
targetType = LookupTypeName(NULL, if (OidIsValid(targetType))
makeTypeNameFromNameList(funcname));
if (OidIsValid(targetType) &&
!ISCOMPLEX(targetType))
{ {
Oid sourceType = argtypes[0]; Oid sourceType = argtypes[0];
Node *arg1 = linitial(fargs); Node *arg1 = linitial(fargs);
...@@ -985,6 +983,33 @@ make_fn_arguments(ParseState *pstate, ...@@ -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 - * ParseComplexProjection -
* handles function calls with a single argument that is of complex type. * 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) ...@@ -1180,6 +1205,27 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
return InvalidOid; 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 * LookupFuncNameTypeNames
* Like LookupFuncName, but the argument types are specified by a * Like LookupFuncName, but the argument types are specified by a
...@@ -1205,14 +1251,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) ...@@ -1205,14 +1251,7 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
{ {
TypeName *t = (TypeName *) lfirst(args_item); TypeName *t = (TypeName *) lfirst(args_item);
argoids[i] = LookupTypeName(NULL, t); argoids[i] = LookupTypeNameOid(t);
if (!OidIsValid(argoids[i]))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(t))));
args_item = lnext(args_item); args_item = lnext(args_item);
} }
...@@ -1250,12 +1289,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError) ...@@ -1250,12 +1289,7 @@ LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
{ {
TypeName *t = (TypeName *) lfirst(lc); TypeName *t = (TypeName *) lfirst(lc);
argoids[i] = LookupTypeName(NULL, t); argoids[i] = LookupTypeNameOid(t);
if (!OidIsValid(argoids[i]))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(t))));
i++; i++;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.95 2007/04/02 03:49:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.96 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -110,12 +110,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername, ...@@ -110,12 +110,12 @@ LookupOperNameTypeNames(ParseState *pstate, List *opername,
if (oprleft == NULL) if (oprleft == NULL)
leftoid = InvalidOid; leftoid = InvalidOid;
else else
leftoid = typenameTypeId(pstate, oprleft); leftoid = typenameTypeId(pstate, oprleft, NULL);
if (oprright == NULL) if (oprright == NULL)
rightoid = InvalidOid; rightoid = InvalidOid;
else else
rightoid = typenameTypeId(pstate, oprright); rightoid = typenameTypeId(pstate, oprright, NULL);
return LookupOperName(pstate, opername, leftoid, rightoid, return LookupOperName(pstate, opername, leftoid, rightoid,
noError, location); noError, location);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.128 2007/09/06 17:31:58 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.129 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -901,8 +901,7 @@ addRangeTableEntryForFunction(ParseState *pstate, ...@@ -901,8 +901,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION), (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" cannot be declared SETOF", errmsg("column \"%s\" cannot be declared SETOF",
attrname))); attrname)));
attrtype = typenameTypeId(pstate, n->typename); attrtype = typenameTypeId(pstate, n->typename, &attrtypmod);
attrtypmod = typenameTypeMod(pstate, n->typename, attrtype);
eref->colnames = lappend(eref->colnames, makeString(attrname)); eref->colnames = lappend(eref->colnames, makeString(attrname));
rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod); rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
......
This diff is collapsed.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.4 2007/10/29 19:40:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.5 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1955,7 +1955,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column) ...@@ -1955,7 +1955,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
/* /*
* All we really need to do here is verify that the type is valid. * All we really need to do here is verify that the type is valid.
*/ */
Type ctype = typenameType(pstate, column->typename); Type ctype = typenameType(pstate, column->typename, NULL);
ReleaseSysCache(ctype); ReleaseSysCache(ctype);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.424 2007/11/09 17:31:07 mha Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.425 2007/11/11 19:22:49 tgl Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -4872,11 +4872,13 @@ flatten_set_variable_args(const char *name, List *args) ...@@ -4872,11 +4872,13 @@ flatten_set_variable_args(const char *name, List *args)
* to interval and back to normalize the value and account * to interval and back to normalize the value and account
* for any typmod. * for any typmod.
*/ */
Oid typoid;
int32 typmod; int32 typmod;
Datum interval; Datum interval;
char *intervalout; char *intervalout;
typmod = typenameTypeMod(NULL, arg->typename, INTERVALOID); typoid = typenameTypeId(NULL, arg->typename, &typmod);
Assert(typoid == INTERVALOID);
interval = interval =
DirectFunctionCall3(interval_in, DirectFunctionCall3(interval_in,
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* parse_type.h * parse_type.h
* * handle type operations for parser
*
* *
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.36 2007/04/02 03:49:41 tgl Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.37 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,13 +19,15 @@ ...@@ -20,13 +19,15 @@
typedef HeapTuple Type; typedef HeapTuple Type;
extern Oid LookupTypeName(ParseState *pstate, const TypeName *typename); extern Type LookupTypeName(ParseState *pstate, const TypeName *typename,
int32 *typmod_p);
extern Type typenameType(ParseState *pstate, const TypeName *typename,
int32 *typmod_p);
extern Oid typenameTypeId(ParseState *pstate, const TypeName *typename,
int32 *typmod_p);
extern char *TypeNameToString(const TypeName *typename); extern char *TypeNameToString(const TypeName *typename);
extern char *TypeNameListToString(List *typenames); extern char *TypeNameListToString(List *typenames);
extern Oid typenameTypeId(ParseState *pstate, const TypeName *typename);
extern int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
Oid typeId);
extern Type typenameType(ParseState *pstate, const TypeName *typename);
extern Type typeidType(Oid id); extern Type typeidType(Oid id);
...@@ -39,7 +40,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod); ...@@ -39,7 +40,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
extern Oid typeidTypeRelid(Oid type_id); extern Oid typeidTypeRelid(Oid type_id);
extern void parseTypeString(const char *str, Oid *type_id, int32 *typmod); extern void parseTypeString(const char *str, Oid *type_id, int32 *typmod_p);
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid) #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.117 2007/07/16 17:01:10 tgl Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.118 2007/11/11 19:22:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1099,7 +1099,7 @@ plpgsql_parse_wordtype(char *word) ...@@ -1099,7 +1099,7 @@ plpgsql_parse_wordtype(char *word)
{ {
PLpgSQL_nsitem *nse; PLpgSQL_nsitem *nse;
bool old_nsstate; bool old_nsstate;
Oid typeOid; HeapTuple typeTup;
char *cp[2]; char *cp[2];
int i; int i;
...@@ -1138,17 +1138,10 @@ plpgsql_parse_wordtype(char *word) ...@@ -1138,17 +1138,10 @@ plpgsql_parse_wordtype(char *word)
/* /*
* Word wasn't found on the namestack. Try to find a data type with that * Word wasn't found on the namestack. Try to find a data type with that
* name, but ignore pg_type entries that are in fact class types. * name, but ignore shell types and complex types.
*/ */
typeOid = LookupTypeName(NULL, makeTypeName(cp[0])); typeTup = LookupTypeName(NULL, makeTypeName(cp[0]), NULL);
if (OidIsValid(typeOid)) if (typeTup)
{
HeapTuple typeTup;
typeTup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeOid),
0, 0, 0);
if (HeapTupleIsValid(typeTup))
{ {
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup); Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
...@@ -1166,7 +1159,6 @@ plpgsql_parse_wordtype(char *word) ...@@ -1166,7 +1159,6 @@ plpgsql_parse_wordtype(char *word)
pfree(cp[0]); pfree(cp[0]);
return T_DTYPE; return T_DTYPE;
} }
}
/* /*
* Nothing found - up to now it's a word without any special meaning for * Nothing found - up to now it's a word without any special meaning for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment