aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-10-08 02:39:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-10-08 02:39:25 +0000
commit717fa274d14d9cd25396b85bb92f567e1c623f0c (patch)
tree4fe298a9faa1fc8f038a9a1f35ee033abc3e41ed /src/backend/utils
parent2eda8dfb52ed9962920282d8384da8bb4c22514d (diff)
downloadpostgresql-717fa274d14d9cd25396b85bb92f567e1c623f0c.tar.gz
postgresql-717fa274d14d9cd25396b85bb92f567e1c623f0c.zip
Support use of function argument names to identify which actual arguments
match which function parameters. The syntax uses AS, for example funcname(value AS arg1, anothervalue AS arg2) Pavel Stehule
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/regproc.c8
-rw-r--r--src/backend/utils/adt/ruleutils.c63
-rw-r--r--src/backend/utils/fmgr/funcapi.c88
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