*** ./doc/src/sgml/xfunc.sgml.orig	2009-03-05 07:37:10.000000000 +0100
--- ./doc/src/sgml/xfunc.sgml	2009-03-05 08:30:48.000000000 +0100
***************
*** 1101,1106 ****
--- 1101,1222 ----
     </para>
    </sect1>
  
+   <sect1 id="xfunc-notation">
+    <title>Positional, Mixed and Named notation</title>
+ 
+    <indexterm zone="xfunc-notation">
+     <primary>notation</primary>
+     <secondary>functions</secondary>
+    </indexterm>
+ 
+    <para>
+     Functions with named parameters should by called with <firstterm>mixed</firstterm> 
+     or <firstterm>named notation</firstterm>. Any typical use expects <firstterm>posiotional 
+     notation</firstterm>, when an order of parameters is important. For named notation 
+     is important name of parameters. You can mix both notation - result is mixed notation.
+     Some first n parameters should be entered in positional parameters
+     and others in named notation. You don't need pass parameters than has
+     default value.
+ <programlisting>
+ CREATE FUNCTION fx(a int, b int, m int = 1, o int = 0) RETURNS int AS $$
+     SELECT ($1 + $2) * $3 + $4
+ $$ LANGUAGE SQL;
+ </programlisting>
+    Function <function>fx</function> has obligatory parameters: <literal>a</literal> and
+    <literal>b</literal> and optional parameters: <literal>m</literal> and <literal>o</literal>.
+    This function should be called with positional parameters. See <xref
+      linkend="xfunc-sql-parameter-defaults"> for a more detailed explanation of calling
+      function with default values.
+    </para>
+    
+    <sect2 id="xfunc-notations-positional">
+     <title>Using positional notation</title>
+ 
+    <indexterm>
+     <primary>function</primary>
+     <secondary>positional notation</secondary>
+    </indexterm>
+ 
+     <para>
+ <screen>
+ SELECT fx(10,20);
+  fx 
+ ----
+  30
+ (1 row)
+   
+ SELECT fx(10,20,2,50);
+   fx  
+ -----
+  110
+ (1 row)
+ </screen>
+     </para>
+   </sect2>
+ 
+   <sect2 id="xfunc-notations-named">
+     <title>Using named notation</title>
+ 
+    <indexterm>
+     <primary>function</primary>
+     <secondary>named notation</secondary>
+    </indexterm>
+ 
+     <para>
+ <screen>
+ SELECT fx(10 as a, 20 as b);
+  fx 
+ ----
+  30
+ (1 row)
+ 
+ SELECT fx(20 as b, 10 as a);
+  fx 
+ ----
+  30
+ (1 row)
+ 
+ SELECT fx(20 as b, 10 as a, 50 as o);
+  fx 
+ ----
+  80
+ (1 row)
+ </screen>
+     </para>
+   </sect2>
+  
+   <sect2 id="xfunc-notations-mixed">
+     <title>Using mixed notation</title>
+ 
+    <indexterm>
+     <primary>function</primary>
+     <secondary>mixed notation</secondary>
+    </indexterm>
+ 
+     <para>
+ <screen>
+ SELECT fx(10,20, 50 as o);
+  fx 
+ ----
+  80
+ (1 row)
+ 
+ SELECT fx(10,20, 10 as m);
+  fx  
+ -----
+  300
+ (1 row)
+ 
+ SELECT fx(10,20, 50 as o, 2 as m);
+  fx  
+ -----
+  110
+ (1 row)
+ </screen>
+     </para>
+    </sect2>
+   </sect1>
+ 
    <sect1 id="xfunc-volatility">
     <title>Function Volatility Categories</title>
  
*** ./src/backend/catalog/namespace.c.orig	2009-03-03 14:48:25.000000000 +0100
--- ./src/backend/catalog/namespace.c	2009-03-04 18:31:20.000000000 +0100
***************
*** 36,41 ****
--- 36,42 ----
  #include "catalog/pg_ts_template.h"
  #include "catalog/pg_type.h"
  #include "commands/dbcommands.h"
+ #include "funcapi.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
  #include "parser/parse_func.h"
***************
*** 603,610 ****
   * The caller might end up discarding such an entry anyway, but if it selects
   * such an entry it should react as though the call were ambiguous.
   */
  FuncCandidateList
