diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 50e41ade60..6e2ac69cc4 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 89ea00d89a..e49a7da3a2 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 89158251aa..c175523c36 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 9e5d0b1095..3a55661502 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 12bca5119f..cc15e2b2cd 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 dd872d6a64..8de6b4bebf 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 38055997fa..0a7f565316 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 0af90cb4ac..23f3619369 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 1f58d989f2..230004c59b 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 86fddc4a7a..52957e825e 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 393fa6c41a..76dcd29185 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); @@ -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++; } diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 42bd04fa01..a51a4d6215 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 10726573e9..f337ded99f 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 f86dd43d54..e61cf08576 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: even if the returned OID is not InvalidOid, the type might be - * just a shell. Caller should check typisdefined before using the type. + * 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. + * + * 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,23 +142,194 @@ 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; + if (!OidIsValid(typoid)) + { + if (typmod_p) + *typmod_p = -1; + return NULL; + } + + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typoid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for type %u", typoid); + + typmod = typenameTypeMod(pstate, typename, (Type) tup); + + if (typmod_p) + *typmod_p = typmod; + + return (Type) tup; +} + +/* + * 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. + */ +Type +typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p) +{ + Type tup; + + 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 (!((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; +} + +/* + * typenameTypeMod - given a TypeName, return the internal typmod value + * + * This will throw an error if the TypeName includes type modifiers that are + * illegal for the data type. + * + * The actual type OID represented by the TypeName must already have been + * looked up, and is passed as "typ". + * + * pstate is only used for error location info, and may be NULL. + */ +static int32 +typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ) +{ + int32 result; + Oid typmodin; + Datum *datums; + int n; + ListCell *l; + ArrayType *arrtypmod; + + /* Return prespecified typmod if no typmod expressions */ + if (typename->typmods == NIL) + return typename->typemod; + + /* + * 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, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("type modifier is not allowed for type \"%s\"", + TypeNameToString(typename)), + parser_errposition(pstate, typename->location))); + + /* + * Convert the list of raw-grammar-output expressions to a cstring array. + * Currently, we allow simple numeric constants, string literals, and + * identifiers; possibly this list could be extended. + */ + datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum)); + n = 0; + foreach(l, typename->typmods) + { + Node *tm = (Node *) lfirst(l); + char *cstr = NULL; + + if (IsA(tm, A_Const)) + { + A_Const *ac = (A_Const *) tm; + + /* + * The grammar hands back some integers with ::int4 attached, + * so allow a cast decoration if it's an Integer value, but + * not otherwise. + */ + if (IsA(&ac->val, Integer)) + { + cstr = (char *) palloc(32); + snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); + } + else if (ac->typename == NULL) /* no casts allowed */ + { + /* otherwise we can just use the str field directly. */ + cstr = ac->val.val.str; + } + } + else if (IsA(tm, ColumnRef)) + { + ColumnRef *cr = (ColumnRef *) tm; + + if (list_length(cr->fields) == 1) + cstr = strVal(linitial(cr->fields)); + } + if (!cstr) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("type modifiers must be simple constants or identifiers"), + parser_errposition(pstate, typename->location))); + datums[n++] = CStringGetDatum(cstr); + } + + /* hardwired knowledge about cstring's representation details here */ + arrtypmod = construct_array(datums, n, CSTRINGOID, + -2, false, 'c'); + + result = DatumGetInt32(OidFunctionCall1(typmodin, + PointerGetDatum(arrtypmod))); + + pfree(datums); + pfree(arrtypmod); + + return result; } /* @@ -221,166 +412,6 @@ TypeNameListToString(List *typenames) return string.data; } -/* - * typenameTypeId - given a TypeName, return the type's OID - * - * This is equivalent to LookupTypeName, except that this will report - * a suitable error message if the type cannot be found or is not defined. - */ -Oid -typenameTypeId(ParseState *pstate, const TypeName *typename) -{ - Oid typoid; - - 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))); - - if (!get_typisdefined(typoid)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" is only a shell", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); - - return typoid; -} - -/* - * typenameTypeMod - given a TypeName, return the internal typmod value - * - * This will throw an error if the TypeName includes type modifiers that are - * 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. - * - * pstate is only used for error location info, and may be NULL. - */ -int32 -typenameTypeMod(ParseState *pstate, const TypeName *typename, - Oid typeId) -{ - int32 result; - Oid typmodin; - Datum *datums; - int n; - 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); - - if (typmodin == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("type modifier is not allowed for type \"%s\"", - TypeNameToString(typename)), - parser_errposition(pstate, typename->location))); - - /* - * Convert the list of raw-grammar-output expressions to a cstring array. - * Currently, we allow simple numeric constants, string literals, and - * identifiers; possibly this list could be extended. - */ - datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum)); - n = 0; - foreach(l, typename->typmods) - { - Node *tm = (Node *) lfirst(l); - char *cstr = NULL; - - if (IsA(tm, A_Const)) - { - A_Const *ac = (A_Const *) tm; - - /* - * The grammar hands back some integers with ::int4 attached, - * so allow a cast decoration if it's an Integer value, but - * not otherwise. - */ - if (IsA(&ac->val, Integer)) - { - cstr = (char *) palloc(32); - snprintf(cstr, 32, "%ld", (long) ac->val.val.ival); - } - else if (ac->typename == NULL) /* no casts allowed */ - { - /* otherwise we can just use the str field directly. */ - cstr = ac->val.val.str; - } - } - else if (IsA(tm, ColumnRef)) - { - ColumnRef *cr = (ColumnRef *) tm; - - if (list_length(cr->fields) == 1) - cstr = strVal(linitial(cr->fields)); - } - if (!cstr) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("type modifiers must be simple constants or identifiers"), - parser_errposition(pstate, typename->location))); - datums[n++] = CStringGetDatum(cstr); - } - - /* hardwired knowledge about cstring's representation details here */ - arrtypmod = construct_array(datums, n, CSTRINGOID, - -2, false, 'c'); - - result = DatumGetInt32(OidFunctionCall1(typmodin, - PointerGetDatum(arrtypmod))); - - pfree(datums); - pfree(arrtypmod); - - return result; -} - -/* - * typenameType - given a TypeName, return a Type structure - * - * This is equivalent to typenameTypeId + syscache fetch of Type tuple. - * NB: caller must ReleaseSysCache the type tuple when done with it. - */ -Type -typenameType(ParseState *pstate, const TypeName *typename) -{ - Oid typoid; - HeapTuple tup; - - 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; -} - /* return a Type structure, given a type id */ /* NB: caller must ReleaseSysCache the type tuple when done with it */ Type @@ -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 287e82ddee..a6306a435c 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 49a4cc722e..02d5fd4bbe 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * 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 3d07b08579..414dd09b91 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 db150632f0..7799cf7c65 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; } /*