On Thu, 2009-10-01 at 17:56 +1000, Brendan Jurd wrote:
> I've had a look through the documentation and cleaned up a few things.

Thanks, that is helpful. I have included that along with some other
comment updates in the attached patch.

Paval,

In ProcedureCreate(), you match the argument names to see if anything
changed (in which case you raise an error). The code for that looks more
complex than I expected because it keeps track of the two argument lists
using different array indexes (i and j). Is there a reason it you can't
just iterate through with something like:

  if (p_oldargmodes[i] == PROARGMODE_OUT ||
      p_oldargmodes[i] == PROARGMODE_TABLE)
    continue;

  if (strcmp(p_oldargnames[i], p_names[i]) != 0)
    elog(ERROR, ...

I'm oversimplifying, of course, but I don't understand why you need both
i and j. Also, there is some unnecessarily verbose code like:

  if (p_modes == NULL || (p_modes != NULL ...

In func_get_detail(), there is:

  /* shouldn't happen, FuncnameGetCandidates messed up */
  if (best_candidate->ndargs > pform->pronargdefaults)
    elog(ERROR, "not enough default arguments");

Why is it only an error if ndargs is greater? Shouldn't they be equal?

  /*                                                                            
                                          
   * Actually only first nargs field of best_candidate->args is valid,
   * Now, we have to refresh last ndargs items.
   */

Can you explain the above comment?

Please review Brendan and my patches and combine them with your patch.

Regards,
        Jeff Davis
diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml
index 50c4128..542646d 100644
--- a/doc/src/sgml/syntax.sgml
+++ b/doc/src/sgml/syntax.sgml
@@ -1505,6 +1505,10 @@ sqrt(2)
     The list of built-in functions is in <xref linkend="functions">.
     Other functions can be added by the user.
    </para>
+
+   <para>
+     See <xref linkend="extend"> for more details.
+   </para>
   </sect2>
 
   <sect2 id="syntax-aggregates">
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 9e8ccfa..1c06885 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -651,21 +651,19 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
 		int			effective_nargs;
 		int			pathpos = 0;
 		bool		variadic;
-		bool		use_defaults = false;		/* be compiler quiet */
+		bool		use_defaults = false;		/* make compiler quiet */
 		Oid			va_elem_type;
 		FuncCandidateList newResult;
 		int		*proargidxs = NULL;
 
-		/* Try to attach names, when mixed or named notation is used. */
+		/* Try to attach names when mixed or named notation is used. */
 		if (argnames != NIL)
 		{
 			/*
-			 * Mixed or named notation 
+			 * Mixed or named notation
 			 *
-			 * We would to disable an call of variadic function with named
-			 * or mixed notation, because it could be messy for users. We
-			 * would to allow only unique arg names, and this is useles for
-			 * variadic functions.
+			 * Variadic functions can't be called using named or mixed
+			 * notation.
 			 */
 			if (OidIsValid(procform->provariadic))
 				continue;
@@ -760,9 +758,12 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
 		newResult->nargs = effective_nargs;
 
 		/*
-		 * Wait with apply proargidxs on args. Detection ambigouos needs
-		 * consistent args (based on proargs). Store proargidxs for later
-		 * use.
+		 * Save proargidxs in newResult. It's needed later to adjust
+		 * the argument types to be the types corresponding to the
+		 * named arguments (if any), and also to assign positions to
+		 * any NamedArgExpr arguments after the best candidate is
+		 * determined. The former could be done here, but we leave
+		 * both for the caller to do.
 		 */
 		newResult->proargidxs = proargidxs; 
 		memcpy(newResult->args, procform->proargtypes.values,
@@ -980,8 +981,9 @@ VerifyCandidateNamedNotation(HeapTuple proctup, int pronargs, int nargs, List *a
 	Assert(p_argnames != NULL);
 
 	/* 
-	 * A number less or equal nargs means explicit arguments,
-	*/
+	 * pronargs equal to nargs means explicit arguments (no defaults)
+	 */
+
 	*proargidxs = palloc(nargs * sizeof(int));
 	for (i = 0; i < pronargs; i++)
 		argfilling[i] = false;
@@ -1004,7 +1006,7 @@ VerifyCandidateNamedNotation(HeapTuple proctup, int pronargs, int nargs, List *a
 					continue;
 				if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
 				{
-					/*  protect us against duplicated entries from bad written  mixed notation */
+					/*  protect us against duplicated entries from badly written  mixed notation */
 					if (argfilling[pp])
 						return false;
 
@@ -1035,9 +1037,13 @@ VerifyCandidateNamedNotation(HeapTuple proctup, int pronargs, int nargs, List *a
 		ap++;
 	}
 
+	/*
+	 * This function is only called for named and mixed notation, and
+	 * the last argument must be named in either case.
+	 */
 	Assert(notation == CALL_NOTATION_NAMED);
 
-	/* Check for default arguments ? */
+	/* Check for default arguments */
 	if (nargs < pronargs)
 	{
 		int first_arg_with_default = pronargs - pronargdefaults;
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index c501a5e..0a34e81 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -445,9 +445,10 @@ ProcedureCreate(const char *procedureName,
 		}
 		
 		/*
-		 * if there are named parameters, check names equality. Any change can break
-		 * exiting calls (when named parameters are used). Only IN and INOUT parameters are 
-		 * checked.
+		 * If there are named parameters, check to make sure the names
+		 * have not been changed. Any change can break exiting calls
+		 * when named parameters are used. Only IN and INOUT
+		 * parameters are checked.
 		 */
 		prooldargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup, 
 									Anum_pg_proc_proargnames,
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index ccc6951..3f67607 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -3300,8 +3300,8 @@ simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
 }
 
 /*
- * This function change order of any arg in arglist. When some arguments missing,
- * then it use defaults.
+ * This function changes the order of any arg in arglist. When some
+ * arguments are missing, then it uses the defaults.
  */
 static List *
 reorder_arguments(List *args, Oid result_type, HeapTuple func_tuple,
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a3d2d94..e86ce8a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11332,7 +11332,7 @@ TableFuncTypeName(List *columns)
 
 /*
  * Append function parameter to function's parameter list. Reject 
- * parameters with uniqueless param_name with same proargmode.
+ * parameters with non-unique param_name with same proargmode.
  * It's enough for sql, plperl, plpython language, but not for
  * plpgsql. 
  * 
@@ -11363,7 +11363,7 @@ AppendFuncParameter(List *list, FunctionParameter *p, int location, base_yyscan_
 			if (p2->name != NULL && strcmp(p->name, p2->name) == 0)
 				ereport(ERROR, 
 						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("parameter has not unique name"),
+						 errmsg("parameter has non-unique name"),
 						  parser_errposition(location)));
 		}
 	
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index e1c8a1c..5ea00c6 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -159,8 +159,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 					if (strcmp(n->name, next_name) == 0)
 						ereport(ERROR,
 								(errcode(ERRCODE_SYNTAX_ERROR),
-								 errmsg("named argument has not unique name"),
-								 errhint("Verify your named parameters for ambiguous argument names."),
+								 errmsg("named argument has non-unique name"),
+								 errhint("Check your named parameters for ambiguous argument names."),
 								 parser_errposition(pstate, exprLocation((Node *) lfirst(lc)))));
 				}
 			}
@@ -179,7 +179,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 		}
 	} 
 	
-	/* forgot argnames list of empty strings when positional notation */
+	/* forget argnames list of empty strings when positional notation */
 	if (notation == CALL_NOTATION_POSITIONAL)
 		fargnames = NIL; 
 
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index dab89ba..32620fe 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -326,10 +326,11 @@ typedef struct FuncExpr
 /*
  * NamedArgExpr - an named argument of function
  *
- * It is used, when argument has name. When positional notation is used, then
- * args list doesn't contain any NamedArgExpr. Named notation means, so all
- * arguments in list are NamedArgExpr. Mixed notation means, so first n arguments
- * are Exprs and last m arguments are NamedArgExpr.
+ * Used when argument has name. When positional notation is used, then
+ * args list doesn't contain any NamedArgExpr. When named notation is
+ * used, all arguments in list are NamedArgExpr. When mixed notation
+ * is used, the first n arguments are Exprs and last m arguments are
+ * NamedArgExpr.
  */
 typedef struct NamedArgExpr
 {
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
index cd437ca..dfac452 100644
--- a/src/test/regress/expected/rangefuncs.out
+++ b/src/test/regress/expected/rangefuncs.out
@@ -838,19 +838,19 @@ LINE 1: select * from testfoo();
 drop function testfoo();
 --fail, named parameter are not unique
 create function testfoo(a int, a int) returns int as $$ select 1;$$ language sql;
-ERROR:  parameter has not unique name
+ERROR:  parameter has non-unique name
 LINE 1: create function testfoo(a int, a int) returns int as $$ sele...
                                        ^
 create function testfoo(int, out a int, out a int) returns int as $$ select 1;$$ language sql;
-ERROR:  parameter has not unique name
+ERROR:  parameter has non-unique name
 LINE 1: create function testfoo(int, out a int, out a int) returns i...
                                                 ^
 create function testfoo(out a int, inout a int) returns int as $$ select 1;$$ language sql;
-ERROR:  parameter has not unique name
+ERROR:  parameter has non-unique name
 LINE 1: create function testfoo(out a int, inout a int) returns int ...
                                            ^
 create function testfoo(a int, inout a int) returns int as $$ select 1;$$ language sql; 
-ERROR:  parameter has not unique name
+ERROR:  parameter has non-unique name
 LINE 1: create function testfoo(a int, inout a int) returns int as $...
                                        ^
 -- valid
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to