! FuncnameGetCandidates(List *names, int nargs,
  					  bool expand_variadic, bool expand_defaults)
  {
  	FuncCandidateList resultList = NULL;
--- 604,723 ----
   * The caller might end up discarding such an entry anyway, but if it selects
   * such an entry it should react as though the call were ambiguous.
   */
+ static bool
+ VerifyCandidateNamedNotation(HeapTuple proctup, int pronargs, int nargs, List *argnames, short int pronargdefaults,
+ 						bool *use_defaults, short int **param_map)
+ {
+ 	Datum		proargnames;
+ 	Oid			*p_argtypes;
+ 	char			**p_argnames;
+ 	char			*p_argmodes;
+ 	bool	isnull;
+ 	int			pronallargs;
+ 	int	i;
+ 	int		pp;			/* proargs position */
+ 	int		ap;			/* args position */
+ 	ListCell	*lc;
+ 	FuncCallNotation		used_notation = POSITIONAL_NOTATION; 		/* used only for asertion */
+ 
+ #define UNDEFINED_PARAMETER		-1
+ 
+ 	Assert(argnames != NIL);
+ 
+ 	/* Ignore if not enough default expressions */
+ 	if (nargs + pronargdefaults < pronargs)
+ 		return false;
+ 
+ 	/* check proargnames */
+ 	proargnames = SysCacheGetAttr(PROCOID, proctup,
+ 							    Anum_pg_proc_proargnames, 
+ 							    &isnull);
+ 	if (isnull)
+ 		return false;
+ 
+ 	pronallargs = get_func_arg_info(proctup, &p_argtypes, &p_argnames, &p_argmodes);
+ 	Assert(p_argnames != NULL);
+ 
+ 	/* 
+ 	 * An number less or equal nargs means some arg,
+ 	 * an number greather than nargs means some default.
+ 	*/
+ 	*param_map = palloc(pronargs * sizeof(short int));
+ 	for (i = 0; i < pronargs; i++)
+ 		(*param_map)[i] = UNDEFINED_PARAMETER;
+ 
+ 	ap = 0;
+ 	foreach(lc, argnames)
+ 	{
+ 		char *argname = (char *) lfirst(lc);
+ 		bool	found;
+ 		
+ 		if (argname != NULL)
+ 		{
+ 			pp = 0;
+ 			found = false;
+ 			for (i = 0; i < pronallargs; i++)
+ 			{
+ 				/* skip all out params */
+ 				if (p_argmodes && (p_argmodes[i] != FUNC_PARAM_IN && p_argmodes[i] != FUNC_PARAM_INOUT))
+ 					continue;
+ 				if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
+ 				{
+ 					/* protect under twice entry same param via positional and named notation */
+ 					if ((*param_map)[pp] != UNDEFINED_PARAMETER)
+ 						ereport(ERROR,
+ 								(errcode(ERRCODE_SYNTAX_ERROR),
+ 								 errmsg("named parameter \"%s\" overlaps %d. positional parameter", argname, i + 1)));
+ 				
+ 					found = true;
+ 					(*param_map)[pp] = ap;		/* named parameter */
+ 					break;
+ 				}
+ 				/* increase only for IN and INOUT args */
+ 				pp++;
+ 			}
+ 			/* any name isn't in proargnames, fast leaving */
+ 			if (!found)
+ 				return false;
+ 
+ 			used_notation = NAMED_NOTATION;
+ 		}
+ 		else
+ 		{
+ 			Assert(used_notation == POSITIONAL_NOTATION);
+ 			
+ 			(*param_map)[ap] = ap;				/* positional parameter */
+ 		}
+ 		ap++;
+ 	}
+ 
+ 	Assert(used_notation == NAMED_NOTATION);
+ 
+ 	/* Have we check defaults? */
+ 	if (nargs < pronargs)
+ 	{
+ 		int first_arg_with_default = pronargs - pronargdefaults;
+ 
+ 		for (i = 0; i < pronargs; i++)
+ 		{
+ 			/* When we still missing param and no default is available, exit */
+ 			if ((*param_map)[i] == UNDEFINED_PARAMETER)
+ 			{
+ 				if (i < first_arg_with_default)
+ 					return false;
+ 				/* offset to defaults + nargs */
+ 				(*param_map)[i] = i - first_arg_with_default + nargs;
+ 			}
+ 		}
+ 		*use_defaults = true;
+ 	}
+ 
+ 	return true;
+ }
+ 
+  
  FuncCandidateList
! FuncnameGetCandidates(List *names, int nargs, List *argnames,
  					  bool expand_variadic, bool expand_defaults)
  {
  	FuncCandidateList resultList = NULL;
***************
*** 645,688 ****
  		int			pronargs = procform->pronargs;
  		int			effective_nargs;
  		int			pathpos = 0;
! 		bool		variadic;
! 		bool		use_defaults;
! 		Oid			va_elem_type;
  		FuncCandidateList newResult;
  
! 		/*
! 		 * Check if function is variadic, and get variadic element type if so.
! 		 * If expand_variadic is false, we should just ignore variadic-ness.
! 		 */
! 		if (pronargs <= nargs && expand_variadic)
  		{
! 			va_elem_type = procform->provariadic;
! 			variadic = OidIsValid(va_elem_type);
! 			any_special |= variadic;
  		}
  		else
  		{
! 			va_elem_type = InvalidOid;
! 			variadic = false;
! 		}
  
! 		/*
! 		 * Check if function can match by using parameter defaults.
! 		 */
! 		if (pronargs > nargs && expand_defaults)
! 		{
! 			/* Ignore if not enough default expressions */
! 			if (nargs + procform->pronargdefaults < pronargs)
  				continue;
- 			use_defaults = true;
- 			any_special = true;
  		}
- 		else
- 			use_defaults = false;
- 
- 		/* Ignore if it doesn't match requested argument count */
- 		if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
- 			continue;
  
  		if (OidIsValid(namespaceId))
  		{
--- 758,811 ----
  		int			pronargs = procform->pronargs;
  		int			effective_nargs;
  		int			pathpos = 0;
! 		bool		variadic = false;
! 		bool		use_defaults = false;
! 		Oid			va_elem_type = InvalidOid;
  		FuncCandidateList newResult;
+ 		short int	*param_map = NULL;
  
! 		if (argnames != NIL)
  		{
! 			if (!VerifyCandidateNamedNotation(proctup, pronargs, nargs, argnames, procform->pronargdefaults,
! 								    &use_defaults, &param_map))
! 				continue;
  		}
  		else
  		{
! 			/*
! 			* Check if function is variadic, and get variadic element type if so.
! 			 * If expand_variadic is false, we should just ignore variadic-ness.
! 			 */
! 			if (pronargs <= nargs && expand_variadic)
! 			{
! 				va_elem_type = procform->provariadic;
! 				variadic = OidIsValid(va_elem_type);
! 				any_special |= variadic;
! 			}
! 			else
! 			{
! 				va_elem_type = InvalidOid;
! 				variadic = false;
! 			}
  
! 			/*
! 			 * Check if function can match by using parameter defaults.
! 			 */
! 			if (pronargs > nargs && expand_defaults)
! 			{
! 				/* Ignore if not enough default expressions */
! 				if (nargs + procform->pronargdefaults < pronargs)
! 					continue;
! 				use_defaults = true;
! 				any_special = true;
! 			}
! 			else
! 				use_defaults = false;
! 
! 			/* Ignore if it doesn't match requested argument count */
! 			if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
  				continue;
  		}
  
  		if (OidIsValid(namespaceId))
  		{
***************
*** 722,727 ****
--- 845,851 ----
  		newResult->pathpos = pathpos;
  		newResult->oid = HeapTupleGetOid(proctup);
  		newResult->nargs = effective_nargs;
+ 		newResult->param_map = param_map;
  		memcpy(newResult->args, procform->proargtypes.values,
  			   pronargs * sizeof(Oid));
  		if (variadic)
***************
*** 735,741 ****
  		}
  		else
  			newResult->nvargs = 0;
! 		newResult->ndargs = use_defaults ? pronargs - nargs : 0;
  
  		/*
  		 * Does it have the same arguments as something we already accepted?
--- 859,872 ----
  		}
  		else
  			newResult->nvargs = 0;
! 		/* When named notation is used, then complete set of defaults is returned */
! 		if (argnames != NIL)
! 		{
! 			Assert(param_map != NULL);
! 			newResult->ndargs = procform->pronargdefaults;
! 		}
! 		else
! 			newResult->ndargs = use_defaults ? pronargs - nargs : 0;
  
  		/*
  		 * Does it have the same arguments as something we already accepted?
***************
*** 932,938 ****
  		visible = false;
  
  		clist = FuncnameGetCandidates(list_make1(makeString(proname)),
! 									  nargs, false, false);
  
  		for (; clist; clist = clist->next)
  		{
--- 1063,1069 ----
  		visible = false;
  
  		clist = FuncnameGetCandidates(list_make1(makeString(proname)),
! 									  nargs, NIL, false, false);
  
  		for (; clist; clist = clist->next)
  		{
***************
*** 953,959 ****
  
  
  /*
!  * OpernameGetOprid
   *		Given a possibly-qualified operator name and exact input datatypes,
   *		look up the operator.  Returns InvalidOid if not found.
   *
--- 1084,1090 ----
  
  
  /*
!  * OpernameGetOpri
   *		Given a possibly-qualified operator name and exact input datatypes,
   *		look up the operator.  Returns InvalidOid if not found.
   *
*** ./src/backend/catalog/pg_aggregate.c.orig	2009-03-03 16:44:18.000000000 +0100
--- ./src/backend/catalog/pg_aggregate.c	2009-03-04 14:15:08.000000000 +0100
***************
*** 321,329 ****
  	 * function's return value.  it also returns the true argument types to
  	 * the function.
  	 */
! 	fdresult = func_get_detail(fnName, NIL, nargs, input_types, false, false,
  							   &fnOid, rettype, &retset, &nvargs,
! 							   &true_oid_array, NULL);
  
  	/* only valid case is a normal function not returning a set */
  	if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
--- 321,329 ----
  	 * function's return value.  it also returns the true argument types to
  	 * the function.
  	 */
! 	fdresult = func_get_detail(fnName, NIL, NIL, nargs, input_types, false, false,
  							   &fnOid, rettype, &retset, &nvargs,
! 							   &true_oid_array, NULL, NULL, NULL);
  
  	/* only valid case is a normal function not returning a set */
  	if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
*** ./src/backend/nodes/copyfuncs.c.orig	2009-03-03 13:11:22.000000000 +0100
--- ./src/backend/nodes/copyfuncs.c	2009-03-04 14:25:54.000000000 +0100
***************
*** 1009,1014 ****
--- 1009,1015 ----
  	COPY_SCALAR_FIELD(funcresulttype);
  	COPY_SCALAR_FIELD(funcretset);
  	COPY_SCALAR_FIELD(funcformat);
+ 	COPY_SCALAR_FIELD(argformat);
  	COPY_NODE_FIELD(args);
  	COPY_LOCATION_FIELD(location);
  
***************
*** 1906,1911 ****
--- 1907,1923 ----
  	return newnode;
  }
  
+ static ArgExpr *
+ _copyArgExpr(ArgExpr *from)
+ {
+ 	ArgExpr *newnode = makeNode(ArgExpr);
+ 	
+ 	COPY_STRING_FIELD(name);
+ 	COPY_NODE_FIELD(expr);
+ 	
+ 	return newnode;
+ }
+ 
  static A_Star *
  _copyAStar(A_Star *from)
  {
***************
*** 4026,4031 ****
--- 4038,4046 ----
  		case T_FuncCall:
  			retval = _copyFuncCall(from);
  			break;
+ 		case T_ArgExpr:
+ 			retval = _copyArgExpr(from);
+ 			break;
  		case T_A_Star:
  			retval = _copyAStar(from);
  			break;
*** ./src/backend/nodes/equalfuncs.c.orig	2009-03-04 14:28:58.000000000 +0100
--- ./src/backend/nodes/equalfuncs.c	2009-03-04 14:31:26.000000000 +0100
***************
*** 235,240 ****
--- 235,241 ----
  		b->funcformat != COERCE_DONTCARE)
  		return false;
  
+ 	COMPARE_SCALAR_FIELD(argformat);
  	COMPARE_NODE_FIELD(args);
  	COMPARE_LOCATION_FIELD(location);
  
*** ./src/backend/nodes/makefuncs.c.orig	2009-03-04 14:26:40.000000000 +0100
--- ./src/backend/nodes/makefuncs.c	2009-03-04 14:27:54.000000000 +0100
***************
*** 342,347 ****
--- 342,348 ----
  	funcexpr->funcresulttype = rettype;
  	funcexpr->funcretset = false;		/* only allowed case here */
  	funcexpr->funcformat = fformat;
+ 	funcexpr->argformat = CONTINUOUS_LIST;
  	funcexpr->args = args;
  	funcexpr->location = -1;
  
*** ./src/backend/nodes/outfuncs.c.orig	2009-03-03 13:11:23.000000000 +0100
--- ./src/backend/nodes/outfuncs.c	2009-03-04 14:31:06.000000000 +0100
***************
*** 866,871 ****
--- 866,872 ----
  	WRITE_OID_FIELD(funcresulttype);
  	WRITE_BOOL_FIELD(funcretset);
  	WRITE_ENUM_FIELD(funcformat, CoercionForm);
+ 	WRITE_ENUM_FIELD(argformat, ArgumentForm);
  	WRITE_NODE_FIELD(args);
  	WRITE_LOCATION_FIELD(location);
  }
***************
*** 1786,1791 ****
--- 1787,1801 ----
  }
  
  static void
