mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +03:00
Default values for function arguments
Pavel Stehule, with some tweaks by Peter Eisentraut
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.642 2008/12/04 11:42:24 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.643 2008/12/04 17:51:26 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -255,6 +255,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
||||
%type <list> stmtblock stmtmulti
|
||||
OptTableElementList TableElementList OptInherit definition
|
||||
OptWith opt_distinct opt_definition func_args func_args_list
|
||||
func_args_with_defaults func_args_with_defaults_list
|
||||
func_as createfunc_opt_list alterfunc_opt_list
|
||||
aggr_args old_aggr_definition old_aggr_list
|
||||
oper_argtypes RuleActionList RuleActionMulti
|
||||
@@ -278,7 +279,7 @@ static TypeName *TableFuncTypeName(List *columns);
|
||||
%type <into> into_clause create_as_target
|
||||
|
||||
%type <defelt> createfunc_opt_item common_func_opt_item
|
||||
%type <fun_param> func_arg table_func_column
|
||||
%type <fun_param> func_arg func_arg_with_default table_func_column
|
||||
%type <fun_param_mode> arg_class
|
||||
%type <typnam> func_return func_type
|
||||
|
||||
@@ -4170,7 +4171,7 @@ opt_nulls_order: NULLS_FIRST { $$ = SORTBY_NULLS_FIRST; }
|
||||
*****************************************************************************/
|
||||
|
||||
CreateFunctionStmt:
|
||||
CREATE opt_or_replace FUNCTION func_name func_args
|
||||
CREATE opt_or_replace FUNCTION func_name func_args_with_defaults
|
||||
RETURNS func_return createfunc_opt_list opt_definition
|
||||
{
|
||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||
@@ -4182,7 +4183,7 @@ CreateFunctionStmt:
|
||||
n->withClause = $9;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| CREATE opt_or_replace FUNCTION func_name func_args
|
||||
| CREATE opt_or_replace FUNCTION func_name func_args_with_defaults
|
||||
RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition
|
||||
{
|
||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||
@@ -4195,7 +4196,7 @@ CreateFunctionStmt:
|
||||
n->withClause = $12;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| CREATE opt_or_replace FUNCTION func_name func_args
|
||||
| CREATE opt_or_replace FUNCTION func_name func_args_with_defaults
|
||||
createfunc_opt_list opt_definition
|
||||
{
|
||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||
@@ -4223,6 +4224,21 @@ func_args_list:
|
||||
| func_args_list ',' func_arg { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
/*
|
||||
* func_args_with_defaults is separate because we only want to accept
|
||||
* defaults in CREATE FUNCTION, not in ALTER etc.
|
||||
*/
|
||||
func_args_with_defaults:
|
||||
'(' func_args_with_defaults_list ')' { $$ = $2; }
|
||||
| '(' ')' { $$ = NIL; }
|
||||
;
|
||||
|
||||
func_args_with_defaults_list:
|
||||
func_arg_with_default { $$ = list_make1( $1); }
|
||||
| func_args_with_defaults_list ',' func_arg_with_default { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* The style with arg_class first is SQL99 standard, but Oracle puts
|
||||
* param_name first; accept both since it's likely people will try both
|
||||
@@ -4240,6 +4256,7 @@ func_arg:
|
||||
n->name = $2;
|
||||
n->argType = $3;
|
||||
n->mode = $1;
|
||||
n->defexpr = NULL;
|
||||
$$ = n;
|
||||
}
|
||||
| param_name arg_class func_type
|
||||
@@ -4248,6 +4265,7 @@ func_arg:
|
||||
n->name = $1;
|
||||
n->argType = $3;
|
||||
n->mode = $2;
|
||||
n->defexpr = NULL;
|
||||
$$ = n;
|
||||
}
|
||||
| param_name func_type
|
||||
@@ -4256,6 +4274,7 @@ func_arg:
|
||||
n->name = $1;
|
||||
n->argType = $2;
|
||||
n->mode = FUNC_PARAM_IN;
|
||||
n->defexpr = NULL;
|
||||
$$ = n;
|
||||
}
|
||||
| arg_class func_type
|
||||
@@ -4264,6 +4283,7 @@ func_arg:
|
||||
n->name = NULL;
|
||||
n->argType = $2;
|
||||
n->mode = $1;
|
||||
n->defexpr = NULL;
|
||||
$$ = n;
|
||||
}
|
||||
| func_type
|
||||
@@ -4272,6 +4292,7 @@ func_arg:
|
||||
n->name = NULL;
|
||||
n->argType = $1;
|
||||
n->mode = FUNC_PARAM_IN;
|
||||
n->defexpr = NULL;
|
||||
$$ = n;
|
||||
}
|
||||
;
|
||||
@@ -4322,6 +4343,23 @@ func_type: Typename { $$ = $1; }
|
||||
}
|
||||
;
|
||||
|
||||
func_arg_with_default:
|
||||
func_arg
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| func_arg DEFAULT a_expr
|
||||
{
|
||||
$$ = $1;
|
||||
$$->defexpr = $3;
|
||||
}
|
||||
| func_arg '=' a_expr
|
||||
{
|
||||
$$ = $1;
|
||||
$$->defexpr = $3;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
createfunc_opt_list:
|
||||
/* Must be at least one to prevent conflict */
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.207 2008/09/01 20:42:44 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.208 2008/12/04 17:51:26 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -77,6 +77,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
bool retset;
|
||||
int nvargs;
|
||||
FuncDetailCode fdresult;
|
||||
List *argdefaults;
|
||||
|
||||
/*
|
||||
* Most of the rest of the parser just assumes that functions do not have
|
||||
@@ -164,7 +165,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
fdresult = func_get_detail(funcname, fargs, nargs, actual_arg_types,
|
||||
!func_variadic,
|
||||
&funcid, &rettype, &retset, &nvargs,
|
||||
&declared_arg_types);
|
||||
&declared_arg_types, &argdefaults);
|
||||
if (fdresult == FUNCDETAIL_COERCION)
|
||||
{
|
||||
/*
|
||||
@@ -234,6 +235,21 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
|
||||
parser_errposition(pstate, location)));
|
||||
}
|
||||
|
||||
/* add stored expressions as called values for arguments with defaults */
|
||||
if (argdefaults)
|
||||
{
|
||||
ListCell *lc;
|
||||
|
||||
foreach(lc, argdefaults)
|
||||
{
|
||||
Node *expr = (Node *) lfirst(lc);
|
||||
|
||||
fargs = lappend(fargs, expr);
|
||||
actual_arg_types[nargs++] = exprType(expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* enforce consistency with polymorphic argument and return types,
|
||||
* possibly adjusting return type or declared_arg_types (which will be
|
||||
@@ -729,7 +745,8 @@ func_get_detail(List *funcname,
|
||||
Oid *rettype, /* return value */
|
||||
bool *retset, /* return value */
|
||||
int *nvargs, /* return value */
|
||||
Oid **true_typeids) /* return value */
|
||||
Oid **true_typeids, /* return value */
|
||||
List **argdefaults) /* return value */
|
||||
{
|
||||
FuncCandidateList raw_candidates;
|
||||
FuncCandidateList best_candidate;
|
||||
@@ -870,6 +887,8 @@ func_get_detail(List *funcname,
|
||||
*funcid = best_candidate->oid;
|
||||
*nvargs = best_candidate->nvargs;
|
||||
*true_typeids = best_candidate->args;
|
||||
if (argdefaults)
|
||||
*argdefaults = best_candidate->argdefaults;
|
||||
|
||||
ftup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(best_candidate->oid),
|
||||
|
Reference in New Issue
Block a user