diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/aggregatecmds.c | 42 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 7 | ||||
-rw-r--r-- | src/backend/commands/conversioncmds.c | 6 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 3 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 101 | ||||
-rw-r--r-- | src/backend/commands/opclasscmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/proclang.c | 14 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 15 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 166 |
9 files changed, 237 insertions, 121 deletions
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c index 1b83f03f48..85ee9e3f53 100644 --- a/src/backend/commands/aggregatecmds.c +++ b/src/backend/commands/aggregatecmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.3 2002/07/12 18:43:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.4 2002/08/22 00:01:41 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -28,6 +28,7 @@ #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_proc.h" +#include "catalog/pg_type.h" #include "commands/defrem.h" #include "miscadmin.h" #include "parser/parse_func.h" @@ -104,29 +105,23 @@ DefineAggregate(List *names, List *parameters) elog(ERROR, "Define: \"sfunc\" unspecified"); /* - * Handle the aggregate's base type (input data type). This can be - * specified as 'ANY' for a data-independent transition function, such - * as COUNT(*). + * look up the aggregate's base type (input datatype) and transtype. + * + * We have historically allowed the command to look like basetype = 'ANY' + * so we must do a case-insensitive comparison for the name ANY. Ugh. + * + * basetype can be a pseudo-type, but transtype can't, since we need + * to be able to store values of the transtype. */ - baseTypeId = LookupTypeName(baseType); - if (OidIsValid(baseTypeId)) - { - /* no need to allow aggregates on as-yet-undefined types */ - if (!get_typisdefined(baseTypeId)) - elog(ERROR, "Type \"%s\" is only a shell", - TypeNameToString(baseType)); - } + if (strcasecmp(TypeNameToString(baseType), "ANY") == 0) + baseTypeId = ANYOID; else - { - char *typnam = TypeNameToString(baseType); - - if (strcasecmp(typnam, "ANY") != 0) - elog(ERROR, "Type \"%s\" does not exist", typnam); - baseTypeId = InvalidOid; - } + baseTypeId = typenameTypeId(baseType); - /* handle transtype --- no special cases here */ transTypeId = typenameTypeId(transType); + if (get_typtype(transTypeId) == 'p') + elog(ERROR, "Aggregate transition datatype cannot be %s", + format_type_be(transTypeId)); /* * Most of the argument-checking is done inside of AggregateCreate @@ -159,14 +154,13 @@ RemoveAggregate(RemoveAggrStmt *stmt) * if a basetype is passed in, then attempt to find an aggregate for * that specific type. * - * else if the basetype is blank, then attempt to find an aggregate with - * a basetype of zero. This is valid. It means that the aggregate is - * to apply to all basetypes (eg, COUNT). + * else attempt to find an aggregate with a basetype of ANYOID. + * This means that the aggregate is to apply to all basetypes (eg, COUNT). */ if (aggType) basetypeID = typenameTypeId(aggType); else - basetypeID = InvalidOid; + basetypeID = ANYOID; procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 41ef71960d..ce48928018 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.56 2002/08/09 16:45:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.57 2002/08/22 00:01:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,6 +24,7 @@ #include "catalog/pg_operator.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_trigger.h" +#include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/dbcommands.h" #include "miscadmin.h" @@ -628,7 +629,7 @@ CommentAggregate(List *aggregate, List *arguments, char *comment) if (aggtype) baseoid = typenameTypeId(aggtype); else - baseoid = InvalidOid; + baseoid = ANYOID; /* Now, attempt to find the actual tuple in pg_proc */ @@ -661,7 +662,7 @@ CommentProc(List *function, List *arguments, char *comment) /* Look up the procedure */ oid = LookupFuncNameTypeNames(function, arguments, - true, "CommentProc"); + "CommentProc"); /* Now, validate the user's ability to comment on this function */ diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c index a8785d7686..7d65a1a785 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * conversionmacmds.c + * conversioncmds.c * conversion creation command support code * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.2 2002/07/25 10:07:11 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.3 2002/08/22 00:01:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ CreateConversionCommand(CreateConversionStmt *stmt) const char *to_encoding_name = stmt->to_encoding_name; List *func_name = stmt->func_name; - static Oid funcargs[] = {INT4OID, INT4OID, 0, 0, INT4OID}; + static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID}; /* Convert list of names to a name and namespace */ namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name, &conversion_name); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 2751fe01d9..e0bbe7560b 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.165 2002/08/19 15:08:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.166 2002/08/22 00:01:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,7 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/relcache.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" #ifdef MULTIBYTE diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 51d003600b..6d6ad94a4e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.17 2002/08/11 17:44:12 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.18 2002/08/22 00:01:42 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -61,7 +61,9 @@ * allow a shell type to be used, or even created if the specified return type * doesn't exist yet. (Without this, there's no way to define the I/O procs * for a new type.) But SQL function creation won't cope, so error out if - * the target language is SQL. + * the target language is SQL. (We do this here, not in the SQL-function + * validator, so as not to produce a WARNING and then an ERROR for the same + * condition.) */ static void compute_return_type(TypeName *returnType, Oid languageOid, @@ -76,7 +78,8 @@ compute_return_type(TypeName *returnType, Oid languageOid, if (!get_typisdefined(rettype)) { if (languageOid == SQLlanguageId) - elog(ERROR, "SQL functions cannot return shell types"); + elog(ERROR, "SQL function cannot return shell type \"%s\"", + TypeNameToString(returnType)); else elog(WARNING, "Return type \"%s\" is only a shell", TypeNameToString(returnType)); @@ -85,29 +88,32 @@ compute_return_type(TypeName *returnType, Oid languageOid, else { char *typnam = TypeNameToString(returnType); + Oid namespaceId; + AclResult aclresult; + char *typname; - if (strcmp(typnam, "opaque") == 0) - rettype = InvalidOid; - else - { - Oid namespaceId; - AclResult aclresult; - char *typname; - - if (languageOid == SQLlanguageId) - elog(ERROR, "Type \"%s\" does not exist", typnam); - elog(WARNING, "ProcedureCreate: type %s is not yet defined", - typnam); - namespaceId = QualifiedNameGetCreationNamespace(returnType->names, - &typname); - aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), - ACL_CREATE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, get_namespace_name(namespaceId)); - rettype = TypeShellMake(typname, namespaceId); - if (!OidIsValid(rettype)) - elog(ERROR, "could not create type %s", typnam); - } + /* + * Only C-coded functions can be I/O functions. We enforce this + * restriction here mainly to prevent littering the catalogs with + * shell types due to simple typos in user-defined function + * definitions. + */ + if (languageOid != INTERNALlanguageId && + languageOid != ClanguageId) + elog(ERROR, "Type \"%s\" does not exist", typnam); + + /* Otherwise, go ahead and make a shell type */ + elog(WARNING, "ProcedureCreate: type %s is not yet defined", + typnam); + namespaceId = QualifiedNameGetCreationNamespace(returnType->names, + &typname); + aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_namespace_name(namespaceId)); + rettype = TypeShellMake(typname, namespaceId); + if (!OidIsValid(rettype)) + elog(ERROR, "could not create type %s", typnam); } *prorettype_p = rettype; @@ -138,25 +144,24 @@ compute_parameter_types(List *argTypes, Oid languageOid, if (OidIsValid(toid)) { if (!get_typisdefined(toid)) - elog(WARNING, "Argument type \"%s\" is only a shell", - TypeNameToString(t)); - } - else - { - char *typnam = TypeNameToString(t); - - if (strcmp(typnam, "opaque") == 0) { + /* As above, hard error if language is SQL */ if (languageOid == SQLlanguageId) - elog(ERROR, "SQL functions cannot have arguments of type \"opaque\""); - toid = InvalidOid; + elog(ERROR, "SQL function cannot accept shell type \"%s\"", + TypeNameToString(t)); + else + elog(WARNING, "Argument type \"%s\" is only a shell", + TypeNameToString(t)); } - else - elog(ERROR, "Type \"%s\" does not exist", typnam); + } + else + { + elog(ERROR, "Type \"%s\" does not exist", + TypeNameToString(t)); } if (t->setof) - elog(ERROR, "functions cannot accept set arguments"); + elog(ERROR, "Functions cannot accept set arguments"); parameterTypes[parameterCount++] = toid; } @@ -492,7 +497,7 @@ RemoveFunction(RemoveFuncStmt *stmt) * Find the function, do permissions and validity checks */ funcOid = LookupFuncNameTypeNames(functionName, argTypes, - true, "RemoveFunction"); + "RemoveFunction"); tup = SearchSysCache(PROCOID, ObjectIdGetDatum(funcOid), @@ -621,6 +626,23 @@ CreateCast(CreateCastStmt *stmt) if (sourcetypeid == targettypeid) elog(ERROR, "source data type and target data type are the same"); + /* No shells, no pseudo-types allowed */ + if (!get_typisdefined(sourcetypeid)) + elog(ERROR, "source data type %s is only a shell", + TypeNameToString(stmt->sourcetype)); + + if (!get_typisdefined(targettypeid)) + elog(ERROR, "target data type %s is only a shell", + TypeNameToString(stmt->targettype)); + + if (get_typtype(sourcetypeid) == 'p') + elog(ERROR, "source data type %s is a pseudo-type", + TypeNameToString(stmt->sourcetype)); + + if (get_typtype(targettypeid) == 'p') + elog(ERROR, "target data type %s is a pseudo-type", + TypeNameToString(stmt->targettype)); + if (!pg_type_ownercheck(sourcetypeid, GetUserId()) && !pg_type_ownercheck(targettypeid, GetUserId())) elog(ERROR, "must be owner of type %s or type %s", @@ -642,7 +664,6 @@ CreateCast(CreateCastStmt *stmt) { funcid = LookupFuncNameTypeNames(stmt->func->funcname, stmt->func->funcargs, - false, "CreateCast"); tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0); diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index f544dc9886..a0430a8786 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.3 2002/08/05 03:29:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.4 2002/08/22 00:01:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -177,7 +177,7 @@ DefineOpClass(CreateOpClassStmt *stmt) elog(ERROR, "DefineOpClass: procedure number %d appears more than once", item->number); funcOid = LookupFuncNameTypeNames(item->name, item->args, - true, "DefineOpClass"); + "DefineOpClass"); /* Caller must have execute permission on functions */ aclresult = pg_proc_aclcheck(funcOid, GetUserId(), ACL_EXECUTE); diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 9672e74ea9..8aa2addc51 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.40 2002/08/13 17:22:08 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.41 2002/08/22 00:01:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,17 +71,18 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) elog(ERROR, "Language %s already exists", languageName); /* - * Lookup the PL handler function and check that it is of return type - * Opaque + * Lookup the PL handler function and check that it is of the expected + * return type */ MemSet(typev, 0, sizeof(typev)); procOid = LookupFuncName(stmt->plhandler, 0, typev); if (!OidIsValid(procOid)) elog(ERROR, "function %s() doesn't exist", NameListToString(stmt->plhandler)); - if (get_func_rettype(procOid) != InvalidOid) - elog(ERROR, "function %s() does not return type \"opaque\"", - NameListToString(stmt->plhandler)); + if (get_func_rettype(procOid) != LANGUAGE_HANDLEROID) + elog(ERROR, "function %s() does not return type %s", + NameListToString(stmt->plhandler), + format_type_be(LANGUAGE_HANDLEROID)); /* validate the validator function */ if (stmt->plvalidator) @@ -91,6 +92,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) if (!OidIsValid(valProcOid)) elog(ERROR, "function %s(oid) doesn't exist", NameListToString(stmt->plvalidator)); + /* return value is ignored, so we don't check the type */ } else valProcOid = InvalidOid; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 312bad4352..82feb9333d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.127 2002/08/18 11:20:05 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.128 2002/08/22 00:01:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,7 @@ #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "catalog/pg_trigger.h" +#include "catalog/pg_type.h" #include "commands/trigger.h" #include "executor/executor.h" #include "miscadmin.h" @@ -222,9 +223,15 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) if (!HeapTupleIsValid(tuple)) elog(ERROR, "CreateTrigger: function %s() does not exist", NameListToString(stmt->funcname)); - if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != 0) - elog(ERROR, "CreateTrigger: function %s() must return OPAQUE", - NameListToString(stmt->funcname)); + if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != TRIGGEROID) + { + /* OPAQUE is deprecated, but allowed for backwards compatibility */ + if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype == OPAQUEOID) + elog(NOTICE, "CreateTrigger: OPAQUE is deprecated, use type TRIGGER instead to define trigger functions"); + else + elog(ERROR, "CreateTrigger: function %s() must return TRIGGER", + NameListToString(stmt->funcname)); + } ReleaseSysCache(tuple); /* diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index f9f27d5867..bfca9c7c8f 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.9 2002/08/15 16:36:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.10 2002/08/22 00:01:42 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -49,7 +49,7 @@ #include "utils/syscache.h" -static Oid findTypeIOFunction(List *procname, bool isOutput); +static Oid findTypeIOFunction(List *procname, Oid typeOid, bool isOutput); /* * DefineType @@ -75,6 +75,7 @@ DefineType(List *names, List *parameters) char *shadow_type; List *pl; Oid typoid; + Oid resulttype; /* Convert list of names to a name and namespace */ typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName); @@ -116,7 +117,13 @@ DefineType(List *names, List *parameters) delimiter = p[0]; } else if (strcasecmp(defel->defname, "element") == 0) + { elemType = typenameTypeId(defGetTypeName(defel)); + /* disallow arrays of pseudotypes */ + if (get_typtype(elemType) == 'p') + elog(ERROR, "Array element type cannot be %s", + format_type_be(elemType)); + } else if (strcasecmp(defel->defname, "default") == 0) defaultValue = defGetString(defel); else if (strcasecmp(defel->defname, "passedbyvalue") == 0) @@ -179,9 +186,36 @@ DefineType(List *names, List *parameters) if (outputName == NIL) elog(ERROR, "Define: \"output\" unspecified"); - /* Convert I/O proc names to OIDs */ - inputOid = findTypeIOFunction(inputName, false); - outputOid = findTypeIOFunction(outputName, true); + /* + * Look to see if type already exists (presumably as a shell; if not, + * TypeCreate will complain). If it does then the declarations of the + * I/O functions might use it. + */ + typoid = GetSysCacheOid(TYPENAMENSP, + CStringGetDatum(typeName), + ObjectIdGetDatum(typeNamespace), + 0, 0); + + /* + * Convert I/O proc names to OIDs + */ + inputOid = findTypeIOFunction(inputName, typoid, false); + outputOid = findTypeIOFunction(outputName, typoid, true); + + /* + * Verify that I/O procs return the expected thing. OPAQUE is an allowed + * (but deprecated) alternative to the fully type-safe choices. + */ + resulttype = get_func_rettype(inputOid); + if (!((OidIsValid(typoid) && resulttype == typoid) || + resulttype == OPAQUEOID)) + elog(ERROR, "Type input function %s must return %s or OPAQUE", + NameListToString(inputName), typeName); + resulttype = get_func_rettype(outputOid); + if (!(resulttype == CSTRINGOID || + resulttype == OPAQUEOID)) + elog(ERROR, "Type output function %s must return CSTRING or OPAQUE", + NameListToString(outputName)); /* * now have TypeCreate do all the real work. @@ -377,10 +411,9 @@ DefineDomain(CreateDomainStmt *stmt) basetypeoid = HeapTupleGetOid(typeTup); /* - * What we really don't want is domains of domains. This could cause all sorts - * of neat issues if we allow that. - * - * With testing, we may determine complex types should be allowed + * Base type must be a plain base type. Domains over pseudo types would + * create a security hole. Domains of domains might be made to work in + * the future, but not today. Ditto for domains over complex types. */ typtype = baseType->typtype; if (typtype != 'b') @@ -621,52 +654,109 @@ RemoveDomain(List *names, DropBehavior behavior) /* * Find a suitable I/O function for a type. + * + * typeOid is the type's OID, if it already exists as a shell type, + * otherwise InvalidOid. */ static Oid -findTypeIOFunction(List *procname, bool isOutput) +findTypeIOFunction(List *procname, Oid typeOid, bool isOutput) { Oid argList[FUNC_MAX_ARGS]; - int nargs; Oid procOid; - /* - * First look for a 1-argument func with all argtypes 0. This is - * valid for all kinds of procedure. - */ - MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); - - procOid = LookupFuncName(procname, 1, argList); - - if (!OidIsValid(procOid)) + if (isOutput) { /* - * Alternatively, input procedures may take 3 args (data - * value, element OID, atttypmod); the pg_proc argtype - * signature is 0,OIDOID,INT4OID. Output procedures may - * take 2 args (data value, element OID). + * Output functions can take a single argument of the type, + * or two arguments (data value, element OID). The signature + * may use OPAQUE in place of the actual type name; this is the + * only possibility if the type doesn't yet exist as a shell. */ - if (isOutput) - { - /* output proc */ - nargs = 2; - argList[1] = OIDOID; - } - else + if (OidIsValid(typeOid)) { - /* input proc */ - nargs = 3; + MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); + + argList[0] = typeOid; + + procOid = LookupFuncName(procname, 1, argList); + if (OidIsValid(procOid)) + return procOid; + argList[1] = OIDOID; - argList[2] = INT4OID; + + procOid = LookupFuncName(procname, 2, argList); + if (OidIsValid(procOid)) + return procOid; + } - procOid = LookupFuncName(procname, nargs, argList); - if (!OidIsValid(procOid)) - func_error("TypeCreate", procname, 1, argList, NULL); + MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); + + argList[0] = OPAQUEOID; + + procOid = LookupFuncName(procname, 1, argList); + if (OidIsValid(procOid)) + return procOid; + + argList[1] = OIDOID; + + procOid = LookupFuncName(procname, 2, argList); + if (OidIsValid(procOid)) + return procOid; + + /* Prefer type name over OPAQUE in the failure message. */ + if (OidIsValid(typeOid)) + argList[0] = typeOid; + + func_error("TypeCreate", procname, 1, argList, NULL); } + else + { + /* + * Input functions can take a single argument of type CSTRING, + * or three arguments (string, element OID, typmod). The signature + * may use OPAQUE in place of CSTRING. + */ + MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); + + argList[0] = CSTRINGOID; + + procOid = LookupFuncName(procname, 1, argList); + if (OidIsValid(procOid)) + return procOid; - return procOid; + argList[1] = OIDOID; + argList[2] = INT4OID; + + procOid = LookupFuncName(procname, 3, argList); + if (OidIsValid(procOid)) + return procOid; + + MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); + + argList[0] = OPAQUEOID; + + procOid = LookupFuncName(procname, 1, argList); + if (OidIsValid(procOid)) + return procOid; + + argList[1] = OIDOID; + argList[2] = INT4OID; + + procOid = LookupFuncName(procname, 3, argList); + if (OidIsValid(procOid)) + return procOid; + + /* Use CSTRING (preferred) in the error message */ + argList[0] = CSTRINGOID; + + func_error("TypeCreate", procname, 1, argList, NULL); + } + + return InvalidOid; /* keep compiler quiet */ } + /*------------------------------------------------------------------- * DefineCompositeType * |