+ _outArgExpr(StringInfo str, ArgExpr *node)
+ {
+ 	WRITE_NODE_TYPE("ARGEXPR");
+ 	
+ 	WRITE_STRING_FIELD(name);
+ 	WRITE_NODE_FIELD(expr);
+ }
+ 
+ static void
  _outDefElem(StringInfo str, DefElem *node)
  {
  	WRITE_NODE_TYPE("DEFELEM");
***************
*** 2764,2769 ****
--- 2774,2782 ----
  			case T_FuncCall:
  				_outFuncCall(str, obj);
  				break;
+ 			case T_ArgExpr:
+ 				_outArgExpr(str, obj);
+ 				break;
  			case T_DefElem:
  				_outDefElem(str, obj);
  				break;
*** ./src/backend/nodes/readfuncs.c.orig	2009-03-04 14:29:23.000000000 +0100
--- ./src/backend/nodes/readfuncs.c	2009-03-04 14:32:00.000000000 +0100
***************
*** 518,523 ****
--- 518,524 ----
  	READ_OID_FIELD(funcresulttype);
  	READ_BOOL_FIELD(funcretset);
  	READ_ENUM_FIELD(funcformat, CoercionForm);
+ 	READ_ENUM_FIELD(argformat, ArgumentForm);
  	READ_NODE_FIELD(args);
  	READ_LOCATION_FIELD(location);
  
*** ./src/backend/optimizer/util/clauses.c.orig	2009-03-04 14:21:48.000000000 +0100
--- ./src/backend/optimizer/util/clauses.c	2009-03-04 17:58:19.000000000 +0100
***************
*** 94,103 ****
  					   bool *haveNull, bool *forceFalse);
  static Expr *simplify_boolean_equality(List *args);
  static Expr *simplify_function(Oid funcid,
! 				  Oid result_type, int32 result_typmod, List **args,
  				  bool allow_inline,
  				  eval_const_expressions_context *context);
! static List *add_function_defaults(List *args, Oid result_type,
  								   HeapTuple func_tuple,
  								   eval_const_expressions_context *context);
  static Expr *evaluate_function(Oid funcid,
--- 94,104 ----
  					   bool *haveNull, bool *forceFalse);
  static Expr *simplify_boolean_equality(List *args);
  static Expr *simplify_function(Oid funcid,
! 				  Oid result_type, int32 result_typmod, 
! 				  List **args, bool leaky_list,
  				  bool allow_inline,
  				  eval_const_expressions_context *context);
