diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/regproc.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 63 | ||||
-rw-r--r-- | src/backend/utils/fmgr/funcapi.c | 88 |
3 files changed, 135 insertions, 24 deletions
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index fd90a290220..dd2a53f5a5f 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.110 2009/01/01 17:23:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.111 2009/10/08 02:39:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -131,7 +131,7 @@ regprocin(PG_FUNCTION_ARGS) * pg_proc entries in the current search path. */ names = stringToQualifiedNameList(pro_name_or_oid); - clist = FuncnameGetCandidates(names, -1, false, false); + clist = FuncnameGetCandidates(names, -1, NIL, false, false); if (clist == NULL) ereport(ERROR, @@ -190,7 +190,7 @@ regprocout(PG_FUNCTION_ARGS) * qualify it. */ clist = FuncnameGetCandidates(list_make1(makeString(proname)), - -1, false, false); + -1, NIL, false, false); if (clist != NULL && clist->next == NULL && clist->oid == proid) nspname = NULL; @@ -277,7 +277,7 @@ regprocedurein(PG_FUNCTION_ARGS) */ parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes); - clist = FuncnameGetCandidates(names, nargs, false, false); + clist = FuncnameGetCandidates(names, nargs, NIL, false, false); for (; clist; clist = clist->next) { diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 38057a0bfdc..4c04bafd7c6 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.306 2009/08/01 19:59:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.307 2009/10/08 02:39:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -218,8 +218,8 @@ static Node *processIndirection(Node *node, deparse_context *context, bool printit); static void printSubscripts(ArrayRef *aref, deparse_context *context); static char *generate_relation_name(Oid relid, List *namespaces); -static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes, - bool *is_variadic); +static char *generate_function_name(Oid funcid, int nargs, List *argnames, + Oid *argtypes, bool *is_variadic); static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); static text *string_to_text(char *str); static char *flatten_reloptions(Oid relid); @@ -558,7 +558,8 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) appendStringInfo(&buf, "FOR EACH STATEMENT "); appendStringInfo(&buf, "EXECUTE PROCEDURE %s(", - generate_function_name(trigrec->tgfoid, 0, NULL, NULL)); + generate_function_name(trigrec->tgfoid, 0, + NIL, NULL, NULL)); if (trigrec->tgnargs > 0) { @@ -4324,6 +4325,15 @@ get_rule_expr(Node *node, deparse_context *context, get_func_expr((FuncExpr *) node, context, showimplicit); break; + case T_NamedArgExpr: + { + NamedArgExpr *na = (NamedArgExpr *) node; + + get_rule_expr((Node *) na->arg, context, showimplicit); + appendStringInfo(buf, " AS %s", quote_identifier(na->name)); + } + break; + case T_OpExpr: get_oper_expr((OpExpr *) node, context); break; @@ -5187,6 +5197,7 @@ get_func_expr(FuncExpr *expr, deparse_context *context, Oid funcoid = expr->funcid; Oid argtypes[FUNC_MAX_ARGS]; int nargs; + List *argnames; bool is_variadic; ListCell *l; @@ -5231,14 +5242,20 @@ get_func_expr(FuncExpr *expr, deparse_context *context, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), errmsg("too many arguments"))); nargs = 0; + argnames = NIL; foreach(l, expr->args) { - argtypes[nargs] = exprType((Node *) lfirst(l)); + Node *arg = (Node *) lfirst(l); + + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); + argtypes[nargs] = exprType(arg); nargs++; } appendStringInfo(buf, "%s(", - generate_function_name(funcoid, nargs, argtypes, + generate_function_name(funcoid, nargs, + argnames, argtypes, &is_variadic)); nargs = 0; foreach(l, expr->args) @@ -5270,13 +5287,16 @@ get_agg_expr(Aggref *aggref, deparse_context *context) nargs = 0; foreach(l, aggref->args) { - argtypes[nargs] = exprType((Node *) lfirst(l)); + Node *arg = (Node *) lfirst(l); + + Assert(!IsA(arg, NamedArgExpr)); + argtypes[nargs] = exprType(arg); nargs++; } appendStringInfo(buf, "%s(%s", - generate_function_name(aggref->aggfnoid, - nargs, argtypes, NULL), + generate_function_name(aggref->aggfnoid, nargs, + NIL, argtypes, NULL), aggref->aggdistinct ? "DISTINCT " : ""); /* aggstar can be set only in zero-argument aggregates */ if (aggref->aggstar) @@ -5304,13 +5324,16 @@ get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) nargs = 0; foreach(l, wfunc->args) { - argtypes[nargs] = exprType((Node *) lfirst(l)); + Node *arg = (Node *) lfirst(l); + + Assert(!IsA(arg, NamedArgExpr)); + argtypes[nargs] = exprType(arg); nargs++; } - appendStringInfo(buf, "%s(%s", - generate_function_name(wfunc->winfnoid, - nargs, argtypes, NULL), ""); + appendStringInfo(buf, "%s(", + generate_function_name(wfunc->winfnoid, nargs, + NIL, argtypes, NULL)); /* winstar can be set only in zero-argument aggregates */ if (wfunc->winstar) appendStringInfoChar(buf, '*'); @@ -6338,15 +6361,15 @@ generate_relation_name(Oid relid, List *namespaces) /* * generate_function_name * Compute the name to display for a function specified by OID, - * given that it is being called with the specified actual arg types. - * (Arg types matter because of ambiguous-function resolution rules.) + * given that it is being called with the specified actual arg names and + * types. (Those matter because of ambiguous-function resolution rules.) * * The result includes all necessary quoting and schema-prefixing. We can * also pass back an indication of whether the function is variadic. */ static char * -generate_function_name(Oid funcid, int nargs, Oid *argtypes, - bool *is_variadic) +generate_function_name(Oid funcid, int nargs, List *argnames, + Oid *argtypes, bool *is_variadic) { HeapTuple proctup; Form_pg_proc procform; @@ -6371,10 +6394,12 @@ generate_function_name(Oid funcid, int nargs, Oid *argtypes, /* * The idea here is to schema-qualify only if the parser would fail to * resolve the correct function given the unqualified func name with the - * specified argtypes. + * specified argtypes. If the function is variadic, we should presume + * that VARIADIC will be included in the call. */ p_result = func_get_detail(list_make1(makeString(proname)), - NIL, nargs, argtypes, false, true, + NIL, argnames, nargs, argtypes, + !OidIsValid(procform->provariadic), true, &p_funcid, &p_rettype, &p_retset, &p_nvargs, &p_true_typeids, NULL); if ((p_result == FUNCDETAIL_NORMAL || diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 7ecd7812206..313b777d04b 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -7,7 +7,7 @@ * Copyright (c) 2002-2009, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.45 2009/06/11 14:49:05 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.46 2009/10/08 02:39:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -767,6 +767,92 @@ get_func_arg_info(HeapTuple procTup, /* + * get_func_input_arg_names + * + * Extract the names of input arguments only, given a function's + * proargnames and proargmodes entries in Datum form. + * + * Returns the number of input arguments, which is the length of the + * palloc'd array returned to *arg_names. Entries for unnamed args + * are set to NULL. You don't get anything if proargnames is NULL. + */ +int +get_func_input_arg_names(Datum proargnames, Datum proargmodes, + char ***arg_names) +{ + ArrayType *arr; + int numargs; + Datum *argnames; + char *argmodes; + char **inargnames; + int numinargs; + int i; + + /* Do nothing if null proargnames */ + if (proargnames == PointerGetDatum(NULL)) + { + *arg_names = NULL; + return 0; + } + + /* + * We expect the arrays to be 1-D arrays of the right types; verify that. + * For proargmodes, we don't need to use deconstruct_array() + * since the array data is just going to look like a C array of values. + */ + arr = DatumGetArrayTypeP(proargnames); /* ensure not toasted */ + if (ARR_NDIM(arr) != 1 || + ARR_HASNULL(arr) || + ARR_ELEMTYPE(arr) != TEXTOID) + elog(ERROR, "proargnames is not a 1-D text array"); + deconstruct_array(arr, TEXTOID, -1, false, 'i', + &argnames, NULL, &numargs); + if (proargmodes != PointerGetDatum(NULL)) + { + arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */ + if (ARR_NDIM(arr) != 1 || + ARR_DIMS(arr)[0] != numargs || + ARR_HASNULL(arr) || + ARR_ELEMTYPE(arr) != CHAROID) + elog(ERROR, "proargmodes is not a 1-D char array"); + argmodes = (char *) ARR_DATA_PTR(arr); + } + else + argmodes = NULL; + + /* zero elements probably shouldn't happen, but handle it gracefully */ + if (numargs <= 0) + { + *arg_names = NULL; + return 0; + } + + /* extract input-argument names */ + inargnames = (char **) palloc(numargs * sizeof(char *)); + numinargs = 0; + for (i = 0; i < numargs; i++) + { + if (argmodes == NULL || + argmodes[i] == PROARGMODE_IN || + argmodes[i] == PROARGMODE_INOUT || + argmodes[i] == PROARGMODE_VARIADIC) + { + char *pname = TextDatumGetCString(argnames[i]); + + if (pname[0] != '\0') + inargnames[numinargs] = pname; + else + inargnames[numinargs] = NULL; + numinargs++; + } + } + + *arg_names = inargnames; + return numinargs; +} + + +/* * get_func_result_name * * If the function has exactly one output parameter, and that parameter |