diff options
Diffstat (limited to 'src/backend/catalog')
| -rw-r--r-- | src/backend/catalog/namespace.c | 87 | ||||
| -rw-r--r-- | src/backend/catalog/pg_aggregate.c | 7 | ||||
| -rw-r--r-- | src/backend/catalog/pg_proc.c | 13 |
3 files changed, 95 insertions, 12 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index f1763e5199..6c83755a4c 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.112 2008/09/09 18:58:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.113 2008/12/04 17:51:26 petere Exp $ * *------------------------------------------------------------------------- */ @@ -571,6 +571,11 @@ TypeIsVisible(Oid typid) * If expand_variadic is false, variadic arguments are not treated specially, * and the returned nvargs will always be zero. * + * If expand_variadic is true, functions with argument default values + * will also be retrieved. If expand_variadic is false, default + * values will not be taken into account and functions that do not + * have exactly nargs arguments in total will not be considered. + * * We search a single namespace if the function name is qualified, else * all namespaces in the search path. The return list will never contain * multiple entries with identical argument lists --- in the multiple- @@ -621,13 +626,45 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) int pathpos = 0; bool variadic; Oid va_elem_type; + List *defaults = NIL; FuncCandidateList newResult; /* + * Check if function has some parameter defaults if some + * parameters are missing. + */ + if (pronargs > nargs && expand_variadic) + { + bool isnull; + Datum proargdefaults; + char *str; + + /* skip when not enough default expressions */ + if (nargs + procform->pronargdefaults < pronargs) + continue; + + proargdefaults = SysCacheGetAttr(PROCOID, proctup, + Anum_pg_proc_proargdefaults, &isnull); + Assert(!isnull); + str = TextDatumGetCString(proargdefaults); + defaults = (List *) stringToNode(str); + + Assert(IsA(defaults, List)); + + /* + * If we don't have to use all default parameters, we skip + * some cells from the left. + */ + defaults = list_copy_tail(defaults, procform->pronargdefaults - pronargs + nargs); + + pfree(str); + } + + /* * Check if function is variadic, and get variadic element type if so. * If expand_variadic is false, we should just ignore variadic-ness. */ - if (expand_variadic) + if (pronargs <= nargs && expand_variadic) { va_elem_type = procform->provariadic; variadic = OidIsValid(va_elem_type); @@ -638,11 +675,16 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) variadic = false; } + Assert(!variadic || !defaults); + /* Ignore if it doesn't match requested argument count */ if (nargs >= 0 && - (variadic ? (pronargs > nargs) : (pronargs != nargs))) + (variadic ? (pronargs > nargs) : (defaults ? (pronargs < nargs) : (pronargs != nargs)))) continue; + Assert(!variadic || (pronargs <= nargs)); + Assert(!defaults || (pronargs > nargs)); + if (OidIsValid(namespaceId)) { /* Consider only procs in specified namespace */ @@ -681,6 +723,7 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) newResult->pathpos = pathpos; newResult->oid = HeapTupleGetOid(proctup); newResult->nargs = effective_nargs; + newResult->argdefaults = defaults; memcpy(newResult->args, procform->proargtypes.values, pronargs * sizeof(Oid)); if (variadic) @@ -695,6 +738,8 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) else newResult->nvargs = 0; + any_variadic = variadic || defaults; + /* * Does it have the same arguments as something we already accepted? * If so, decide which one to keep. We can skip this check for the @@ -704,6 +749,9 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) */ if (any_variadic || !OidIsValid(namespaceId)) { + if (defaults) + effective_nargs = nargs; + /* * If we have an ordered list from SearchSysCacheList (the normal * case), then any conflicting proc must immediately adjoin this @@ -733,11 +781,21 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) prevResult; prevResult = prevResult->next) { - if (effective_nargs == prevResult->nargs && - memcmp(newResult->args, - prevResult->args, - effective_nargs * sizeof(Oid)) == 0) + if (!defaults) + { + if (effective_nargs == prevResult->nargs && + memcmp(newResult->args, + prevResult->args, + effective_nargs * sizeof(Oid)) == 0) + break; + } + else + { + if (memcmp(newResult->args, + prevResult->args, + effective_nargs * sizeof(Oid)) == 0) break; + } } } if (prevResult) @@ -777,6 +835,20 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) pfree(newResult); continue; /* keep previous result */ } + + if (defaults) + { + if (prevResult->argdefaults != NIL) + ereport(ERROR, + (errcode(ERRCODE_AMBIGUOUS_FUNCTION), + errmsg("functions with parameter defaults %s and %s are ambiguous", + func_signature_string(names, pronargs, procform->proargtypes.values), + func_signature_string(names, prevResult->nargs, prevResult->args)))); + /* else, previous result didn't have defaults */ + pfree(newResult); + continue; /* keep previous result */ + } + /* non-variadic can replace a previous variadic */ Assert(prevResult->nvargs > 0); } @@ -784,6 +856,7 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic) prevResult->pathpos = pathpos; prevResult->oid = newResult->oid; prevResult->nvargs = newResult->nvargs; + prevResult->argdefaults = newResult->argdefaults; pfree(newResult); continue; /* args are same, of course */ } diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index fc5ed83937..7cd0d513ed 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.97 2008/11/14 19:47:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_aggregate.c,v 1.98 2008/12/04 17:51:26 petere Exp $ * *------------------------------------------------------------------------- */ @@ -229,7 +229,8 @@ AggregateCreate(const char *aggName, PointerGetDatum(NULL), /* parameterNames */ PointerGetDatum(NULL), /* proconfig */ 1, /* procost */ - 0); /* prorows */ + 0, /* prorows */ + NULL); /* parameterDefaults */ /* * Okay to create the pg_aggregate entry. @@ -321,7 +322,7 @@ lookup_agg_function(List *fnName, */ fdresult = func_get_detail(fnName, NIL, nargs, input_types, false, &fnOid, rettype, &retset, &nvargs, - &true_oid_array); + &true_oid_array, NULL); /* only valid case is a normal function not returning a set */ if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid)) diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index e17aa43fd5..1b414e3e5a 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.154 2008/11/02 01:45:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.155 2008/12/04 17:51:26 petere Exp $ * *------------------------------------------------------------------------- */ @@ -75,7 +75,8 @@ ProcedureCreate(const char *procedureName, Datum parameterNames, Datum proconfig, float4 procost, - float4 prorows) + float4 prorows, + List *parameterDefaults) { Oid retval; int parameterCount; @@ -295,6 +296,7 @@ ProcedureCreate(const char *procedureName, values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet); values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility); values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount); + values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults)); values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType); values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes); if (allParameterTypes != PointerGetDatum(NULL)) @@ -309,6 +311,13 @@ ProcedureCreate(const char *procedureName, values[Anum_pg_proc_proargnames - 1] = parameterNames; else nulls[Anum_pg_proc_proargnames - 1] = true; + if (parameterDefaults != PointerGetDatum(NULL)) + { + Assert(list_length(parameterDefaults) > 0); + values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults)); + } + else + nulls[Anum_pg_proc_proargdefaults - 1] = true; values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc); if (probin) values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin); |