! static List *add_function_defaults(List *args, bool leaky_list, Oid result_type,
  								   HeapTuple func_tuple,
  								   eval_const_expressions_context *context);
  static Expr *evaluate_function(Oid funcid,
***************
*** 2132,2138 ****
  		 */
  		simple = simplify_function(expr->funcid,
  								   expr->funcresulttype, exprTypmod(node),
! 								   &args,
  								   true, context);
  		if (simple)				/* successfully simplified it */
  			return (Node *) simple;
--- 2133,2139 ----
  		 */
  		simple = simplify_function(expr->funcid,
  								   expr->funcresulttype, exprTypmod(node),
! 								   &args, expr->argformat == LEAKY_LIST,
  								   true, context);
  		if (simple)				/* successfully simplified it */
  			return (Node *) simple;
***************
*** 2147,2152 ****
--- 2148,2154 ----
  		newexpr->funcresulttype = expr->funcresulttype;
  		newexpr->funcretset = expr->funcretset;
  		newexpr->funcformat = expr->funcformat;
+ 		newexpr->argformat = expr->argformat;
  		newexpr->args = args;
  		newexpr->location = expr->location;
  		return (Node *) newexpr;
***************
*** 2179,2185 ****
  		 */
  		simple = simplify_function(expr->opfuncid,
  								   expr->opresulttype, -1,
! 								   &args,
  								   true, context);
  		if (simple)				/* successfully simplified it */
  			return (Node *) simple;
--- 2181,2187 ----
  		 */
  		simple = simplify_function(expr->opfuncid,
  								   expr->opresulttype, -1,
! 								   &args, false,
  								   true, context);
  		if (simple)				/* successfully simplified it */
  			return (Node *) simple;
***************
*** 2270,2276 ****
  			 */
  			simple = simplify_function(expr->opfuncid,
  									   expr->opresulttype, -1,
! 									   &args,
  									   false, context);
  			if (simple)			/* successfully simplified it */
  			{
--- 2272,2278 ----
  			 */
  			simple = simplify_function(expr->opfuncid,
  									   expr->opresulttype, -1,
! 									   &args, false,
  									   false, context);
  			if (simple)			/* successfully simplified it */
  			{
***************
*** 2462,2468 ****
  
  		simple = simplify_function(outfunc,
  								   CSTRINGOID, -1,
! 								   &args,
  								   true, context);
  		if (simple)				/* successfully simplified output fn */
  		{
--- 2464,2470 ----
  
  		simple = simplify_function(outfunc,
  								   CSTRINGOID, -1,
! 								   &args, false,
  								   true, context);
  		if (simple)				/* successfully simplified output fn */
  		{
***************
*** 2480,2486 ****
  
  			simple = simplify_function(infunc,
  									   expr->resulttype, -1,
! 									   &args,
  									   true, context);
  			if (simple)			/* successfully simplified input fn */
  				return (Node *) simple;
--- 2482,2488 ----
  
  			simple = simplify_function(infunc,
  									   expr->resulttype, -1,
! 									   &args, false,
  									   true, context);
  			if (simple)			/* successfully simplified input fn */
  				return (Node *) simple;
***************
*** 3225,3230 ****
--- 3227,3233 ----
  static Expr *
  simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
  				  List **args,
+ 				  bool leaky_list,
  				  bool allow_inline,
  				  eval_const_expressions_context *context)
  {
***************
*** 3246,3253 ****
  		elog(ERROR, "cache lookup failed for function %u", funcid);
  
  	/* While we have the tuple, check if we need to add defaults */
! 	if (((Form_pg_proc) GETSTRUCT(func_tuple))->pronargs > list_length(*args))
! 		*args = add_function_defaults(*args, result_type, func_tuple, context);
  
  	newexpr = evaluate_function(funcid, result_type, result_typmod, *args,
  								func_tuple, context);
--- 3249,3256 ----
  		elog(ERROR, "cache lookup failed for function %u", funcid);
  
  	/* While we have the tuple, check if we need to add defaults */
! 	if (((Form_pg_proc) GETSTRUCT(func_tuple))->pronargs > list_length(*args) || leaky_list)
! 		*args = add_function_defaults(*args, leaky_list, result_type, func_tuple, context);
  
  	newexpr = evaluate_function(funcid, result_type, result_typmod, *args,
  								func_tuple, context);
***************
*** 3270,3276 ****
   * just like the parser did.
   */
  static List *
! add_function_defaults(List *args, Oid result_type, HeapTuple func_tuple,
  					  eval_const_expressions_context *context)
  {
  	Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
--- 3273,3279 ----
   * just like the parser did.
   */
  static List *
! add_function_defaults(List *args, bool leaky_list, Oid result_type, HeapTuple func_tuple,
  					  eval_const_expressions_context *context)
  {
  	Form_pg_proc funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
***************
*** 3296,3309 ****
  	defaults = (List *) stringToNode(str);
  	Assert(IsA(defaults, List));
  	pfree(str);
! 	/* Delete any unused defaults from the list */
! 	ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
! 	if (ndelete < 0)
! 		elog(ERROR, "not enough default arguments");
! 	while (ndelete-- > 0)
! 		defaults = list_delete_first(defaults);
! 	/* And form the combined argument list */
! 	args = list_concat(args, defaults);
  	Assert(list_length(args) == funcform->pronargs);
  
  	/*
--- 3299,3339 ----
  	defaults = (List *) stringToNode(str);
  	Assert(IsA(defaults, List));
  	pfree(str);
! 	
! 	if (leaky_list)
! 	{
! 		List	*cargs = NIL;			/* continuous argument list */
! 		ListCell	*lc;
! 		int		i = 0;
! 		bool		first_default = funcform->pronargs - funcform->pronargdefaults;
! 		
! 		/* Replace gaps with elements from defaults */
! 		foreach(lc, args)
! 		{
! 			Node *arg = (Node *) lfirst(lc);
! 			
! 			if (arg == NULL)
! 			{
! 				Assert(i >= first_default);
! 				cargs = lappend(cargs, list_nth(defaults, i - first_default));
! 			}
! 			else
! 				cargs = lappend(cargs, arg);
! 			i++;
! 		}
! 		args = cargs;
! 	}
! 	else
! 	{
! 		/* Delete any unused defaults from the list */
! 		ndelete = nargsprovided + list_length(defaults) - funcform->pronargs;
! 		if (ndelete < 0)
! 			elog(ERROR, "not enough default arguments");
! 		while (ndelete-- > 0)
! 			defaults = list_delete_first(defaults);
! 		/* And form the combined argument list */
! 		args = list_concat(args, defaults);
! 	}
  	Assert(list_length(args) == funcform->pronargs);
  
  	/*
***************
*** 3442,3447 ****
--- 3472,3478 ----
  	newexpr->funcresulttype = result_type;
  	newexpr->funcretset = false;
  	newexpr->funcformat = COERCE_DONTCARE;		/* doesn't matter */
+ 	newexpr->funcformat = CONTINUOUS_LIST;
  	newexpr->args = args;
  	newexpr->location = -1;
  
*** ./src/backend/parser/gram.y.orig	2009-02-24 11:06:33.000000000 +0100
--- ./src/backend/parser/gram.y	2009-03-03 13:08:21.000000000 +0100
***************
*** 420,425 ****
--- 420,428 ----
  %type <str>		opt_existing_window_name
  %type <ival>	opt_frame_clause frame_extent frame_bound
  
+ %type <list>	arg_expr_list
+ %type <node>	arg_expr
+ 
  
  /*
   * If you make any token changes, update the keyword table in
***************
*** 8776,8782 ****
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
--- 8779,8785 ----
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' arg_expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
***************
*** 8800,8806 ****
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' expr_list ',' VARIADIC a_expr ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
--- 8803,8809 ----
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' arg_expr_list ',' VARIADIC a_expr ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
***************
*** 8812,8818 ****
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' ALL expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
--- 8815,8821 ----
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' ALL arg_expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
***************
*** 8828,8834 ****
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' DISTINCT expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
--- 8831,8837 ----
  					n->location = @1;
  					$$ = (Node *)n;
  				}
! 			| func_name '(' DISTINCT arg_expr_list ')' over_clause
  				{
  					FuncCall *n = makeNode(FuncCall);
  					n->funcname = $1;
***************
*** 9550,9555 ****
--- 9553,9583 ----
  					$$ = lappend($1, $3);
  				}
  		;
+ 		
+ /*  Used for support of named notation.
+  */
+ arg_expr_list: arg_expr
+ 				{
+ 					$$ = list_make1($1);
+ 				}
+ 			| arg_expr_list ',' arg_expr
+ 				{
+ 					$$ = lappend($1, $3);
+ 				}
+ 		;
+ 		
+ arg_expr:	a_expr
+ 				{
+ 					$$ = $1;
+ 				}
+ 			| a_expr AS param_name
+ 				{
+ 					ArgExpr *ae = makeNode(ArgExpr); 
+ 					ae->expr = $1;
+ 					ae->name = $3;
+ 					$$ = (Node *) ae;
+ 				}
+ 		; 
  
  type_list:	Typename								{ $$ = list_make1($1); }
  			| type_list ',' Typename				{ $$ = lappend($1, $3); }
***************
*** 9950,9956 ****
  		;
  
  
! name:		ColId									{ $$ = $1; };
  
  database_name:
  			ColId									{ $$ = $1; };
--- 9978,9984 ----
  		;
  
  
! name:		ColId								{ $$ = $1; };
  
  database_name:
  			ColId									{ $$ = $1; };
***************
*** 9980,9986 ****
  
  
  /*
!  * Constants
   */
  AexprConst: Iconst
  				{
--- 10008,10014 ----
  
  
  /*
!  * Constants ToDo - PStehule
   */
  AexprConst: Iconst
  				{
***************
*** 10014,10023 ****
  					t->location = @1;
  					$$ = makeStringConstCast($2, @2, t);
  				}
! 			| func_name '(' expr_list ')' Sconst
  				{
  					/* generic syntax with a type modifier */
  					TypeName *t = makeTypeNameFromNameList($1);
  					t->typmods = $3;
  					t->location = @1;
  					$$ = makeStringConstCast($5, @5, t);
--- 10042,10059 ----
  					t->location = @1;
  					$$ = makeStringConstCast($2, @2, t);
  				}
! 			| func_name '(' arg_expr_list ')' Sconst
  				{
  					/* generic syntax with a type modifier */
  					TypeName *t = makeTypeNameFromNameList($1);
+ 					ListCell *lc;
+ 					
+ 					/* Don't allow ArgExpr in this context */
+ 					foreach(lc, $3)
+ 					{
+ 						if (IsA((Node *) lfirst(lc),ArgExpr))
+ 							elog(ERROR, "don't use named parameters in this context");
+ 					}
  					t->typmods = $3;
  					t->location = @1;
  					$$ = makeStringConstCast($5, @5, t);
*** ./src/backend/parser/parse_expr.c.orig	2009-03-03 12:56:38.000000000 +0100
--- ./src/backend/parser/parse_expr.c	2009-03-03 14:18:12.000000000 +0100
***************
*** 362,368 ****
  									   list_make1(n),
  									   list_make1(result),
  									   false, false, false,
! 									   NULL, true, -1);
  		}
  	}
  	/* process trailing subscripts, if any */
--- 362,368 ----
  									   list_make1(n),
  									   list_make1(result),
  									   false, false, false,
! 									   NULL, true, NIL, -1);
  		}
  	}
  	/* process trailing subscripts, if any */
***************
*** 506,512 ****
  											 list_make1(makeString(name2)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, cref->location);
  				}
  				break;
  			}
