diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/namespace.c | 49 | ||||
-rw-r--r-- | src/backend/catalog/pg_aggregate.c | 4 | ||||
-rw-r--r-- | src/backend/catalog/pg_proc.c | 72 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 56 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 31 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 10 |
6 files changed, 122 insertions, 100 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 48b8ee45e6b..c6db3d16b92 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.108 2008/07/16 01:30:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.109 2008/07/16 16:55:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -619,50 +619,23 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) int pronargs = procform->pronargs; int effective_nargs; int pathpos = 0; - bool variadic = false; - Oid va_elem_type = InvalidOid; + bool variadic; + Oid va_elem_type; FuncCandidateList newResult; /* * Check if function is variadic, and get variadic element type if so. - * If expand_variadic is false, we can just ignore variadic-ness. - * - * XXX it's annoying to inject something as expensive as this even - * when there are no variadic functions involved. Find a better way. + * If expand_variadic is false, we should just ignore variadic-ness. */ if (expand_variadic) { - Datum proargmodes; - bool isnull; - - proargmodes = SysCacheGetAttr(PROCOID, proctup, - Anum_pg_proc_proargmodes, &isnull); - if (!isnull) - { - ArrayType *ar = DatumGetArrayTypeP(proargmodes); - char *argmodes; - int j; - - argmodes = ARR_DATA_PTR(ar); - j = ARR_DIMS(ar)[0] - 1; - if (j >= 0 && argmodes[j] == PROARGMODE_VARIADIC) - { - variadic = any_variadic = true; - switch (procform->proargtypes.values[j]) - { - case ANYOID: - va_elem_type = ANYOID; - break; - case ANYARRAYOID: - va_elem_type = ANYELEMENTOID; - break; - default: - va_elem_type = get_element_type(procform->proargtypes.values[j]); - Assert(OidIsValid(va_elem_type)); - break; - } - } - } + va_elem_type = procform->provariadic; + variadic = OidIsValid(va_elem_type); + } + else + { + va_elem_type = InvalidOid; + variadic = false; } /* Ignore if it doesn't match requested argument count */ diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index e1c67ce5cd4..42eadca1e2b 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.94 2008/07/16 01:30:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.95 2008/07/16 16:55:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -202,7 +202,7 @@ AggregateCreate(const char *aggName, INTERNALlanguageId, /* languageObjectId */ InvalidOid, /* no validator */ "aggregate_dummy", /* placeholder proc */ - "-", /* probin */ + NULL, /* probin */ true, /* isAgg */ false, /* security invoker (currently not * definable for agg) */ diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 1f11f82a304..37e7ed4343e 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.151 2008/03/27 03:57:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.152 2008/07/16 16:55:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,6 +85,7 @@ ProcedureCreate(const char *procedureName, bool genericOutParam = false; bool internalInParam = false; bool internalOutParam = false; + Oid variadicType = InvalidOid; Relation rel; HeapTuple tup; HeapTuple oldtup; @@ -103,7 +104,6 @@ ProcedureCreate(const char *procedureName, * sanity checks */ Assert(PointerIsValid(prosrc)); - Assert(PointerIsValid(probin)); parameterCount = parameterTypes->dim1; if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS) @@ -211,6 +211,64 @@ ProcedureCreate(const char *procedureName, procedureName, format_type_be(parameterTypes->values[0])))); + if (parameterModes != PointerGetDatum(NULL)) + { + /* + * We expect the array to be a 1-D CHAR array; verify that. We don't + * need to use deconstruct_array() since the array data is just going + * to look like a C array of char values. + */ + ArrayType *modesArray = (ArrayType *) DatumGetPointer(parameterModes); + char *modes; + + if (ARR_NDIM(modesArray) != 1 || + ARR_DIMS(modesArray)[0] != allParamCount || + ARR_HASNULL(modesArray) || + ARR_ELEMTYPE(modesArray) != CHAROID) + elog(ERROR, "parameterModes is not a 1-D char array"); + modes = (char *) ARR_DATA_PTR(modesArray); + /* + * Only the last input parameter can be variadic; if it is, save + * its element type. Errors here are just elog since caller should + * have checked this already. + */ + for (i = 0; i < allParamCount; i++) + { + switch (modes[i]) + { + case PROARGMODE_IN: + case PROARGMODE_INOUT: + if (OidIsValid(variadicType)) + elog(ERROR, "variadic parameter must be last"); + break; + case PROARGMODE_OUT: + /* okay */ + break; + case PROARGMODE_VARIADIC: + if (OidIsValid(variadicType)) + elog(ERROR, "variadic parameter must be last"); + switch (allParams[i]) + { + case ANYOID: + variadicType = ANYOID; + break; + case ANYARRAYOID: + variadicType = ANYELEMENTOID; + break; + default: + variadicType = get_element_type(allParams[i]); + if (!OidIsValid(variadicType)) + elog(ERROR, "variadic parameter is not an array"); + break; + } + break; + default: + elog(ERROR, "invalid parameter mode '%c'", modes[i]); + break; + } + } + } + /* * All seems OK; prepare the data to be inserted into pg_proc. */ @@ -229,6 +287,7 @@ ProcedureCreate(const char *procedureName, values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId); values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost); values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); + values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); values[Anum_pg_proc_proisagg - 1] = BoolGetDatum(isAgg); values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); @@ -250,7 +309,10 @@ ProcedureCreate(const char *procedureName, else nulls[Anum_pg_proc_proargnames - 1] = 'n'; values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); - values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); + if (probin) + values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); + else + nulls[Anum_pg_proc_probin - 1] = 'n'; if (proconfig != PointerGetDatum(NULL)) values[Anum_pg_proc_proconfig - 1] = proconfig; else @@ -497,12 +559,12 @@ fmgr_c_validator(PG_FUNCTION_ARGS) tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); if (isnull) - elog(ERROR, "null prosrc"); + elog(ERROR, "null prosrc for C function %u", funcoid); prosrc = TextDatumGetCString(tmp); tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull); if (isnull) - elog(ERROR, "null probin"); + elog(ERROR, "null probin for C function %u", funcoid); probin = TextDatumGetCString(tmp); (void) load_external_function(probin, prosrc, true, &libraryhandle); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index cb249d9c7d1..d03de8bff17 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.96 2008/07/16 01:30:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.97 2008/07/16 16:55:23 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -590,7 +590,8 @@ compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatili * AS <object reference, or sql code> */ static void -interpret_AS_clause(Oid languageOid, const char *languageName, List *as, +interpret_AS_clause(Oid languageOid, const char *languageName, + char *funcname, List *as, char **prosrc_str_p, char **probin_str_p) { Assert(as != NIL); @@ -599,25 +600,47 @@ interpret_AS_clause(Oid languageOid, const char *languageName, List *as, { /* * For "C" language, store the file name in probin and, when given, - * the link symbol name in prosrc. + * the link symbol name in prosrc. If link symbol is omitted, + * substitute procedure name. We also allow link symbol to be + * specified as "-", since that was the habit in PG versions before + * 8.4, and there might be dump files out there that don't translate + * that back to "omitted". */ *probin_str_p = strVal(linitial(as)); if (list_length(as) == 1) - *prosrc_str_p = "-"; + *prosrc_str_p = funcname; else + { *prosrc_str_p = strVal(lsecond(as)); + if (strcmp(*prosrc_str_p, "-") == 0) + *prosrc_str_p = funcname; + } } else { /* Everything else wants the given string in prosrc. */ *prosrc_str_p = strVal(linitial(as)); - *probin_str_p = "-"; + *probin_str_p = NULL; if (list_length(as) != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("only one AS item needed for language \"%s\"", languageName))); + + if (languageOid == INTERNALlanguageId) + { + /* + * In PostgreSQL versions before 6.5, the SQL name of the created + * function could not be different from the internal name, and + * "prosrc" wasn't used. So there is code out there that does + * CREATE FUNCTION xyz AS '' LANGUAGE internal. To preserve some + * modicum of backwards compatibility, accept an empty "prosrc" + * value as meaning the supplied SQL function name. + */ + if (strlen(*prosrc_str_p) == 0) + *prosrc_str_p = funcname; + } } } @@ -759,30 +782,9 @@ CreateFunction(CreateFunctionStmt *stmt) compute_attributes_with_style(stmt->withClause, &isStrict, &volatility); - interpret_AS_clause(languageOid, languageName, as_clause, + interpret_AS_clause(languageOid, languageName, funcname, as_clause, &prosrc_str, &probin_str); - if (languageOid == INTERNALlanguageId) - { - /* - * In PostgreSQL versions before 6.5, the SQL name of the created - * function could not be different from the internal name, and - * "prosrc" wasn't used. So there is code out there that does CREATE - * FUNCTION xyz AS '' LANGUAGE internal. To preserve some modicum of - * backwards compatibility, accept an empty "prosrc" value as meaning - * the supplied SQL function name. - */ - if (strlen(prosrc_str) == 0) - prosrc_str = funcname; - } - - if (languageOid == ClanguageId) - { - /* If link symbol is specified as "-", substitute procedure name */ - if (strcmp(prosrc_str, "-") == 0) - prosrc_str = funcname; - } - /* * Set default values for COST and ROWS depending on other parameters; * reject ROWS if it's not returnsSet. NB: pg_dump knows these default diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index dc4a6cc4a8f..c7f896c524a 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.276 2008/07/16 01:30:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.277 2008/07/16 16:55:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -5389,29 +5389,12 @@ generate_function_name(Oid funcid, int nargs, Oid *argtypes, /* Check variadic-ness if caller cares */ if (is_variadic) { - /* XXX change this if we simplify code in FuncnameGetCandidates */ - Datum proargmodes; - bool isnull; - - *is_variadic = false; - - proargmodes = SysCacheGetAttr(PROCOID, proctup, - Anum_pg_proc_proargmodes, &isnull); - if (!isnull) - { - ArrayType *ar = DatumGetArrayTypeP(proargmodes); - char *argmodes; - int j; - - argmodes = ARR_DATA_PTR(ar); - j = ARR_DIMS(ar)[0] - 1; - if (j >= 0 && argmodes[j] == PROARGMODE_VARIADIC) - { - /* "any" variadics are not treated as variadics for listing */ - if (procform->proargtypes.values[j] != ANYOID) - *is_variadic = true; - } - } + /* "any" variadics are not treated as variadics for listing */ + if (OidIsValid(procform->provariadic) && + procform->provariadic != ANYOID) + *is_variadic = true; + else + *is_variadic = false; } ReleaseSysCache(proctup); diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index b0553b026b8..cd23bae0779 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.120 2008/06/06 22:35:22 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.121 2008/07/16 16:55:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -324,18 +324,20 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) void *libraryhandle; /* - * Get prosrc and probin strings (link symbol and library filename) + * Get prosrc and probin strings (link symbol and library filename). + * While in general these columns might be null, that's not allowed + * for C-language functions. */ prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_prosrc, &isnull); if (isnull) - elog(ERROR, "null prosrc for function %u", functionId); + elog(ERROR, "null prosrc for C function %u", functionId); prosrcstring = TextDatumGetCString(prosrcattr); probinattr = SysCacheGetAttr(PROCOID, procedureTuple, Anum_pg_proc_probin, &isnull); if (isnull) - elog(ERROR, "null probin for function %u", functionId); + elog(ERROR, "null probin for C function %u", functionId); probinstring = TextDatumGetCString(probinattr); /* Look up the function itself */ |