aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/tupdesc.c5
-rw-r--r--src/backend/commands/aggregatecmds.c8
-rw-r--r--src/backend/commands/comment.c8
-rw-r--r--src/backend/commands/functioncmds.c36
-rw-r--r--src/backend/commands/opclasscmds.c10
-rw-r--r--src/backend/commands/operatorcmds.c6
-rw-r--r--src/backend/commands/prepare.c4
-rw-r--r--src/backend/commands/tablecmds.c23
-rw-r--r--src/backend/commands/typecmds.c57
-rw-r--r--src/backend/parser/parse_expr.c10
-rw-r--r--src/backend/parser/parse_func.c74
-rw-r--r--src/backend/parser/parse_oper.c6
-rw-r--r--src/backend/parser/parse_relation.c5
-rw-r--r--src/backend/parser/parse_type.c310
-rw-r--r--src/backend/parser/parse_utilcmd.c4
-rw-r--r--src/backend/utils/misc/guc.c6
-rw-r--r--src/include/parser/parse_type.h19
-rw-r--r--src/pl/plpgsql/src/pl_comp.c38
18 files changed, 341 insertions, 288 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 50e41ade60e..6e2ac69cc40 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
*
*
* 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
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -534,8 +534,7 @@ BuildDescForRelation(List *schema)
attnum++;
attname = entry->colname;
- atttypid = typenameTypeId(NULL, entry->typename);
- atttypmod = typenameTypeMod(NULL, entry->typename, atttypid);
+ atttypid = typenameTypeId(NULL, entry->typename, &atttypmod);
attdim = list_length(entry->typename->arrayBounds);
if (entry->typename->setof)
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
index 89ea00d89a6..e49a7da3a29 100644
--- a/src/backend/commands/aggregatecmds.c
+++ b/src/backend/commands/aggregatecmds.c
@@ -9,7 +9,7 @@
*
*
* 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
* The "DefineFoo" routines take the parse tree and pick out the
@@ -142,7 +142,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
{
numArgs = 1;
aggArgTypes = (Oid *) palloc(sizeof(Oid));
- aggArgTypes[0] = typenameTypeId(NULL, baseType);
+ aggArgTypes[0] = typenameTypeId(NULL, baseType, NULL);
}
}
else
@@ -164,7 +164,7 @@ DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
{
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)
* values of the transtype. However, we can allow polymorphic transtype
* in some cases (AggregateCreate will check).
*/
- transTypeId = typenameTypeId(NULL, transType);
+ transTypeId = typenameTypeId(NULL, transType, NULL);
if (get_typtype(transTypeId) == TYPTYPE_PSEUDO &&
!IsPolymorphicType(transTypeId))
ereport(ERROR,
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 89158251aa4..c175523c36b 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
* Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* 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)
/* Find the type's oid */
- oid = typenameTypeId(NULL, tname);
+ oid = typenameTypeId(NULL, tname, NULL);
/* Check object security */
@@ -1451,8 +1451,8 @@ CommentCast(List *qualname, List *arguments, char *comment)
targettype = (TypeName *) linitial(arguments);
Assert(IsA(targettype, TypeName));
- sourcetypeid = typenameTypeId(NULL, sourcetype);
- targettypeid = typenameTypeId(NULL, targettype);
+ sourcetypeid = typenameTypeId(NULL, sourcetype, NULL);
+ targettypeid = typenameTypeId(NULL, targettype, NULL);
tuple = SearchSysCache(CASTSOURCETARGET,
ObjectIdGetDatum(sourcetypeid),
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),
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 12bca5119fe..cc15e2b2cdb 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -9,7 +9,7 @@
*
*
* 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)
errmsg("must be superuser to create an operator class")));
/* Look up the datatype */
- typeoid = typenameTypeId(NULL, stmt->datatype);
+ typeoid = typenameTypeId(NULL, stmt->datatype, NULL);
#ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */
@@ -481,7 +481,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("storage type specified more than once")));
- storageoid = typenameTypeId(NULL, item->storedtype);
+ storageoid = typenameTypeId(NULL, item->storedtype, NULL);
#ifdef NOT_USED
/* XXX this is unnecessary given the superuser check above */
@@ -1035,12 +1035,12 @@ processTypesSpec(List *args, Oid *lefttype, Oid *righttype)
Assert(args != NIL);
typeName = (TypeName *) linitial(args);
- *lefttype = typenameTypeId(NULL, typeName);
+ *lefttype = typenameTypeId(NULL, typeName, NULL);
if (list_length(args) > 1)
{
typeName = (TypeName *) lsecond(args);
- *righttype = typenameTypeId(NULL, typeName);
+ *righttype = typenameTypeId(NULL, typeName, NULL);
}
else
*righttype = *lefttype;
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index dd872d6a642..8de6b4bebfd 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -9,7 +9,7 @@
*
*
* 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
* The "DefineFoo" routines take the parse tree and pick out the
@@ -149,9 +149,9 @@ DefineOperator(List *names, List *parameters)
/* Transform type names to type OIDs */
if (typeName1)
- typeId1 = typenameTypeId(NULL, typeName1);
+ typeId1 = typenameTypeId(NULL, typeName1, NULL);
if (typeName2)
- typeId2 = typenameTypeId(NULL, typeName2);
+ typeId2 = typenameTypeId(NULL, typeName2, NULL);
/*
* now have OperatorCreate do all the work..
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 38055997faa..0a7f5653167 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
*
* 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)
foreach(l, stmt->argtypes)
{
TypeName *tn = lfirst(l);
- Oid toid = typenameTypeId(pstate, tn);
+ Oid toid = typenameTypeId(pstate, tn, NULL);
argtypes[i++] = toid;
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0af90cb4ac6..23f36193690 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* 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,
(errmsg("merging multiple inherited definitions of column \"%s\"",
attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
- defTypeId = typenameTypeId(NULL, def->typename);
- deftypmod = typenameTypeMod(NULL, def->typename, defTypeId);
+ defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
if (defTypeId != attribute->atttypid ||
deftypmod != attribute->atttypmod)
ereport(ERROR,
@@ -1044,10 +1043,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
(errmsg("merging column \"%s\" with inherited definition",
attributeName)));
def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
- defTypeId = typenameTypeId(NULL, def->typename);
- deftypmod = typenameTypeMod(NULL, def->typename, defTypeId);
- newTypeId = typenameTypeId(NULL, newdef->typename);
- newtypmod = typenameTypeMod(NULL, newdef->typename, newTypeId);
+ defTypeId = typenameTypeId(NULL, def->typename, &deftypmod);
+ newTypeId = typenameTypeId(NULL, newdef->typename, &newtypmod);
if (defTypeId != newTypeId || deftypmod != newtypmod)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -3018,8 +3015,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
int32 ctypmod;
/* Okay if child matches by type */
- ctypeId = typenameTypeId(NULL, colDef->typename);
- ctypmod = typenameTypeMod(NULL, colDef->typename, ctypeId);
+ ctypeId = typenameTypeId(NULL, colDef->typename, &ctypmod);
if (ctypeId != childatt->atttypid ||
ctypmod != childatt->atttypmod)
ereport(ERROR,
@@ -3074,10 +3070,9 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
MaxHeapAttributeNumber)));
i = minattnum + 1;
- typeTuple = typenameType(NULL, colDef->typename);
+ typeTuple = typenameType(NULL, colDef->typename, &typmod);
tform = (Form_pg_type) GETSTRUCT(typeTuple);
typeOid = HeapTupleGetOid(typeTuple);
- typmod = typenameTypeMod(NULL, colDef->typename, typeOid);
/* make sure datatype is legal for a column */
CheckAttributeType(colDef->colname, typeOid);
@@ -4777,8 +4772,7 @@ ATPrepAlterColumnType(List **wqueue,
colName)));
/* Look up the target type */
- targettype = typenameTypeId(NULL, typename);
- targettypmod = typenameTypeMod(NULL, typename, targettype);
+ targettype = typenameTypeId(NULL, typename, &targettypmod);
/* make sure datatype is legal for a column */
CheckAttributeType(colName, targettype);
@@ -4905,10 +4899,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
colName)));
/* 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);
targettype = HeapTupleGetOid(typeTuple);
- targettypmod = typenameTypeMod(NULL, typename, targettype);
/*
* If there is a default expression for the column, get it and ensure we
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 1f58d989f26..230004c59bb 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.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
* The "DefineFoo" routines take the parse tree and pick out the
@@ -211,7 +211,7 @@ DefineType(List *names, List *parameters)
}
else if (pg_strcasecmp(defel->defname, "element") == 0)
{
- elemType = typenameTypeId(NULL, defGetTypeName(defel));
+ elemType = typenameTypeId(NULL, defGetTypeName(defel), NULL);
/* disallow arrays of pseudotypes */
if (get_typtype(elemType) == TYPTYPE_PSEUDO)
ereport(ERROR,
@@ -497,8 +497,8 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok)
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */
- typeoid = LookupTypeName(NULL, typename);
- if (!OidIsValid(typeoid))
+ tup = LookupTypeName(NULL, typename, NULL);
+ if (tup == NULL)
{
if (!missing_ok)
{
@@ -517,11 +517,7 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok)
return;
}
- tup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(typeoid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "cache lookup failed for type %u", typeoid);
+ typeoid = typeTypeId(tup);
typ = (Form_pg_type) GETSTRUCT(tup);
/* Permission check: must own type or its namespace */
@@ -650,10 +646,9 @@ DefineDomain(CreateDomainStmt *stmt)
/*
* Look up the base type.
*/
- typeTup = typenameType(NULL, stmt->typename);
+ typeTup = typenameType(NULL, stmt->typename, &basetypeMod);
baseType = (Form_pg_type) GETSTRUCT(typeTup);
basetypeoid = HeapTupleGetOid(typeTup);
- basetypeMod = typenameTypeMod(NULL, stmt->typename, basetypeoid);
/*
* 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)
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be removed. */
- typeoid = LookupTypeName(NULL, typename);
- if (!OidIsValid(typeoid))
+ tup = LookupTypeName(NULL, typename, NULL);
+ if (tup == NULL)
{
if (!missing_ok)
{
@@ -966,11 +961,7 @@ RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
return;
}
- tup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(typeoid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "cache lookup failed for type %u", typeoid);
+ typeoid = typeTypeId(tup);
/* Permission check: must own type or its namespace */
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
@@ -1443,7 +1434,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
- domainoid = typenameTypeId(NULL, typename);
+ domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock);
@@ -1573,7 +1564,7 @@ AlterDomainNotNull(List *names, bool notNull)
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
- domainoid = typenameTypeId(NULL, typename);
+ domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock);
@@ -1675,7 +1666,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
- domainoid = typenameTypeId(NULL, typename);
+ domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */
rel = heap_open(TypeRelationId, RowExclusiveLock);
@@ -1750,7 +1741,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
- domainoid = typenameTypeId(NULL, typename);
+ domainoid = typenameTypeId(NULL, typename, NULL);
/* Look up the domain in the type table */
typrel = heap_open(TypeRelationId, RowExclusiveLock);
@@ -2358,28 +2349,28 @@ AlterTypeOwner(List *names, Oid newOwnerId)
Oid typeOid;
Relation rel;
HeapTuple tup;
+ HeapTuple newtup;
Form_pg_type typTup;
AclResult aclresult;
+ rel = heap_open(TypeRelationId, RowExclusiveLock);
+
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
/* Use LookupTypeName here so that shell types can be processed */
- typeOid = LookupTypeName(NULL, typename);
- if (!OidIsValid(typeOid))
+ tup = LookupTypeName(NULL, typename, NULL);
+ if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typename))));
+ typeOid = typeTypeId(tup);
- /* Look up the type in the type table */
- rel = heap_open(TypeRelationId, RowExclusiveLock);
-
- tup = SearchSysCacheCopy(TYPEOID,
- ObjectIdGetDatum(typeOid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "cache lookup failed for type %u", typeOid);
+ /* Copy the syscache entry so we can scribble on it below */
+ newtup = heap_copytuple(tup);
+ ReleaseSysCache(tup);
+ tup = newtup;
typTup = (Form_pg_type) GETSTRUCT(tup);
/*
@@ -2526,7 +2517,7 @@ AlterTypeNamespace(List *names, const char *newschema)
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeTypeNameFromNameList(names);
- typeOid = typenameTypeId(NULL, typename);
+ typeOid = typenameTypeId(NULL, typename, NULL);
/* check permissions on type */
if (!pg_type_ownercheck(typeOid, GetUserId()))
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 86fddc4a7a6..52957e825e7 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* 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)
ltype = exprType(lexpr);
foreach(telem, (List *) a->rexpr)
{
- rtype = typenameTypeId(pstate, lfirst(telem));
+ rtype = typenameTypeId(pstate, lfirst(telem), NULL);
matched = (rtype == ltype);
if (matched)
break;
@@ -1550,8 +1550,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
XMLOID,
"XMLSERIALIZE"));
- targetType = typenameTypeId(pstate, xs->typename);
- targetTypmod = typenameTypeMod(pstate, xs->typename, targetType);
+ targetType = typenameTypeId(pstate, xs->typename, &targetTypmod);
xexpr->xmloption = xs->xmloption;
/* 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)
Oid targetType;
int32 targetTypmod;
- targetType = typenameTypeId(pstate, typename);
- targetTypmod = typenameTypeMod(pstate, typename, targetType);
+ targetType = typenameTypeId(pstate, typename, &targetTypmod);
if (inputType == InvalidOid)
return expr; /* do nothing if NULL input */
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 393fa6c41ac..76dcd29185c 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -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);
@@ -986,6 +984,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.
* If the function call is actually a column projection, return a suitably
@@ -1181,6 +1206,27 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
}
/*
+ * 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
* list of TypeName nodes.
@@ -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++;
}
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 42bd04fa01e..a51a4d6215d 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
*
*
* 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,
if (oprleft == NULL)
leftoid = InvalidOid;
else
- leftoid = typenameTypeId(pstate, oprleft);
+ leftoid = typenameTypeId(pstate, oprleft, NULL);
if (oprright == NULL)
rightoid = InvalidOid;
else
- rightoid = typenameTypeId(pstate, oprright);
+ rightoid = typenameTypeId(pstate, oprright, NULL);
return LookupOperName(pstate, opername, leftoid, rightoid,
noError, location);
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 10726573e92..f337ded99f7 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* 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,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("column \"%s\" cannot be declared SETOF",
attrname)));
- attrtype = typenameTypeId(pstate, n->typename);
- attrtypmod = typenameTypeMod(pstate, n->typename, attrtype);
+ attrtype = typenameTypeId(pstate, n->typename, &attrtypmod);
eref->colnames = lappend(eref->colnames, makeString(attrname));
rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index f86dd43d548..e61cf085764 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.91 2007/06/15 20:56:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.92 2007/11/11 19:22:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,26 +26,46 @@
#include "utils/syscache.h"
+static int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
+ Type typ);
+
+
/*
* LookupTypeName
- * Given a TypeName object, get the OID of the referenced type.
- * Returns InvalidOid if no such type can be found.
+ * Given a TypeName object, lookup the pg_type syscache entry of the type.
+ * Returns NULL if no such type can be found. If the type is found,
+ * the typmod value represented in the TypeName struct is computed and
+ * stored into *typmod_p.
+ *
+ * NB: on success, the caller must ReleaseSysCache the type tuple when done
+ * with it.
+ *
+ * NB: direct callers of this function MUST check typisdefined before assuming
+ * that the type is fully valid. Most code should go through typenameType
+ * or typenameTypeId instead.
*
- * NB: even if the returned OID is not InvalidOid, the type might be
- * just a shell. Caller should check typisdefined before using the type.
+ * typmod_p can be passed as NULL if the caller does not care to know the
+ * typmod value, but the typmod decoration (if any) will be validated anyway,
+ * except in the case where the type is not found. Note that if the type is
+ * found but is a shell, and there is typmod decoration, an error will be
+ * thrown --- this is intentional.
*
* pstate is only used for error location info, and may be NULL.
*/
-Oid
-LookupTypeName(ParseState *pstate, const TypeName *typename)
+Type
+LookupTypeName(ParseState *pstate, const TypeName *typename,
+ int32 *typmod_p)
{
- Oid restype;
+ Oid typoid;
+ HeapTuple tup;
+ int32 typmod;
- /* Easy if it's an internally generated TypeName */
if (typename->names == NIL)
- return typename->typeid;
-
- if (typename->pct_type)
+ {
+ /* We have the OID already if it's an internally generated TypeName */
+ typoid = typename->typeid;
+ }
+ else if (typename->pct_type)
{
/* Handle %TYPE reference to type of an existing field */
RangeVar *rel = makeRangeVar(NULL, NULL);
@@ -96,7 +116,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typename)
errmsg("column \"%s\" of relation \"%s\" does not exist",
field, rel->relname),
parser_errposition(pstate, typename->location)));
- restype = get_atttype(relid, attnum);
+ typoid = get_atttype(relid, attnum);
/* this construct should never have an array indicator */
Assert(typename->arrayBounds == NIL);
@@ -105,7 +125,7 @@ LookupTypeName(ParseState *pstate, const TypeName *typename)
ereport(NOTICE,
(errmsg("type reference %s converted to %s",
TypeNameToString(typename),
- format_type_be(restype))));
+ format_type_be(typoid))));
}
else
{
@@ -122,130 +142,86 @@ LookupTypeName(ParseState *pstate, const TypeName *typename)
Oid namespaceId;
namespaceId = LookupExplicitNamespace(schemaname);
- restype = GetSysCacheOid(TYPENAMENSP,
- PointerGetDatum(typname),
- ObjectIdGetDatum(namespaceId),
- 0, 0);
+ typoid = GetSysCacheOid(TYPENAMENSP,
+ PointerGetDatum(typname),
+ ObjectIdGetDatum(namespaceId),
+ 0, 0);
}
else
{
/* Unqualified type name, so search the search path */
- restype = TypenameGetTypid(typname);
+ typoid = TypenameGetTypid(typname);
}
/* If an array reference, return the array type instead */
if (typename->arrayBounds != NIL)
- restype = get_array_type(restype);
+ typoid = get_array_type(typoid);
}
- return restype;
-}
-
-/*
- * appendTypeNameToBuffer
- * Append a string representing the name of a TypeName to a StringInfo.
- * This is the shared guts of TypeNameToString and TypeNameListToString.
- *
- * NB: this must work on TypeNames that do not describe any actual type;
- * it is mostly used for reporting lookup errors.
- */
-static void
-appendTypeNameToBuffer(const TypeName *typename, StringInfo string)
-{
- if (typename->names != NIL)
- {
- /* Emit possibly-qualified name as-is */
- ListCell *l;
-
- foreach(l, typename->names)
- {
- if (l != list_head(typename->names))
- appendStringInfoChar(string, '.');
- appendStringInfoString(string, strVal(lfirst(l)));
- }
- }
- else
+ if (!OidIsValid(typoid))
{
- /* Look up internally-specified type */
- appendStringInfoString(string, format_type_be(typename->typeid));
+ if (typmod_p)
+ *typmod_p = -1;
+ return NULL;
}
- /*
- * Add decoration as needed, but only for fields considered by
- * LookupTypeName
- */
- if (typename->pct_type)
- appendStringInfoString(string, "%TYPE");
-
- if (typename->arrayBounds != NIL)
- appendStringInfoString(string, "[]");
-}
-
-/*
- * TypeNameToString
- * Produce a string representing the name of a TypeName.
- *
- * NB: this must work on TypeNames that do not describe any actual type;
- * it is mostly used for reporting lookup errors.
- */
-char *
-TypeNameToString(const TypeName *typename)
-{
- StringInfoData string;
-
- initStringInfo(&string);
- appendTypeNameToBuffer(typename, &string);
- return string.data;
-}
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typoid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for type %u", typoid);
-/*
- * TypeNameListToString
- * Produce a string representing the name(s) of a List of TypeNames
- */
-char *
-TypeNameListToString(List *typenames)
-{
- StringInfoData string;
- ListCell *l;
+ typmod = typenameTypeMod(pstate, typename, (Type) tup);
- initStringInfo(&string);
- foreach(l, typenames)
- {
- TypeName *typename = (TypeName *) lfirst(l);
+ if (typmod_p)
+ *typmod_p = typmod;
- Assert(IsA(typename, TypeName));
- if (l != list_head(typenames))
- appendStringInfoChar(&string, ',');
- appendTypeNameToBuffer(typename, &string);
- }
- return string.data;
+ return (Type) tup;
}
/*
- * typenameTypeId - given a TypeName, return the type's OID
+ * typenameType - given a TypeName, return a Type structure and typmod
*
* This is equivalent to LookupTypeName, except that this will report
* a suitable error message if the type cannot be found or is not defined.
+ * Callers of this can therefore assume the result is a fully valid type.
*/
-Oid
-typenameTypeId(ParseState *pstate, const TypeName *typename)
+Type
+typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
{
- Oid typoid;
+ Type tup;
- typoid = LookupTypeName(pstate, typename);
- if (!OidIsValid(typoid))
+ tup = LookupTypeName(pstate, typename, typmod_p);
+ if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" does not exist",
TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
-
- if (!get_typisdefined(typoid))
+ if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("type \"%s\" is only a shell",
TypeNameToString(typename)),
parser_errposition(pstate, typename->location)));
+ return tup;
+}
+
+/*
+ * typenameTypeId - given a TypeName, return the type's OID and typmod
+ *
+ * This is equivalent to typenameType, but we only hand back the type OID
+ * not the syscache entry.
+ */
+Oid
+typenameTypeId(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
+{
+ Oid typoid;
+ Type tup;
+
+ tup = typenameType(pstate, typename, typmod_p);
+ typoid = HeapTupleGetOid(tup);
+ ReleaseSysCache(tup);
return typoid;
}
@@ -257,13 +233,12 @@ typenameTypeId(ParseState *pstate, const TypeName *typename)
* illegal for the data type.
*
* The actual type OID represented by the TypeName must already have been
- * determined (usually by typenameTypeId()), and is passed as typeId.
+ * looked up, and is passed as "typ".
*
* pstate is only used for error location info, and may be NULL.
*/
-int32
-typenameTypeMod(ParseState *pstate, const TypeName *typename,
- Oid typeId)
+static int32
+typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ)
{
int32 result;
Oid typmodin;
@@ -272,14 +247,23 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename,
ListCell *l;
ArrayType *arrtypmod;
- Assert(OidIsValid(typeId));
-
/* Return prespecified typmod if no typmod expressions */
if (typename->typmods == NIL)
return typename->typemod;
- /* Else, type had better accept typmods */
- typmodin = get_typmodin(typeId);
+ /*
+ * Else, type had better accept typmods. We give a special error
+ * message for the shell-type case, since a shell couldn't possibly
+ * have a typmodin function.
+ */
+ if (!((Form_pg_type) GETSTRUCT(typ))->typisdefined)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("type modifier cannot be specified for shell type \"%s\"",
+ TypeNameToString(typename)),
+ parser_errposition(pstate, typename->location)));
+
+ typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;
if (typmodin == InvalidOid)
ereport(ERROR,
@@ -349,36 +333,83 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename,
}
/*
- * typenameType - given a TypeName, return a Type structure
+ * appendTypeNameToBuffer
+ * Append a string representing the name of a TypeName to a StringInfo.
+ * This is the shared guts of TypeNameToString and TypeNameListToString.
*
- * This is equivalent to typenameTypeId + syscache fetch of Type tuple.
- * NB: caller must ReleaseSysCache the type tuple when done with it.
+ * NB: this must work on TypeNames that do not describe any actual type;
+ * it is mostly used for reporting lookup errors.
*/
-Type
-typenameType(ParseState *pstate, const TypeName *typename)
+static void
+appendTypeNameToBuffer(const TypeName *typename, StringInfo string)
{
- Oid typoid;
- HeapTuple tup;
+ if (typename->names != NIL)
+ {
+ /* Emit possibly-qualified name as-is */
+ ListCell *l;
- typoid = LookupTypeName(pstate, typename);
- if (!OidIsValid(typoid))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("type \"%s\" does not exist",
- TypeNameToString(typename)),
- parser_errposition(pstate, typename->location)));
- tup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(typoid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup)) /* should not happen */
- elog(ERROR, "cache lookup failed for type %u", typoid);
- if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("type \"%s\" is only a shell",
- TypeNameToString(typename)),
- parser_errposition(pstate, typename->location)));
- return (Type) tup;
+ foreach(l, typename->names)
+ {
+ if (l != list_head(typename->names))
+ appendStringInfoChar(string, '.');
+ appendStringInfoString(string, strVal(lfirst(l)));
+ }
+ }
+ else
+ {
+ /* Look up internally-specified type */
+ appendStringInfoString(string, format_type_be(typename->typeid));
+ }
+
+ /*
+ * Add decoration as needed, but only for fields considered by
+ * LookupTypeName
+ */
+ if (typename->pct_type)
+ appendStringInfoString(string, "%TYPE");
+
+ if (typename->arrayBounds != NIL)
+ appendStringInfoString(string, "[]");
+}
+
+/*
+ * TypeNameToString
+ * Produce a string representing the name of a TypeName.
+ *
+ * NB: this must work on TypeNames that do not describe any actual type;
+ * it is mostly used for reporting lookup errors.
+ */
+char *
+TypeNameToString(const TypeName *typename)
+{
+ StringInfoData string;
+
+ initStringInfo(&string);
+ appendTypeNameToBuffer(typename, &string);
+ return string.data;
+}
+
+/*
+ * TypeNameListToString
+ * Produce a string representing the name(s) of a List of TypeNames
+ */
+char *
+TypeNameListToString(List *typenames)
+{
+ StringInfoData string;
+ ListCell *l;
+
+ initStringInfo(&string);
+ foreach(l, typenames)
+ {
+ TypeName *typename = (TypeName *) lfirst(l);
+
+ Assert(IsA(typename, TypeName));
+ if (l != list_head(typenames))
+ appendStringInfoChar(&string, ',');
+ appendTypeNameToBuffer(typename, &string);
+ }
+ return string.data;
}
/* return a Type structure, given a type id */
@@ -507,7 +538,7 @@ pts_error_callback(void *arg)
* the string and convert it to a type OID and type modifier.
*/
void
-parseTypeString(const char *str, Oid *type_id, int32 *typmod)
+parseTypeString(const char *str, Oid *type_id, int32 *typmod_p)
{
StringInfoData buf;
List *raw_parsetree_list;
@@ -579,8 +610,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
if (typename->setof)
goto fail;
- *type_id = typenameTypeId(NULL, typename);
- *typmod = typenameTypeMod(NULL, typename, *type_id);
+ *type_id = typenameTypeId(NULL, typename, typmod_p);
pfree(buf.data);
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 287e82ddeec..a6306a435cc 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -19,7 +19,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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)
/*
* 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);
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 49a4cc722e0..02d5fd4bbe6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* 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)
* to interval and back to normalize the value and account
* for any typmod.
*/
+ Oid typoid;
int32 typmod;
Datum interval;
char *intervalout;
- typmod = typenameTypeMod(NULL, arg->typename, INTERVALOID);
+ typoid = typenameTypeId(NULL, arg->typename, &typmod);
+ Assert(typoid == INTERVALOID);
interval =
DirectFunctionCall3(interval_in,
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
index 3d07b085793..414dd09b91e 100644
--- a/src/include/parser/parse_type.h
+++ b/src/include/parser/parse_type.h
@@ -1,13 +1,12 @@
/*-------------------------------------------------------------------------
*
* parse_type.h
- *
- *
+ * handle type operations for parser
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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 @@
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 *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);
@@ -39,7 +40,7 @@ extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
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)
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index db150632f05..7799cf7c656 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -8,7 +8,7 @@
*
*
* 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)
{
PLpgSQL_nsitem *nse;
bool old_nsstate;
- Oid typeOid;
+ HeapTuple typeTup;
char *cp[2];
int i;
@@ -1138,34 +1138,26 @@ plpgsql_parse_wordtype(char *word)
/*
* 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]));
- if (OidIsValid(typeOid))
+ typeTup = LookupTypeName(NULL, makeTypeName(cp[0]), NULL);
+ if (typeTup)
{
- HeapTuple typeTup;
+ Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- typeTup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(typeOid),
- 0, 0, 0);
- if (HeapTupleIsValid(typeTup))
+ if (!typeStruct->typisdefined ||
+ typeStruct->typrelid != InvalidOid)
{
- Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
-
- if (!typeStruct->typisdefined ||
- typeStruct->typrelid != InvalidOid)
- {
- ReleaseSysCache(typeTup);
- pfree(cp[0]);
- return T_ERROR;
- }
-
- plpgsql_yylval.dtype = build_datatype(typeTup, -1);
-
ReleaseSysCache(typeTup);
pfree(cp[0]);
- return T_DTYPE;
+ return T_ERROR;
}
+
+ plpgsql_yylval.dtype = build_datatype(typeTup, -1);
+
+ ReleaseSysCache(typeTup);
+ pfree(cp[0]);
+ return T_DTYPE;
}
/*