--- 506,512 ----
  											 list_make1(makeString(name2)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, NIL, cref->location);
  				}
  				break;
  			}
***************
*** 547,553 ****
  											 list_make1(makeString(name3)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, cref->location);
  				}
  				break;
  			}
--- 547,553 ----
  											 list_make1(makeString(name3)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, NIL, cref->location);
  				}
  				break;
  			}
***************
*** 602,608 ****
  											 list_make1(makeString(name4)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, cref->location);
  				}
  				break;
  			}
--- 602,608 ----
  											 list_make1(makeString(name4)),
  											 list_make1(node),
  											 false, false, false,
! 											 NULL, true, NIL, cref->location);
  				}
  				break;
  			}
***************
*** 1091,1107 ****
  static Node *
  transformFuncCall(ParseState *pstate, FuncCall *fn)
  {
! 	List	   *targs;
  	ListCell   *args;
  
  	/* Transform the list of arguments ... */
- 	targs = NIL;
  	foreach(args, fn->args)
  	{
! 		targs = lappend(targs, transformExpr(pstate,
! 											 (Node *) lfirst(args)));
  	}
  
  	/* ... and hand off to ParseFuncOrColumn */
  	return ParseFuncOrColumn(pstate,
  							 fn->funcname,
--- 1091,1158 ----
  static Node *
  transformFuncCall(ParseState *pstate, FuncCall *fn)
  {
! 	List	   *targs = NIL;
  	ListCell   *args;
+ 	List		*argnames = NIL;
+ 	bool		argnames_used = false;
+ 	FuncCallNotation	notation = POSITIONAL_NOTATION;
  
  	/* Transform the list of arguments ... */
  	foreach(args, fn->args)
  	{
! 		char	*name = NULL;
! 		Node	*targ = NULL;
! 		Node		*arg = lfirst(args);
! 		
! 		if (IsA(arg, ArgExpr))
! 		{
! 			ArgExpr    *argexpr = (ArgExpr *) arg;
! 			ListCell	*lc;
! 			
! 			Assert(argexpr->name != NULL);
! 			
! 			argnames_used = true;
! 			notation = NAMED_NOTATION;
! 			
! 			name = argexpr->name;
! 			targ = transformExpr(pstate, argexpr->expr);
! 
! 			/* Check duplicates */
! 			for_each_cell(lc, lnext(args))
! 			{
! 				if (IsA(lfirst(lc), ArgExpr))
! 				{
! 					char *next_name = ((ArgExpr *) lfirst(lc))->name;
! 				
! 					Assert(next_name != NULL);
! 					if (strcmp(name, next_name) == 0)
! 						ereport(ERROR,
! 							(errcode(ERRCODE_SYNTAX_ERROR),
! 							 errmsg("function parameter \"%s\" is used more then once", name),
! 							 errhint("Check used names of next parameters."),
! 							 parser_errposition(pstate, exprLocation(targ))));
! 				}
! 			}
! 		}
! 		else
! 		{
! 			targ = transformExpr(pstate, arg);
! 			if (notation != POSITIONAL_NOTATION)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_SYNTAX_ERROR),
! 						 errmsg("expected named expression"),
! 						 errhint("You can't put positionals arguments behind the named arguments."),
! 						 parser_errposition(pstate, exprLocation(targ))));
! 		}
! 		
! 		targs = lappend(targs, targ);
! 		argnames = lappend(argnames, name);
  	}
  
+ 	/* forgot list of NULLs */
+ 	if (!argnames_used)
+ 		argnames = NIL;
+ 
  	/* ... and hand off to ParseFuncOrColumn */
  	return ParseFuncOrColumn(pstate,
  							 fn->funcname,
***************
*** 1111,1116 ****
--- 1162,1168 ----
  							 fn->func_variadic,
  							 fn->over,
  							 false,
+ 							 argnames,
  							 fn->location);
  }
  
***************
*** 1167,1173 ****
  		Node	   *warg;
  
  		Assert(IsA(w, CaseWhen));
- 
  		warg = (Node *) w->expr;
  		if (placeholder)
  		{
--- 1219,1224 ----
*** ./src/backend/parser/parse_func.c.orig	2009-03-03 12:56:45.000000000 +0100
--- ./src/backend/parser/parse_func.c	2009-03-04 15:46:52.000000000 +0100
***************
*** 63,69 ****
  Node *
  ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
  				  bool agg_star, bool agg_distinct, bool func_variadic,
! 				  WindowDef *over, bool is_column, int location)
  {
  	Oid			rettype;
  	Oid			funcid;
--- 63,69 ----
  Node *
  ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
  				  bool agg_star, bool agg_distinct, bool func_variadic,
! 				  WindowDef *over, bool is_column, List *argnames, int location)
  {
  	Oid			rettype;
  	Oid			funcid;
***************
*** 79,84 ****
--- 79,87 ----
  	bool		retset;
  	int			nvargs;
  	FuncDetailCode fdresult;
+ 	short int	*param_map;
+ 	int		pronargs;
+ 	ArgumentForm	argformat = CONTINUOUS_LIST;
  
  	/*
  	 * Most of the rest of the parser just assumes that functions do not have
***************
*** 132,138 ****
  	 * wasn't any aggregate or variadic decoration.
  	 */
  	if (nargs == 1 && !agg_star && !agg_distinct && over == NULL &&
! 		!func_variadic && list_length(funcname) == 1)
  	{
  		Oid			argtype = actual_arg_types[0];
  
--- 135,141 ----
  	 * wasn't any aggregate or variadic decoration.
  	 */
  	if (nargs == 1 && !agg_star && !agg_distinct && over == NULL &&
! 		!func_variadic && list_length(funcname) == 1 && argnames == NIL)
  	{
  		Oid			argtype = actual_arg_types[0];
  
***************
*** 163,172 ****
  	 * replaced by a suitable number of copies of its element type.  We'll fix
  	 * it up below.  We may also have to deal with default arguments.
  	 */
! 	fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
  							   !func_variadic, true,
  							   &funcid, &rettype, &retset, &nvargs,
! 							   &declared_arg_types, &argdefaults);
  	if (fdresult == FUNCDETAIL_COERCION)
  	{
  		/*
--- 166,175 ----
  	 * replaced by a suitable number of copies of its element type.  We'll fix
  	 * it up below.  We may also have to deal with default arguments.
  	 */
! 	fdresult = func_get_detail(funcname, fargs, argnames, nargs, actual_arg_types,
  							   !func_variadic, true,
  							   &funcid, &rettype, &retset, &nvargs,
! 							   &declared_arg_types, &argdefaults, &param_map, &pronargs);
  	if (fdresult == FUNCDETAIL_COERCION)
  	{
  		/*
***************
*** 243,248 ****
--- 246,281 ----
  					 parser_errposition(pstate, location)));
  	}
  
+ 	
+ 	if (param_map != NULL)
+ 	{
+ 		List	*rfargs = NIL;			/* reordered list of function arguments */
+ 		int		i;
+ 	
+ 		for (i = 0; i < pronargs; i++)
+ 		{
+ 			Node	*expr = NULL;
+ 			
+ 			if (param_map[i] < nargs)
+ 			{
+ 				expr = (Node *) list_nth(fargs, param_map[i]);
+ 				rfargs = lappend(rfargs, expr);
+ 				/* when any arg goes out of narg */
+ 				if (i >= nargs)
+ 					argformat = LEAKY_LIST;
+ 			}
+ 			else
+ 			{
+ 				expr = (Node *) list_nth(argdefaults, param_map[i] - nargs);
+ 				rfargs = lappend(rfargs, NULL);
+ 			}
+ 			actual_arg_types[i] = exprType(expr);
+ 		}
+ 		
+ 		fargs = (argformat == LEAKY_LIST) ? rfargs : list_truncate(rfargs, nargs);
+ 		nargsplusdefs = pronargs;
+ 	}
+ 	else
  	/*
  	 * If there are default arguments, we have to include their types in
  	 * actual_arg_types for the purpose of checking generic type consistency.
***************
*** 250,269 ****
  	 * their actual values might change before the query gets run.  The
  	 * planner has to insert the up-to-date values at plan time.
  	 */
- 	nargsplusdefs = nargs;
- 	foreach(l, argdefaults)
  	{
! 		Node	*expr = (Node *) lfirst(l);
  
! 		/* probably shouldn't happen ... */
! 		if (nargsplusdefs >= FUNC_MAX_ARGS)
! 			ereport(ERROR,
! 					(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
! 					 errmsg("cannot pass more than %d arguments to a function",
! 							FUNC_MAX_ARGS),
! 					 parser_errposition(pstate, location)));
  
! 		actual_arg_types[nargsplusdefs++] = exprType(expr);
  	}
  
  	/*
--- 283,304 ----
  	 * their actual values might change before the query gets run.  The
  	 * planner has to insert the up-to-date values at plan time.
  	 */
  	{
! 		nargsplusdefs = nargs;
! 		foreach(l, argdefaults)
! 		{
! 			Node	*expr = (Node *) lfirst(l);
  
! 			/* probably shouldn't happen ... */
! 			if (nargsplusdefs >= FUNC_MAX_ARGS)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
! 						 errmsg("cannot pass more than %d arguments to a function",
! 								FUNC_MAX_ARGS),
! 						 parser_errposition(pstate, location)));
  
! 			actual_arg_types[nargsplusdefs++] = exprType(expr);
! 		}
  	}
  
  	/*
***************
*** 319,324 ****
--- 354,360 ----
  		funcexpr->funcresulttype = rettype;
  		funcexpr->funcretset = retset;
  		funcexpr->funcformat = COERCE_EXPLICIT_CALL;
+ 		funcexpr->argformat = argformat;
  		funcexpr->args = fargs;
  		funcexpr->location = location;
  
***************
*** 807,812 ****
--- 843,849 ----
  FuncDetailCode
  func_get_detail(List *funcname,
  				List *fargs,
+ 				List *argnames,
  				int nargs,
  				Oid *argtypes,
  				bool expand_variadic,
***************
*** 816,828 ****
  				bool *retset,	/* return value */
  				int *nvargs,	/* return value */
  				Oid **true_typeids,		/* return value */
! 				List **argdefaults)		/* optional return value */
  {
  	FuncCandidateList raw_candidates;
  	FuncCandidateList best_candidate;
  
  	/* Get list of possible candidates from namespace search */
! 	raw_candidates = FuncnameGetCandidates(funcname, nargs,
  										   expand_variadic, expand_defaults);
  
  	/*
--- 853,867 ----
  				bool *retset,	/* return value */
  				int *nvargs,	/* return value */
  				Oid **true_typeids,		/* return value */
! 				List **argdefaults,		/* optional return value */
! 				short int **param_map,		/* optional return value */
! 				int *pronargs)			/* optional return value */
  {
  	FuncCandidateList raw_candidates;
  	FuncCandidateList best_candidate;
  
  	/* Get list of possible candidates from namespace search */
! 	raw_candidates = FuncnameGetCandidates(funcname, nargs, argnames,
  										   expand_variadic, expand_defaults);
  
  	/*
***************
*** 976,981 ****
--- 1015,1028 ----
  		pform = (Form_pg_proc) GETSTRUCT(ftup);
  		*rettype = pform->prorettype;
  		*retset = pform->proretset;
+ 		
+ 		if (param_map)
+ 		{
+ 			Assert(pronargs != NULL);
+ 			*pronargs = best_candidate->nargs;
+ 			*param_map = best_candidate->param_map;
+ 		}
+ 		
  		/* fetch default args if caller wants 'em */
  		if (argdefaults)
  		{
***************
*** 1141,1146 ****
--- 1188,1195 ----
  		/* types don't match? then force coercion using a function call... */
  		if (actual_arg_types[i] != declared_arg_types[i])
  		{
+ 			Assert(lfirst(current_fargs) != NULL);
+ 			
  			lfirst(current_fargs) = coerce_type(pstate,
  												lfirst(current_fargs),
  												actual_arg_types[i],
***************
*** 1357,1363 ****
  {
  	FuncCandidateList clist;
  
! 	clist = FuncnameGetCandidates(funcname, nargs, false, false);
  
  	while (clist)
  	{
--- 1406,1412 ----
  {
  	FuncCandidateList clist;
  
! 	clist = FuncnameGetCandidates(funcname, nargs, NIL, false, false);
  
  	while (clist)
  	{
*** ./src/backend/utils/adt/regproc.c.orig	2009-03-03 14:56:09.000000000 +0100
--- ./src/backend/utils/adt/regproc.c	2009-03-03 14:57:02.000000000 +0100
***************
*** 131,137 ****
  	 * pg_proc entries in the current search path.
  	 */
  	names = stringToQualifiedNameList(pro_name_or_oid);
! 	clist = FuncnameGetCandidates(names, -1, false, false);
  
  	if (clist == NULL)
  		ereport(ERROR,
--- 131,137 ----
  	 * pg_proc entries in the current search path.
  	 */
  	names = stringToQualifiedNameList(pro_name_or_oid);
! 	clist = FuncnameGetCandidates(names, -1, NIL, false, false);
  
  	if (clist == NULL)
  		ereport(ERROR,
***************
*** 190,196 ****
  			 * qualify it.
  			 */
  			clist = FuncnameGetCandidates(list_make1(makeString(proname)),
! 										  -1, false, false);
  			if (clist != NULL && clist->next == NULL &&
  				clist->oid == proid)
  				nspname = NULL;
--- 190,196 ----
  			 * qualify it.
  			 */
  			clist = FuncnameGetCandidates(list_make1(makeString(proname)),
! 										  -1, NIL, false, false);
  			if (clist != NULL && clist->next == NULL &&
  				clist->oid == proid)
  				nspname = NULL;
***************
*** 277,283 ****
  	 */
  	parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes);
  
! 	clist = FuncnameGetCandidates(names, nargs, false, false);
  
  	for (; clist; clist = clist->next)
  	{
--- 277,283 ----
  	 */
  	parseNameAndArgTypes(pro_name_or_oid, false, &names, &nargs, argtypes);
  
! 	clist = FuncnameGetCandidates(names, nargs, NIL, false, false);
  
  	for (; clist; clist = clist->next)
  	{
*** ./src/backend/utils/adt/ruleutils.c.orig	2009-03-03 14:56:02.000000000 +0100
--- ./src/backend/utils/adt/ruleutils.c	2009-03-04 14:17:33.000000000 +0100
***************
*** 6322,6330 ****
  	 * specified argtypes.
  	 */
  	p_result = func_get_detail(list_make1(makeString(proname)),
! 							   NIL, nargs, argtypes, false, true,
  							   &p_funcid, &p_rettype,
! 							   &p_retset, &p_nvargs, &p_true_typeids, NULL);
  	if ((p_result == FUNCDETAIL_NORMAL ||
  		 p_result == FUNCDETAIL_AGGREGATE ||
  		 p_result == FUNCDETAIL_WINDOWFUNC) &&
--- 6322,6330 ----
  	 * specified argtypes.
  	 */
  	p_result = func_get_detail(list_make1(makeString(proname)),
! 							   NIL, NIL, nargs, argtypes, false, true,
  							   &p_funcid, &p_rettype,
! 							   &p_retset, &p_nvargs, &p_true_typeids, NULL, NULL, NULL);
  	if ((p_result == FUNCDETAIL_NORMAL ||
  		 p_result == FUNCDETAIL_AGGREGATE ||
  		 p_result == FUNCDETAIL_WINDOWFUNC) &&
*** ./src/include/catalog/namespace.h.orig	2009-03-03 14:49:23.000000000 +0100
--- ./src/include/catalog/namespace.h	2009-03-04 09:14:42.000000000 +0100
***************
*** 32,37 ****
--- 32,38 ----
  	int			nargs;			/* number of arg types returned */
  	int			nvargs;			/* number of args to become variadic array */
  	int			ndargs;			/* number of defaulted args */
+ 	short int		*param_map;		/* maps external arguments to function arguments */
  	Oid			args[1];		/* arg types --- VARIABLE LENGTH ARRAY */
  }	*FuncCandidateList;	/* VARIABLE LENGTH STRUCT */
  
***************
*** 54,60 ****
  extern Oid	TypenameGetTypid(const char *typname);
  extern bool TypeIsVisible(Oid typid);
  
! extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs,
  											   bool expand_variadic,
  											   bool expand_defaults);
  extern bool FunctionIsVisible(Oid funcid);
--- 55,61 ----
  extern Oid	TypenameGetTypid(const char *typname);
  extern bool TypeIsVisible(Oid typid);
  
! extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs, List *argnames,
  											   bool expand_variadic,
  											   bool expand_defaults);
  extern bool FunctionIsVisible(Oid funcid);
*** ./src/include/nodes/nodes.h.orig	2009-02-25 04:30:37.000000000 +0100
--- ./src/include/nodes/nodes.h	2009-03-03 13:13:42.000000000 +0100
***************
*** 378,383 ****
--- 378,384 ----
  	T_XmlSerialize,
  	T_WithClause,
  	T_CommonTableExpr,
+ 	T_ArgExpr,
  
  	/*
  	 * TAGS FOR RANDOM OTHER STUFF
*** ./src/include/nodes/parsenodes.h.orig	2009-03-03 13:13:22.000000000 +0100
--- ./src/include/nodes/parsenodes.h	2009-03-03 14:15:03.000000000 +0100
***************
*** 289,294 ****
--- 289,312 ----
  } FuncCall;
  
  /*
+  * ArgExpr - an argument of function
+  */
+ typedef struct ArgExpr
+ {
+ 	NodeTag		type;
+ 	char	   *name;		/* an name of argument (when is specified) */
+ 	Node	   *expr;		/* the argument */
+ } ArgExpr;
+ 
+ 
+ /* notation used for Func call params */
+ typedef enum FuncCallNotation
+ {
+ 	POSITIONAL_NOTATION,
+ 	NAMED_NOTATION
+ } FuncCallNotation;
+ 
+ /*
   * A_Star - '*' representing all columns of a table or compound field
   *
   * This can appear within ColumnRef.fields, A_Indirection.indirection, and
*** ./src/include/nodes/primnodes.h.orig	2009-03-04 14:12:16.000000000 +0100
--- ./src/include/nodes/primnodes.h	2009-03-04 14:13:43.000000000 +0100
***************
*** 299,304 ****
--- 299,310 ----
  	COERCE_DONTCARE				/* special case for planner */
  } CoercionForm;
  
+ typedef enum ArgumentForm
+ {
+ 	CONTINUOUS_LIST,		/* used for positional notation */
+ 	LEAKY_LIST			/* used for named and mixed notation */
+ } ArgumentForm;
+ 
  /*
   * FuncExpr - expression node for a function call
   */
***************
*** 309,314 ****
--- 315,321 ----
  	Oid			funcresulttype; /* PG_TYPE OID of result value */
  	bool		funcretset;		/* true if function returns set */
  	CoercionForm funcformat;	/* how to display this function call */
+ 	ArgumentForm argformat;		/* what is format of argument list */
  	List	   *args;			/* arguments to the function */
  	int			location;		/* token location, or -1 if unknown */
  } FuncExpr;
*** ./src/include/parser/parse_func.h.orig	2009-03-03 14:16:15.000000000 +0100
--- ./src/include/parser/parse_func.h	2009-03-04 11:52:54.000000000 +0100
***************
*** 45,58 ****
  extern Node *ParseFuncOrColumn(ParseState *pstate,
  				  List *funcname, List *fargs,
  				  bool agg_star, bool agg_distinct, bool func_variadic,
! 				  WindowDef *over, bool is_column, int location);
  
! extern FuncDetailCode func_get_detail(List *funcname, List *fargs,
! 				int nargs, Oid *argtypes,
  				bool expand_variadic, bool expand_defaults,
  				Oid *funcid, Oid *rettype,
  				bool *retset, int *nvargs, Oid **true_typeids,
! 				List **argdefaults);
  
  extern int func_match_argtypes(int nargs,
  					Oid *input_typeids,
--- 45,58 ----
  extern Node *ParseFuncOrColumn(ParseState *pstate,
  				  List *funcname, List *fargs,
  				  bool agg_star, bool agg_distinct, bool func_variadic,
! 				  WindowDef *over, bool is_column, List *argnames, int location);
  
! extern FuncDetailCode func_get_detail(List *funcname, List *fargs, List *argnames,
! 				int nargs, Oid *argtypes, 
  				bool expand_variadic, bool expand_defaults,
  				Oid *funcid, Oid *rettype,
  				bool *retset, int *nvargs, Oid **true_typeids,
! 				List **argdefaults, short int **param_map, int *pronargs);
  
  extern int func_match_argtypes(int nargs,
  					Oid *input_typeids,
*** ./src/test/regress/expected/polymorphism.out.orig	2009-03-04 18:57:59.000000000 +0100
--- ./src/test/regress/expected/polymorphism.out	2009-03-04 18:57:14.000000000 +0100
***************
*** 1038,1040 ****
--- 1038,1104 ----
  drop function dfunc(int, int, int);
  drop function dfunc(int, int);
  drop function dfunc(text);
+ -- test function with named params and using named or mixed notation
+ -- fail, unnamed param behind named
+ create function dfunc(a int, b int = 1, c int) returns table (a int, b int, c int) as $$
+   select $1, $2, $3;
+ $$ language sql;
+ ERROR:  input parameters after one with a default value must also have defaults
+ create function dfunc(a int, b int, c int=0, d int = 0) returns table (a int, b int, c int, d int) as $$
+   select $1, $2, $3, $4;
+ $$ language sql;
+ select (dfunc(10,20,30)).*;
+  a  | b  | c  | d 
+ ----+----+----+---
+  10 | 20 | 30 | 0
+ (1 row)
+ 
+ select (dfunc(10 as a, 20 as b, 30 as c)).*;
+  a  | b  | c  | d 
+ ----+----+----+---
+  10 | 20 | 30 | 0
+ (1 row)
+ 
+ select * from dfunc(10 as a, 20 as b);
+  a  | b  | c | d 
+ ----+----+---+---
+  10 | 20 | 0 | 0
+ (1 row)
+ 
+ select * from dfunc(10 as b, 20 as a);
+  a  | b  | c | d 
+ ----+----+---+---
+  20 | 10 | 0 | 0
+ (1 row)
+ 
+ select * from dfunc(0,0);
+  a | b | c | d 
+ ---+---+---+---
+  0 | 0 | 0 | 0
+ (1 row)
+ 
+ select * from dfunc(0,0,10 as c);
+  a | b | c  | d 
+ ---+---+----+---
+  0 | 0 | 10 | 0
+ (1 row)
+ 
+ select * from dfunc(0,0,10 as d);
+  a | b | c | d  
+ ---+---+---+----
+  0 | 0 | 0 | 10
+ (1 row)
+ 
+ select * from dfunc(10 as x, 20 as b, 30 as c); --fail - unknown param
+ ERROR:  function dfunc(integer, integer, integer) does not exist
+ LINE 1: select * from dfunc(10 as x, 20 as b, 30 as c);
+                       ^
+ HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
+ select * from dfunc(10, 20 as b, 30); -- fail using positional notation begind named notation
+ ERROR:  expected named expression
+ LINE 1: select * from dfunc(10, 20 as b, 30);
+                                          ^
+ HINT:  You can't put positionals arguments behind the named arguments.
+ select * from dfunc(10,10,20 as a); --fail - a overlaps first positional parameter
+ ERROR:  named parameter "a" overlaps 1. positional parameter
+ drop function dfunc(int, int, int, int);
*** ./src/test/regress/sql/polymorphism.sql.orig	2009-03-04 18:48:30.000000000 +0100
--- ./src/test/regress/sql/polymorphism.sql	2009-03-04 18:56:35.000000000 +0100
***************
*** 624,626 ****
--- 624,650 ----
  drop function dfunc(int, int, int);
  drop function dfunc(int, int);
  drop function dfunc(text);
+ 
+ -- test function with named params and using named or mixed notation
+ -- fail, unnamed param behind named
+ create function dfunc(a int, b int = 1, c int) returns table (a int, b int, c int) as $$
+   select $1, $2, $3;
+ $$ language sql;
+ 
+ create function dfunc(a int, b int, c int=0, d int = 0) returns table (a int, b int, c int, d int) as $$
+   select $1, $2, $3, $4;
+ $$ language sql;
+ 
+ select (dfunc(10,20,30)).*;
+ select (dfunc(10 as a, 20 as b, 30 as c)).*;
+ select * from dfunc(10 as a, 20 as b);
+ select * from dfunc(10 as b, 20 as a);
+ select * from dfunc(0,0);
+ select * from dfunc(0,0,10 as c);
+ select * from dfunc(0,0,10 as d);
+ 
+ select * from dfunc(10 as x, 20 as b, 30 as c); --fail - unknown param
+ select * from dfunc(10, 20 as b, 30); -- fail using positional notation begind named notation
+ select * from dfunc(10,10,20 as a); --fail - a overlaps first positional parameter
+ 
+ drop function dfunc(int, int, int, int);
